*/
#include "includes.h"
+#include "lib/ldb/include/includes.h"
#ifdef HAVE_LDAP
#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. */
if (gotalarm != 0)
return LDAP_TIMELIMIT_EXCEEDED;
+ /*
+ * A bug in OpenLDAP means ldap_search_ext_s can return
+ * LDAP_SUCCESS but with a NULL res pointer. Cope with
+ * this. See bug #6279 for details. JRA.
+ */
+
+ if (*res == NULL) {
+ return LDAP_TIMELIMIT_EXCEEDED;
+ }
+
return result;
}
Do client and server sitename match ?
**********************************************/
-BOOL ads_sitename_match(ADS_STRUCT *ads)
+bool ads_sitename_match(ADS_STRUCT *ads)
{
if (ads->config.server_site_name == NULL &&
ads->config.client_site_name == NULL ) {
Is this the closest DC ?
**********************************************/
-BOOL ads_closest_dc(ADS_STRUCT *ads)
+bool ads_closest_dc(ADS_STRUCT *ads)
{
- if (ads->config.flags & ADS_CLOSEST) {
- DEBUG(10,("ads_closest_dc: ADS_CLOSEST flag set\n"));
+ if (ads->config.flags & NBT_SERVER_CLOSEST) {
+ DEBUG(10,("ads_closest_dc: NBT_SERVER_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"));
+ DEBUG(10,("ads_closest_dc: NBT_SERVER_CLOSEST flag not set but sites match\n"));
+ return True;
+ }
+
+ if (ads->config.client_site_name == NULL) {
+ DEBUG(10,("ads_closest_dc: client belongs to no site\n"));
return True;
}
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;
+ struct nbt_cldap_netlogon_5 cldap_reply;
+ TALLOC_CTX *mem_ctx = NULL;
+ bool ret = false;
if (!server || !*server) {
return False;
DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n",
server, ads->server.realm));
+ mem_ctx = talloc_init("ads_try_connect");
+ if (!mem_ctx) {
+ DEBUG(0,("out of memory\n"));
+ return false;
+ }
+
/* this copes with inet_ntoa brokenness */
srv = SMB_STRDUP(server);
ZERO_STRUCT( cldap_reply );
- if ( !ads_cldap_netlogon( srv, ads->server.realm, &cldap_reply ) ) {
+ if ( !ads_cldap_netlogon_5(mem_ctx, srv, ads->server.realm, &cldap_reply ) ) {
DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", srv));
- SAFE_FREE( srv );
- return False;
+ ret = false;
+ goto out;
}
/* Check the CLDAP reply flags */
- if ( !(cldap_reply.flags & ADS_LDAP) ) {
+ if ( !(cldap_reply.server_type & NBT_SERVER_LDAP) ) {
DEBUG(1,("ads_try_connect: %s's CLDAP reply says it is not an LDAP server!\n",
srv));
- SAFE_FREE( srv );
- return False;
+ ret = false;
+ goto out;
}
/* Fill in the ads->config values */
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.flags = cldap_reply.server_type;
+ ads->config.ldap_server_name = SMB_STRDUP(cldap_reply.pdc_dns_name);
+ ads->config.realm = SMB_STRDUP(cldap_reply.dns_domain);
+ strupper_m(ads->config.realm);
ads->config.bind_path = ads_build_dn(ads->config.realm);
- if (*cldap_reply.server_site_name) {
+ if (*cldap_reply.server_site) {
ads->config.server_site_name =
- SMB_STRDUP(cldap_reply.server_site_name);
+ SMB_STRDUP(cldap_reply.server_site);
}
- if (*cldap_reply.client_site_name) {
+ if (*cldap_reply.client_site) {
ads->config.client_site_name =
- SMB_STRDUP(cldap_reply.client_site_name);
+ SMB_STRDUP(cldap_reply.client_site);
}
-
- ads->server.workgroup = SMB_STRDUP(cldap_reply.netbios_domain);
+ ads->server.workgroup = SMB_STRDUP(cldap_reply.domain);
ads->ldap.port = LDAP_PORT;
- ads->ldap.ip = *interpret_addr2(srv);
- SAFE_FREE(srv);
-
+ if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) {
+ DEBUG(1,("ads_try_connect: unable to convert %s "
+ "to an address\n",
+ srv));
+ ret = false;
+ goto out;
+ }
+
/* Store our site name. */
- sitename_store( cldap_reply.domain, cldap_reply.client_site_name );
+ sitename_store( cldap_reply.domain, cldap_reply.client_site);
+ sitename_store( cldap_reply.dns_domain, cldap_reply.client_site);
- return True;
+ ret = true;
+ out:
+ SAFE_FREE(srv);
+ TALLOC_FREE(mem_ctx);
+
+ return ret;
}
/**********************************************************************
static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
{
+ const char *c_domain;
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;
+ const char *domain;
+ bool got_realm = False;
+ bool use_own_domain = False;
char *sitename;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
/* 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;
-
- /* we need to try once with the realm name and fallback to the
+
+ 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 */
-
+
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 ... */
+ }
+
+ 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 ... */
+ }
+
+ if ( use_own_domain ) {
+ c_domain = lp_workgroup();
+ } else {
+ c_domain = ads->server.workgroup;
+ }
+
+ realm = c_realm;
+ domain = c_domain;
+
+ /*
+ * In case of LDAP we use get_dc_name() as that
+ * creates the custom krb5.conf file
+ */
+ if (!(ads->auth.flags & ADS_AUTH_NO_BIND)) {
+ fstring srv_name;
+ struct sockaddr_storage ip_out;
+
+ DEBUG(6,("ads_find_dc: (ldap) looking for %s '%s'\n",
+ (got_realm ? "realm" : "domain"), realm));
+
+ if (get_dc_name(domain, realm, srv_name, &ip_out)) {
+ /*
+ * we call ads_try_connect() to fill in the
+ * ads->config details
+ */
+ if (ads_try_connect(ads, srv_name)) {
+ return NT_STATUS_OK;
+ }
}
+
+ return NT_STATUS_NO_LOGON_SERVERS;
}
-
- pstrcpy( realm, c_realm );
sitename = sitename_fetch(realm);
- again:
-
- DEBUG(6,("ads_find_dc: looking for %s '%s'\n",
+ DEBUG(6,("ads_find_dc: (cldap) looking for %s '%s'\n",
(got_realm ? "realm" : "domain"), realm));
status = get_sorted_dc_list(realm, sitename, &ip_list, &count, got_realm);
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;
continue;
}
}
-
+
if ( ads_try_connect(ads, server) ) {
SAFE_FREE(ip_list);
SAFE_FREE(sitename);
int version = LDAP_VERSION3;
ADS_STATUS status;
NTSTATUS ntstatus;
+ char addr[INET6_ADDRSTRLEN];
ZERO_STRUCT(ads->ldap);
ads->ldap.last_attempt = time(NULL);
/* 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_new("ads LDAP connection memory");
+ ads->ldap.mem_ctx = talloc_init("ads LDAP connection memory");
if (!ads->ldap.mem_ctx) {
- return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto out;
}
/* Otherwise setup the TCP LDAP session */
- if ( (ads->ldap.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)) {
- saf_store( ads->server.workgroup, inet_ntoa(ads->ldap.ip));
- saf_store( ads->server.realm, inet_ntoa(ads->ldap.ip));
+ saf_store( ads->server.workgroup, ads->config.ldap_server_name);
+ saf_store( ads->server.realm, ads->config.ldap_server_name);
}
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->ldap.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->ldap.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;
}
- return ads_sasl_bind(ads);
+ 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 status;
}
/**
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;
}
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;
}
}
/* 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);
}
/* this relies on the way that ldap_add_result_entry() works internally. I hope
that this works on all ldap libs, but I have only tested with openldap */
- for (msg = ads_first_entry(ads, res2); msg; msg = next) {
- next = ads_next_entry(ads, msg);
+ for (msg = ads_first_message(ads, res2); msg; msg = next) {
+ next = ads_next_message(ads, msg);
ldap_add_result_entry((LDAPMessage **)res, msg);
}
/* note that we do not free res2, as the memory is now
**/
ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
int scope, const char *expr, const char **attrs,
- BOOL(*fn)(ADS_STRUCT *, char *, void **, void *),
+ bool (*fn)(ADS_STRUCT *, char *, void **, void *),
void *data_area)
{
struct berval *cookie = 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;
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);
}
/**
**/
ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name,
- const char *org_unit, BOOL *moved)
+ const char *org_unit, bool *moved)
{
ADS_STATUS rc;
int ldap_status;
char *computer_dn = NULL;
char *parent_dn;
char *computer_rdn = NULL;
- BOOL need_move = False;
+ bool need_move = False;
if (asprintf(&filter, "(samAccountName=%s$)", machine_name) == -1) {
rc = ADS_ERROR(LDAP_NO_MEMORY);
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));
}
}
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));
}
}
*/
static void dump_sd(ADS_STRUCT *ads, const char *filed, struct berval **values)
{
- prs_struct ps;
-
- SEC_DESC *psd = 0;
- TALLOC_CTX *ctx = 0;
-
- if (!(ctx = talloc_init("sec_io_desc")))
- return;
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct security_descriptor *psd;
+ NTSTATUS status;
- /* 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);
+ 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;
}
+
if (psd) {
- ads_disp_sd(ads, ctx, psd);
+ ads_disp_sd(ads, talloc_tos(), psd);
}
- prs_mem_free(&ps);
- talloc_destroy(ctx);
+ TALLOC_FREE(frame);
}
/*
used for debugging
*/
-static BOOL ads_dump_field(ADS_STRUCT *ads, 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;
+ bool string;
void (*handler)(ADS_STRUCT *, const char *, struct berval **);
} handlers[] = {
{"objectGUID", False, dump_guid},
{"tokenGroupsNoGCAcceptable", False, dump_sid},
{"tokengroupsGlobalandUniversal", False, dump_sid},
{"mS-DS-CreatorSID", False, dump_sid},
+ {"msExchMailboxGuid", False, dump_guid},
{NULL, True, NULL}
};
int i;
* @param data_area user-defined area to pass to function
**/
void ads_process_results(ADS_STRUCT *ads, LDAPMessage *res,
- BOOL(*fn)(ADS_STRUCT *, char *, void **, void *),
+ bool (*fn)(ADS_STRUCT *, char *, void **, void *),
void *data_area)
{
LDAPMessage *msg;
struct berval **ber_vals;
char **str_vals, **utf8_vals;
char *field;
- BOOL string;
+ bool string;
pull_utf8_talloc(ctx, &field, utf8_field);
string = fn(ads, field, NULL, data_area);
return ldap_next_entry(ads->ldap.ld, res);
}
+/**
+ * pull the first message from a ADS result
+ * @param ads connection to ads server
+ * @param res Results of search
+ * @return first message from result
+ **/
+ LDAPMessage *ads_first_message(ADS_STRUCT *ads, LDAPMessage *res)
+{
+ return ldap_first_message(ads->ldap.ld, res);
+}
+
+/**
+ * pull the next message from a ADS result
+ * @param ads connection to ads server
+ * @param res Results of search
+ * @return next message from result
+ **/
+ LDAPMessage *ads_next_message(ADS_STRUCT *ads, LDAPMessage *res)
+{
+ return ldap_next_message(ads->ldap.ld, res);
+}
+
/**
* pull a single string from a ADS result
* @param ads connection to ads server
char **current_strings,
const char **next_attribute,
size_t *num_strings,
- BOOL *more_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, LDAPMessage *msg, const char *field,
+ 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, LDAPMessage *msg, struct GUID *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, LDAPMessage *msg, const char *field,
+ 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->ldap.ld, msg, field);
LDAPMessage *msg, const char *field, DOM_SID **sids)
{
struct berval **values;
- BOOL ret;
+ bool ret;
int count, i;
values = ldap_get_values_len(ads->ldap.ld, msg, field);
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,
+ bool ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
LDAPMessage *msg, const char *field, SEC_DESC **sd)
{
struct berval **values;
- BOOL ret = False;
+ bool ret = true;
values = ldap_get_values_len(ads->ldap.ld, msg, field);
- if (!values) return False;
+ 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);
+ 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);
if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup,
ads->server.ldap_server )) == NULL )
{
+ status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto done;
}
ads_s->auth.flags = ADS_AUTH_ANON_BIND;
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);
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 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
+ * @return NT_STATUS_OK on success,
+ * NT_INVALID_PARAMETER on error,
+ * NT_STATUS_NOT_FOUND if no SID present
**/
-BOOL ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
- const char *extended_dn,
- enum ads_extended_dn_flags flags,
- DOM_SID *sid)
+ADS_STATUS 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, *dn;
if (!extended_dn) {
- return False;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
/* otherwise extended_dn gets stripped off */
if ((dn = talloc_strdup(mem_ctx, extended_dn)) == NULL) {
- return False;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- /*
+ /*
* ADS_EXTENDED_DN_HEX_STRING:
* <GUID=238e1963cb390f4bb032ba0105525a29>;<SID=010500000000000515000000bb68c8fd6b61b427572eb04556040000>;CN=gd,OU=berlin,OU=suse,DC=ber,DC=suse,DC=de
*
* ADS_EXTENDED_DN_STRING (only with w2k3):
- <GUID=63198e23-39cb-4b0f-b032-ba0105525a29>;<SID=S-1-5-21-4257769659-666132843-1169174103-1110>;CN=gd,OU=berlin,OU=suse,DC=ber,DC=suse,DC=de
+ * <GUID=63198e23-39cb-4b0f-b032-ba0105525a29>;<SID=S-1-5-21-4257769659-666132843-1169174103-1110>;CN=gd,OU=berlin,OU=suse,DC=ber,DC=suse,DC=de
+ *
+ * Object with no SID, such as an Exchange Public Folder
+ * <GUID=28907fb4bdf6854993e7f0a10b504e7c>;CN=public,CN=Microsoft Exchange System Objects,DC=sd2k3ms,DC=west,DC=isilon,DC=com
*/
p = strchr(dn, ';');
if (!p) {
- return False;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
if (strncmp(p, ";<SID=", strlen(";<SID=")) != 0) {
- return False;
+ DEBUG(5,("No SID present in extended dn\n"));
+ return ADS_ERROR_NT(NT_STATUS_NOT_FOUND);
}
p += strlen(";<SID=");
q = strchr(p, '>');
if (!q) {
- return False;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
-
+
*q = '\0';
DEBUG(100,("ads_get_sid_from_extended_dn: sid string is %s\n", p));
switch (flags) {
-
+
case ADS_EXTENDED_DN_STRING:
if (!string_to_sid(sid, p)) {
- return False;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
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;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
if (!sid_parse(buf, buf_len, sid)) {
DEBUG(10,("failed to parse sid\n"));
- return False;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
break;
}
default:
DEBUG(10,("unknown extended dn format\n"));
- return False;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- return True;
+ return ADS_ERROR_NT(NT_STATUS_OK);
}
/**
* @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,
- LDAPMessage *msg,
+ 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;
+ ADS_STATUS rc;
+ size_t dn_count, ret_count = 0;
char **dn_strings;
- if ((dn_strings = ads_pull_strings(ads, mem_ctx, msg, field,
+ if ((dn_strings = ads_pull_strings(ads, mem_ctx, msg, field,
&dn_count)) == NULL) {
return 0;
}
}
for (i=0; i<dn_count; i++) {
-
- if (!ads_get_sid_from_extended_dn(mem_ctx, dn_strings[i],
- flags, &(*sids)[i])) {
- TALLOC_FREE(*sids);
- TALLOC_FREE(dn_strings);
- return 0;
+ rc = ads_get_sid_from_extended_dn(mem_ctx, dn_strings[i],
+ flags, &(*sids)[i]);
+ if (!ADS_ERR_OK(rc)) {
+ if (NT_STATUS_EQUAL(ads_ntstatus(rc),
+ NT_STATUS_NOT_FOUND)) {
+ continue;
+ }
+ else {
+ TALLOC_FREE(*sids);
+ TALLOC_FREE(dn_strings);
+ return 0;
+ }
}
+ ret_count++;
}
TALLOC_FREE(dn_strings);
- return dn_count;
+ return ret_count;
}
/********************************************************************
ADS_STATUS status;
int count = 0;
char *name = NULL;
-
- status = ads_find_machine_acct(ads, &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;
}
filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))",
samaccountname);
if (filter == NULL) {
+ status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto out;
}
}
expr = talloc_asprintf(mem_ctx, "(rightsGuid=%s)",
- smb_uuid_string_static(*rights_guid));
+ smb_uuid_string(mem_ctx, *rights_guid));
if (!expr) {
goto done;
}
}
+/**
+ * verify or build and verify an account ou
+ * @param mem_ctx Pointer to talloc context
+ * @param ads connection to ads server
+ * @param account_ou
+ * @return status of search
+ **/
+
+ADS_STATUS ads_check_ou_dn(TALLOC_CTX *mem_ctx,
+ ADS_STRUCT *ads,
+ const char **account_ou)
+{
+ struct ldb_dn *name_dn = NULL;
+ const char *name = NULL;
+ char *ou_string = NULL;
+
+ name_dn = ldb_dn_explode(mem_ctx, *account_ou);
+ if (name_dn) {
+ return ADS_SUCCESS;
+ }
+
+ ou_string = ads_ou_string(ads, *account_ou);
+ if (!ou_string) {
+ return ADS_ERROR_LDAP(LDAP_INVALID_DN_SYNTAX);
+ }
+
+ name = talloc_asprintf(mem_ctx, "%s,%s", ou_string,
+ ads->config.bind_path);
+ SAFE_FREE(ou_string);
+ if (!name) {
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ name_dn = ldb_dn_explode(mem_ctx, name);
+ if (!name_dn) {
+ return ADS_ERROR_LDAP(LDAP_INVALID_DN_SYNTAX);
+ }
+
+ *account_ou = talloc_strdup(mem_ctx, name);
+ if (!*account_ou) {
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+
+ return ADS_SUCCESS;
+}
+
#endif