PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/samba-3.5.6/source3/libsmb/namequery_dc.c

https://github.com/theuni/XBMC-deps
C | 249 lines | 148 code | 46 blank | 55 comment | 29 complexity | e6bbca505d8f48448a6828c2e18ef1f9 MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. Winbind daemon connection manager
  4. Copyright (C) Tim Potter 2001
  5. Copyright (C) Andrew Bartlett 2002
  6. Copyright (C) Gerald Carter 2003
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 3 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "includes.h"
  19. /**********************************************************************
  20. Is this our primary domain ?
  21. **********************************************************************/
  22. #ifdef HAVE_KRB5
  23. static bool is_our_primary_domain(const char *domain)
  24. {
  25. int role = lp_server_role();
  26. if ((role == ROLE_DOMAIN_MEMBER) && strequal(lp_workgroup(), domain)) {
  27. return True;
  28. } else if (strequal(get_global_sam_name(), domain)) {
  29. return True;
  30. }
  31. return False;
  32. }
  33. #endif
  34. /**************************************************************************
  35. Find the name and IP address for a server in the realm/domain
  36. *************************************************************************/
  37. static bool ads_dc_name(const char *domain,
  38. const char *realm,
  39. struct sockaddr_storage *dc_ss,
  40. fstring srv_name)
  41. {
  42. ADS_STRUCT *ads;
  43. char *sitename;
  44. int i;
  45. char addr[INET6_ADDRSTRLEN];
  46. if (!realm && strequal(domain, lp_workgroup())) {
  47. realm = lp_realm();
  48. }
  49. sitename = sitename_fetch(realm);
  50. /* Try this 3 times then give up. */
  51. for( i =0 ; i < 3; i++) {
  52. ads = ads_init(realm, domain, NULL);
  53. if (!ads) {
  54. SAFE_FREE(sitename);
  55. return False;
  56. }
  57. DEBUG(4,("ads_dc_name: domain=%s\n", domain));
  58. #ifdef HAVE_ADS
  59. /* we don't need to bind, just connect */
  60. ads->auth.flags |= ADS_AUTH_NO_BIND;
  61. ads_connect(ads);
  62. #endif
  63. if (!ads->config.realm) {
  64. SAFE_FREE(sitename);
  65. ads_destroy(&ads);
  66. return False;
  67. }
  68. /* Now we've found a server, see if our sitename
  69. has changed. If so, we need to re-do the DNS query
  70. to ensure we only find servers in our site. */
  71. if (stored_sitename_changed(realm, sitename)) {
  72. SAFE_FREE(sitename);
  73. sitename = sitename_fetch(realm);
  74. ads_destroy(&ads);
  75. /* Ensure we don't cache the DC we just connected to. */
  76. namecache_delete(realm, 0x1C);
  77. namecache_delete(domain, 0x1C);
  78. continue;
  79. }
  80. #ifdef HAVE_KRB5
  81. if (is_our_primary_domain(domain) && (ads->config.flags & NBT_SERVER_KDC)) {
  82. if (ads_closest_dc(ads)) {
  83. /* We're going to use this KDC for this realm/domain.
  84. If we are using sites, then force the krb5 libs
  85. to use this KDC. */
  86. create_local_private_krb5_conf_for_domain(realm,
  87. domain,
  88. sitename,
  89. &ads->ldap.ss,
  90. ads->config.ldap_server_name);
  91. } else {
  92. create_local_private_krb5_conf_for_domain(realm,
  93. domain,
  94. NULL,
  95. &ads->ldap.ss,
  96. ads->config.ldap_server_name);
  97. }
  98. }
  99. #endif
  100. break;
  101. }
  102. if (i == 3) {
  103. DEBUG(1,("ads_dc_name: sitename (now \"%s\") keeps changing ???\n",
  104. sitename ? sitename : ""));
  105. SAFE_FREE(sitename);
  106. return False;
  107. }
  108. SAFE_FREE(sitename);
  109. fstrcpy(srv_name, ads->config.ldap_server_name);
  110. strupper_m(srv_name);
  111. #ifdef HAVE_ADS
  112. *dc_ss = ads->ldap.ss;
  113. #else
  114. zero_sockaddr(dc_ss);
  115. #endif
  116. ads_destroy(&ads);
  117. print_sockaddr(addr, sizeof(addr), dc_ss);
  118. DEBUG(4,("ads_dc_name: using server='%s' IP=%s\n",
  119. srv_name, addr));
  120. return True;
  121. }
  122. /****************************************************************************
  123. Utility function to return the name of a DC. The name is guaranteed to be
  124. valid since we have already done a name_status_find on it
  125. ***************************************************************************/
  126. static bool rpc_dc_name(const char *domain,
  127. fstring srv_name,
  128. struct sockaddr_storage *ss_out)
  129. {
  130. struct ip_service *ip_list = NULL;
  131. struct sockaddr_storage dc_ss;
  132. int count, i;
  133. NTSTATUS result;
  134. char addr[INET6_ADDRSTRLEN];
  135. /* get a list of all domain controllers */
  136. if (!NT_STATUS_IS_OK(get_sorted_dc_list(domain, NULL, &ip_list, &count,
  137. False))) {
  138. DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
  139. return False;
  140. }
  141. /* Remove the entry we've already failed with (should be the PDC). */
  142. for (i = 0; i < count; i++) {
  143. if (is_zero_addr((struct sockaddr *)&ip_list[i].ss))
  144. continue;
  145. if (name_status_find(domain, 0x1c, 0x20, &ip_list[i].ss, srv_name)) {
  146. result = check_negative_conn_cache( domain, srv_name );
  147. if ( NT_STATUS_IS_OK(result) ) {
  148. dc_ss = ip_list[i].ss;
  149. goto done;
  150. }
  151. }
  152. }
  153. SAFE_FREE(ip_list);
  154. /* No-one to talk to )-: */
  155. return False; /* Boo-hoo */
  156. done:
  157. /* We have the netbios name and IP address of a domain controller.
  158. Ideally we should sent a SAMLOGON request to determine whether
  159. the DC is alive and kicking. If we can catch a dead DC before
  160. performing a cli_connect() we can avoid a 30-second timeout. */
  161. print_sockaddr(addr, sizeof(addr), &dc_ss);
  162. DEBUG(3, ("rpc_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
  163. addr, domain));
  164. *ss_out = dc_ss;
  165. SAFE_FREE(ip_list);
  166. return True;
  167. }
  168. /**********************************************************************
  169. wrapper around ads and rpc methods of finds DC's
  170. **********************************************************************/
  171. bool get_dc_name(const char *domain,
  172. const char *realm,
  173. fstring srv_name,
  174. struct sockaddr_storage *ss_out)
  175. {
  176. struct sockaddr_storage dc_ss;
  177. bool ret;
  178. bool our_domain = False;
  179. zero_sockaddr(&dc_ss);
  180. ret = False;
  181. if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), realm) )
  182. our_domain = True;
  183. /* always try to obey what the admin specified in smb.conf
  184. (for the local domain) */
  185. if ( (our_domain && lp_security()==SEC_ADS) || realm ) {
  186. ret = ads_dc_name(domain, realm, &dc_ss, srv_name);
  187. }
  188. if (!domain) {
  189. /* if we have only the realm we can't do anything else */
  190. return False;
  191. }
  192. if (!ret) {
  193. /* fall back on rpc methods if the ADS methods fail */
  194. ret = rpc_dc_name(domain, srv_name, &dc_ss);
  195. }
  196. *ss_out = dc_ss;
  197. return ret;
  198. }