return result;
}
+/**********************************************
+ Do client and server sitename match ?
+**********************************************/
+
+BOOL ads_sitename_match(ADS_STRUCT *ads)
+{
+ if (ads->config.server_site_name == NULL &&
+ ads->config.client_site_name == NULL ) {
+ DEBUG(10,("ads_sitename_match: both null\n"));
+ return True;
+ }
+ if (ads->config.server_site_name &&
+ ads->config.client_site_name &&
+ strequal(ads->config.server_site_name,
+ ads->config.client_site_name)) {
+ DEBUG(10,("ads_sitename_match: name %s match\n", ads->config.server_site_name));
+ return True;
+ }
+ DEBUG(10,("ads_sitename_match: no match between server: %s and client: %s\n",
+ ads->config.server_site_name ? ads->config.server_site_name : "NULL",
+ ads->config.client_site_name ? ads->config.client_site_name : "NULL"));
+ return False;
+}
+
+/**********************************************
+ Is this the closest DC ?
+**********************************************/
+
+BOOL ads_closest_dc(ADS_STRUCT *ads)
+{
+ if (ads->config.flags & ADS_CLOSEST) {
+ DEBUG(10,("ads_closest_dc: ADS_CLOSEST flag set\n"));
+ return True;
+ }
+
+ /* not sure if this can ever happen */
+ if (ads_sitename_match(ads)) {
+ DEBUG(10,("ads_closest_dc: ADS_CLOSEST flag not set but sites match\n"));
+ return True;
+ }
+
+ DEBUG(10,("ads_closest_dc: %s is not the closest DC\n",
+ ads->config.ldap_server_name));
+
+ return False;
+}
+
+
/*
try a connection to a given ldap server, returning True and setting the servers IP
in the ads struct if successful
SAFE_FREE(ads->config.realm);
SAFE_FREE(ads->config.bind_path);
SAFE_FREE(ads->config.ldap_server_name);
+ SAFE_FREE(ads->config.server_site_name);
+ SAFE_FREE(ads->config.client_site_name);
SAFE_FREE(ads->server.workgroup);
ads->config.flags = cldap_reply.flags;
strupper_m(cldap_reply.domain);
ads->config.realm = SMB_STRDUP(cldap_reply.domain);
ads->config.bind_path = ads_build_dn(ads->config.realm);
+ if (*cldap_reply.server_site_name) {
+ ads->config.server_site_name =
+ SMB_STRDUP(cldap_reply.server_site_name);
+ }
+ if (*cldap_reply.client_site_name) {
+ ads->config.client_site_name =
+ SMB_STRDUP(cldap_reply.client_site_name);
+ }
+
ads->server.workgroup = SMB_STRDUP(cldap_reply.netbios_domain);
ads->ldap_port = LDAP_PORT;
SAFE_FREE(srv);
/* Store our site name. */
- sitename_store( cldap_reply.client_site_name );
+ sitename_store( cldap_reply.domain, cldap_reply.client_site_name );
return True;
}
pstring realm;
BOOL got_realm = False;
BOOL use_own_domain = False;
+ char *sitename;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
/* if the realm and workgroup are both empty, assume they are ours */
if (c_realm && *c_realm)
got_realm = True;
-again:
/* we need to try once with the realm name and fallback to the
netbios domain name if we fail (if netbios has not been disabled */
pstrcpy( realm, c_realm );
+ sitename = sitename_fetch(realm);
+
+ again:
+
DEBUG(6,("ads_find_dc: looking for %s '%s'\n",
(got_realm ? "realm" : "domain"), realm));
- status = get_sorted_dc_list(realm, &ip_list, &count, got_realm);
+ status = get_sorted_dc_list(realm, sitename, &ip_list, &count, got_realm);
if (!NT_STATUS_IS_OK(status)) {
/* fall back to netbios if we can */
if ( got_realm && !lp_disable_netbios() ) {
goto again;
}
+ SAFE_FREE(sitename);
return status;
}
if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) )
continue;
+
+ if (!got_realm) {
+ /* realm in this case is a workgroup name. We need
+ to ignore any IP addresses in the negative connection
+ cache that match ip addresses returned in the ad realm
+ case. It sucks that I have to reproduce the logic above... */
+ c_realm = ads->server.realm;
+ if ( !c_realm || !*c_realm ) {
+ if ( !ads->server.workgroup || !*ads->server.workgroup ) {
+ c_realm = lp_realm();
+ }
+ }
+ if (c_realm && *c_realm &&
+ !NT_STATUS_IS_OK(check_negative_conn_cache(c_realm, server))) {
+ /* Ensure we add the workgroup name for this
+ IP address as negative too. */
+ add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL );
+ continue;
+ }
+ }
if ( ads_try_connect(ads, server) ) {
SAFE_FREE(ip_list);
+ SAFE_FREE(sitename);
return NT_STATUS_OK;
}
}
SAFE_FREE(ip_list);
-
+
+ /* In case we failed to contact one of our closest DC on our site we
+ * need to try to find another DC, retry with a site-less SRV DNS query
+ * - Guenther */
+
+ if (sitename) {
+ DEBUG(1,("ads_find_dc: failed to find a valid DC on our site (%s), "
+ "trying to find another DC\n", sitename));
+ SAFE_FREE(sitename);
+ namecache_delete(realm, 0x1C);
+ goto again;
+ }
+
return NT_STATUS_NO_LOGON_SERVERS;
}
return ADS_ERROR(LDAP_OPERATIONS_ERROR);
}
- /* cache the successful connection */
- saf_store( ads->server.workgroup, inet_ntoa(ads->ldap_ip));
+ /* cache the successful connection for workgroup and realm */
+ if (ads_closest_dc(ads)) {
+ saf_store( ads->server.workgroup, inet_ntoa(ads->ldap_ip));
+ saf_store( ads->server.realm, inet_ntoa(ads->ldap_ip));
+ }
ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
if (in_val->bv_len == 0) return value;
value->bv_len = in_val->bv_len;
- value->bv_val = TALLOC_MEMDUP(ctx, in_val->bv_val, in_val->bv_len);
+ value->bv_val = (char *)TALLOC_MEMDUP(ctx, in_val->bv_val,
+ in_val->bv_len);
return value;
}
* @param cookie The paged results cookie to be returned on subsequent calls
* @return status of search
**/
-ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void *args, void **res,
- int *count, void **cookie)
+static ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads,
+ const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res,
+ int *count, struct berval **cookie)
{
int rc, i, version;
char *utf8_expr, *utf8_path, **search_attrs;
- LDAPControl PagedResults, NoReferrals, ExtendedDn, *controls[4], **rcontrols;
+ LDAPControl PagedResults, NoReferrals, ExternalCtrl, *controls[4], **rcontrols;
BerElement *cookie_be = NULL;
struct berval *cookie_bv= NULL;
- BerElement *extdn_be = NULL;
- struct berval *extdn_bv= NULL;
+ BerElement *ext_be = NULL;
+ struct berval *ext_bv= NULL;
TALLOC_CTX *ctx;
ads_control *external_control = (ads_control *) args;
}
}
-
/* Paged results only available on ldap v3 or later */
ldap_get_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
if (version < LDAP_VERSION3) {
NoReferrals.ldctl_value.bv_len = 0;
NoReferrals.ldctl_value.bv_val = CONST_DISCARD(char *, "");
- if (external_control && strequal(external_control->control, ADS_EXTENDED_DN_OID)) {
+ if (external_control &&
+ (strequal(external_control->control, ADS_EXTENDED_DN_OID) ||
+ strequal(external_control->control, ADS_SD_FLAGS_OID))) {
- ExtendedDn.ldctl_oid = CONST_DISCARD(char *, external_control->control);
- ExtendedDn.ldctl_iscritical = (char) external_control->critical;
+ ExternalCtrl.ldctl_oid = CONST_DISCARD(char *, external_control->control);
+ ExternalCtrl.ldctl_iscritical = (char) external_control->critical;
/* win2k does not accept a ldctl_value beeing passed in */
if (external_control->val != 0) {
- if ((extdn_be = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ if ((ext_be = ber_alloc_t(LBER_USE_DER)) == NULL ) {
rc = LDAP_NO_MEMORY;
goto done;
}
- if ((ber_printf(extdn_be, "{i}", (ber_int_t) external_control->val)) == -1) {
+ if ((ber_printf(ext_be, "{i}", (ber_int_t) external_control->val)) == -1) {
rc = LDAP_NO_MEMORY;
goto done;
}
- if ((ber_flatten(extdn_be, &extdn_bv)) == -1) {
+ if ((ber_flatten(ext_be, &ext_bv)) == -1) {
rc = LDAP_NO_MEMORY;
goto done;
}
- ExtendedDn.ldctl_value.bv_len = extdn_bv->bv_len;
- ExtendedDn.ldctl_value.bv_val = extdn_bv->bv_val;
+ ExternalCtrl.ldctl_value.bv_len = ext_bv->bv_len;
+ ExternalCtrl.ldctl_value.bv_val = ext_bv->bv_val;
} else {
- ExtendedDn.ldctl_value.bv_len = 0;
- ExtendedDn.ldctl_value.bv_val = NULL;
+ ExternalCtrl.ldctl_value.bv_len = 0;
+ ExternalCtrl.ldctl_value.bv_val = NULL;
}
controls[0] = &NoReferrals;
controls[1] = &PagedResults;
- controls[2] = &ExtendedDn;
+ controls[2] = &ExternalCtrl;
controls[3] = NULL;
} else {
done:
talloc_destroy(ctx);
- if (extdn_be) {
- ber_free(extdn_be, 1);
+ if (ext_be) {
+ ber_free(ext_be, 1);
}
- if (extdn_bv) {
- ber_bvfree(extdn_bv);
+ if (ext_bv) {
+ ber_bvfree(ext_bv);
}
/* if/when we decide to utf8-encode attrs, take out this next line */
return ADS_ERROR(rc);
}
-ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res,
- int *count, void **cookie)
+static ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res,
+ int *count, struct berval **cookie)
{
return ads_do_paged_search_args(ads, bind_path, scope, expr, attrs, NULL, res, count, cookie);
}
* @param res ** which will contain results - free res* with ads_msgfree()
* @return status of search
**/
-ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void *args, void **res)
+ ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args,
+ LDAPMessage **res)
{
- void *cookie = NULL;
+ struct berval *cookie = NULL;
int count = 0;
ADS_STATUS status;
#ifdef HAVE_LDAP_ADD_RESULT_ENTRY
while (cookie) {
- void *res2 = NULL;
+ LDAPMessage *res2 = NULL;
ADS_STATUS status2;
LDAPMessage *msg, *next;
return status;
}
-ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, LDAPMessage **res)
{
return ads_do_search_all_args(ads, bind_path, scope, expr, attrs, NULL, res);
}
+ ADS_STATUS ads_do_search_all_sd_flags(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, uint32 sd_flags,
+ LDAPMessage **res)
+{
+ ads_control args;
+
+ args.control = ADS_SD_FLAGS_OID;
+ args.val = sd_flags;
+ args.critical = True;
+
+ return ads_do_search_all_args(ads, bind_path, scope, expr, attrs, &args, res);
+}
+
+
/**
* Run a function on all results for a search. Uses ads_do_paged_search() and
* runs the function as each page is returned, using ads_process_results()
BOOL(*fn)(char *, void **, void *),
void *data_area)
{
- void *cookie = NULL;
+ struct berval *cookie = NULL;
int count = 0;
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
status = ads_do_paged_search(ads, bind_path, scope, expr, attrs, &res,
&count, &cookie);
* @param res ** which will contain results - free res* with ads_msgfree()
* @return status of search
**/
-ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void **res)
+ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, LDAPMessage **res)
{
int rc;
char *utf8_expr, *utf8_path, **search_attrs = NULL;
* @param attrs Attributes to retrieve
* @return status of search
**/
-ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
- const char *expr,
- const char **attrs)
+ ADS_STATUS ads_search(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *expr, const char **attrs)
{
return ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
expr, attrs, res);
* @param attrs Attributes to retrieve
* @return status of search
**/
-ADS_STATUS ads_search_dn(ADS_STRUCT *ads, void *_res,
- const char *dn,
- const char **attrs)
+ ADS_STATUS ads_search_dn(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *dn, const char **attrs)
{
- void **res = (void **)_res;
- return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, res);
+ return ads_do_search(ads, dn, LDAP_SCOPE_BASE, "(objectclass=*)",
+ attrs, res);
}
/**
* @param ads connection to ads server
* @param msg Search results to free
**/
-void ads_msgfree(ADS_STRUCT *ads, void *msg)
+ void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg)
{
if (!msg) return;
ldap_msgfree(msg);
* @param msg Search result
* @return dn string
**/
-char *ads_get_dn(ADS_STRUCT *ads, void *msg)
+ char *ads_get_dn(ADS_STRUCT *ads, LDAPMessage *msg)
{
char *utf8_dn, *unix_dn;
return unix_dn;
}
-/**
- * Get a canonical dn from search results
- * @param ads connection to ads server
- * @param msg Search result
- * @return dn string
- **/
-char *ads_get_dn_canonical(ADS_STRUCT *ads, void *msg)
-{
-#ifdef HAVE_LDAP_DN2AD_CANONICAL
- return ldap_dn2ad_canonical(ads_get_dn(ads, msg));
-#else
- return NULL;
-#endif
-}
-
/**
* Get the parent from a dn
* @param dn the dn to return the parent from
* @param host Hostname to search for
* @return status of search
**/
-ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *machine)
+ ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, LDAPMessage **res,
+ const char *machine)
{
ADS_STATUS status;
char *expr;
}
ret = ldap_delete_s(ads->ld, utf8_dn);
+ SAFE_FREE(utf8_dn);
return ADS_ERROR(ret);
}
char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid)
{
ADS_STATUS status;
- void *res;
- char *base, *wkn_dn, *ret, **wkn_dn_exp, **bind_dn_exp;
+ LDAPMessage *res = NULL;
+ char *base, *wkn_dn = NULL, *ret = NULL, **wkn_dn_exp = NULL,
+ **bind_dn_exp = NULL;
const char *attrs[] = {"distinguishedName", NULL};
int new_ln, wkn_ln, bind_ln, i;
status = ads_search_dn(ads, &res, base, attrs);
if (!ADS_ERR_OK(status)) {
DEBUG(1,("Failed while searching for: %s\n", base));
- SAFE_FREE(base);
- return NULL;
+ goto out;
}
- SAFE_FREE(base);
if (ads_count_replies(ads, res) != 1) {
- return NULL;
+ goto out;
}
/* substitute the bind-path from the well-known-guid-search result */
wkn_dn = ads_get_dn(ads, res);
+ if (!wkn_dn) {
+ goto out;
+ }
+
wkn_dn_exp = ldap_explode_dn(wkn_dn, 0);
+ if (!wkn_dn_exp) {
+ goto out;
+ }
+
bind_dn_exp = ldap_explode_dn(ads->config.bind_path, 0);
+ if (!bind_dn_exp) {
+ goto out;
+ }
for (wkn_ln=0; wkn_dn_exp[wkn_ln]; wkn_ln++)
;
new_ln = wkn_ln - bind_ln;
- ret = wkn_dn_exp[0];
+ ret = SMB_STRDUP(wkn_dn_exp[0]);
+ if (!ret) {
+ goto out;
+ }
for (i=1; i < new_ln; i++) {
- char *s;
- asprintf(&s, "%s,%s", ret, wkn_dn_exp[i]);
+ char *s = NULL;
+
+ if (asprintf(&s, "%s,%s", ret, wkn_dn_exp[i]) == -1) {
+ SAFE_FREE(ret);
+ goto out;
+ }
+
+ SAFE_FREE(ret);
ret = SMB_STRDUP(s);
free(s);
+ if (!ret) {
+ goto out;
+ }
}
+ out:
+ SAFE_FREE(base);
+ ads_msgfree(ads, res);
ads_memfree(ads, wkn_dn);
- ldap_value_free(wkn_dn_exp);
- ldap_value_free(bind_dn_exp);
+ if (wkn_dn_exp) {
+ ldap_value_free(wkn_dn_exp);
+ }
+ if (bind_dn_exp) {
+ ldap_value_free(bind_dn_exp);
+ }
return ret;
}
ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
const char *name, const char **vals)
{
- return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name, (const void **) vals);
+ return ads_modlist_add(ctx, mods, LDAP_MOD_ADD, name,
+ (const void *) vals);
}
/**
if (asprintf(&filter, "(samAccountName=%s$)", machine_name) == -1) {
return kvno;
}
- ret = ads_search(ads, (void**)(void *)&res, filter, attrs);
+ ret = ads_search(ads, &res, filter, attrs);
SAFE_FREE(filter);
if (!ADS_ERR_OK(ret) && ads_count_replies(ads, res)) {
DEBUG(1,("ads_get_kvno: Computer Account For %s not found.\n", machine_name));
ADS_STATUS ret = ADS_ERROR(LDAP_SUCCESS);
char *dn_string = NULL;
- ret = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ ret = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
DEBUG(5,("ads_clear_service_principal_names: WARNING: Host Account for %s not found... skipping operation.\n", machine_name));
DEBUG(5,("ads_clear_service_principal_names: WARNING: Service Principals for %s have NOT been cleared.\n", machine_name));
char *dn_string = NULL;
const char *servicePrincipalName[3] = {NULL, NULL, NULL};
- ret = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
+ ret = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(ret) || ads_count_replies(ads, res) != 1) {
DEBUG(1,("ads_add_service_principal_name: WARNING: Host Account for %s not found... skipping operation.\n",
machine_name));
char *samAccountName, *controlstr;
TALLOC_CTX *ctx;
ADS_MODLIST mods;
+ char *machine_escaped = NULL;
char *new_dn;
const char *objectClass[] = {"top", "person", "organizationalPerson",
"user", "computer", NULL};
return ADS_ERROR(LDAP_NO_MEMORY);
ret = ADS_ERROR(LDAP_NO_MEMORY);
-
- new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_name, org_unit);
+
+ machine_escaped = escape_rdn_val_string_alloc(machine_name);
+ if (!machine_escaped) {
+ goto done;
+ }
+
+ new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_escaped, org_unit);
samAccountName = talloc_asprintf(ctx, "%s$", machine_name);
if ( !new_dn || !samAccountName ) {
ret = ads_gen_add(ads, new_dn, mods);
done:
+ SAFE_FREE(machine_escaped);
ads_msgfree(ads, res);
talloc_destroy(ctx);
return ret;
}
+/**
+ * move a machine account to another OU on the ADS server
+ * @param ads - An intialized ADS_STRUCT
+ * @param machine_name - the NetBIOS machine name of this account.
+ * @param org_unit - The LDAP path in which to place this account
+ * @param moved - whether we moved the machine account (optional)
+ * @return 0 upon success, or non-zero otherwise
+**/
+
+ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name,
+ const char *org_unit, BOOL *moved)
+{
+ ADS_STATUS rc;
+ int ldap_status;
+ LDAPMessage *res = NULL;
+ char *filter = NULL;
+ char *computer_dn = NULL;
+ char *parent_dn;
+ char *computer_rdn = NULL;
+ BOOL need_move = False;
+
+ if (asprintf(&filter, "(samAccountName=%s$)", machine_name) == -1) {
+ rc = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ /* Find pre-existing machine */
+ rc = ads_search(ads, &res, filter, NULL);
+ if (!ADS_ERR_OK(rc)) {
+ goto done;
+ }
+
+ computer_dn = ads_get_dn(ads, res);
+ if (!computer_dn) {
+ rc = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ parent_dn = ads_parent_dn(computer_dn);
+ if (strequal(parent_dn, org_unit)) {
+ goto done;
+ }
+
+ need_move = True;
+
+ if (asprintf(&computer_rdn, "CN=%s", machine_name) == -1) {
+ rc = ADS_ERROR(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ ldap_status = ldap_rename2_s(ads->ld, computer_dn, computer_rdn, org_unit, 1);
+ rc = ADS_ERROR(ldap_status);
+
+done:
+ ads_msgfree(ads, res);
+ SAFE_FREE(filter);
+ SAFE_FREE(computer_dn);
+ SAFE_FREE(computer_rdn);
+
+ if (!ADS_ERR_OK(rc)) {
+ need_move = False;
+ }
+
+ if (moved) {
+ *moved = need_move;
+ }
+
+ return rc;
+}
+
/*
dump a binary result from ldap
*/
{"tokenGroups", False, dump_sid},
{"tokenGroupsNoGCAcceptable", False, dump_sid},
{"tokengroupsGlobalandUniversal", False, dump_sid},
+ {"mS-DS-CreatorSID", False, dump_sid},
{NULL, True, NULL}
};
int i;
* @param res Results to dump
**/
-void ads_dump(ADS_STRUCT *ads, void *res)
+ void ads_dump(ADS_STRUCT *ads, LDAPMessage *res)
{
ads_process_results(ads, res, ads_dump_field, NULL);
}
* @param fn Function for processing each result
* @param data_area user-defined area to pass to function
**/
-void ads_process_results(ADS_STRUCT *ads, void *res,
- BOOL(*fn)(char *, void **, void *),
- void *data_area)
+ void ads_process_results(ADS_STRUCT *ads, LDAPMessage *res,
+ BOOL(*fn)(char *, void **, void *),
+ void *data_area)
{
- void *msg;
+ LDAPMessage *msg;
TALLOC_CTX *ctx;
if (!(ctx = talloc_init("ads_process_results")))
* @param res Results of search
* @return first entry from result
**/
-void *ads_first_entry(ADS_STRUCT *ads, void *res)
+ LDAPMessage *ads_first_entry(ADS_STRUCT *ads, LDAPMessage *res)
{
- return (void *)ldap_first_entry(ads->ld, (LDAPMessage *)res);
+ return ldap_first_entry(ads->ld, res);
}
/**
* @param res Results of search
* @return next entry from result
**/
-void *ads_next_entry(ADS_STRUCT *ads, void *res)
+ LDAPMessage *ads_next_entry(ADS_STRUCT *ads, LDAPMessage *res)
{
- return (void *)ldap_next_entry(ads->ld, (LDAPMessage *)res);
+ return ldap_next_entry(ads->ld, res);
}
/**
* @param field Attribute to retrieve
* @return Result string in talloc context
**/
-char *ads_pull_string(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx, void *msg, const char *field)
+ char *ads_pull_string(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg,
+ const char *field)
{
char **values;
char *ret = NULL;
* @param field Attribute to retrieve
* @return Result strings in talloc context
**/
-char **ads_pull_strings(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx, void *msg, const char *field,
- size_t *num_values)
+ char **ads_pull_strings(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ size_t *num_values)
{
char **values;
char **ret = NULL;
* @param more_values Are there more values to get?
* @return Result strings in talloc context
**/
-char **ads_pull_strings_range(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *msg, const char *field,
- char **current_strings,
- const char **next_attribute,
- size_t *num_strings,
- BOOL *more_strings)
+ char **ads_pull_strings_range(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field,
+ char **current_strings,
+ const char **next_attribute,
+ size_t *num_strings,
+ BOOL *more_strings)
{
char *attr;
char *expected_range_attrib, *range_attr;
* @param v Pointer to int to store result
* @return boolean inidicating success
*/
-BOOL ads_pull_uint32(ADS_STRUCT *ads,
- void *msg, const char *field, uint32 *v)
+ BOOL ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ uint32 *v)
{
char **values;
* @param guid 37-byte area to receive text guid
* @return boolean indicating success
**/
-BOOL ads_pull_guid(ADS_STRUCT *ads,
- void *msg, struct uuid *guid)
+ BOOL ads_pull_guid(ADS_STRUCT *ads, LDAPMessage *msg, struct GUID *guid)
{
char **values;
UUID_FLAT flat_guid;
* @param sid Pointer to sid to store result
* @return boolean inidicating success
*/
-BOOL ads_pull_sid(ADS_STRUCT *ads,
- void *msg, const char *field, DOM_SID *sid)
+ BOOL ads_pull_sid(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
+ DOM_SID *sid)
{
struct berval **values;
BOOL ret = False;
* @param sids pointer to sid array to allocate
* @return the count of SIDs pulled
**/
-int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- void *msg, const char *field, DOM_SID **sids)
+ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, DOM_SID **sids)
{
struct berval **values;
BOOL ret;
for (i=0; values[i]; i++)
/* nop */ ;
- (*sids) = TALLOC_ARRAY(mem_ctx, DOM_SID, i);
- if (!(*sids)) {
- ldap_value_free_len(values);
- return 0;
+ if (i) {
+ (*sids) = TALLOC_ARRAY(mem_ctx, DOM_SID, i);
+ if (!(*sids)) {
+ ldap_value_free_len(values);
+ return 0;
+ }
+ } else {
+ (*sids) = NULL;
}
count = 0;
* @param sd Pointer to *SEC_DESC to store result (talloc()ed)
* @return boolean inidicating success
*/
-BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- void *msg, const char *field, SEC_DESC **sd)
+ BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg, const char *field, SEC_DESC **sd)
{
struct berval **values;
- prs_struct ps;
BOOL ret = False;
values = ldap_get_values_len(ads->ld, msg, field);
if (!values) return False;
if (values[0]) {
+ prs_struct ps;
prs_init(&ps, values[0]->bv_len, mem_ctx, UNMARSHALL);
prs_copy_data_in(&ps, values[0]->bv_val, values[0]->bv_len);
prs_set_offset(&ps,0);
ret = sec_io_desc("sd", sd, &ps, 1);
+ prs_mem_free(&ps);
}
ldap_value_free_len(values);
* @param msg Results of search
* @return the username
*/
-char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, void *msg)
+ char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg)
{
#if 0 /* JERRY */
char *ret, *p;
{
const char *attrs[] = {"highestCommittedUSN", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
status = ads_do_search_retry(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
if (!ADS_ERR_OK(status))
return status;
if (ads_count_replies(ads, res) != 1) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
}
- ads_pull_uint32(ads, res, "highestCommittedUSN", usn);
+ if (!ads_pull_uint32(ads, res, "highestCommittedUSN", usn)) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
+ }
+
ads_msgfree(ads, res);
return ADS_SUCCESS;
}
{
const char *attrs[] = {"currentTime", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
char *timestr;
TALLOC_CTX *ctx;
ADS_STRUCT *ads_s = ads;
timestr = ads_pull_string(ads_s, ctx, res, "currentTime");
if (!timestr) {
- ads_msgfree(ads, res);
+ ads_msgfree(ads_s, res);
status = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
goto done;
}
{
const char *attrs[] = {"domainFunctionality", NULL};
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
ADS_STRUCT *ads_s = ads;
*val = DS_DOMAIN_FUNCTION_2000;
ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
{
const char *attrs[] = {"objectSid", NULL};
- void *res;
+ LDAPMessage *res;
ADS_STATUS rc;
rc = ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_BASE, "(objectclass=*)",
ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *dn, *service_name;
const char *attrs[] = { "dsServiceName", NULL };
service_name = ads_pull_string(ads, mem_ctx, res, "dsServiceName");
if (service_name == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
}
+ ads_msgfree(ads, res);
+
/* go up three levels */
dn = ads_parent_dn(ads_parent_dn(ads_parent_dn(service_name)));
if (dn == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
- ads_msgfree(ads, res);
-
return status;
/*
dsServiceName: CN=NTDS Settings,CN=W2K3DC,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=ber,DC=suse,DC=de
ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *computer_name, const char **site_dn)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *parent, *config_context, *filter;
const char *attrs[] = { "configurationNamingContext", NULL };
char *dn;
config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
if (config_context == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
filter = talloc_asprintf(mem_ctx, "(cn=%s)", computer_name);
if (filter == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
+ ads_msgfree(ads, res);
+
status = ads_do_search(ads, config_context, LDAP_SCOPE_SUBTREE, filter, NULL, &res);
if (!ADS_ERR_OK(status)) {
return status;
}
if (ads_count_replies(ads, res) != 1) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
dn = ads_get_dn(ads, res);
if (dn == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
/* go up three levels */
parent = ads_parent_dn(ads_parent_dn(ads_parent_dn(dn)));
if (parent == NULL) {
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
return ADS_ERROR(LDAP_NO_MEMORY);
}
*site_dn = talloc_strdup(mem_ctx, parent);
if (*site_dn == NULL) {
+ ads_msgfree(ads, res);
ads_memfree(ads, dn);
ADS_ERROR(LDAP_NO_MEMORY);
}
* @param ads connection to ads server
* @param mem_ctx Pointer to talloc context
* @param suffixes Pointer to an array of suffixes
- * @param site_name Pointer to the number of suffixes
+ * @param num_suffixes Pointer to the number of suffixes
* @return status of search
**/
-ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixes, size_t *num_suffixes)
+ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char ***suffixes, size_t *num_suffixes)
{
ADS_STATUS status;
- void *res;
+ LDAPMessage *res;
const char *config_context, *base;
const char *attrs[] = { "configurationNamingContext", NULL };
const char *attrs2[] = { "uPNSuffixes", NULL };
config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
if (config_context == NULL) {
+ ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
+ ads_msgfree(ads, res);
+
base = talloc_asprintf(mem_ctx, "cn=Partitions,%s", config_context);
if (base == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
}
- suffixes = ads_pull_strings(ads, mem_ctx, &res, "uPNSuffixes", num_suffixes);
- if (suffixes == NULL) {
+ (*suffixes) = ads_pull_strings(ads, mem_ctx, res, "uPNSuffixes", num_suffixes);
+ if ((*suffixes) == NULL) {
ads_msgfree(ads, res);
return ADS_ERROR(LDAP_NO_MEMORY);
}
return status;
}
+/**
+ * pull a dn from an extended dn string
+ * @param mem_ctx TALLOC_CTX
+ * @param extended_dn string
+ * @param dn pointer to the dn
+ * @return boolean inidicating success
+ **/
+BOOL ads_get_dn_from_extended_dn(TALLOC_CTX *mem_ctx,
+ const char *extended_dn,
+ char **dn)
+{
+ char *p;
+ pstring tok;
+
+ if (!extended_dn) {
+ return False;
+ }
+
+ while (next_token(&extended_dn, tok, ";", sizeof(tok))) {
+ p = tok;
+ }
+
+ if ((*dn = talloc_strdup(mem_ctx, p)) == NULL) {
+ return False;
+ }
+
+ return True;
+}
+
/**
* pull a DOM_SID from an extended dn string
* @param mem_ctx TALLOC_CTX
+ * @param extended_dn string
* @param flags string type of extended_dn
* @param sid pointer to a DOM_SID
* @return boolean inidicating success
**/
BOOL ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
- const char *dn,
+ const char *extended_dn,
enum ads_extended_dn_flags flags,
DOM_SID *sid)
{
- char *p, *q;
+ char *p, *q, *dn;
- if (!dn) {
+ if (!extended_dn) {
return False;
}
+ /* otherwise extended_dn gets stripped off */
+ if ((dn = talloc_strdup(mem_ctx, extended_dn)) == NULL) {
+ return False;
+ }
/*
* ADS_EXTENDED_DN_HEX_STRING:
* <GUID=238e1963cb390f4bb032ba0105525a29>;<SID=010500000000000515000000bb68c8fd6b61b427572eb04556040000>;CN=gd,OU=berlin,OU=suse,DC=ber,DC=suse,DC=de
* @param sids pointer to sid array to allocate
* @return the count of SIDs pulled
**/
-int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- void *msg,
- const char *field,
- enum ads_extended_dn_flags flags,
- DOM_SID **sids)
+ int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *msg,
+ const char *field,
+ enum ads_extended_dn_flags flags,
+ DOM_SID **sids)
{
int i;
size_t dn_count;
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
global_myname()));
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_upn: Failed to find account for %s\n",
global_myname()));
int count = 0;
char *name = NULL;
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+ status = ads_find_machine_acct(ads, &res, global_myname());
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
global_myname()));
return name;
}
+#if 0
+
+ SAVED CODE - we used to join via ldap - remember how we did this. JRA.
+
+/**
+ * Join a machine to a realm
+ * Creates the machine account and sets the machine password
+ * @param ads connection to ads server
+ * @param machine name of host to add
+ * @param org_unit Organizational unit to place machine in
+ * @return status of join
+ **/
+ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
+ uint32 account_type, const char *org_unit)
+{
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ char *machine;
+
+ /* machine name must be lowercase */
+ machine = SMB_STRDUP(machine_name);
+ strlower_m(machine);
+
+ /*
+ status = ads_find_machine_acct(ads, (void **)&res, machine);
+ if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
+ DEBUG(0, ("Host account for %s already exists - deleting old account\n", machine));
+ status = ads_leave_realm(ads, machine);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n",
+ machine, ads->config.realm));
+ return status;
+ }
+ }
+ */
+ status = ads_add_machine_acct(ads, machine, account_type, org_unit);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("ads_join_realm: ads_add_machine_acct failed (%s): %s\n", machine, ads_errstr(status)));
+ SAFE_FREE(machine);
+ return status;
+ }
+
+ status = ads_find_machine_acct(ads, (void **)(void *)&res, machine);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("ads_join_realm: Host account test failed for machine %s\n", machine));
+ SAFE_FREE(machine);
+ return status;
+ }
+
+ SAFE_FREE(machine);
+ ads_msgfree(ads, res);
+
+ return status;
+}
+#endif
+
+/**
+ * Delete a machine from the realm
+ * @param ads connection to ads server
+ * @param hostname Machine to remove
+ * @return status of delete
+ **/
+ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
+{
+ ADS_STATUS status;
+ void *msg;
+ LDAPMessage *res;
+ char *hostnameDN, *host;
+ int rc;
+ LDAPControl ldap_control;
+ LDAPControl * pldap_control[2] = {NULL, NULL};
+
+ pldap_control[0] = &ldap_control;
+ memset(&ldap_control, 0, sizeof(LDAPControl));
+ ldap_control.ldctl_oid = (char *)LDAP_SERVER_TREE_DELETE_OID;
+
+ /* hostname must be lowercase */
+ host = SMB_STRDUP(hostname);
+ strlower_m(host);
+
+ status = ads_find_machine_acct(ads, &res, host);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("Host account for %s does not exist.\n", host));
+ SAFE_FREE(host);
+ return status;
+ }
+
+ msg = ads_first_entry(ads, res);
+ if (!msg) {
+ SAFE_FREE(host);
+ return ADS_ERROR_SYSTEM(ENOENT);
+ }
+
+ hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg);
+
+ rc = ldap_delete_ext_s(ads->ld, hostnameDN, pldap_control, NULL);
+ if (rc) {
+ DEBUG(3,("ldap_delete_ext_s failed with error code %d\n", rc));
+ }else {
+ DEBUG(3,("ldap_delete_ext_s succeeded with error code %d\n", rc));
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ const char *attrs[] = { "cn", NULL };
+ LDAPMessage *msg_sub;
+
+ /* we only search with scope ONE, we do not expect any further
+ * objects to be created deeper */
+
+ status = ads_do_search_retry(ads, hostnameDN,
+ LDAP_SCOPE_ONELEVEL,
+ "(objectclass=*)", attrs, &res);
+
+ if (!ADS_ERR_OK(status)) {
+ SAFE_FREE(host);
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+
+ for (msg_sub = ads_first_entry(ads, res); msg_sub;
+ msg_sub = ads_next_entry(ads, msg_sub)) {
+
+ char *dn = NULL;
+
+ if ((dn = ads_get_dn(ads, msg_sub)) == NULL) {
+ SAFE_FREE(host);
+ ads_memfree(ads, hostnameDN);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_del_dn(ads, dn);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3,("failed to delete dn %s: %s\n", dn, ads_errstr(status)));
+ SAFE_FREE(host);
+ ads_memfree(ads, dn);
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+
+ ads_memfree(ads, dn);
+ }
+
+ /* there should be no subordinate objects anymore */
+ status = ads_do_search_retry(ads, hostnameDN,
+ LDAP_SCOPE_ONELEVEL,
+ "(objectclass=*)", attrs, &res);
+
+ if (!ADS_ERR_OK(status) || ( (ads_count_replies(ads, res)) > 0 ) ) {
+ SAFE_FREE(host);
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+
+ /* delete hostnameDN now */
+ status = ads_del_dn(ads, hostnameDN);
+ if (!ADS_ERR_OK(status)) {
+ SAFE_FREE(host);
+ DEBUG(3,("failed to delete dn %s: %s\n", hostnameDN, ads_errstr(status)));
+ ads_memfree(ads, hostnameDN);
+ return status;
+ }
+ }
+
+ ads_memfree(ads, hostnameDN);
+
+ status = ads_find_machine_acct(ads, &res, host);
+ if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
+ DEBUG(3, ("Failed to remove host account.\n"));
+ SAFE_FREE(host);
+ return status;
+ }
+
+ SAFE_FREE(host);
+ return status;
+}
+
+/**
+ * pull all token-sids from an LDAP dn
+ * @param ads connection to ads server
+ * @param mem_ctx TALLOC_CTX for allocating sid array
+ * @param dn of LDAP object
+ * @param user_sid pointer to DOM_SID (objectSid)
+ * @param primary_group_sid pointer to DOM_SID (self composed)
+ * @param sids pointer to sid array to allocate
+ * @param num_sids counter of SIDs pulled
+ * @return status of token query
+ **/
+ ADS_STATUS ads_get_tokensids(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *dn,
+ DOM_SID *user_sid,
+ DOM_SID *primary_group_sid,
+ DOM_SID **sids,
+ size_t *num_sids)
+{
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ int count = 0;
+ size_t tmp_num_sids;
+ DOM_SID *tmp_sids;
+ DOM_SID tmp_user_sid;
+ DOM_SID tmp_primary_group_sid;
+ uint32 pgid;
+ const char *attrs[] = {
+ "objectSid",
+ "tokenGroups",
+ "primaryGroupID",
+ NULL
+ };
+
+ status = ads_search_retry_dn(ads, &res, dn, attrs);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ count = ads_count_replies(ads, res);
+ if (count != 1) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR_LDAP(LDAP_NO_SUCH_OBJECT);
+ }
+
+ if (!ads_pull_sid(ads, res, "objectSid", &tmp_user_sid)) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ if (!ads_pull_uint32(ads, res, "primaryGroupID", &pgid)) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ {
+ /* hack to compose the primary group sid without knowing the
+ * domsid */
+
+ DOM_SID domsid;
+ uint32 dummy_rid;
+
+ sid_copy(&domsid, &tmp_user_sid);
+
+ if (!sid_split_rid(&domsid, &dummy_rid)) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ if (!sid_compose(&tmp_primary_group_sid, &domsid, pgid)) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+ }
+
+ tmp_num_sids = ads_pull_sids(ads, mem_ctx, res, "tokenGroups", &tmp_sids);
+
+ if (tmp_num_sids == 0 || !tmp_sids) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ if (num_sids) {
+ *num_sids = tmp_num_sids;
+ }
+
+ if (sids) {
+ *sids = tmp_sids;
+ }
+
+ if (user_sid) {
+ *user_sid = tmp_user_sid;
+ }
+
+ if (primary_group_sid) {
+ *primary_group_sid = tmp_primary_group_sid;
+ }
+
+ DEBUG(10,("ads_get_tokensids: returned %d sids\n", (int)tmp_num_sids + 2));
+
+ ads_msgfree(ads, res);
+ return ADS_ERROR_LDAP(LDAP_SUCCESS);
+}
+
#endif