setups.
- split up the ads structure into logical pieces. This makes it much
easier to keep things like the authentication realm and the server
realm separate (they can be different).
- allow ads callers to specify that no sasl bind should be performed
(used by "net ads info" for example)
- fix an error with handing ADS_ERROR_SYSTEM() when errno is 0
- completely rewrote the code for finding the LDAP server. Now try DNS
methods first, and try all DNS servers returned from the SRV DNS
query, sorted by closeness to our interfaces (using the same sort code
as we use in replies from WINS servers). This allows us to cope with
ADS DCs that are down, and ensures we don't pick one that is on the
other side of the country unless absolutely necessary.
- recognise dnsRecords as binary when displaying them
- cope with the realm not being configured in smb.conf (work it out
from the LDAP server)
- look at the trustDirection when looking up trusted domains and don't
include trusts that trust our domains but we don't trust
theirs.
- use LDAP to query the alternate (netbios) name for a realm, and make
sure that both and long and short forms of the name are accepted by
winbindd. Use the short form by default for listing users/groups.
- rescan the list of trusted domains every 5 minutes in case new trust
relationships are added while winbindd is running
- include transient trust relationships (ie. C trusts B, B trusts A,
so C trusts A) in winbindd.
- don't do a gratuituous node status lookup when finding an ADS DC (we
don't need it and it could fail)
- remove unused sid_to_distinguished_name function
- make sure we find the allternate name of our primary domain when
operating with a netbiosless ADS DC (using LDAP to do the lookup)
- fixed the rpc trusted domain enumeration to support up to approx
2000 trusted domains (the old limit was 3)
- use the IP for the remote_machine (%m) macro when the client doesn't
supply us with a name via a netbios session request (eg. port 445)
- if the client uses SPNEGO then use the machine name from the SPNEGO
auth packet for remote_machine (%m) macro
- add new 'net ads workgroup' command to find the netbios workgroup
name for a realm
return NT_STATUS_NO_LOGON_SERVERS;
}
- DEBUG(4,("ads_resolve_dc: realm=%s\n", ads->realm));
+ DEBUG(4,("ads_resolve_dc: realm=%s\n", ads->config.realm));
+
+ ads->auth.no_bind = 1;
#ifdef HAVE_ADS
/* a full ads_connect() is actually overkill, as we don't srictly need
ads_connect(ads);
#endif
- fstrcpy(remote_machine, ads->ldap_server_name);
+ fstrcpy(remote_machine, ads->config.ldap_server_name);
strupper(remote_machine);
*dest_ip = ads->ldap_ip;
ads_destroy(&ads);
*/
typedef struct {
- void *ld;
- char *realm;
- char *workgroup;
- char *ldap_server;
- char *ldap_server_name;
- char *kdc_server;
+ void *ld; /* the active ldap structure */
+ struct in_addr ldap_ip; /* the ip of the active connection, if any */
+ time_t last_attempt; /* last attempt to reconnect */
int ldap_port;
- char *bind_path;
- time_t last_attempt;
- char *password;
- char *user_name;
- char *server_realm;
- struct in_addr ldap_ip;
+
+ /* info needed to find the server */
+ struct {
+ char *realm;
+ char *workgroup;
+ char *ldap_server;
+ int foreign; /* set to 1 if connecting to a foreign realm */
+ } server;
+
+ /* info needed to authenticate */
+ struct {
+ char *realm;
+ char *password;
+ char *user_name;
+ char *kdc_server;
+ int no_bind;
+ } auth;
+
+ /* info derived from the servers config */
+ struct {
+ char *realm;
+ char *bind_path;
+ char *ldap_server_name;
+ } config;
} ADS_STRUCT;
typedef struct {
/* macros to simplify error returning */
#define ADS_ERROR(rc) ads_build_error(ADS_ERROR_LDAP, rc, 0)
-#define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc, 0)
+#define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc?rc:EINVAL, 0)
#define ADS_ERROR_KRB5(rc) ads_build_error(ADS_ERROR_KRB5, rc, 0)
#define ADS_ERROR_GSS(rc, minor) ads_build_error(ADS_ERROR_GSS, rc, minor)
}
-#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
*/
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->realm && strchr_m(ads->workgroup, '.')) {
- /* the smb.conf has specified the realm in 'workgroup =' */
- ads->realm = strdup(ads->workgroup);
- }
-
- 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]) {
- SAFE_FREE(ads->ldap_server);
- 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 (ads->ldap_server) {
- /* its very useful knowing the IP of the ldap server */
- ads->ldap_ip = *interpret_addr2(ads->ldap_server);
+ if (workgroup && strcasecmp(lp_workgroup(), workgroup) != 0) {
+ ads->server.foreign = 1;
}
return ads;
/* 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);
}
/*
#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);
}
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",
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);
* 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) {
+ SAFE_FREE(realm);
+ realm = lp_realm();
+ }
+ if (!realm || !*realm) {
+ SAFE_FREE(realm);
+ realm = ads->server.workgroup;
+ }
+ if (!realm || !*realm) {
+ SAFE_FREE(realm);
+ realm = lp_workgroup();
+ }
+ if (!realm) {
+ return False;
+ }
+
+ DEBUG(6,("ads_try_dns: looking for realm '%s'\n", realm));
+ if (ldap_domain2hostlist(realm, &list) != LDAP_SUCCESS) {
+ return False;
+ }
+
+ DEBUG(6,("ads_try_dns: ldap realm '%s' host list '%s'\n", realm, list));
+
+ 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));
+
+ if (!get_dc_list(True, workgroup, &ip_list, &count) &&
+ !get_dc_list(False, workgroup, &ip_list, &count)) {
+ return False;
+ }
+
+ 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
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)) {
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);
}
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);
}
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;
} handlers[] = {
{"objectGUID", False, dump_binary},
{"nTSecurityDescriptor", False, dump_sd},
+ {"dnsRecord", False, dump_binary},
{"objectSid", False, dump_sid},
{NULL, True, NULL}
};
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;
}
}
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);
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;
}
* @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;
}
(*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++;
}
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)) {
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
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;
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;
/* 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);
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 */
*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,
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)) {
/*
comparison function used by sort_ip_list
*/
-static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
+int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
{
int max_bits1=0, max_bits2=0;
int num_interfaces = iface_count();
struct winbindd_domain {
fstring name; /* Domain name */
- fstring full_name; /* full Domain name (realm) */
+ fstring alt_name; /* alt Domain name (if any) */
DOM_SID sid; /* SID for this domain */
/* Lookup methods for this domain (LDAP or RPC) */
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids);
/* find the domain sid */
NTSTATUS (*domain_sid)(struct winbindd_domain *domain,
DOM_SID *sid);
+
+ /* setup the list of alternate names for the domain, if any */
+ NTSTATUS (*alternate_name)(struct winbindd_domain *domain);
};
/* Used to glue a policy handle and cli_state together */
#include "rpc_client.h"
#define WINBINDD_ESTABLISH_LOOP 30
+#define WINBINDD_RESCAN_FREQ 300
+
#define DOM_SEQUENCE_NONE ((uint32)-1)
/* SETENV */
if (*res) ads_msgfree(ads, *res);
*res = NULL;
- DEBUG(3,("Reopening ads connection to %s after error %s\n",
- ads->ldap_server, ads_errstr(status)));
+ DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n",
+ ads->config.realm, ads_errstr(status)));
if (ads->ld) {
ldap_unbind(ads->ld);
}
const char *exp,
const char **attrs)
{
- return ads_do_search_retry(ads, ads->bind_path, LDAP_SCOPE_SUBTREE,
+ return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
exp, attrs, res);
}
ADS_STRUCT *ads;
ADS_STATUS status;
char *ccache;
- struct in_addr server_ip;
- char *sname;
if (domain->private) {
return (ADS_STRUCT *)domain->private;
SETENV("KRB5CCNAME", ccache, 1);
unlink(ccache);
- 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));
- return NULL;
- }
- sname = NULL;
- }
-
- ads = ads_init(primary_realm, domain->name, NULL, NULL, NULL);
+ ads = ads_init(domain->alt_name, domain->name, NULL);
if (!ads) {
DEBUG(1,("ads_init for domain %s failed\n", domain->name));
return NULL;
}
/* the machine acct password might have change - fetch it every time */
- SAFE_FREE(ads->password);
- ads->password = secrets_fetch_machine_password();
+ SAFE_FREE(ads->auth.password);
+ ads->auth.password = secrets_fetch_machine_password();
+
+ if (primary_realm) {
+ SAFE_FREE(ads->auth.realm);
+ ads->auth.realm = strdup(primary_realm);
+ }
status = ads_connect(ads);
- if (!ADS_ERR_OK(status) || !ads->realm) {
+ if (!ADS_ERR_OK(status) || !ads->config.realm) {
extern struct winbindd_methods msrpc_methods;
DEBUG(1,("ads_connect for domain %s failed: %s\n",
domain->name, ads_errstr(status)));
/* remember our primary realm for trusted domain support */
if (!primary_realm) {
- primary_realm = strdup(ads->realm);
+ primary_realm = strdup(ads->config.realm);
}
- fstrcpy(domain->full_name, ads->server_realm);
-
domain->private = (void *)ads;
return ads;
}
/* accept either the win2000 or the pre-win2000 username */
asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
- name, name, ads->realm);
+ name, name, ads->config.realm);
rc = ads_search_retry(ads, &res, exp, attrs);
free(exp);
if (!ADS_ERR_OK(rc)) {
return False;
}
-
-/* convert a sid to a distnguished name */
-static NTSTATUS sid_to_distinguished_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
- char **dn)
-{
- ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"distinguishedName", NULL};
- ADS_STATUS rc;
- void *msg = NULL;
- char *exp;
- char *sidstr;
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-
- DEBUG(3,("ads: sid_to_distinguished_name\n"));
-
- ads = ads_cached_connection(domain);
- if (!ads) goto done;
-
- sidstr = sid_binstring(sid);
- asprintf(&exp, "(objectSid=%s)", sidstr);
- rc = ads_search_retry(ads, &msg, exp, attrs);
- free(exp);
- free(sidstr);
- if (!ADS_ERR_OK(rc)) {
- DEBUG(1,("sid_to_distinguished_name ads_search: %s\n", ads_errstr(rc)));
- goto done;
- }
-
- *dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName");
-
- status = NT_STATUS_OK;
-
- DEBUG(3,("ads sid_to_distinguished_name mapped %s\n", *dn));
-
-done:
- if (msg) ads_msgfree(ads, msg);
-
- return status;
-}
-
-
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
ADS_STRUCT *ads;
ads = ads_cached_connection(domain);
if (!ads) return NT_STATUS_UNSUCCESSFUL;
- rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, dom_sids);
+ rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids);
return ads_ntstatus(rc);
}
return ads_ntstatus(rc);
}
+
+/* find alternate names list for the domain - for ADS this is the
+ netbios name */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ TALLOC_CTX *ctx;
+ char *workgroup;
+
+ ads = ads_cached_connection(domain);
+ if (!ads) return NT_STATUS_UNSUCCESSFUL;
+
+ if (!(ctx = talloc_init_named("alternate_name"))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = ads_workgroup_name(ads, ctx, &workgroup);
+
+ if (ADS_ERR_OK(rc)) {
+ fstrcpy(domain->name, workgroup);
+ fstrcpy(domain->alt_name, ads->config.realm);
+ strupper(domain->alt_name);
+ strupper(domain->name);
+ }
+
+ talloc_destroy(ctx);
+
+ return ads_ntstatus(rc);
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods ads_methods = {
True,
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
#endif
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
struct winbind_cache *cache = get_cache(domain);
/* we don't cache this call */
return cache->backend->trusted_domains(domain, mem_ctx, num_domains,
- names, dom_sids);
+ names, alt_names, dom_sids);
}
/* find the domain sid */
return cache->backend->domain_sid(domain, sid);
}
+/* find the alternate names for the domain, if any */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ struct winbind_cache *cache = get_cache(domain);
+
+ /* we don't cache this call */
+ return cache->backend->alternate_name(domain);
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods cache_methods = {
True,
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
{
ADS_STRUCT *ads;
- ads = ads_init_simple();
+ ads = ads_init(domain, domain, NULL);
if (!ads) {
return False;
}
- DEBUG(4,("cm_ads_find_dc: realm=%s\n", ads->realm));
+ /* we don't need to bind, just connect */
+ ads->auth.no_bind = 1;
+
+ DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
#ifdef HAVE_ADS
/* a full ads_connect() is actually overkill, as we don't srictly need
ads_connect(ads);
#endif
- fstrcpy(srv_name, ads->ldap_server_name);
+ if (!ads->config.realm) {
+ return False;
+ }
+
+ fstrcpy(srv_name, ads->config.ldap_server_name);
strupper(srv_name);
*dc_ip = ads->ldap_ip;
ads_destroy(&ads);
- if (!*srv_name || is_zero_ip(*dc_ip)) {
- return False;
- }
-
DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n",
srv_name, inet_ntoa(*dc_ip)));
zero_ip(&dc_ip);
+ ret = False;
if (lp_security() == SEC_ADS) {
ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
- } else {
+ }
+ if (!ret) {
+ /* fall back on rpc methods if the ADS methods fail */
ret = cm_rpc_find_dc(domain, &dc_ip, srv_name);
}
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
CLI_POLICY_HND *hnd;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
uint32 enum_ctx = 0;
- uint32 pref_num_domains = 5;
DEBUG(3,("rpc: trusted_domains\n"));
*num_domains = 0;
+ *alt_names = NULL;
if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
goto done;
result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
- &hnd->pol, &enum_ctx, &pref_num_domains,
+ &hnd->pol, &enum_ctx,
num_domains, names, dom_sids);
done:
return result;
return status;
}
+/* find alternate names list for the domain - none for rpc */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ return NT_STATUS_OK;
+}
+
+
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
False,
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
}
/* Add a trusted domain to our list of domains */
-
-static struct winbindd_domain *add_trusted_domain(char *domain_name,
- struct winbindd_methods *methods)
+static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
+ struct winbindd_methods *methods,
+ DOM_SID *sid)
{
struct winbindd_domain *domain;
/* We can't call domain_list() as this function is called from
init_domain_list() and we'll get stuck in a loop. */
-
for (domain = _domain_list; domain; domain = domain->next) {
- if (strcmp(domain_name, domain->name) == 0) {
- DEBUG(3, ("domain %s already in domain list\n",
- domain_name));
+ if (strcmp(domain_name, domain->name) == 0 ||
+ strcmp(domain_name, domain->alt_name) == 0) {
return domain;
}
}
ZERO_STRUCTP(domain);
+ /* prioritise the short name */
+ if (strchr_m(domain_name, '.') && alt_name && *alt_name) {
+ fstrcpy(domain->name, alt_name);
+ fstrcpy(domain->alt_name, domain_name);
+ } else {
fstrcpy(domain->name, domain_name);
+ if (alt_name) {
+ fstrcpy(domain->alt_name, alt_name);
+ }
+ }
+
domain->methods = methods;
domain->sequence_number = DOM_SEQUENCE_NONE;
domain->last_seq_check = 0;
+ if (sid) {
+ sid_copy(&domain->sid, sid);
+ }
/* Link to domain list */
-
DLIST_ADD(_domain_list, domain);
+ DEBUG(1,("Added domain %s %s %s\n",
+ domain->name, domain->alt_name,
+ sid?sid_string_static(&domain->sid):""));
+
return domain;
}
-/* Look up global info for the winbind daemon */
+/*
+ rescan our domains looking for new trusted domains
+ */
+void rescan_trusted_domains(void)
+{
+ struct winbindd_domain *domain;
+ TALLOC_CTX *mem_ctx;
+ static time_t last_scan;
+ time_t t = time(NULL);
+
+ /* ony rescan every few minutes */
+ if ((unsigned)(t - last_scan) < WINBINDD_RESCAN_FREQ) {
+ return;
+ }
+ last_scan = time(NULL);
+
+ DEBUG(1, ("scanning trusted domain list\n"));
+
+ if (!(mem_ctx = talloc_init_named("init_domain_list")))
+ return;
+
+ for (domain = _domain_list; domain; domain = domain->next) {
+ NTSTATUS result;
+ char **names;
+ char **alt_names;
+ int num_domains = 0;
+ DOM_SID *dom_sids;
+ int i;
+
+ result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains,
+ &names, &alt_names, &dom_sids);
+ if (!NT_STATUS_IS_OK(result)) {
+ continue;
+ }
+
+ /* Add each domain to the trusted domain list. Each domain inherits
+ the access methods of its parent */
+ for(i = 0; i < num_domains; i++) {
+ DEBUG(10,("Found domain %s\n", names[i]));
+ add_trusted_domain(names[i],
+ alt_names?alt_names[i]:NULL,
+ domain->methods, &dom_sids[i]);
+ }
+ }
+
+ talloc_destroy(mem_ctx);
+}
+
+/* Look up global info for the winbind daemon */
BOOL init_domain_list(void)
{
NTSTATUS result;
- TALLOC_CTX *mem_ctx;
extern struct winbindd_methods cache_methods;
struct winbindd_domain *domain;
- DOM_SID *dom_sids;
- char **names;
- uint32 num_domains = 0;
-
- if (!(mem_ctx = talloc_init_named("init_domain_list")))
- return False;
/* Free existing list */
-
free_domain_list();
/* Add ourselves as the first entry */
-
- domain = add_trusted_domain(lp_workgroup(), &cache_methods);
+ domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL);
/* Now we *must* get the domain sid for our primary domain. Go into
a holding pattern until that is available */
result = cache_methods.domain_sid(domain, &domain->sid);
}
- DEBUG(1,("Added domain %s (%s)\n",
- domain->name,
- sid_string_static(&domain->sid)));
-
- DEBUG(1, ("getting trusted domain list\n"));
+ /* get any alternate name for the primary domain */
+ cache_methods.alternate_name(domain);
- result = cache_methods.trusted_domains(domain, mem_ctx, &num_domains,
- &names, &dom_sids);
+ /* do an initial scan for trusted domains */
+ rescan_trusted_domains();
- /* Add each domain to the trusted domain list */
- if (NT_STATUS_IS_OK(result)) {
- int i;
- for(i = 0; i < num_domains; i++) {
- domain = add_trusted_domain(names[i], &cache_methods);
- if (!domain) continue;
- sid_copy(&domain->sid, &dom_sids[i]);
- DEBUG(1,("Added domain %s (%s)\n",
- domain->name,
- sid_string_static(&domain->sid)));
- }
- }
-
- talloc_destroy(mem_ctx);
return True;
}
for (domain = domain_list(); domain != NULL; domain = domain->next) {
if (strequal(domain_name, domain->name) ||
- strequal(domain_name, domain->full_name))
+ (domain->alt_name[0] && strequal(domain_name, domain->alt_name)))
return domain;
}
NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 *enum_ctx,
- uint32 *pref_num_domains, uint32 *num_domains,
+ uint32 *num_domains,
char ***domain_names, DOM_SID **domain_sids)
{
prs_struct qbuf, rbuf;
/* Marshall data and send request */
- init_q_enum_trust_dom(&q, pol, *enum_ctx, *pref_num_domains);
+ /* 64k is enough for about 2000 trusted domains */
+ init_q_enum_trust_dom(&q, pol, *enum_ctx, 0x10000);
if (!lsa_io_q_enum_trust_dom("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, LSA_ENUMTRUSTDOM, &qbuf, &rbuf)) {
/* defaults, but may be changed using params */
uint32 enum_ctx = 0;
- uint32 preferred_maxnum = 5;
uint32 num_domains = 0;
int i;
- if (argc > 3) {
- printf("Usage: %s [preferred max number (%d)] [enum context (0)]\n",
- argv[0], preferred_maxnum);
+ if (argc > 2) {
+ printf("Usage: %s [enum context (0)]\n", argv[0]);
return NT_STATUS_OK;
}
- /* enumeration context */
- if (argc >= 2 && argv[1]) {
- preferred_maxnum = atoi(argv[1]);
- }
-
- /* preferred maximum number */
- if (argc == 3 && argv[2]) {
+ if (argc == 2 && argv[1]) {
enum_ctx = atoi(argv[2]);
}
/* Lookup list of trusted domains */
result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
- &preferred_maxnum, &num_domains,
- &domain_names, &domain_sids);
+ &num_domains,
+ &domain_names, &domain_sids);
if (!NT_STATUS_IS_OK(result) &&
!NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) &&
!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
if (lp_security() != SEC_ADS) {
blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
} else {
- ADS_STRUCT *ads;
- 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);
+ asprintf(&principal, "HOST/%s@%s", guid, lp_realm());
blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
free(principal);
- ads_destroy(&ads);
}
memcpy(p, blob.data, blob.length);
len = blob.length;
set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
set_socket_options(smbd_server_fd(),user_socket_options);
+ /* this is needed so that we get decent entries
+ in smbstatus for port 445 connects */
+ fstrcpy(remote_machine, get_socket_addr(smbd_server_fd()));
+
/* Reset global variables in util.c so
that client substitutions will be
done correctly in the process. */
ads = ads_init_simple();
+ if (!ads) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
+ ads->auth.realm = strdup(lp_realm());
+
ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(1,("Failed to verify incoming ticket!\n"));
}
*p = 0;
- if (strcasecmp(p+1, ads->realm) != 0) {
+ if (strcasecmp(p+1, ads->auth.realm) != 0) {
DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
if (!lp_allow_trusted_domains()) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
uint32 auth_flags = AUTH_FLAG_NONE;
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
+ extern fstring remote_machine;
/* we must have setup the auth context by now */
if (!ntlmssp_auth_context) {
DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
user, workgroup, machine, lmhash.length, nthash.length));
+ /* the client has given us its machine name (which we otherwise would not get on port 445).
+ we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
+ fstrcpy(remote_machine, machine);
+ reload_services(True);
+
#if 0
file_save("nthash1.dat", nthash.data, nthash.length);
file_save("lmhash1.dat", lmhash.data, lmhash.length);
{
ADS_STRUCT *ads;
- ads = ads_init(NULL, NULL, opt_host, NULL, NULL);
+ ads = ads_init(NULL, NULL, opt_host);
- /* we want this servers realm, not our realm */
- SAFE_FREE(ads->realm);
+ if (ads) {
+ ads->auth.no_bind = 1;
+ }
ads_connect(ads);
- if (!ads) {
+ if (!ads || !ads->config.realm) {
d_printf("Didn't find the ldap server!\n");
return -1;
}
- d_printf("LDAP server: %s\n", ads->ldap_server);
- d_printf("LDAP server IP: %s\n", inet_ntoa(ads->ldap_ip));
- d_printf("LDAP server name: %s\n", ads->ldap_server_name);
- d_printf("Realm: %s\n", ads->realm);
- d_printf("Bind Path: %s\n", ads->bind_path);
+ d_printf("LDAP server: %s\n", inet_ntoa(ads->ldap_ip));
+ d_printf("LDAP server name: %s\n", ads->config.ldap_server_name);
+ d_printf("Realm: %s\n", ads->config.realm);
+ d_printf("Bind Path: %s\n", ads->config.bind_path);
d_printf("LDAP port: %d\n", ads->ldap_port);
return 0;
BOOL need_password = False;
BOOL second_time = False;
- ads = ads_init(NULL, NULL, opt_host, NULL, NULL);
+ ads = ads_init(NULL, NULL, opt_host);
if (!opt_user_name) {
opt_user_name = "administrator";
}
if (opt_password)
- ads->password = strdup(opt_password);
+ ads->auth.password = strdup(opt_password);
- ads->user_name = strdup(opt_user_name);
+ ads->auth.user_name = strdup(opt_user_name);
status = ads_connect(ads);
if (!ADS_ERR_OK(status)) {
return 0;
}
+/*
+ determine the netbios workgroup name for a domain
+ */
+static int net_ads_workgroup(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ TALLOC_CTX *ctx;
+ char *workgroup;
+
+ if (!(ads = ads_startup())) return -1;
+
+ if (!(ctx = talloc_init_named("net_ads_workgroup"))) {
+ return -1;
+ }
+
+ if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
+ d_printf("Failed to find workgroup for realm '%s'\n",
+ ads->config.realm);
+ talloc_destroy(ctx);
+ return -1;
+ }
+
+ d_printf("Workgroup: %s\n", workgroup);
+
+ talloc_destroy(ctx);
+
+ return 0;
+}
+
+
-static BOOL usergrp_display(char *field, void **values, void *data_area)
+static void usergrp_display(char *field, void **values, void *data_area)
{
char **disp_fields = (char **) data_area;
}
SAFE_FREE(disp_fields[0]);
SAFE_FREE(disp_fields[1]);
- return True;
+ return;
}
if (!values) /* must be new field, indicate string field */
- return True;
+ return;
if (StrCaseCmp(field, "sAMAccountName") == 0) {
disp_fields[0] = strdup((char *) values[0]);
}
if (StrCaseCmp(field, "description") == 0)
disp_fields[1] = strdup((char *) values[0]);
- return True; /* always strings here */
}
static int net_ads_user_usage(int argc, const char **argv)
}
/* try setting the password */
- asprintf(&upn, "%s@%s", argv[0], ads->realm);
- status = krb5_set_password(ads->kdc_server, upn, argv[1]);
+ asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
+ status = krb5_set_password(ads->auth.kdc_server, upn, argv[1]);
safe_free(upn);
if (ADS_ERR_OK(status)) {
d_printf("User %s added\n", argv[0]);
d_printf("\nUser name Comment"\
"\n-----------------------------\n");
- rc = ads_do_search_all_fn(ads, ads->bind_path,
+ rc = ads_do_search_all_fn(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE,
"(objectclass=user)",
opt_long_list_entries ? longattrs :
if (opt_long_list_entries)
d_printf("\nGroup name Comment"\
"\n-----------------------------\n");
- rc = ads_do_search_all_fn(ads, ads->bind_path,
+ rc = ads_do_search_all_fn(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE,
"(objectclass=group)",
opt_long_list_entries ? longattrs :
rc = ads_leave_realm(ads, global_myname);
if (!ADS_ERR_OK(rc)) {
d_printf("Failed to delete host '%s' from the '%s' realm.\n",
- global_myname, ads->realm);
+ global_myname, ads->config.realm);
return -1;
}
- d_printf("Removed '%s' from realm '%s'\n", global_myname, ads->realm);
+ d_printf("Removed '%s' from realm '%s'\n", global_myname, ads->config.realm);
return 0;
}
if (!(ads = ads_startup())) return -1;
ou_str = ads_ou_string(org_unit);
- asprintf(&dn, "%s,%s", ou_str, ads->bind_path);
+ asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
free(ou_str);
rc = ads_search_dn(ads, &res, dn, NULL);
return -1;
}
- d_printf("Joined '%s' to realm '%s'\n", global_myname, ads->realm);
+ d_printf("Joined '%s' to realm '%s'\n", global_myname, ads->config.realm);
free(password);
get_a_printer, because the server name might be
localhost or an ip address */
prt.printerName = argv[0];
- asprintf(&servername, "%s.%s", global_myname, ads->realm);
+ asprintf(&servername, "%s.%s", global_myname, ads->config.realm);
prt.serverName = servername;
prt.shortServerName = global_myname;
prt.versionNumber = "4";
/* use the realm so we can eventually change passwords for users
in realms other than default */
- if (!(ads = ads_init(realm, NULL, NULL, NULL, NULL))) return -1;
+ if (!(ads = ads_init(realm, NULL, NULL))) return -1;
asprintf(&prompt, "Enter new password for %s:", argv[0]);
new_password = getpass(prompt);
- ret = kerberos_set_password(ads->kdc_server, auth_principal,
+ ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
auth_password, argv[0], new_password);
if (!ADS_ERR_OK(ret)) {
d_printf("Password change failed :-( ...\n");
hostname = strdup(global_myname);
strlower(hostname);
- asprintf(&host_principal, "%s@%s", hostname, ads->realm);
+ asprintf(&host_principal, "%s@%s", hostname, ads->config.realm);
SAFE_FREE(hostname);
d_printf("Changing password for principal: HOST/%s\n", host_principal);
exp = argv[0];
attrs = (argv + 1);
- rc = ads_do_search_all(ads, ads->bind_path,
+ rc = ads_do_search_all(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE,
exp, attrs, &res);
if (!ADS_ERR_OK(rc)) {
{"CHOSTPASS", net_ads_change_localhost_pass},
{"PRINTER", net_ads_printer},
{"SEARCH", net_ads_search},
+ {"WORKGROUP", net_ads_workgroup},
{"HELP", net_ads_help},
{NULL, NULL}
};
DEBUG(1, ("No kerberos support\n"));
return -1;
}
+
+
/* lookup hosts or IP addresses using internal samba lookup fns */
int net_lookup(int argc, const char **argv)
{
POLICY_HND connect_hnd;
/* trusted domains listing variables */
- int enum_ctx = 0, pref_num_domains = 5;
+ int enum_ctx = 0;
int num_domains, i, pad_len, col_len = 20;
DOM_SID *domain_sids;
char **trusted_dom_names;
do {
nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
- &pref_num_domains, &num_domains,
+ &num_domains,
&trusted_dom_names, &domain_sids);
if (NT_STATUS_IS_ERR(nt_status)) {