summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/ads.h1
-rw-r--r--source3/libads/ads_struct.c19
-rw-r--r--source3/libads/ldap.c24
-rw-r--r--source3/nsswitch/winbindd_ads.c4
-rw-r--r--source3/smbd/negprot.c2
-rw-r--r--source3/smbd/sesssetup.c2
-rw-r--r--source3/utils/net_ads.c9
7 files changed, 52 insertions, 9 deletions
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 8658e72f6a..b3e18f18b8 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -7,6 +7,7 @@
typedef struct {
void *ld;
char *realm;
+ char *workgroup;
char *ldap_server;
char *ldap_server_name;
char *kdc_server;
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c
index 489f301ae2..816b616097 100644
--- a/source3/libads/ads_struct.c
+++ b/source3/libads/ads_struct.c
@@ -90,7 +90,12 @@ static char *find_ldap_server(ADS_STRUCT *ads)
}
/* get desperate, find the domain controller IP */
- if (resolve_name(lp_workgroup(), &ip, 0x1B)) {
+ if (resolve_name(ads->workgroup, &ip, 0x1B)) {
+ return strdup(inet_ntoa(ip));
+ }
+
+ /* or a BDC ... */
+ if (resolve_name(ads->workgroup, &ip, 0x1C)) {
return strdup(inet_ntoa(ip));
}
@@ -115,6 +120,7 @@ static char *find_ldap_server(ADS_STRUCT *ads)
initialise a ADS_STRUCT, ready for some ads_ ops
*/
ADS_STRUCT *ads_init(const char *realm,
+ const char *workgroup,
const char *ldap_server,
const char *bind_path,
const char *password)
@@ -124,7 +130,12 @@ ADS_STRUCT *ads_init(const char *realm,
ads = (ADS_STRUCT *)smb_xmalloc(sizeof(*ads));
ZERO_STRUCTP(ads);
+ if (!workgroup) {
+ workgroup = lp_workgroup();
+ }
+
ads->realm = realm? strdup(realm) : NULL;
+ ads->workgroup = strdup(workgroup);
ads->ldap_server = ldap_server? strdup(ldap_server) : NULL;
ads->bind_path = bind_path? strdup(bind_path) : NULL;
ads->ldap_port = LDAP_PORT;
@@ -153,6 +164,12 @@ ADS_STRUCT *ads_init(const char *realm,
return ads;
}
+/* a simpler ads_init() interface using all defaults */
+ADS_STRUCT *ads_init_simple(void)
+{
+ return ads_init(NULL, NULL, NULL, NULL, NULL);
+}
+
/*
free the memory used by the ADS structure initialized with 'ads_init(...)'
*/
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index e2e351bd4b..3b787c6a8f 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -46,9 +46,33 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
ads->last_attempt = time(NULL);
ads->ld = ldap_open(ads->ldap_server, ads->ldap_port);
+
+ /* if that failed then try each of the BDC's in turn */
+ if (!ads->ld) {
+ struct in_addr *ip_list;
+ int count;
+
+ if (get_dc_list(False, ads->workgroup, &ip_list, &count)) {
+ int i;
+ for (i=0;i<count;i++) {
+ ads->ld = ldap_open(inet_ntoa(ip_list[i]),
+ ads->ldap_port);
+ if (ads->ld) break;
+ }
+ if (ads->ld) {
+ free(ads->ldap_server);
+ ads->ldap_server = strdup(inet_ntoa(ip_list[i]));
+ }
+ free(ip_list);
+ }
+ }
+
if (!ads->ld) {
return ADS_ERROR_SYSTEM(errno);
}
+
+ DEBUG(3,("Connected to LDAP server %s\n", ads->ldap_server));
+
status = ads_server_info(ads);
if (!ADS_ERR_OK(status)) {
DEBUG(1,("Failed to get ldap server info\n"));
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index af0933716b..6c00ddb95f 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -119,6 +119,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
if (resolve_name(domain->name, &server_ip, 0x1b)) {
sname = inet_ntoa(server_ip);
+ } else if (resolve_name(domain->name, &server_ip, 0x1c)) {
+ sname = inet_ntoa(server_ip);
} else {
if (strcasecmp(domain->name, lp_workgroup()) != 0) {
DEBUG(1,("can't find domain controller for %s\n", domain->name));
@@ -127,7 +129,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
sname = NULL;
}
- ads = ads_init(primary_realm, sname, NULL, NULL);
+ ads = ads_init(primary_realm, domain->name, NULL, NULL, NULL);
if (!ads) {
DEBUG(1,("ads_init for domain %s failed\n", domain->name));
return NULL;
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 18682e6c9f..c548ee6196 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -197,7 +197,7 @@ static int negprot_spnego(char *p)
blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
} else {
ADS_STRUCT *ads;
- ads = ads_init(NULL, NULL, NULL, NULL);
+ ads = ads_init_simple();
/* win2000 uses host$@REALM, which we will probably use eventually,
but for now this works */
asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 8b9d826067..66eb6a2d92 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -120,7 +120,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- ads = ads_init(NULL, NULL, NULL, NULL);
+ ads = ads_init_simple();
ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
if (!NT_STATUS_IS_OK(ret)) {
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 68fa89ea35..ea261187ce 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -56,7 +56,7 @@ static int net_ads_info(int argc, const char **argv)
{
ADS_STRUCT *ads;
- ads = ads_init(NULL, opt_host, NULL, NULL);
+ ads = ads_init(NULL, NULL, opt_host, NULL, NULL);
ads_connect(ads);
if (!ads) {
@@ -81,7 +81,7 @@ static ADS_STRUCT *ads_startup(void)
BOOL need_password = False;
BOOL second_time = False;
- ads = ads_init(NULL, opt_host, NULL, NULL);
+ ads = ads_init(NULL, NULL, opt_host, NULL, NULL);
if (!opt_user_name) {
opt_user_name = "administrator";
@@ -650,7 +650,7 @@ static int net_ads_password(int argc, const char **argv)
/* use the realm so we can eventually change passwords for users
in realms other than default */
- if (!(ads = ads_init(realm, NULL, NULL, NULL))) return -1;
+ if (!(ads = ads_init(realm, NULL, NULL, NULL, NULL))) return -1;
asprintf(&prompt, "Enter new password for %s:", argv[0]);
@@ -681,8 +681,7 @@ static int net_ads_change_localhost_pass(int argc, const char **argv)
char *hostname;
ADS_STATUS ret;
-
- if (!(ads = ads_init(NULL, NULL, NULL, NULL))) return -1;
+ if (!(ads = ads_init_simple())) return -1;
hostname = strdup(global_myname);
strlower(hostname);