libsmb/namequery_dc.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    Winbind daemon connection manager
00005 
00006    Copyright (C) Tim Potter 2001
00007    Copyright (C) Andrew Bartlett 2002
00008    Copyright (C) Gerald Carter 2003
00009    
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 
00026 #include "includes.h"
00027 
00028 /**********************************************************************
00029  Is this our primary domain ?
00030 **********************************************************************/
00031 
00032 #ifdef HAVE_KRB5
00033 static BOOL is_our_primary_domain(const char *domain)
00034 {
00035         int role = lp_server_role();
00036 
00037         if ((role == ROLE_DOMAIN_MEMBER) && strequal(lp_workgroup(), domain)) {
00038                 return True;
00039         } else if (strequal(get_global_sam_name(), domain)) {
00040                 return True;
00041         }
00042         return False;
00043 }
00044 #endif
00045 
00046 /**************************************************************************
00047  Find the name and IP address for a server in the realm/domain
00048  *************************************************************************/
00049  
00050 static BOOL ads_dc_name(const char *domain,
00051                         const char *realm,
00052                         struct in_addr *dc_ip,
00053                         fstring srv_name)
00054 {
00055         ADS_STRUCT *ads;
00056         char *sitename;
00057         int i;
00058 
00059         if (!realm && strequal(domain, lp_workgroup())) {
00060                 realm = lp_realm();
00061         }
00062 
00063         sitename = sitename_fetch(realm);
00064 
00065         /* Try this 3 times then give up. */
00066         for( i =0 ; i < 3; i++) {
00067                 ads = ads_init(realm, domain, NULL);
00068                 if (!ads) {
00069                         SAFE_FREE(sitename);
00070                         return False;
00071                 }
00072 
00073                 DEBUG(4,("ads_dc_name: domain=%s\n", domain));
00074 
00075 #ifdef HAVE_ADS
00076                 /* we don't need to bind, just connect */
00077                 ads->auth.flags |= ADS_AUTH_NO_BIND;
00078                 ads_connect(ads);
00079 #endif
00080 
00081                 if (!ads->config.realm) {
00082                         SAFE_FREE(sitename);
00083                         ads_destroy(&ads);
00084                         return False;
00085                 }
00086 
00087                 /* Now we've found a server, see if our sitename
00088                    has changed. If so, we need to re-do the DNS query
00089                    to ensure we only find servers in our site. */
00090 
00091                 if (stored_sitename_changed(realm, sitename)) {
00092                         SAFE_FREE(sitename);
00093                         sitename = sitename_fetch(realm);
00094                         ads_destroy(&ads);
00095                         /* Ensure we don't cache the DC we just connected to. */
00096                         namecache_delete(realm, 0x1C);
00097                         namecache_delete(domain, 0x1C);
00098                         continue;
00099                 }
00100 
00101 #ifdef HAVE_KRB5
00102                 if (is_our_primary_domain(domain) && (ads->config.flags & ADS_KDC)) {
00103                         if (ads_closest_dc(ads)) {
00104                                 /* We're going to use this KDC for this realm/domain.
00105                                    If we are using sites, then force the krb5 libs
00106                                    to use this KDC. */
00107 
00108                                 create_local_private_krb5_conf_for_domain(realm,
00109                                                                         domain,
00110                                                                         sitename,
00111                                                                         ads->ldap_ip);
00112                         } else {
00113                                 /* use an off site KDC */
00114                                 create_local_private_krb5_conf_for_domain(realm,
00115                                                                         domain,
00116                                                                         NULL,
00117                                                                         ads->ldap_ip);
00118                         }
00119                 }
00120 #endif
00121                 break;
00122         }
00123 
00124         if (i == 3) {
00125                 DEBUG(1,("ads_dc_name: sitename (now \"%s\") keeps changing ???\n",
00126                         sitename ? sitename : ""));
00127                 SAFE_FREE(sitename);
00128                 return False;
00129         }
00130 
00131         SAFE_FREE(sitename);
00132 
00133         fstrcpy(srv_name, ads->config.ldap_server_name);
00134         strupper_m(srv_name);
00135         *dc_ip = ads->ldap_ip;
00136         ads_destroy(&ads);
00137         
00138         DEBUG(4,("ads_dc_name: using server='%s' IP=%s\n",
00139                  srv_name, inet_ntoa(*dc_ip)));
00140         
00141         return True;
00142 }
00143 
00144 /****************************************************************************
00145  Utility function to return the name of a DC. The name is guaranteed to be 
00146  valid since we have already done a name_status_find on it 
00147  ***************************************************************************/
00148 
00149 static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
00150 {
00151         struct ip_service *ip_list = NULL;
00152         struct in_addr dc_ip, exclude_ip;
00153         int count, i;
00154         NTSTATUS result;
00155         
00156         zero_ip(&exclude_ip);
00157 
00158         /* get a list of all domain controllers */
00159         
00160         if (!NT_STATUS_IS_OK(get_sorted_dc_list(domain, NULL, &ip_list, &count,
00161                                                 False))) {
00162                 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
00163                 return False;
00164         }
00165 
00166         /* Remove the entry we've already failed with (should be the PDC). */
00167 
00168         for (i = 0; i < count; i++) {
00169                 if (is_zero_ip(ip_list[i].ip))
00170                         continue;
00171 
00172                 if (name_status_find(domain, 0x1c, 0x20, ip_list[i].ip, srv_name)) {
00173                         result = check_negative_conn_cache( domain, srv_name );
00174                         if ( NT_STATUS_IS_OK(result) ) {
00175                                 dc_ip = ip_list[i].ip;
00176                                 goto done;
00177                         }
00178                 }
00179         }
00180         
00181 
00182         SAFE_FREE(ip_list);
00183 
00184         /* No-one to talk to )-: */
00185         return False;           /* Boo-hoo */
00186         
00187  done:
00188         /* We have the netbios name and IP address of a domain controller.
00189            Ideally we should sent a SAMLOGON request to determine whether
00190            the DC is alive and kicking.  If we can catch a dead DC before
00191            performing a cli_connect() we can avoid a 30-second timeout. */
00192 
00193         DEBUG(3, ("rpc_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
00194                   inet_ntoa(dc_ip), domain));
00195 
00196         *ip_out = dc_ip;
00197 
00198         SAFE_FREE(ip_list);
00199 
00200         return True;
00201 }
00202 
00203 /**********************************************************************
00204  wrapper around ads and rpc methods of finds DC's
00205 **********************************************************************/
00206 
00207 BOOL get_dc_name(const char *domain, const char *realm, fstring srv_name, struct in_addr *ip_out)
00208 {
00209         struct in_addr dc_ip;
00210         BOOL ret;
00211         BOOL our_domain = False;
00212 
00213         zero_ip(&dc_ip);
00214 
00215         ret = False;
00216         
00217         if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), realm) )
00218                 our_domain = True;
00219         
00220         /* always try to obey what the admin specified in smb.conf 
00221            (for the local domain) */
00222         
00223         if ( (our_domain && lp_security()==SEC_ADS) || realm ) {
00224                 ret = ads_dc_name(domain, realm, &dc_ip, srv_name);
00225         }
00226 
00227         if (!domain) {
00228                 /* if we have only the realm we can't do anything else */
00229                 return False;
00230         }
00231         
00232         if (!ret) {
00233                 /* fall back on rpc methods if the ADS methods fail */
00234                 ret = rpc_dc_name(domain, srv_name, &dc_ip);
00235         }
00236                 
00237         *ip_out = dc_ip;
00238 
00239         return ret;
00240 }

Sambaに対してSat Aug 29 21:23:05 2009に生成されました。  doxygen 1.4.7