summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/ads.h1
-rw-r--r--source3/libads/cldap.c2
-rw-r--r--source3/libads/kerberos.c58
-rw-r--r--source3/libads/ldap.c1
-rw-r--r--source3/libsmb/namequery_dc.c27
-rw-r--r--source3/nsswitch/winbindd_cm.c63
6 files changed, 117 insertions, 35 deletions
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 0ef84b4805..365ac3e852 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -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;
diff --git a/source3/libads/cldap.c b/source3/libads/cldap.c
index 3a6083558f..da1dec6b93 100644
--- a/source3/libads/cldap.c
+++ b/source3/libads/cldap.c
@@ -306,5 +306,3 @@ BOOL ads_cldap_netlogon(const char *server, const char *realm, struct cldap_net
return True;
}
-
-
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 910207968c..4e4e4cfebf 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -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
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 947f58a8fd..1d192895d9 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -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);
diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c
index ed71a9816a..4099cc9dd8 100644
--- a/source3/libsmb/namequery_dc.c
+++ b/source3/libsmb/namequery_dc.c
@@ -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;
}
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index 2f2bfb60ee..a09faaed94 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -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;
}