This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#define LDAP_SERVER_TREE_DELETE_OID "1.2.840.113556.1.4.805"
static SIG_ATOMIC_T gotalarm;
-
+
/***************************************************************
Signal function to tell us we timed out.
****************************************************************/
{
LDAP *ldp = NULL;
+
+ DEBUG(10, ("Opening connection to LDAP server '%s:%d', timeout "
+ "%u seconds\n", server, port, to));
+
/* Setup timeout */
gotalarm = 0;
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
ldp = ldap_open(server, port);
if (ldp == NULL) {
- DEBUG(2,("Could not open LDAP connection to %s:%d: %s\n",
+ DEBUG(2,("Could not open connection to LDAP server %s:%d: %s\n",
server, port, strerror(errno)));
+ } else {
+ DEBUG(10, ("Connected to LDAP server '%s:%d'\n", server, port));
}
/* Teardown timeout. */
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
*/
-BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
+bool ads_try_connect(ADS_STRUCT *ads, const char *server )
{
char *srv;
struct cldap_netlogon_reply cldap_reply;
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;
ads->config.ldap_server_name = SMB_STRDUP(cldap_reply.hostname);
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;
- ads->ldap_ip = *interpret_addr2(srv);
+ ads->ldap.port = LDAP_PORT;
+ if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) {
+ DEBUG(1,("ads_try_connect: unable to convert %s "
+ "to an address\n",
+ srv));
+ SAFE_FREE( srv );
+ return False;
+ }
+
SAFE_FREE(srv);
-
- /* cache the successful connection */
- saf_store( ads->server.workgroup, server );
+ /* Store our site name. */
+ sitename_store( cldap_reply.domain, cldap_reply.client_site_name );
return True;
}
const char *c_realm;
int count, i=0;
struct ip_service *ip_list;
- pstring realm;
- BOOL got_realm = False;
- BOOL use_own_domain = False;
+ const char *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 */
/* realm */
c_realm = ads->server.realm;
-
+
if ( !c_realm || !*c_realm ) {
/* special case where no realm and no workgroup means our own */
if ( !ads->server.workgroup || !*ads->server.workgroup ) {
c_realm = lp_realm();
}
}
-
- if (c_realm && *c_realm)
+
+ if (c_realm && *c_realm)
got_realm = True;
-
-again:
- /* we need to try once with the realm name and fallback to the
+
+ /* 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 */
-
+
if ( !got_realm && !lp_disable_netbios() ) {
c_realm = ads->server.workgroup;
if (!c_realm || !*c_realm) {
if ( use_own_domain )
c_realm = lp_workgroup();
}
-
+
if ( !c_realm || !*c_realm ) {
DEBUG(0,("ads_find_dc: no realm or workgroup! Don't know what to do\n"));
return NT_STATUS_INVALID_PARAMETER; /* rather need MISSING_PARAMETER ... */
}
}
-
- pstrcpy( realm, c_realm );
- DEBUG(6,("ads_find_dc: looking for %s '%s'\n",
+ 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() ) {
got_realm = False;
goto again;
}
-
+
+ SAFE_FREE(sitename);
return status;
}
-
+
/* if we fail this loop, then giveup since all the IP addresses returned were dead */
for ( i=0; i<count; i++ ) {
- fstring server;
-
- fstrcpy( server, inet_ntoa(ip_list[i].ip) );
-
+ char server[INET6_ADDRSTRLEN];
+
+ print_sockaddr(server, sizeof(server), &ip_list[i].ss);
+
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;
}
int version = LDAP_VERSION3;
ADS_STATUS status;
NTSTATUS ntstatus;
+ char addr[INET6_ADDRSTRLEN];
- ads->last_attempt = time(NULL);
- ads->ld = NULL;
+ ZERO_STRUCT(ads->ldap);
+ ads->ldap.last_attempt = time(NULL);
+ ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
/* try with a user specified server */
- if (ads->server.ldap_server &&
+ if (DEBUGLEVEL >= 11) {
+ char *s = NDR_PRINT_STRUCT_STRING(talloc_tos(), ads_struct, ads);
+ DEBUG(11,("ads_connect: entering\n"));
+ DEBUGADD(11,("%s\n", s));
+ TALLOC_FREE(s);
+ }
+
+ if (ads->server.ldap_server &&
ads_try_connect(ads, ads->server.ldap_server)) {
goto got_connection;
}
goto got_connection;
}
- return ADS_ERROR_NT(ntstatus);
+ status = ADS_ERROR_NT(ntstatus);
+ goto out;
got_connection:
- DEBUG(3,("Connected to LDAP server %s\n", inet_ntoa(ads->ldap_ip)));
+
+ print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
+ DEBUG(3,("Successfully contacted LDAP server %s\n", addr));
if (!ads->auth.user_name) {
/* Must use the userPrincipalName value here or sAMAccountName
}
if (!ads->auth.kdc_server) {
- ads->auth.kdc_server = SMB_STRDUP(inet_ntoa(ads->ldap_ip));
+ print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
+ ads->auth.kdc_server = SMB_STRDUP(addr);
}
#if KRB5_DNS_HACK
/* If the caller() requested no LDAP bind, then we are done */
if (ads->auth.flags & ADS_AUTH_NO_BIND) {
- return ADS_SUCCESS;
+ status = ADS_SUCCESS;
+ goto out;
+ }
+
+ ads->ldap.mem_ctx = talloc_init("ads LDAP connection memory");
+ if (!ads->ldap.mem_ctx) {
+ status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto out;
}
/* Otherwise setup the TCP LDAP session */
- if ( (ads->ld = ldap_open_with_timeout(ads->config.ldap_server_name,
- LDAP_PORT, lp_ldap_timeout())) == NULL )
- {
- return ADS_ERROR(LDAP_OPERATIONS_ERROR);
+ ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
+ LDAP_PORT, lp_ldap_timeout());
+ if (ads->ldap.ld == NULL) {
+ status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
+ goto out;
+ }
+ DEBUG(3,("Connected to LDAP server %s\n", ads->config.ldap_server_name));
+
+ /* cache the successful connection for workgroup and realm */
+ if (ads_closest_dc(ads)) {
+ print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
+ saf_store( ads->server.workgroup, addr);
+ saf_store( ads->server.realm, addr);
}
- ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
- status = ADS_ERROR(smb_ldap_start_tls(ads->ld, version));
+ ldap_set_option(ads->ldap.ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+
+ status = ADS_ERROR(smb_ldap_start_tls(ads->ldap.ld, version));
if (!ADS_ERR_OK(status)) {
- return status;
+ goto out;
}
/* fill in the current time and offsets */
status = ads_current_time( ads );
if ( !ADS_ERR_OK(status) ) {
- return status;
+ goto out;
}
/* Now do the bind */
if (ads->auth.flags & ADS_AUTH_ANON_BIND) {
- return ADS_ERROR(ldap_simple_bind_s( ads->ld, NULL, NULL));
+ status = ADS_ERROR(ldap_simple_bind_s(ads->ldap.ld, NULL, NULL));
+ goto out;
}
if (ads->auth.flags & ADS_AUTH_SIMPLE_BIND) {
- return ADS_ERROR(ldap_simple_bind_s( ads->ld, ads->auth.user_name, ads->auth.password));
+ status = ADS_ERROR(ldap_simple_bind_s(ads->ldap.ld, ads->auth.user_name, ads->auth.password));
+ goto out;
+ }
+
+ status = ads_sasl_bind(ads);
+
+ out:
+ if (DEBUGLEVEL >= 11) {
+ char *s = NDR_PRINT_STRUCT_STRING(talloc_tos(), ads_struct, ads);
+ DEBUG(11,("ads_connect: leaving with: %s\n",
+ ads_errstr(status)));
+ DEBUGADD(11,("%s\n", s));
+ TALLOC_FREE(s);
}
- return ads_sasl_bind(ads);
+ return status;
+}
+
+/**
+ * Disconnect the LDAP server
+ * @param ads Pointer to an existing ADS_STRUCT
+ **/
+void ads_disconnect(ADS_STRUCT *ads)
+{
+ if (ads->ldap.ld) {
+ ldap_unbind(ads->ldap.ld);
+ ads->ldap.ld = NULL;
+ }
+ if (ads->ldap.wrap_ops && ads->ldap.wrap_ops->disconnect) {
+ ads->ldap.wrap_ops->disconnect(ads);
+ }
+ if (ads->ldap.mem_ctx) {
+ talloc_free(ads->ldap.mem_ctx);
+ }
+ ZERO_STRUCT(ads->ldap);
}
/*
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;
}
if (!values) return NULL;
for (i=0; in_vals[i]; i++) {
- push_utf8_talloc(ctx, &values[i], in_vals[i]);
+ if (push_utf8_talloc(ctx, &values[i], in_vals[i]) == (size_t) -1) {
+ TALLOC_FREE(values);
+ return NULL;
+ }
}
return values;
}
* @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;
else {
/* This would be the utf8-encoded version...*/
/* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */
- if (!(str_list_copy(&search_attrs, attrs))) {
+ if (!(str_list_copy(talloc_tos(), &search_attrs, attrs))) {
rc = LDAP_NO_MEMORY;
goto done;
}
}
-
/* Paged results only available on ldap v3 or later */
- ldap_get_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ ldap_get_option(ads->ldap.ld, LDAP_OPT_PROTOCOL_VERSION, &version);
if (version < LDAP_VERSION3) {
rc = LDAP_NOT_SUPPORTED;
goto done;
}
cookie_be = ber_alloc_t(LBER_USE_DER);
- if (cookie && *cookie) {
+ if (*cookie) {
ber_printf(cookie_be, "{iO}", (ber_int_t) 1000, *cookie);
ber_bvfree(*cookie); /* don't need it from last time */
*cookie = NULL;
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 {
leaving this in despite the control that says don't generate
referrals, in case the server doesn't support it (jmcd)
*/
- ldap_set_option(ads->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+ ldap_set_option(ads->ldap.ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
- rc = ldap_search_with_timeout(ads->ld, utf8_path, scope, utf8_expr,
+ rc = ldap_search_with_timeout(ads->ldap.ld, utf8_path, scope, utf8_expr,
search_attrs, 0, controls,
NULL, LDAP_NO_LIMIT,
(LDAPMessage **)res);
goto done;
}
- rc = ldap_parse_result(ads->ld, *res, NULL, NULL, NULL,
+ rc = ldap_parse_result(ads->ldap.ld, *res, NULL, NULL, NULL,
NULL, &rcontrols, 0);
if (!rcontrols) {
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 */
- str_list_free(&search_attrs);
+ TALLOC_FREE(search_attrs);
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()
**/
ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
int scope, const char *expr, const char **attrs,
- BOOL(*fn)(char *, void **, void *),
+ bool (*fn)(ADS_STRUCT *, 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;
else {
/* This would be the utf8-encoded version...*/
/* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */
- if (!(str_list_copy(&search_attrs, attrs)))
+ if (!(str_list_copy(talloc_tos(), &search_attrs, attrs)))
{
DEBUG(1,("ads_do_search: str_list_copy() failed!"));
rc = LDAP_NO_MEMORY;
}
/* see the note in ads_do_paged_search - we *must* disable referrals */
- ldap_set_option(ads->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+ ldap_set_option(ads->ldap.ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
- rc = ldap_search_with_timeout(ads->ld, utf8_path, scope, utf8_expr,
+ rc = ldap_search_with_timeout(ads->ldap.ld, utf8_path, scope, utf8_expr,
search_attrs, 0, NULL, NULL,
LDAP_NO_LIMIT,
(LDAPMessage **)res);
done:
talloc_destroy(ctx);
/* if/when we decide to utf8-encode attrs, take out this next line */
- str_list_free(&search_attrs);
+ TALLOC_FREE(search_attrs);
return ADS_ERROR(rc);
}
/**
* @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;
- utf8_dn = ldap_get_dn(ads->ld, msg);
+ utf8_dn = ldap_get_dn(ads->ldap.ld, msg);
if (!utf8_dn) {
DEBUG (5, ("ads_get_dn: ldap_get_dn failed\n"));
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;
for(i=0;(mods[i]!=0)&&(mods[i]!=(LDAPMod *) -1);i++);
/* make sure the end of the list is NULL */
mods[i] = NULL;
- ret = ldap_modify_ext_s(ads->ld, utf8_dn,
+ ret = ldap_modify_ext_s(ads->ldap.ld, utf8_dn,
(LDAPMod **) mods, controls, NULL);
SAFE_FREE(utf8_dn);
return ADS_ERROR(ret);
/* make sure the end of the list is NULL */
mods[i] = NULL;
- ret = ldap_add_s(ads->ld, utf8_dn, (LDAPMod**)mods);
+ ret = ldap_add_s(ads->ldap.ld, utf8_dn, (LDAPMod**)mods);
SAFE_FREE(utf8_dn);
return ADS_ERROR(ret);
}
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
- ret = ldap_delete_s(ads->ld, utf8_dn);
+ ret = ldap_delete_s(ads->ldap.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_rename_s(ads->ldap.ld, computer_dn, computer_rdn,
+ org_unit, 1, NULL, NULL);
+ 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
*/
-static void dump_binary(const char *field, struct berval **values)
+static void dump_binary(ADS_STRUCT *ads, const char *field, struct berval **values)
{
int i, j;
for (i=0; values[i]; i++) {
}
}
-static void dump_guid(const char *field, struct berval **values)
+static void dump_guid(ADS_STRUCT *ads, const char *field, struct berval **values)
{
int i;
- UUID_FLAT guid;
for (i=0; values[i]; i++) {
+
+ UUID_FLAT guid;
+ struct GUID tmp;
+
memcpy(guid.info, values[i]->bv_val, sizeof(guid.info));
- printf("%s: %s\n", field,
- smb_uuid_string_static(smb_uuid_unpack_static(guid)));
+ smb_uuid_unpack(guid, &tmp);
+ printf("%s: %s\n", field, smb_uuid_string(talloc_tos(), tmp));
}
}
/*
dump a sid result from ldap
*/
-static void dump_sid(const char *field, struct berval **values)
+static void dump_sid(ADS_STRUCT *ads, const char *field, struct berval **values)
{
int i;
for (i=0; values[i]; i++) {
DOM_SID sid;
+ fstring tmp;
sid_parse(values[i]->bv_val, values[i]->bv_len, &sid);
- printf("%s: %s\n", field, sid_string_static(&sid));
+ printf("%s: %s\n", field, sid_to_fstring(tmp, &sid));
}
}
/*
dump ntSecurityDescriptor
*/
-static void dump_sd(const char *filed, struct berval **values)
+static void dump_sd(ADS_STRUCT *ads, const char *filed, struct berval **values)
{
- prs_struct ps;
-
- SEC_DESC *psd = 0;
- TALLOC_CTX *ctx = 0;
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct security_descriptor *psd;
+ NTSTATUS status;
- if (!(ctx = talloc_init("sec_io_desc")))
+ status = unmarshall_sec_desc(talloc_tos(), (uint8 *)values[0]->bv_val,
+ values[0]->bv_len, &psd);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("unmarshall_sec_desc failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(frame);
return;
+ }
- /* prepare data */
- prs_init(&ps, values[0]->bv_len, ctx, UNMARSHALL);
- prs_copy_data_in(&ps, values[0]->bv_val, values[0]->bv_len);
- prs_set_offset(&ps,0);
-
- /* parse secdesc */
- if (!sec_io_desc("sd", &psd, &ps, 1)) {
- prs_mem_free(&ps);
- talloc_destroy(ctx);
- return;
+ if (psd) {
+ ads_disp_sd(ads, talloc_tos(), psd);
}
- if (psd) ads_disp_sd(psd);
- prs_mem_free(&ps);
- talloc_destroy(ctx);
+ TALLOC_FREE(frame);
}
/*
used for debugging
*/
-static BOOL ads_dump_field(char *field, void **values, void *data_area)
+static bool ads_dump_field(ADS_STRUCT *ads, char *field, void **values, void *data_area)
{
const struct {
const char *name;
- BOOL string;
- void (*handler)(const char *, struct berval **);
+ bool string;
+ void (*handler)(ADS_STRUCT *, const char *, struct berval **);
} handlers[] = {
{"objectGUID", False, dump_guid},
{"netbootGUID", False, dump_guid},
{"tokenGroups", False, dump_sid},
{"tokenGroupsNoGCAcceptable", False, dump_sid},
{"tokengroupsGlobalandUniversal", False, dump_sid},
+ {"mS-DS-CreatorSID", False, dump_sid},
+ {"msExchMailboxGuid", False, dump_guid},
{NULL, True, NULL}
};
int i;
if (StrCaseCmp(handlers[i].name, field) == 0) {
if (!values) /* first time, indicate string or not */
return handlers[i].string;
- handlers[i].handler(field, (struct berval **) values);
+ handlers[i].handler(ads, field, (struct berval **) values);
break;
}
}
* @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)(ADS_STRUCT *, char *, void **, void *),
+ void *data_area)
{
- void *msg;
+ LDAPMessage *msg;
TALLOC_CTX *ctx;
if (!(ctx = talloc_init("ads_process_results")))
char *utf8_field;
BerElement *b;
- for (utf8_field=ldap_first_attribute(ads->ld,
+ for (utf8_field=ldap_first_attribute(ads->ldap.ld,
(LDAPMessage *)msg,&b);
utf8_field;
- utf8_field=ldap_next_attribute(ads->ld,
+ utf8_field=ldap_next_attribute(ads->ldap.ld,
(LDAPMessage *)msg,b)) {
struct berval **ber_vals;
char **str_vals, **utf8_vals;
char *field;
- BOOL string;
+ bool string;
pull_utf8_talloc(ctx, &field, utf8_field);
- string = fn(field, NULL, data_area);
+ string = fn(ads, field, NULL, data_area);
if (string) {
- utf8_vals = ldap_get_values(ads->ld,
+ utf8_vals = ldap_get_values(ads->ldap.ld,
(LDAPMessage *)msg, field);
str_vals = ads_pull_strvals(ctx,
(const char **) utf8_vals);
- fn(field, (void **) str_vals, data_area);
+ fn(ads, field, (void **) str_vals, data_area);
ldap_value_free(utf8_vals);
} else {
- ber_vals = ldap_get_values_len(ads->ld,
+ ber_vals = ldap_get_values_len(ads->ldap.ld,
(LDAPMessage *)msg, field);
- fn(field, (void **) ber_vals, data_area);
+ fn(ads, field, (void **) ber_vals, data_area);
ldap_value_free_len(ber_vals);
}
}
ber_free(b, 0);
talloc_free_children(ctx);
- fn(NULL, NULL, data_area); /* completed an entry */
+ fn(ads, NULL, NULL, data_area); /* completed an entry */
}
talloc_destroy(ctx);
**/
int ads_count_replies(ADS_STRUCT *ads, void *res)
{
- return ldap_count_entries(ads->ld, (LDAPMessage *)res);
+ return ldap_count_entries(ads->ldap.ld, (LDAPMessage *)res);
}
/**
* @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->ldap.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->ldap.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;
char *ux_string;
size_t rc;
- values = ldap_get_values(ads->ld, msg, field);
+ values = ldap_get_values(ads->ldap.ld, msg, field);
if (!values)
return 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;
int i;
- values = ldap_get_values(ads->ld, msg, field);
+ values = ldap_get_values(ads->ldap.ld, msg, field);
if (!values)
return 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;
expected_range_attrib = talloc_asprintf(mem_ctx, "%s;Range=", field);
/* look for Range result */
- for (attr = ldap_first_attribute(ads->ld, (LDAPMessage *)msg, &ptr);
+ for (attr = ldap_first_attribute(ads->ldap.ld, (LDAPMessage *)msg, &ptr);
attr;
- attr = ldap_next_attribute(ads->ld, (LDAPMessage *)msg, ptr)) {
+ attr = ldap_next_attribute(ads->ldap.ld, (LDAPMessage *)msg, ptr)) {
/* we ignore the fact that this is utf8, as all attributes are ascii... */
if (strnequal(attr, expected_range_attrib, strlen(expected_range_attrib))) {
range_attr = 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;
- values = ldap_get_values(ads->ld, msg, field);
+ values = ldap_get_values(ads->ldap.ld, msg, field);
if (!values)
return False;
if (!values[0]) {
* @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;
- values = ldap_get_values(ads->ld, msg, "objectGUID");
+ values = ldap_get_values(ads->ldap.ld, msg, "objectGUID");
if (!values)
return False;
* @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;
+ bool ret = False;
- values = ldap_get_values_len(ads->ld, msg, field);
+ values = ldap_get_values_len(ads->ldap.ld, msg, field);
if (!values)
return 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;
+ bool ret;
int count, i;
- values = ldap_get_values_len(ads->ld, msg, field);
+ values = ldap_get_values_len(ads->ldap.ld, msg, field);
if (!values)
return 0;
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;
for (i=0; values[i]; i++) {
ret = sid_parse(values[i]->bv_val, values[i]->bv_len, &(*sids)[count]);
if (ret) {
- fstring sid;
- DEBUG(10, ("pulling SID: %s\n", sid_to_string(sid, &(*sids)[count])));
+ DEBUG(10, ("pulling SID: %s\n",
+ sid_string_dbg(&(*sids)[count])));
count++;
}
}
* @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;
+ bool ret = true;
- values = ldap_get_values_len(ads->ld, msg, field);
+ values = ldap_get_values_len(ads->ldap.ld, msg, field);
- if (!values) return False;
+ if (!values) return false;
if (values[0]) {
- 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);
+ NTSTATUS status;
+ status = unmarshall_sec_desc(mem_ctx,
+ (uint8 *)values[0]->bv_val,
+ values[0]->bv_len, sd);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("unmarshall_sec_desc failed: %s\n",
+ nt_errstr(status)));
+ ret = false;
+ }
}
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;
/* establish a new ldap tcp session if necessary */
- if ( !ads->ld ) {
+ if ( !ads->ldap.ld ) {
if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup,
ads->server.ldap_server )) == NULL )
{
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;
/* establish a new ldap tcp session if necessary */
- if ( !ads->ld ) {
+ if ( !ads->ldap.ld ) {
if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup,
ads->server.ldap_server )) == NULL )
{
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;
- const char *parent, *config_context, *filter;
- const char *attrs[] = { "configurationNamingContext", NULL };
+ LDAPMessage *res;
+ const char *parent, *filter;
+ char *config_context = NULL;
char *dn;
/* shortcut a query */
return ads_site_dn(ads, mem_ctx, site_dn);
}
- status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+ status = ads_config_path(ads, mem_ctx, &config_context);
if (!ADS_ERR_OK(status)) {
return status;
}
- config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
- if (config_context == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
-
filter = talloc_asprintf(mem_ctx, "(cn=%s)", computer_name);
if (filter == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
- status = ads_do_search(ads, config_context, LDAP_SCOPE_SUBTREE, filter, NULL, &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);
+ return ADS_ERROR(LDAP_NO_MEMORY);
}
ads_memfree(ads, dn);
* @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;
- const char *config_context, *base;
- const char *attrs[] = { "configurationNamingContext", NULL };
- const char *attrs2[] = { "uPNSuffixes", NULL };
+ LDAPMessage *res;
+ const char *base;
+ char *config_context = NULL;
+ const char *attrs[] = { "uPNSuffixes", NULL };
- status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+ status = ads_config_path(ads, mem_ctx, &config_context);
if (!ADS_ERR_OK(status)) {
return status;
}
- config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
- if (config_context == NULL) {
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
-
base = talloc_asprintf(mem_ctx, "cn=Partitions,%s", config_context);
if (base == NULL) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
- status = ads_search_dn(ads, &res, base, attrs2);
+ status = ads_search_dn(ads, &res, base, attrs);
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);
}
- 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;
}
+/**
+ * get the joinable ous for a domain
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param ous Pointer to an array of ous
+ * @param num_ous Pointer to the number of ous
+ * @return status of search
+ **/
+ADS_STATUS ads_get_joinable_ous(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ char ***ous,
+ size_t *num_ous)
+{
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ LDAPMessage *msg = NULL;
+ const char *attrs[] = { "dn", NULL };
+ int count = 0;
+
+ status = ads_search(ads, &res,
+ "(|(objectClass=domain)(objectclass=organizationalUnit))",
+ 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_NO_RESULTS_RETURNED);
+ }
+
+ for (msg = ads_first_entry(ads, res); msg;
+ msg = ads_next_entry(ads, msg)) {
+
+ char *dn = NULL;
+
+ dn = ads_get_dn(ads, msg);
+ if (!dn) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if (!add_string_to_array(mem_ctx, dn,
+ (const char ***)ous,
+ (int *)num_ous)) {
+ ads_memfree(ads, dn);
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ ads_memfree(ads, dn);
+ }
+
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+
/**
* 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,
+bool ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
+ 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
}
break;
case ADS_EXTENDED_DN_HEX_STRING: {
- pstring buf;
+ fstring buf;
size_t buf_len;
- buf_len = strhex_to_str(buf, strlen(p), p);
+ buf_len = strhex_to_str(buf, sizeof(buf), p, strlen(p));
if (buf_len == 0) {
return False;
}
* @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()));
ADS_STATUS status;
int count = 0;
char *name = NULL;
-
- status = ads_find_machine_acct(ads, (void **)(void *)&res, global_myname());
+
+ status = ads_find_machine_acct(ads, &res, machine_name);
if (!ADS_ERR_OK(status)) {
DEBUG(0,("ads_get_upn: Failed to find account for %s\n",
global_myname()));
goto out;
}
-
+
if ( (count = ads_count_replies(ads, res)) != 1 ) {
DEBUG(1,("ads_get_upn: %d entries returned!\n", count));
goto out;
}
-
+
if ( (name = ads_pull_string(ads, ctx, res, "userPrincipalName")) == NULL ) {
DEBUG(2,("ads_get_upn: No userPrincipalName attribute!\n"));
}
out:
ads_msgfree(ads, res);
-
+
return name;
}
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->ldap.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);
+}
+
+/**
+ * Find a sAMAccoutName in LDAP
+ * @param ads connection to ads server
+ * @param mem_ctx TALLOC_CTX for allocating sid array
+ * @param samaccountname to search
+ * @param uac_ret uint32 pointer userAccountControl attribute value
+ * @param dn_ret pointer to dn
+ * @return status of token query
+ **/
+ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *samaccountname,
+ uint32 *uac_ret,
+ const char **dn_ret)
+{
+ ADS_STATUS status;
+ const char *attrs[] = { "userAccountControl", NULL };
+ const char *filter;
+ LDAPMessage *res = NULL;
+ char *dn = NULL;
+ uint32 uac = 0;
+
+ filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))",
+ samaccountname);
+ if (filter == NULL) {
+ status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto out;
+ }
+
+ status = ads_do_search_all(ads, ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ filter, attrs, &res);
+
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ status = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ goto out;
+ }
+
+ dn = ads_get_dn(ads, res);
+ if (dn == NULL) {
+ status = ADS_ERROR(LDAP_NO_MEMORY);
+ goto out;
+ }
+
+ if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+ status = ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
+ goto out;
+ }
+
+ if (uac_ret) {
+ *uac_ret = uac;
+ }
+
+ if (dn_ret) {
+ *dn_ret = talloc_strdup(mem_ctx, dn);
+ if (!*dn_ret) {
+ status = ADS_ERROR(LDAP_NO_MEMORY);
+ goto out;
+ }
+ }
+ out:
+ ads_memfree(ads, dn);
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+/**
+ * find our configuration path
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param config_path Pointer to the config path
+ * @return status of search
+ **/
+ADS_STATUS ads_config_path(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ char **config_path)
+{
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ const char *config_context = NULL;
+ const char *attrs[] = { "configurationNamingContext", NULL };
+
+ status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
+ "(objectclass=*)", attrs, &res);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ config_context = ads_pull_string(ads, mem_ctx, res,
+ "configurationNamingContext");
+ ads_msgfree(ads, res);
+ if (!config_context) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if (config_path) {
+ *config_path = talloc_strdup(mem_ctx, config_context);
+ if (!*config_path) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+ }
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
+
+/**
+ * find the displayName of an extended right
+ * @param ads connection to ads server
+ * @param config_path The config path
+ * @param mem_ctx Pointer to talloc context
+ * @param GUID struct of the rightsGUID
+ * @return status of search
+ **/
+const char *ads_get_extended_right_name_by_guid(ADS_STRUCT *ads,
+ const char *config_path,
+ TALLOC_CTX *mem_ctx,
+ const struct GUID *rights_guid)
+{
+ ADS_STATUS rc;
+ LDAPMessage *res = NULL;
+ char *expr = NULL;
+ const char *attrs[] = { "displayName", NULL };
+ const char *result = NULL;
+ const char *path;
+
+ if (!ads || !mem_ctx || !rights_guid) {
+ goto done;
+ }
+
+ expr = talloc_asprintf(mem_ctx, "(rightsGuid=%s)",
+ smb_uuid_string(mem_ctx, *rights_guid));
+ if (!expr) {
+ goto done;
+ }
+
+ path = talloc_asprintf(mem_ctx, "cn=Extended-Rights,%s", config_path);
+ if (!path) {
+ goto done;
+ }
+
+ rc = ads_do_search_retry(ads, path, LDAP_SCOPE_SUBTREE,
+ expr, attrs, &res);
+ if (!ADS_ERR_OK(rc)) {
+ goto done;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ goto done;
+ }
+
+ result = ads_pull_string(ads, mem_ctx, res, "displayName");
+
+ done:
+ ads_msgfree(ads, res);
+ return result;
+
+}
+
#endif