summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2002-08-17 17:00:51 +0000
committerJelmer Vernooij <jelmer@samba.org>2002-08-17 17:00:51 +0000
commitb2edf254eda92f775e7d3d9b6793b4d77f9000b6 (patch)
tree18eb2564a769678c774a19bb07c00fc4aa7b2758 /source3/libads
parent669a39fae36f8bc60753c9b352556ef8ffaeb568 (diff)
downloadsamba-b2edf254eda92f775e7d3d9b6793b4d77f9000b6.tar.gz
samba-b2edf254eda92f775e7d3d9b6793b4d77f9000b6.tar.bz2
samba-b2edf254eda92f775e7d3d9b6793b4d77f9000b6.zip
sync 3.0 branch with head
(This used to be commit 3928578b52cfc949be5e0ef444fce1558d75f290)
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/ads_struct.c107
-rw-r--r--source3/libads/kerberos.c12
-rw-r--r--source3/libads/kerberos_verify.c2
-rw-r--r--source3/libads/ldap.c389
-rw-r--r--source3/libads/ldap_user.c6
-rw-r--r--source3/libads/sasl.c9
-rw-r--r--source3/libads/util.c2
7 files changed, 358 insertions, 169 deletions
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c
index 638dc0b22e..b68c822ce3 100644
--- a/source3/libads/ads_struct.c
+++ b/source3/libads/ads_struct.c
@@ -72,47 +72,6 @@ char *ads_build_dn(const char *realm)
}
-#ifdef HAVE_LDAP
-/*
- find the ldap server from DNS
-*/
-static char *find_ldap_server(ADS_STRUCT *ads)
-{
- char *list = NULL;
- struct in_addr ip;
-
- if (ads->realm &&
- strcasecmp(ads->workgroup, lp_workgroup()) == 0 &&
- ldap_domain2hostlist(ads->realm, &list) == LDAP_SUCCESS) {
- char *p;
- p = strchr(list, ':');
- if (p) *p = 0;
- return list;
- }
-
- /* get desperate, find the domain controller IP */
- 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));
- }
-
- return NULL;
-}
-
-#else
-
-static char *find_ldap_server(ADS_STRUCT *ads)
-{
- /* Without LDAP this doesn't make much sense */
- return NULL;
-}
-
-#endif
-
#ifndef LDAP_PORT
#define LDAP_PORT 389
#endif
@@ -122,46 +81,24 @@ static char *find_ldap_server(ADS_STRUCT *ads)
*/
ADS_STRUCT *ads_init(const char *realm,
const char *workgroup,
- const char *ldap_server,
- const char *bind_path,
- const char *password)
+ const char *ldap_server)
{
ADS_STRUCT *ads;
ads = (ADS_STRUCT *)smb_xmalloc(sizeof(*ads));
ZERO_STRUCTP(ads);
- if (!workgroup) {
- workgroup = lp_workgroup();
+ ads->server.realm = realm? strdup(realm) : NULL;
+ ads->server.workgroup = workgroup ? strdup(workgroup) : NULL;
+ ads->server.ldap_server = ldap_server? strdup(ldap_server) : NULL;
+
+ /* we need to know if this is a foreign realm to know if we can
+ use lp_ads_server() */
+ if (realm && strcasecmp(lp_realm(), realm) != 0) {
+ ads->server.foreign = 1;
}
-
- 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;
- if (password) ads->password = strdup(password);
-
- if (!ads->realm) {
- ads->realm = strdup(lp_realm());
- if (!ads->realm[0]) {
- SAFE_FREE(ads->realm);
- }
- }
- if (!ads->bind_path && ads->realm) {
- ads->bind_path = ads_build_dn(ads->realm);
- }
- if (!ads->ldap_server) {
- if (strcasecmp(ads->workgroup, lp_workgroup()) == 0) {
- ads->ldap_server = strdup(lp_ads_server());
- }
- if (!ads->ldap_server || !ads->ldap_server[0]) {
- ads->ldap_server = find_ldap_server(ads);
- }
- }
- if (!ads->kdc_server) {
- /* assume its the same as LDAP */
- ads->kdc_server = ads->ldap_server? strdup(ads->ldap_server) : NULL;
+ if (workgroup && strcasecmp(lp_workgroup(), workgroup) != 0) {
+ ads->server.foreign = 1;
}
return ads;
@@ -170,7 +107,7 @@ ADS_STRUCT *ads_init(const char *realm,
/* a simpler ads_init() interface using all defaults */
ADS_STRUCT *ads_init_simple(void)
{
- return ads_init(NULL, NULL, NULL, NULL, NULL);
+ return ads_init(NULL, NULL, NULL);
}
/*
@@ -182,13 +119,19 @@ void ads_destroy(ADS_STRUCT **ads)
#if HAVE_LDAP
if ((*ads)->ld) ldap_unbind((*ads)->ld);
#endif
- SAFE_FREE((*ads)->realm);
- SAFE_FREE((*ads)->ldap_server);
- SAFE_FREE((*ads)->ldap_server_name);
- SAFE_FREE((*ads)->kdc_server);
- SAFE_FREE((*ads)->bind_path);
- SAFE_FREE((*ads)->password);
- SAFE_FREE((*ads)->user_name);
+ SAFE_FREE((*ads)->server.realm);
+ SAFE_FREE((*ads)->server.workgroup);
+ SAFE_FREE((*ads)->server.ldap_server);
+
+ SAFE_FREE((*ads)->auth.realm);
+ SAFE_FREE((*ads)->auth.password);
+ SAFE_FREE((*ads)->auth.user_name);
+ SAFE_FREE((*ads)->auth.kdc_server);
+
+ SAFE_FREE((*ads)->config.realm);
+ SAFE_FREE((*ads)->config.bind_path);
+ SAFE_FREE((*ads)->config.ldap_server_name);
+
ZERO_STRUCTP(*ads);
SAFE_FREE(*ads);
}
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 1ba5d978e8..9a486237c9 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -110,16 +110,8 @@ int ads_kinit_password(ADS_STRUCT *ads)
char *s;
int ret;
- if (!ads->user_name) {
- /* by default use the machine account */
- extern pstring global_myname;
- fstring myname;
- fstrcpy(myname, global_myname);
- strlower(myname);
- asprintf(&ads->user_name, "HOST/%s", global_myname);
- }
- asprintf(&s, "%s@%s", ads->user_name, ads->realm);
- ret = kerberos_kinit_password(s, ads->password);
+ asprintf(&s, "%s@%s", ads->auth.user_name, ads->auth.realm);
+ ret = kerberos_kinit_password(s, ads->auth.password);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index dac90908c4..22b58f47dd 100644
--- a/source3/libads/kerberos_verify.c
+++ b/source3/libads/kerberos_verify.c
@@ -67,7 +67,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
return NT_STATUS_LOGON_FAILURE;
}
- ret = krb5_set_default_realm(context, ads->realm);
+ ret = krb5_set_default_realm(context, ads->auth.realm);
if (ret) {
DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret)));
ads_destroy(&ads);
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 9d15c4e33c..2672489482 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -37,6 +37,165 @@
* codepoints in UTF-8). This may have to change at some point
**/
+
+/*
+ try a connection to a given ldap server, returning True and setting the servers IP
+ in the ads struct if successful
+ */
+static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
+{
+ char *srv;
+
+ if (!server || !*server) {
+ return False;
+ }
+
+ DEBUG(5,("ads_try_connect: trying ldap server '%s' port %u\n", server, port));
+
+ /* this copes with inet_ntoa brokenness */
+ srv = strdup(server);
+
+ ads->ld = ldap_open(srv, port);
+ if (!ads->ld) {
+ free(srv);
+ return False;
+ }
+ ads->ldap_port = port;
+ ads->ldap_ip = *interpret_addr2(srv);
+ free(srv);
+ return True;
+}
+
+/* used by the IP comparison function */
+struct ldap_ip {
+ struct in_addr ip;
+ unsigned port;
+};
+
+/* compare 2 ldap IPs by nearness to our interfaces - used in qsort */
+static int ldap_ip_compare(struct ldap_ip *ip1, struct ldap_ip *ip2)
+{
+ return ip_compare(&ip1->ip, &ip2->ip);
+}
+
+/* try connecting to a ldap server via DNS */
+static BOOL ads_try_dns(ADS_STRUCT *ads)
+{
+ char *realm, *ptr;
+ char *list = NULL;
+ pstring tok;
+ struct ldap_ip *ip_list;
+ int count, i=0;
+
+ realm = ads->server.realm;
+ if (!realm || !*realm) {
+ realm = lp_realm();
+ }
+ if (!realm || !*realm) {
+ realm = ads->server.workgroup;
+ }
+ if (!realm || !*realm) {
+ realm = lp_workgroup();
+ }
+ if (!realm) {
+ return False;
+ }
+ realm = smb_xstrdup(realm);
+
+ DEBUG(6,("ads_try_dns: looking for realm '%s'\n", realm));
+ if (ldap_domain2hostlist(realm, &list) != LDAP_SUCCESS) {
+ SAFE_FREE(realm);
+ return False;
+ }
+
+ DEBUG(6,("ads_try_dns: ldap realm '%s' host list '%s'\n", realm, list));
+ SAFE_FREE(realm);
+
+ count = count_chars(list, ' ') + 1;
+ ip_list = malloc(count * sizeof(struct ldap_ip));
+ if (!ip_list) {
+ return False;
+ }
+
+ ptr = list;
+ while (next_token(&ptr, tok, " ", sizeof(tok))) {
+ unsigned port = LDAP_PORT;
+ char *p = strchr(tok, ':');
+ if (p) {
+ *p = 0;
+ port = atoi(p+1);
+ }
+ ip_list[i].ip = *interpret_addr2(tok);
+ ip_list[i].port = port;
+ if (!is_zero_ip(ip_list[i].ip)) {
+ i++;
+ }
+ }
+ free(list);
+
+ count = i;
+
+ /* we sort the list of addresses by closeness to our interfaces. This
+ tries to prevent us using a DC on the other side of the country */
+ if (count > 1) {
+ qsort(ip_list, count, sizeof(struct ldap_ip),
+ QSORT_CAST ldap_ip_compare);
+ }
+
+ for (i=0;i<count;i++) {
+ if (ads_try_connect(ads, inet_ntoa(ip_list[i].ip), ip_list[i].port)) {
+ free(ip_list);
+ return True;
+ }
+ }
+
+ SAFE_FREE(ip_list);
+ return False;
+}
+
+/* try connecting to a ldap server via netbios */
+static BOOL ads_try_netbios(ADS_STRUCT *ads)
+{
+ struct in_addr *ip_list;
+ int count;
+ int i;
+ char *workgroup = ads->server.workgroup;
+
+ if (!workgroup) {
+ workgroup = lp_workgroup();
+ }
+
+ DEBUG(6,("ads_try_netbios: looking for workgroup '%s'\n", workgroup));
+
+ /* try the PDC first */
+ if (get_dc_list(True, workgroup, &ip_list, &count)) {
+ for (i=0;i<count;i++) {
+ DEBUG(6,("ads_try_netbios: trying server '%s'\n",
+ inet_ntoa(ip_list[i])));
+ if (ads_try_connect(ads, inet_ntoa(ip_list[i]), LDAP_PORT)) {
+ free(ip_list);
+ return True;
+ }
+ }
+ free(ip_list);
+ }
+
+ /* now any DC, including backups */
+ if (get_dc_list(False, workgroup, &ip_list, &count)) {
+ for (i=0;i<count;i++) {
+ DEBUG(6,("ads_try_netbios: trying server '%s'\n",
+ inet_ntoa(ip_list[i])));
+ if (ads_try_connect(ads, inet_ntoa(ip_list[i]), LDAP_PORT)) {
+ free(ip_list);
+ return True;
+ }
+ }
+ free(ip_list);
+ }
+
+ return False;
+}
+
/**
* Connect to the LDAP server
* @param ads Pointer to an existing ADS_STRUCT
@@ -49,38 +208,35 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
ADS_STATUS status;
ads->last_attempt = time(NULL);
-
ads->ld = NULL;
- if (ads->ldap_server) {
- ads->ld = ldap_open(ads->ldap_server, ads->ldap_port);
+ /* try with a user specified server */
+ if (ads->server.ldap_server &&
+ ads_try_connect(ads, ads->server.ldap_server, LDAP_PORT)) {
+ goto got_connection;
}
- /* 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) {
- SAFE_FREE(ads->ldap_server);
- ads->ldap_server = strdup(inet_ntoa(ip_list[i]));
- }
- free(ip_list);
- }
+ /* try with a smb.conf ads server setting if we are connecting
+ to the primary workgroup or realm */
+ if (!ads->server.foreign &&
+ ads_try_connect(ads, lp_ads_server(), LDAP_PORT)) {
+ goto got_connection;
}
- if (!ads->ld) {
- return ADS_ERROR_SYSTEM(errno);
+ /* try via DNS */
+ if (ads_try_dns(ads)) {
+ goto got_connection;
+ }
+
+ /* try via netbios lookups */
+ if (!lp_disable_netbios() && ads_try_netbios(ads)) {
+ goto got_connection;
}
- DEBUG(3,("Connected to LDAP server %s\n", ads->ldap_server));
+ return ADS_ERROR_SYSTEM(errno?errno:ENOENT);
+
+got_connection:
+ DEBUG(3,("Connected to LDAP server %s\n", inet_ntoa(ads->ldap_ip)));
status = ads_server_info(ads);
if (!ADS_ERR_OK(status)) {
@@ -90,22 +246,43 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ if (!ads->auth.user_name) {
+ /* by default use the machine account */
+ extern pstring global_myname;
+ fstring myname;
+ fstrcpy(myname, global_myname);
+ strlower(myname);
+ asprintf(&ads->auth.user_name, "HOST/%s", myname);
+ }
+
+ if (!ads->auth.realm) {
+ ads->auth.realm = strdup(ads->config.realm);
+ }
+
+ if (!ads->auth.kdc_server) {
+ ads->auth.kdc_server = strdup(inet_ntoa(ads->ldap_ip));
+ }
+
#if KRB5_DNS_HACK
/* this is a really nasty hack to avoid ADS DNS problems. It needs a patch
to MIT kerberos to work (tridge) */
{
char *env;
- asprintf(&env, "KRB5_KDC_ADDRESS_%s", ads->server_realm);
- setenv(env, inet_ntoa(*interpret_addr2(ads->ldap_server)), 1);
+ asprintf(&env, "KRB5_KDC_ADDRESS_%s", ads->config.realm);
+ setenv(env, ads->auth.kdc_server, 1);
free(env);
}
#endif
- if (ads->password) {
+ if (ads->auth.password) {
if ((code = ads_kinit_password(ads)))
return ADS_ERROR_KRB5(code);
}
+ if (ads->auth.no_bind) {
+ return ADS_SUCCESS;
+ }
+
return ads_sasl_bind(ads);
}
@@ -161,7 +338,7 @@ static char **ads_push_strvals(TALLOC_CTX *ctx, const char **in_vals)
if (!values) return NULL;
for (i=0; in_vals[i]; i++) {
- push_utf8_talloc(ctx, (void **) &values[i], in_vals[i]);
+ push_utf8_talloc(ctx, &values[i], in_vals[i]);
}
return values;
}
@@ -180,7 +357,7 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals)
if (!values) return NULL;
for (i=0; in_vals[i]; i++) {
- pull_utf8_talloc(ctx, (void **) &values[i], in_vals[i]);
+ pull_utf8_talloc(ctx, &values[i], in_vals[i]);
}
return values;
}
@@ -219,8 +396,8 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
/* 0 means the conversion worked but the result was empty
so we only fail if it's negative. In any case, it always
at least nulls out the dest */
- if ((push_utf8_talloc(ctx, (void **) &utf8_exp, exp) < 0) ||
- (push_utf8_talloc(ctx, (void **) &utf8_path, bind_path) < 0)) {
+ if ((push_utf8_talloc(ctx, &utf8_exp, exp) < 0) ||
+ (push_utf8_talloc(ctx, &utf8_path, bind_path) < 0)) {
rc = LDAP_NO_MEMORY;
goto done;
}
@@ -230,7 +407,7 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
else {
/* This would be the utf8-encoded version...*/
/* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */
- if (!(str_list_copy(&search_attrs, (char **) attrs)))
+ if (!(str_list_copy(&search_attrs, attrs)))
{
rc = LDAP_NO_MEMORY;
goto done;
@@ -442,8 +619,8 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
/* 0 means the conversion worked but the result was empty
so we only fail if it's negative. In any case, it always
at least nulls out the dest */
- if ((push_utf8_talloc(ctx, (void **) &utf8_exp, exp) < 0) ||
- (push_utf8_talloc(ctx, (void **) &utf8_path, bind_path) < 0)) {
+ if ((push_utf8_talloc(ctx, &utf8_exp, exp) < 0) ||
+ (push_utf8_talloc(ctx, &utf8_path, bind_path) < 0)) {
rc = LDAP_NO_MEMORY;
goto done;
}
@@ -453,7 +630,7 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
else {
/* This would be the utf8-encoded version...*/
/* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */
- if (!(str_list_copy(&search_attrs, (char **) attrs)))
+ if (!(str_list_copy(&search_attrs, attrs)))
{
rc = LDAP_NO_MEMORY;
goto done;
@@ -494,7 +671,7 @@ ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
const char *exp,
const char **attrs)
{
- return ads_do_search(ads, ads->bind_path, LDAP_SCOPE_SUBTREE,
+ return ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
exp, attrs, res);
}
@@ -805,11 +982,11 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
if (!(host_spn = talloc_asprintf(ctx, "HOST/%s", hostname)))
goto done;
- if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->realm)))
+ if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm)))
goto done;
ou_str = ads_ou_string(org_unit);
new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", hostname, ou_str,
- ads->bind_path);
+ ads->config.bind_path);
free(ou_str);
if (!new_dn)
goto done;
@@ -925,6 +1102,7 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
} handlers[] = {
{"objectGUID", False, dump_binary},
{"nTSecurityDescriptor", False, dump_sd},
+ {"dnsRecord", False, dump_binary},
{"objectSid", False, dump_sid},
{NULL, True, NULL}
};
@@ -999,7 +1177,7 @@ void ads_process_results(ADS_STRUCT *ads, void *res,
char *field;
BOOL string;
- pull_utf8_talloc(ctx, (void **) &field, utf8_field);
+ pull_utf8_talloc(ctx, &field, utf8_field);
string = fn(field, NULL, data_area);
if (string) {
@@ -1061,7 +1239,7 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, const char *org
status = ads_leave_realm(ads, host);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n",
- host, ads->realm));
+ host, ads->config.realm));
return status;
}
}
@@ -1224,20 +1402,15 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
char *host = strdup(hostname);
char *principal;
- if (!ads->kdc_server) {
- DEBUG(0, ("Unable to find KDC server\n"));
- return ADS_ERROR(LDAP_SERVER_DOWN);
- }
-
strlower(host);
/*
we need to use the '$' form of the name here, as otherwise the
server might end up setting the password for a user instead
*/
- asprintf(&principal, "%s$@%s", host, ads->realm);
+ asprintf(&principal, "%s$@%s", host, ads->auth.realm);
- status = krb5_set_password(ads->kdc_server, principal, password);
+ status = krb5_set_password(ads->auth.kdc_server, principal, password);
free(host);
free(principal);
@@ -1287,7 +1460,7 @@ char *ads_pull_string(ADS_STRUCT *ads,
if (!values) return NULL;
if (values[0]) {
- rc = pull_utf8_talloc(mem_ctx, (void **)&ux_string,
+ rc = pull_utf8_talloc(mem_ctx, &ux_string,
values[0]);
if (rc != -1)
ret = ux_string;
@@ -1321,7 +1494,7 @@ char **ads_pull_strings(ADS_STRUCT *ads,
ret = talloc(mem_ctx, sizeof(char *) * (n+1));
for (i=0;i<n;i++) {
- if (pull_utf8_talloc(mem_ctx, (void **)&ret[i], values[i]) == -1) {
+ if (pull_utf8_talloc(mem_ctx, &ret[i], values[i]) == -1) {
return NULL;
}
}
@@ -1472,33 +1645,27 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
return ADS_ERROR(LDAP_DECODING_ERROR);
}
- SAFE_FREE(ads->ldap_server_name);
+ SAFE_FREE(ads->config.ldap_server_name);
- ads->ldap_server_name = strdup(p+1);
- p = strchr(ads->ldap_server_name, '$');
+ ads->config.ldap_server_name = strdup(p+1);
+ p = strchr(ads->config.ldap_server_name, '$');
if (!p || p[1] != '@') {
ldap_value_free(values);
ldap_msgfree(res);
- SAFE_FREE(ads->ldap_server_name);
+ SAFE_FREE(ads->config.ldap_server_name);
return ADS_ERROR(LDAP_DECODING_ERROR);
}
*p = 0;
- SAFE_FREE(ads->server_realm);
- SAFE_FREE(ads->bind_path);
+ SAFE_FREE(ads->config.realm);
+ SAFE_FREE(ads->config.bind_path);
- ads->server_realm = strdup(p+2);
- ads->bind_path = ads_build_dn(ads->server_realm);
-
- /* in case the realm isn't configured in smb.conf */
- if (!ads->realm || !ads->realm[0]) {
- SAFE_FREE(ads->realm);
- ads->realm = strdup(ads->server_realm);
- }
+ ads->config.realm = strdup(p+2);
+ ads->config.bind_path = ads_build_dn(ads->config.realm);
DEBUG(3,("got ldap server name %s@%s\n",
- ads->ldap_server_name, ads->realm));
+ ads->config.ldap_server_name, ads->config.realm));
return ADS_SUCCESS;
}
@@ -1514,9 +1681,13 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
* @return the count of SIDs pulled
**/
ADS_STATUS ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- int *num_trusts, char ***names, DOM_SID **sids)
+ int *num_trusts,
+ char ***names,
+ char ***alt_names,
+ DOM_SID **sids)
{
- const char *attrs[] = {"flatName", "securityIdentifier", NULL};
+ const char *attrs[] = {"name", "flatname", "securityIdentifier",
+ "trustDirection", NULL};
ADS_STATUS status;
void *res, *msg;
int count, i;
@@ -1533,11 +1704,31 @@ ADS_STATUS ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
}
(*names) = talloc(mem_ctx, sizeof(char *) * count);
+ (*alt_names) = talloc(mem_ctx, sizeof(char *) * count);
(*sids) = talloc(mem_ctx, sizeof(DOM_SID) * count);
if (! *names || ! *sids) return ADS_ERROR(LDAP_NO_MEMORY);
for (i=0, msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
- (*names)[i] = ads_pull_string(ads, mem_ctx, msg, "flatName");
+ uint32 direction;
+
+ /* direction is a 2 bit bitfield, 1 means they trust us
+ but we don't trust them, so we should not list them
+ as users from that domain can't login */
+ if (ads_pull_uint32(ads, msg, "trustDirection", &direction) &&
+ direction == 1) {
+ continue;
+ }
+
+ (*names)[i] = ads_pull_string(ads, mem_ctx, msg, "name");
+ (*alt_names)[i] = ads_pull_string(ads, mem_ctx, msg, "flatname");
+
+ if ((*alt_names)[i] && (*alt_names)[i][0]) {
+ /* we prefer the flatname as the primary name
+ for consistency with RPC */
+ char *name = (*alt_names)[i];
+ (*alt_names)[i] = (*names)[i];
+ (*names)[i] = name;
+ }
if (ads_pull_sid(ads, msg, "securityIdentifier", &(*sids)[i])) {
i++;
}
@@ -1562,7 +1753,7 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
void *res;
ADS_STATUS rc;
- rc = ads_do_search(ads, ads->bind_path, LDAP_SCOPE_BASE, "(objectclass=*)",
+ rc = ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_BASE, "(objectclass=*)",
attrs, &res);
if (!ADS_ERR_OK(rc)) return rc;
if (!ads_pull_sid(ads, res, "objectSid", sid)) {
@@ -1573,4 +1764,66 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
return ADS_SUCCESS;
}
+/* this is rather complex - we need to find the allternate (netbios) name
+ for the domain, but there isn't a simple query to do this. Instead
+ we look for the principle names on the DCs account and find one that has
+ the right form, then extract the netbios name of the domain from that
+*/
+ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **workgroup)
+{
+ char *exp;
+ ADS_STATUS rc;
+ char **principles;
+ char *prefix;
+ int prefix_length;
+ int i;
+ void *res;
+ const char *attrs[] = {"servicePrincipalName", NULL};
+
+ (*workgroup) = NULL;
+
+ asprintf(&exp, "(&(objectclass=computer)(dnshostname=%s.%s))",
+ ads->config.ldap_server_name, ads->config.realm);
+ rc = ads_search(ads, &res, exp, attrs);
+ free(exp);
+
+ if (!ADS_ERR_OK(rc)) {
+ return rc;
+ }
+
+ principles = ads_pull_strings(ads, mem_ctx, res, "servicePrincipalName");
+
+ ads_msgfree(ads, res);
+
+ if (!principles) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ asprintf(&prefix, "HOST/%s.%s/",
+ ads->config.ldap_server_name,
+ ads->config.realm);
+
+ prefix_length = strlen(prefix);
+
+ for (i=0;principles[i]; i++) {
+ if (strncasecmp(principles[i], prefix, prefix_length) == 0 &&
+ strcasecmp(ads->config.realm, principles[i]+prefix_length) != 0 &&
+ !strchr(principles[i]+prefix_length, '.')) {
+ /* found an alternate (short) name for the domain. */
+ DEBUG(3,("Found alternate name '%s' for realm '%s'\n",
+ principles[i]+prefix_length,
+ ads->config.realm));
+ (*workgroup) = talloc_strdup(mem_ctx, principles[i]+prefix_length);
+ break;
+ }
+ }
+ free(prefix);
+
+ if (!*workgroup) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ return ADS_SUCCESS;
+}
+
#endif
diff --git a/source3/libads/ldap_user.c b/source3/libads/ldap_user.c
index b6e3d189c5..b6fef24b5c 100644
--- a/source3/libads/ldap_user.c
+++ b/source3/libads/ldap_user.c
@@ -55,10 +55,10 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
status = ADS_ERROR(LDAP_NO_MEMORY);
- if (!(upn = talloc_asprintf(ctx, "%s@%s", user, ads->realm)))
+ if (!(upn = talloc_asprintf(ctx, "%s@%s", user, ads->config.realm)))
goto done;
if (!(new_dn = talloc_asprintf(ctx, "cn=%s,cn=Users,%s", name,
- ads->bind_path)))
+ ads->config.bind_path)))
goto done;
if (!(controlstr = talloc_asprintf(ctx, "%u", UF_NORMAL_ACCOUNT)))
goto done;
@@ -94,7 +94,7 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
status = ADS_ERROR(LDAP_NO_MEMORY);
if (!(new_dn = talloc_asprintf(ctx, "cn=%s,cn=Users,%s", group,
- ads->bind_path)))
+ ads->config.bind_path)))
goto done;
if (!(mods = ads_init_mods(ctx)))
goto done;
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 1b55453cac..81dedb0a81 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -77,7 +77,7 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
/* we need to fetch a service ticket as the ldap user in the
servers realm, regardless of our realm */
- asprintf(&sname, "ldap/%s@%s", ads->ldap_server_name, ads->server_realm);
+ asprintf(&sname, "ldap/%s@%s", ads->config.ldap_server_name, ads->config.realm);
krb5_init_context(&ctx);
krb5_set_default_tgs_ktypes(ctx, enc_types);
krb5_parse_name(ctx, sname, &principal);
@@ -163,7 +163,7 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
gss_release_buffer(&minor_status, &output_token);
- output_token.value = malloc(strlen(ads->bind_path) + 8);
+ output_token.value = malloc(strlen(ads->config.bind_path) + 8);
p = output_token.value;
*p++ = 1; /* no sign or seal */
@@ -171,9 +171,10 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
*p++ = max_msg_size>>16;
*p++ = max_msg_size>>8;
*p++ = max_msg_size;
- snprintf(p, strlen(ads->bind_path)+4, "dn:%s", ads->bind_path);
+ snprintf(p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path);
+ p += strlen(ads->config.bind_path);
- output_token.length = strlen(ads->bind_path) + 8;
+ output_token.length = strlen(ads->config.bind_path) + 8;
gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
&output_token, &conf_state,
diff --git a/source3/libads/util.c b/source3/libads/util.c
index d48eb10b71..b10b130a31 100644
--- a/source3/libads/util.c
+++ b/source3/libads/util.c
@@ -39,7 +39,7 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
new_password = strdup(tmp_password);
asprintf(&service_principal, "HOST/%s", host_principal);
- ret = kerberos_set_password(ads->kdc_server, host_principal, password,
+ ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password,
service_principal, new_password);
if (!secrets_store_machine_password(new_password)) {