r17943: The horror, the horror. Add KDC site support by
authorJeremy Allison <jra@samba.org>
Thu, 31 Aug 2006 01:20:21 +0000 (01:20 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:39:01 +0000 (11:39 -0500)
writing out a custom krb5.conf file containing
the KDC I need. This may suck.... Needs some
testing :-).
Jeremy.

source/include/ads.h
source/libads/cldap.c
source/libads/kerberos.c
source/libads/ldap.c
source/libsmb/namequery_dc.c
source/nsswitch/winbindd_cm.c

index 0ef84b48058d4825c9f6cd3b226fa0176666ee6a..365ac3e852629be6ab11f9b44b6611e974528e8d 100644 (file)
@@ -42,6 +42,7 @@ typedef struct {
 
        /* info derived from the servers config */
        struct {
+               uint32 flags; /* cldap flags identifying the services. */
                char *realm;
                char *bind_path;
                char *ldap_server_name;
index 3a6083558f13380bce902dbd96fc64963372ec69..da1dec6b931c9841e45b7ab7443c9542523c9d0f 100644 (file)
@@ -306,5 +306,3 @@ BOOL ads_cldap_netlogon(const char *server, const char *realm,  struct cldap_net
 
        return True;
 }
-
-
index 910207968c8e35b46a5b6b6d32b247774139cc96..4e4e4cfebf8db4bf26f67fd73a71b0287e43af2b 100644 (file)
@@ -464,4 +464,62 @@ int kerberos_kinit_password(const char *principal,
                                           0);
 }
 
+/************************************************************************
+ Create  a specific krb5.conf file in the private directory pointing
+ at a specific kdc for a realm. Keyed off domain name. Sets
+ KRB5_CONFIG environment variable to point to this file. Must be
+ run as root or will fail (which is a good thing :-).
+************************************************************************/
+
+BOOL create_local_private_krb5_conf_for_domain(const char *realm, const char *domain, struct in_addr ip)
+{
+       XFILE *xfp = NULL;
+       char *fname = talloc_asprintf(NULL, "%s/smb_krb5.conf.%s", lp_private_dir(), domain);
+       char *file_contents = NULL;
+       size_t flen = 0;
+
+       if (!fname) {
+               return False;
+       }
+
+       file_contents = talloc_asprintf(fname, "[libdefaults]\n\tdefault_realm = %s\n"
+                               "[realms]\n\t%s = {\n"
+                               "\t\tkdc = %s\n]\n",
+                               realm, realm, inet_ntoa(ip));
+
+       if (!file_contents) {
+               TALLOC_FREE(fname);
+               return False;
+       }
+
+       flen = strlen(file_contents);
+       xfp = x_fopen(fname, O_CREAT|O_WRONLY, 0600);
+       if (!xfp) {
+               TALLOC_FREE(fname);
+               return False;
+       }
+       /* Lock the file. */
+       if (!fcntl_lock(xfp->fd, F_SETLKW, 0, 1, F_WRLCK)) {
+               unlink(fname);
+               x_fclose(xfp);
+               TALLOC_FREE(fname);
+               return False;
+       }
+
+       if (x_fwrite(file_contents, flen, 1, xfp) != flen) {
+               unlink(fname);
+               x_fclose(xfp);
+               TALLOC_FREE(fname);
+               return False;
+       }
+       if (x_fclose(xfp)==-1) {
+               unlink(fname);
+               TALLOC_FREE(fname);
+               return False;
+       }
+       /* Set the environment variable to this file. */
+       setenv("KRB5_CONFIG", fname, 1);
+       TALLOC_FREE(fname);
+       return True;
+}
 #endif
index 947f58a8fd5b55f997a34591907f21bdc3a89eb5..1d192895d905891a5fc908efa7c8c341c1f3ac3b 100644 (file)
@@ -159,6 +159,7 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
        SAFE_FREE(ads->config.ldap_server_name);
        SAFE_FREE(ads->server.workgroup);
 
+       ads->config.flags              = cldap_reply.flags;
        ads->config.ldap_server_name   = SMB_STRDUP(cldap_reply.hostname);
        strupper_m(cldap_reply.domain);
        ads->config.realm              = SMB_STRDUP(cldap_reply.domain);
index ed71a9816a99f6b517594aaa7940538f0b7a26ad..4099cc9dd8fb05838f3196d077d0e679cbade368 100644 (file)
@@ -38,8 +38,9 @@ static BOOL ads_dc_name(const char *domain,
        char *sitename = sitename_fetch();
        int i;
 
-       if (!realm && strequal(domain, lp_workgroup()))
+       if (!realm && strequal(domain, lp_workgroup())) {
                realm = lp_realm();
+       }
 
        /* Try this 3 times then give up. */
        for( i =0 ; i < 3; i++) {
@@ -64,22 +65,34 @@ static BOOL ads_dc_name(const char *domain,
                }
 
                /* Now we've found a server, see if our sitename
-                  has changed. If so, we need to re-do the query
+                  has changed. If so, we need to re-do the DNS query
                   to ensure we only find servers in our site. */
 
-               if (!sitename_changed(sitename)) {
-                       break;
+               if (sitename_changed(sitename)) {
+                       SAFE_FREE(sitename);
+                       sitename = sitename_fetch();
+                       ads_destroy(&ads);
+                       continue;
                }
 
-               ads_destroy(&ads);
-       }
+#ifdef HAVE_KRB5
+               if ((ads->config.flags & ADS_KDC) && sitename) {
+                       /* We're going to use this KDC for this realm/domain.
+                          If we are using sites, then force the krb5 libs
+                          to use this KDC. */
 
+                       create_local_private_krb5_conf_for_domain(realm,
+                                                               domain,
+                                                               ads->ldap_ip);
+               }
+#endif
+               break;
+       }
 
        if (i == 3) {
                DEBUG(1,("ads_dc_name: sitename (now \"%s\") keeps changing ???\n",
                        sitename ? sitename : ""));
                SAFE_FREE(sitename);
-               ads_destroy(&ads);
                return False;
        }
 
index 2f2bfb60ee88679cf29532212ab3505a45a10621..a09faaed949bc588cd1c2bb162b4059b0b2943d4 100644 (file)
@@ -590,7 +590,43 @@ static BOOL dcip_to_name( const char *domainname, const char *realm,
        ip_list.ip = ip;
        ip_list.port = 0;
 
-       /* try GETDC requests first */
+#ifdef WITH_ADS
+       /* For active directory servers, try to get the ldap server name.
+          None of these failures should be considered critical for now */
+
+       if ( lp_security() == SEC_ADS ) {
+               ADS_STRUCT *ads;
+
+               ads = ads_init(realm, domainname, NULL);
+               ads->auth.flags |= ADS_AUTH_NO_BIND;
+
+               if (ads_try_connect( ads, inet_ntoa(ip) ) )  {
+                       const char *sitename = sitename_fetch();
+                       /* We got a cldap packet. */
+                       fstrcpy(name, ads->config.ldap_server_name);
+                       namecache_store(name, 0x20, 1, &ip_list);
+
+#ifdef HAVE_KRB5
+                       if ((ads->config.flags & ADS_KDC) && sitename) {
+                               /* We're going to use this KDC for this realm/domain.
+                                  If we are using sites, then force the krb5 libs
+                                  to use this KDC. */
+
+                               create_local_private_krb5_conf_for_domain(realm,
+                                                               domainname,
+                                                               ip);
+                       }
+#endif
+                       SAFE_FREE(sitename);
+                       ads_destroy( &ads );
+                       return True;
+               }
+
+               ads_destroy( &ads );
+       }
+#endif
+
+       /* try GETDC requests next */
        
        if (send_getdc_request(ip, domainname, sid)) {
                int i;
@@ -610,31 +646,6 @@ static BOOL dcip_to_name( const char *domainname, const char *realm,
                namecache_store(name, 0x20, 1, &ip_list);
                return True;
        }
-
-#ifdef WITH_ADS
-       /* for active directory servers, try to get the ldap server name.
-          None of these failure should be considered critical for now */
-
-       if ( lp_security() == SEC_ADS ) 
-       {
-               ADS_STRUCT *ads;
-
-               ads = ads_init( realm, domainname, NULL );
-               ads->auth.flags |= ADS_AUTH_NO_BIND;
-
-               if ( !ads_try_connect( ads, inet_ntoa(ip) ) )  {
-                       ads_destroy( &ads );
-                       return False;
-               }
-
-               fstrcpy(name, ads->config.ldap_server_name);
-               namecache_store(name, 0x20, 1, &ip_list);
-
-               ads_destroy( &ads );
-               return True;
-       }
-#endif
-
        return False;
 }