#include "smbldap.h"
-struct ldapsam_privates {
- struct smbldap_state *smbldap_state;
-
- /* Former statics */
- LDAPMessage *result;
- LDAPMessage *entry;
- int index;
-
- const char *domain_name;
- DOM_SID domain_sid;
-
- /* configuration items */
- int schema_ver;
-};
-
/**********************************************************************
Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
**********************************************************************/
-static void private_data_free_fn(void **result)
+void private_data_free_fn(void **result)
{
ldap_msgfree(*result);
*result = NULL;
Return the list of attribute names given a user schema version.
**********************************************************************/
-static char** get_userattr_list( int schema_ver )
+const char** get_userattr_list( int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
Return the list of attribute names to delete given a user schema version.
**************************************************************************/
-static char** get_userattr_delete_list( int schema_ver )
+static const char** get_userattr_delete_list( int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
return objclass_filter;
}
+/*****************************************************************
+ Scan a sequence number off OpenLDAP's syncrepl contextCSN
+******************************************************************/
+
+static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_num)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ LDAPMessage *msg = NULL;
+ LDAPMessage *entry = NULL;
+ TALLOC_CTX *mem_ctx;
+ char **values = NULL;
+ int rc, num_result, num_values, rid;
+ pstring suffix;
+ fstring tok;
+ const char *p;
+ const char **attrs;
+
+ /* Unfortunatly there is no proper way to detect syncrepl-support in
+ * smbldap_connect_system(). The syncrepl OIDs are submitted for publication
+ * but do not show up in the root-DSE yet. Neither we can query the
+ * subschema-context for the syncProviderSubentry or syncConsumerSubentry
+ * objectclass. Currently we require lp_ldap_suffix() to show up as
+ * namingContext. - Guenther
+ */
+
+ if (!lp_parm_bool(-1, "ldapsam", "syncrepl_seqnum", False)) {
+ return ntstatus;
+ }
+
+ if (!seq_num) {
+ DEBUG(3,("ldapsam_get_seq_num: no sequence_number\n"));
+ return ntstatus;
+ }
+
+ if (!smbldap_has_naming_context(ldap_state->smbldap_state, lp_ldap_suffix())) {
+ DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s "
+ "as top-level namingContext\n", lp_ldap_suffix()));
+ return ntstatus;
+ }
+
+ mem_ctx = talloc_init("ldapsam_get_seq_num");
+
+ if (mem_ctx == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ attrs = TALLOC_ARRAY(mem_ctx, const char *, 2);
+
+ /* if we got a syncrepl-rid (up to three digits long) we speak with a consumer */
+ rid = lp_parm_int(-1, "ldapsam", "syncrepl_rid", -1);
+ if (rid > 0) {
+
+ /* consumer syncreplCookie: */
+ /* csn=20050126161620Z#0000001#00#00000 */
+ attrs[0] = talloc_strdup(mem_ctx, "syncreplCookie");
+ attrs[1] = NULL;
+ pstr_sprintf( suffix, "cn=syncrepl%d,%s", rid, lp_ldap_suffix());
+
+ } else {
+
+ /* provider contextCSN */
+ /* 20050126161620Z#000009#00#000000 */
+ attrs[0] = talloc_strdup(mem_ctx, "contextCSN");
+ attrs[1] = NULL;
+ pstr_sprintf( suffix, "cn=ldapsync,%s", lp_ldap_suffix());
+
+ }
+
+ rc = smbldap_search(ldap_state->smbldap_state, suffix,
+ LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
+
+ if (rc != LDAP_SUCCESS) {
+
+ char *ld_error = NULL;
+ ldap_get_option(ldap_state->smbldap_state->ldap_struct,
+ LDAP_OPT_ERROR_STRING, &ld_error);
+ DEBUG(0,("ldapsam_get_seq_num: Failed search for suffix: %s, error: %s (%s)\n",
+ suffix,ldap_err2string(rc), ld_error?ld_error:"unknown"));
+ SAFE_FREE(ld_error);
+ goto done;
+ }
+
+ num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg);
+ if (num_result != 1) {
+ DEBUG(3,("ldapsam_get_seq_num: Expected one entry, got %d\n", num_result));
+ goto done;
+ }
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg);
+ if (entry == NULL) {
+ DEBUG(3,("ldapsam_get_seq_num: Could not retrieve entry\n"));
+ goto done;
+ }
+
+ values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, attrs[0]);
+ if (values == NULL) {
+ DEBUG(3,("ldapsam_get_seq_num: no values\n"));
+ goto done;
+ }
+
+ num_values = ldap_count_values(values);
+ if (num_values == 0) {
+ DEBUG(3,("ldapsam_get_seq_num: not a single value\n"));
+ goto done;
+ }
+
+ p = values[0];
+ if (!next_token(&p, tok, "#", sizeof(tok))) {
+ DEBUG(0,("ldapsam_get_seq_num: failed to parse sequence number\n"));
+ goto done;
+ }
+
+ p = tok;
+ if (!strncmp(p, "csn=", strlen("csn=")))
+ p += strlen("csn=");
+
+ DEBUG(10,("ldapsam_get_seq_num: got %s: %s\n", attrs[0], p));
+
+ *seq_num = generalized_to_unix_time(p);
+
+ /* very basic sanity check */
+ if (*seq_num <= 0) {
+ DEBUG(3,("ldapsam_get_seq_num: invalid sequence number: %d\n",
+ (int)*seq_num));
+ goto done;
+ }
+
+ ntstatus = NT_STATUS_OK;
+
+ done:
+ if (values != NULL)
+ ldap_value_free(values);
+ if (msg != NULL)
+ ldap_msgfree(msg);
+ if (mem_ctx)
+ talloc_destroy(mem_ctx);
+
+ return ntstatus;
+}
+
/*******************************************************************
Run the search by name.
******************************************************************/
-static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state,
+int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
const char *user,
- LDAPMessage ** result, char **attr)
+ LDAPMessage ** result,
+ const char **attr)
{
pstring filter;
char *escape_user = escape_ldap_string_alloc(user);
* in the filter expression, replace %u with the real name
* so in ldap filter, %u MUST exist :-)
*/
- pstr_sprintf(filter, "(&%s%s)", lp_ldap_filter(),
+ pstr_sprintf(filter, "(&%s%s)", "(uid=%u)",
get_objclass_filter(ldap_state->schema_ver));
/*
static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
uint32 rid, LDAPMessage ** result,
- char **attr)
+ const char **attr)
{
pstring filter;
int rc;
static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
const DOM_SID *sid, LDAPMessage ** result,
- char **attr)
+ const char **attr)
{
pstring filter;
int rc;
static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
LDAPMessage *result,
const char *objectclass,
- char **attrs)
+ const char **attrs)
{
int rc;
LDAPMessage *entry = NULL;
for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
name != NULL;
name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
- char **attrib;
+ const char **attrib;
/* We are only allowed to delete the attributes that
really exist. */
(Based on init_sam_from_buffer in pdb_tdb.c)
*********************************************************************/
-static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
+static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
SAM_ACCOUNT * sampass,
LDAPMessage * entry)
{
uint32 user_rid;
uint8 smblmpwd[LM_HASH_LEN],
smbntpwd[NT_HASH_LEN];
+ BOOL use_samba_attrs = True;
uint16 acct_ctrl = 0,
logon_divs;
uint16 bad_password_count = 0,
uint8 hours[MAX_HOURS_LEN];
pstring temp;
LOGIN_CACHE *cache_entry = NULL;
- int pwHistLen;
+ uint32 pwHistLen;
+ pstring tmpstring;
/*
* do a little initialization
if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive))
{
- pdb_set_dir_drive( sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
- PDB_DEFAULT );
+ pdb_set_dir_drive( sampass, lp_logon_drive(), PDB_DEFAULT );
} else {
pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
}
talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
PDB_DEFAULT );
} else {
- pdb_set_homedir(sampass, homedir, PDB_SET);
+ pstrcpy( tmpstring, homedir );
+ standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
+ pdb_set_homedir(sampass, tmpstring, PDB_SET);
}
if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
PDB_DEFAULT );
} else {
- pdb_set_logon_script(sampass, logon_script, PDB_SET);
+ pstrcpy( tmpstring, logon_script );
+ standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
+ pdb_set_logon_script(sampass, tmpstring, PDB_SET);
}
if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
talloc_sub_basic( sampass->mem_ctx, username, lp_logon_path()),
PDB_DEFAULT );
} else {
- pdb_set_profile_path(sampass, profile_path, PDB_SET);
+ pstrcpy( tmpstring, profile_path );
+ standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
+ pdb_set_profile_path(sampass, tmpstring, PDB_SET);
}
if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
hours_len = 21;
memset(hours, 0xff, hours_len);
- if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) {
- /* leave as default */
- } else {
- pdb_gethexpwd(temp, smblmpwd);
- memset((char *)temp, '\0', strlen(temp)+1);
- if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
- return False;
- ZERO_STRUCT(smblmpwd);
+ if (ldap_state->is_nds_ldap) {
+ char *user_dn;
+ size_t pwd_len;
+ char clear_text_pw[512];
+
+ /* Make call to Novell eDirectory ldap extension to get clear text password.
+ NOTE: This will only work if we have an SSL connection to eDirectory. */
+ user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ if (user_dn != NULL) {
+ DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn));
+
+ pwd_len = sizeof(clear_text_pw);
+ if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
+ nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
+ if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smblmpwd);
+ if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smbntpwd);
+ use_samba_attrs = False;
+ }
+ } else {
+ DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
+ }
}
- if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) {
- /* leave as default */
- } else {
- pdb_gethexpwd(temp, smbntpwd);
- memset((char *)temp, '\0', strlen(temp)+1);
- if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
- return False;
- ZERO_STRUCT(smbntpwd);
+ if (use_samba_attrs) {
+ if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) {
+ /* leave as default */
+ } else {
+ pdb_gethexpwd(temp, smblmpwd);
+ memset((char *)temp, '\0', strlen(temp)+1);
+ if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smblmpwd);
+ }
+
+ if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) {
+ /* leave as default */
+ } else {
+ pdb_gethexpwd(temp, smbntpwd);
+ memset((char *)temp, '\0', strlen(temp)+1);
+ if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smbntpwd);
+ }
}
- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ pwHistLen = 0;
+
+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
if (pwHistLen > 0){
uint8 *pwhist = NULL;
int i;
}
if (need_update(sampass, PDB_PWHISTORY)) {
- int pwHistLen = 0;
- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ uint32 pwHistLen = 0;
+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
if (pwHistLen == 0) {
/* Remove any password history from the LDAP store. */
memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */
temp[64] = '\0';
} else {
- int i, currHistLen = 0;
+ int i;
+ uint32 currHistLen = 0;
const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen);
if (pwhist != NULL) {
/* We can only store (sizeof(pstring)-1)/64 password history entries. */
}
if (need_update(sampass, PDB_HOURS)) {
- const char *hours = pdb_get_hours(sampass);
+ const uint8 *hours = pdb_get_hours(sampass);
if (hours) {
pdb_sethexhours(temp, hours);
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct,
uint16 badcount = pdb_get_bad_password_count(sampass);
time_t badtime = pdb_get_bad_password_time(sampass);
uint32 pol;
- account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &pol);
+ pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol);
DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
(unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
Connect to LDAP server for password enumeration.
*********************************************************************/
-static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
+static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
int rc;
- pstring filter;
- char **attr_list;
+ pstring filter, suffix;
+ const char **attr_list;
+ BOOL machine_mask = False, user_mask = False;
- pstr_sprintf( filter, "(&%s%s)", lp_ldap_filter(),
+ pstr_sprintf( filter, "(&%s%s)", "(uid=%u)",
get_objclass_filter(ldap_state->schema_ver));
all_string_sub(filter, "%u", "*", sizeof(pstring));
+ machine_mask = ((acb_mask != 0) && (acb_mask & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)));
+ user_mask = ((acb_mask != 0) && (acb_mask & ACB_NORMAL));
+
+ if (machine_mask) {
+ pstrcpy(suffix, lp_ldap_machine_suffix());
+ } else if (user_mask) {
+ pstrcpy(suffix, lp_ldap_user_suffix());
+ } else {
+ pstrcpy(suffix, lp_ldap_suffix());
+ }
+
+ DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n",
+ acb_mask, suffix));
+
attr_list = get_userattr_list(ldap_state->schema_ver);
- rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
- attr_list, &ldap_state->result);
+ rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter,
+ attr_list, 0, &ldap_state->result);
free_attr_list( attr_list );
if (rc != LDAP_SUCCESS) {
DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
- DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", lp_ldap_suffix(), filter));
+ DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", suffix, filter));
ldap_msgfree(ldap_state->result);
ldap_state->result = NULL;
return NT_STATUS_UNSUCCESSFUL;
}
- DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
- ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
- ldap_state->result)));
+ DEBUG(2, ("ldapsam_setsampwent: %d entries in the base %s\n",
+ ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
+ ldap_state->result), suffix));
ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
ldap_state->result);
return NT_STATUS_OK;
}
-static void append_attr(char ***attr_list, const char *new_attr)
+static void append_attr(const char ***attr_list, const char *new_attr)
{
int i;
;
}
- (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), char *, i+2);
+ (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), const char *, i+2);
SMB_ASSERT((*attr_list) != NULL);
(*attr_list)[i] = SMB_STRDUP(new_attr);
(*attr_list)[i+1] = NULL;
LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
int count;
- char ** attr_list;
+ const char ** attr_list;
int rc;
attr_list = get_userattr_list( ldap_state->schema_ver );
const DOM_SID *sid, LDAPMessage **result)
{
int rc = -1;
- char ** attr_list;
+ const char ** attr_list;
uint32 rid;
switch ( ldap_state->schema_ver ) {
(pdb_get_plaintext_passwd(newpwd)!=NULL)) {
BerElement *ber;
struct berval *bv;
- char *retoid;
- struct berval *retdata;
+ char *retoid = NULL;
+ struct berval *retdata = NULL;
char *utf8_password;
char *utf8_dn;
- if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
- DEBUG(2, ("ldap password change requested, but LDAP "
- "server does not support it -- ignoring\n"));
- return NT_STATUS_OK;
+ if (!ldap_state->is_nds_ldap) {
+ if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
+ DEBUG(2, ("ldap password change requested, but LDAP "
+ "server does not support it -- ignoring\n"));
+ return NT_STATUS_OK;
+ }
}
if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
SAFE_FREE(utf8_password);
ber_free(ber, 1);
- if ((rc = smbldap_extended_operation(ldap_state->smbldap_state,
- LDAP_EXOP_MODIFY_PASSWD,
- bv, NULL, NULL, &retoid,
- &retdata)) != LDAP_SUCCESS) {
+ if (!ldap_state->is_nds_ldap) {
+ rc = smbldap_extended_operation(ldap_state->smbldap_state,
+ LDAP_EXOP_MODIFY_PASSWD,
+ bv, NULL, NULL, &retoid,
+ &retdata);
+ } else {
+ rc = pdb_nds_set_password(ldap_state->smbldap_state, dn,
+ pdb_get_plaintext_passwd(newpwd));
+ }
+ if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
#ifdef DEBUG_PASSWORD
DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
#endif
- ber_bvfree(retdata);
- ber_memfree(retoid);
+ if (retdata)
+ ber_bvfree(retdata);
+ if (retoid)
+ ber_memfree(retoid);
}
ber_bvfree(bv);
}
int rc;
LDAPMessage *result = NULL;
NTSTATUS ret;
- char **attr_list;
+ const char **attr_list;
fstring objclass;
if (!sam_acct) {
LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
- char **attr_list;
+ const char **attr_list;
result = pdb_get_backend_private_data(newpwd, my_methods);
if (!result) {
LDAPMod **mods = NULL;
int ldap_op = LDAP_MOD_REPLACE;
uint32 num_result;
- char **attr_list;
+ const char **attr_list;
char *escape_user;
const char *username = pdb_get_username(newpwd);
const DOM_SID *sid = pdb_get_user_sid(newpwd);
we need to return the samba attributes here */
escape_user = escape_ldap_string_alloc( username );
- pstrcpy( filter, lp_ldap_filter() );
+ pstrcpy( filter, "(uid=%u)" );
all_string_sub( filter, "%u", escape_user, sizeof(filter) );
SAFE_FREE( escape_user );
{
int scope = LDAP_SCOPE_SUBTREE;
int rc;
- char **attr_list;
+ const char **attr_list;
attr_list = get_attr_list(groupmap_attr_list);
rc = smbldap_search(ldap_state->smbldap_state,
return ldapsam_getgroup(methods, filter, map);
}
+static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
+ uint32 rid, uint32 **rids, int *num)
+{
+ int i;
+
+ for (i=0; i<*num; i++) {
+ if ((*rids)[i] == rid)
+ return;
+ }
+
+ *rids = TALLOC_REALLOC_ARRAY(mem_ctx, *rids, uint32, *num+1);
+
+ if (*rids == NULL)
+ return;
+
+ (*rids)[*num] = rid;
+ *num += 1;
+}
+
+static BOOL ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
+ LDAPMessage *entry,
+ const DOM_SID *domain_sid,
+ uint32 *rid)
+{
+ fstring str;
+ DOM_SID sid;
+
+ if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID",
+ str, sizeof(str)-1)) {
+ DEBUG(10, ("Could not find sambaSID attribute\n"));
+ return False;
+ }
+
+ if (!string_to_sid(&sid, str)) {
+ DEBUG(10, ("Could not convert string %s to sid\n", str));
+ return False;
+ }
+
+ if (sid_compare_domain(&sid, domain_sid) != 0) {
+ DEBUG(10, ("SID %s is not in expected domain %s\n",
+ str, sid_string_static(domain_sid)));
+ return False;
+ }
+
+ if (!sid_peek_rid(&sid, rid)) {
+ DEBUG(10, ("Could not peek into RID\n"));
+ return False;
+ }
+
+ return True;
+}
+
+static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *group,
+ uint32 **member_rids,
+ int *num_members)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ struct smbldap_state *conn = ldap_state->smbldap_state;
+ pstring filter;
+ int rc, count;
+ LDAPMessage *msg = NULL;
+ LDAPMessage *entry;
+ char **values = NULL;
+ char **memberuid;
+ char *sid_filter = NULL;
+ char *tmp;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
+ return pdb_default_enum_group_members(methods, mem_ctx, group,
+ member_rids,
+ num_members);
+
+ *member_rids = NULL;
+ *num_members = 0;
+
+ pstr_sprintf(filter,
+ "(&(objectClass=sambaSamAccount)"
+ "(sambaPrimaryGroupSid=%s))",
+ sid_string_static(group));
+
+ {
+ const char *attrs[] = { "sambaSID", NULL };
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0,
+ &msg);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(conn->ldap_struct, entry))
+ {
+ uint32 rid;
+
+ if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
+ entry,
+ get_global_sam_sid(),
+ &rid)) {
+ DEBUG(2, ("Could not find sid from ldap entry\n"));
+ continue;
+ }
+
+ add_rid_to_array_unique(mem_ctx, rid, member_rids,
+ num_members);
+ }
+
+ if (msg != NULL)
+ ldap_msgfree(msg);
+
+ pstr_sprintf(filter,
+ "(&(objectClass=sambaGroupMapping)"
+ "(objectClass=posixGroup)"
+ "(sambaSID=%s))",
+ sid_string_static(group));
+
+ {
+ const char *attrs[] = { "memberUid", NULL };
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0,
+ &msg);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ count = ldap_count_entries(conn->ldap_struct, msg);
+
+ if (count > 1) {
+ DEBUG(1, ("Found more than one groupmap entry for %s\n",
+ sid_string_static(group)));
+ goto done;
+ }
+
+ if (count == 0) {
+ result = NT_STATUS_OK;
+ goto done;
+ }
+
+ entry = ldap_first_entry(conn->ldap_struct, msg);
+ if (entry == NULL)
+ goto done;
+
+ values = ldap_get_values(conn->ldap_struct, msg, "memberUid");
+ if (values == NULL) {
+ result = NT_STATUS_OK;
+ goto done;
+ }
+
+ sid_filter = SMB_STRDUP("(&(objectClass=sambaSamAccount)(|");
+ if (sid_filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (memberuid = values; *memberuid != NULL; memberuid += 1) {
+ tmp = sid_filter;
+ asprintf(&sid_filter, "%s(uid=%s)", tmp, *memberuid);
+ free(tmp);
+ if (sid_filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+
+ tmp = sid_filter;
+ asprintf(&sid_filter, "%s))", sid_filter);
+ free(tmp);
+ if (sid_filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ {
+ const char *attrs[] = { "sambaSID", NULL };
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, sid_filter, attrs, 0,
+ &msg);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(conn->ldap_struct, entry))
+ {
+ fstring str;
+ DOM_SID sid;
+ uint32 rid;
+
+ if (!smbldap_get_single_attribute(conn->ldap_struct,
+ entry, "sambaSID",
+ str, sizeof(str)-1))
+ continue;
+
+ if (!string_to_sid(&sid, str))
+ goto done;
+
+ if (!sid_check_is_in_our_domain(&sid)) {
+ DEBUG(1, ("Inconsistent SAM -- group member uid not "
+ "in our domain\n"));
+ continue;
+ }
+
+ sid_peek_rid(&sid, &rid);
+
+ add_rid_to_array_unique(mem_ctx, rid, member_rids,
+ num_members);
+ }
+
+ result = NT_STATUS_OK;
+
+ done:
+ SAFE_FREE(sid_filter);
+
+ if (values != NULL)
+ ldap_value_free(values);
+
+ if (msg != NULL)
+ ldap_msgfree(msg);
+
+ return result;
+}
+
static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
const char *username,
gid_t primary_gid,
(struct ldapsam_privates *)methods->private_data;
struct smbldap_state *conn = ldap_state->smbldap_state;
pstring filter;
- char *attrs[] = { "gidNumber", "sambaSID", NULL };
+ const char *attrs[] = { "gidNumber", "sambaSID", NULL };
char *escape_name;
int rc;
LDAPMessage *msg = NULL;
LDAPMessage *entry;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
int num_sids, num_gids;
- extern DOM_SID global_sid_NULL;
if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
return pdb_default_enum_group_memberships(methods, username,
/* We need to add the primary group as the first gid/sid */
- add_gid_to_array_unique(primary_gid, gids, &num_gids);
+ add_gid_to_array_unique(NULL, primary_gid, gids, &num_gids);
/* This sid will be replaced later */
- add_sid_to_array_unique(&global_sid_NULL, sids, &num_sids);
+ add_sid_to_array_unique(NULL, &global_sid_NULL, sids, &num_sids);
for (entry = ldap_first_entry(conn->ldap_struct, msg);
entry != NULL;
if (!smbldap_get_single_attribute(conn->ldap_struct,
entry, "sambaSID",
str, sizeof(str)-1))
- goto done;
+ continue;
if (!string_to_sid(&sid, str))
goto done;
if (!smbldap_get_single_attribute(conn->ldap_struct,
entry, "gidNumber",
str, sizeof(str)-1))
- goto done;
+ continue;
gid = strtoul(str, &end, 10);
if (gid == primary_gid) {
sid_copy(&(*sids)[0], &sid);
} else {
- add_gid_to_array_unique(gid, gids, &num_gids);
- add_sid_to_array_unique(&sid, sids, &num_sids);
+ add_gid_to_array_unique(NULL, gid, gids, &num_gids);
+ add_sid_to_array_unique(NULL, &sid, sids, &num_sids);
}
}
if (sid_compare(&global_sid_NULL, &(*sids)[0]) == 0) {
- DEBUG(3, ("primary group not found\n"));
+ DEBUG(3, ("primary group of [%s] not found\n", username));
goto done;
}
pstring suffix;
pstring filter;
- char **attr_list;
+ const char **attr_list;
ldap_msgfree(result);
LDAPMessage *result = NULL;
int rc;
NTSTATUS ret;
- char **attr_list;
+ const char **attr_list;
sid_to_string(sidstring, &sid);
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
fstring filter;
int rc;
- char **attr_list;
+ const char **attr_list;
pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
attr_list = get_attr_list( groupmap_attr_list );
if (!string_to_sid(&member, values[i]))
continue;
- add_sid_to_array(&member, members, num_members);
+ add_sid_to_array(NULL, &member, members, num_members);
}
ldap_value_free(values);
}
static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
const DOM_SID *members,
int num_members,
- DOM_SID **aliases, int *num_aliases)
+ uint32 **alias_rids,
+ int *num_alias_rids)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
LDAP *ldap_struct;
- char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
+ const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
int i;
int rc;
char *filter;
- TALLOC_CTX *mem_ctx;
-
- mem_ctx = talloc_init("ldapsam_alias_memberships");
-
- if (mem_ctx == NULL)
- return NT_STATUS_NO_MEMORY;
/* This query could be further optimized by adding a
(&(sambaSID=<domain-sid>*)) so that only those aliases that are
rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
- talloc_destroy(mem_ctx);
-
if (rc != LDAP_SUCCESS)
return NT_STATUS_UNSUCCESSFUL;
- *aliases = NULL;
- *num_aliases = 0;
-
ldap_struct = ldap_state->smbldap_state->ldap_struct;
for (entry = ldap_first_entry(ldap_struct, result);
{
fstring sid_str;
DOM_SID sid;
+ uint32 rid;
if (!smbldap_get_single_attribute(ldap_struct, entry,
LDAP_ATTRIBUTE_SID,
if (!string_to_sid(&sid, sid_str))
continue;
- add_sid_to_array_unique(&sid, aliases, num_aliases);
+ if (!sid_peek_check_rid(domain_sid, &sid, &rid))
+ continue;
+
+ add_rid_to_array_unique(mem_ctx, rid, alias_rids,
+ num_alias_rids);
}
ldap_msgfree(result);
return NT_STATUS_OK;
}
-/**********************************************************************
- Housekeeping
- *********************************************************************/
-
-static void free_private_data(void **vp)
+static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value)
{
- struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
-
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ int rc;
+ LDAPMod **mods = NULL;
+ fstring value_string;
+ const char *policy_attr = NULL;
+
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+
+ const char *attrs[2];
+
+ DEBUG(10,("ldapsam_set_account_policy\n"));
+
+ if (!ldap_state->domain_dn) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ policy_attr = get_account_policy_attr(policy_index);
+ if (policy_attr == NULL) {
+ DEBUG(0,("ldapsam_set_account_policy: invalid policy\n"));
+ return ntstatus;
+ }
+
+ attrs[0] = policy_attr;
+ attrs[1] = NULL;
+
+ slprintf(value_string, sizeof(value_string) - 1, "%i", value);
+
+ smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
+
+ rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn, mods);
+
+ ldap_mods_free(mods, True);
+
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ ldap_get_option(ldap_state->smbldap_state->ldap_struct,
+ LDAP_OPT_ERROR_STRING,&ld_error);
+
+ DEBUG(0, ("ldapsam_set_account_policy: Could not set account policy "
+ "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
+ ld_error?ld_error:"unknown"));
+ SAFE_FREE(ld_error);
+ return ntstatus;
+ }
+
+ if (!cache_account_policy_set(policy_index, value)) {
+ DEBUG(0,("ldapsam_set_account_policy: failed to update local tdb cache\n"));
+ return ntstatus;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, int policy_index, uint32 *value)
+{
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int count;
+ int rc;
+ char **vals = NULL;
+ const char *policy_attr = NULL;
+
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+
+ const char *attrs[2];
+
+ DEBUG(10,("ldapsam_get_account_policy_from_ldap\n"));
+
+ if (!ldap_state->domain_dn) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ policy_attr = get_account_policy_attr(policy_index);
+ if (!policy_attr) {
+ DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid policy index: %d\n", policy_index));
+ return ntstatus;
+ }
+
+ attrs[0] = policy_attr;
+ attrs[1] = NULL;
+
+ rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
+ LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &result);
+
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ ldap_get_option(ldap_state->smbldap_state->ldap_struct,
+ LDAP_OPT_ERROR_STRING,&ld_error);
+
+ DEBUG(0, ("ldapsam_get_account_policy_from_ldap: Could not set account policy "
+ "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
+ ld_error?ld_error:"unknown"));
+ SAFE_FREE(ld_error);
+ return ntstatus;
+ }
+
+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ if (count < 1) {
+ goto out;
+ }
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ if (entry == NULL) {
+ goto out;
+ }
+
+ vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, policy_attr);
+ if (vals == NULL) {
+ goto out;
+ }
+
+ *value = (uint32)atol(vals[0]);
+
+ ntstatus = NT_STATUS_OK;
+
+out:
+ if (vals)
+ ldap_value_free(vals);
+ ldap_msgfree(result);
+
+ return ntstatus;
+}
+
+/* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache
+
+ - if there is a valid cache entry, return that
+ - if there is an LDAP entry, update cache and return
+ - otherwise set to default, update cache and return
+
+ Guenther
+*/
+static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
+{
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+
+ if (cache_account_policy_get(policy_index, value)) {
+ DEBUG(11,("ldapsam_get_account_policy: got valid value from cache\n"));
+ return NT_STATUS_OK;
+ }
+
+ ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index, value);
+ if (NT_STATUS_IS_OK(ntstatus)) {
+ goto update_cache;
+ }
+
+ DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from ldap, returning default.\n"));
+
+#if 0
+ /* should we automagically migrate old tdb value here ? */
+ if (account_policy_get(policy_index, value))
+ goto update_ldap;
+
+ DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying default\n", policy_index));
+#endif
+
+ if (!account_policy_get_default(policy_index, value)) {
+ return ntstatus;
+ }
+
+/* update_ldap: */
+
+ ntstatus = ldapsam_set_account_policy(methods, policy_index, *value);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ return ntstatus;
+ }
+
+ update_cache:
+
+ if (!cache_account_policy_set(policy_index, *value)) {
+ DEBUG(0,("ldapsam_get_account_policy: failed to update local tdb as a cache\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids,
+ uint32 *rids,
+ const char ***names,
+ uint32 **attrs)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct;
+ LDAPMessage *msg = NULL;
+ LDAPMessage *entry;
+ char *allsids = NULL;
+ char *tmp;
+ int i, rc, num_mapped;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
+ return pdb_default_lookup_rids(methods, mem_ctx, domain_sid,
+ num_rids, rids, names, attrs);
+
+ if (!sid_equal(domain_sid, get_global_sam_sid())) {
+ /* TODO: Sooner or later we need to look up BUILTIN rids as
+ * well. -- vl */
+ goto done;
+ }
+
+ (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
+ (*attrs) = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
+
+ if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL)))
+ return NT_STATUS_NO_MEMORY;
+
+ for (i=0; i<num_rids; i++)
+ (*attrs)[i] = SID_NAME_UNKNOWN;
+
+ allsids = SMB_STRDUP("");
+ if (allsids == NULL) return NT_STATUS_NO_MEMORY;
+
+ for (i=0; i<num_rids; i++) {
+ DOM_SID sid;
+ sid_copy(&sid, domain_sid);
+ sid_append_rid(&sid, rids[i]);
+ tmp = allsids;
+ asprintf(&allsids, "%s(sambaSid=%s)", allsids,
+ sid_string_static(&sid));
+ if (allsids == NULL) return NT_STATUS_NO_MEMORY;
+ free(tmp);
+ }
+
+ /* First look for users */
+
+ {
+ char *filter;
+ const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
+
+ asprintf(&filter, ("(&(objectClass=sambaSamAccount)(|%s))"),
+ allsids);
+ if (filter == NULL) return NT_STATUS_NO_MEMORY;
+
+ rc = smbldap_search(ldap_state->smbldap_state,
+ lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
+ &msg);
+
+ SAFE_FREE(filter);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ num_mapped = 0;
+
+ for (entry = ldap_first_entry(ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(ldap_struct, entry))
+ {
+ uint32 rid;
+ int rid_index;
+ fstring str;
+
+ if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
+ get_global_sam_sid(),
+ &rid)) {
+ DEBUG(2, ("Could not find sid from ldap entry\n"));
+ continue;
+ }
+
+ if (!smbldap_get_single_attribute(ldap_struct, entry,
+ "uid", str, sizeof(str)-1)) {
+ DEBUG(2, ("Could not retrieve uid attribute\n"));
+ continue;
+ }
+
+ for (rid_index = 0; rid_index < num_rids; rid_index++) {
+ if (rid == rids[rid_index])
+ break;
+ }
+
+ if (rid_index == num_rids) {
+ DEBUG(2, ("Got a RID not asked for: %d\n", rid));
+ continue;
+ }
+
+ (*attrs)[rid_index] = SID_NAME_USER;
+ (*names)[rid_index] = talloc_strdup(mem_ctx, str);
+ if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+
+ num_mapped += 1;
+ }
+
+ if (num_mapped == num_rids) {
+ /* No need to look for groups anymore -- we're done */
+ result = NT_STATUS_OK;
+ goto done;
+ }
+
+ /* Same game for groups */
+
+ {
+ char *filter;
+ const char *ldap_attrs[] = { "cn", "sambaSid", NULL };
+
+ asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"),
+ allsids);
+ if (filter == NULL) return NT_STATUS_NO_MEMORY;
+
+ rc = smbldap_search(ldap_state->smbldap_state,
+ lp_ldap_group_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
+ &msg);
+
+ SAFE_FREE(filter);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ for (entry = ldap_first_entry(ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(ldap_struct, entry))
+ {
+ uint32 rid;
+ int rid_index;
+ fstring str;
+
+ if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
+ get_global_sam_sid(),
+ &rid)) {
+ DEBUG(2, ("Could not find sid from ldap entry\n"));
+ continue;
+ }
+
+ if (!smbldap_get_single_attribute(ldap_struct, entry,
+ "cn", str, sizeof(str)-1)) {
+ DEBUG(2, ("Could not retrieve cn attribute\n"));
+ continue;
+ }
+
+ for (rid_index = 0; rid_index < num_rids; rid_index++) {
+ if (rid == rids[rid_index])
+ break;
+ }
+
+ if (rid_index == num_rids) {
+ DEBUG(2, ("Got a RID not asked for: %d\n", rid));
+ continue;
+ }
+
+ (*attrs)[rid_index] = SID_NAME_DOM_GRP;
+ (*names)[rid_index] = talloc_strdup(mem_ctx, str);
+ if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+ num_mapped += 1;
+ }
+
+ result = NT_STATUS_NONE_MAPPED;
+
+ if (num_mapped > 0)
+ result = (num_mapped == num_rids) ?
+ NT_STATUS_OK : STATUS_SOME_UNMAPPED;
+ done:
+ SAFE_FREE(allsids);
+
+ if (msg != NULL)
+ ldap_msgfree(msg);
+
+ return result;
+}
+
+char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
+{
+ char *filter = NULL;
+ char *escaped = NULL;
+ char *result = NULL;
+
+ asprintf(&filter, "(&%s(objectclass=sambaSamAccount))",
+ "(uid=%u)");
+ if (filter == NULL) goto done;
+
+ escaped = escape_ldap_string_alloc(username);
+ if (escaped == NULL) goto done;
+
+ filter = realloc_string_sub(filter, "%u", username);
+ result = talloc_strdup(mem_ctx, filter);
+
+ done:
+ SAFE_FREE(filter);
+ SAFE_FREE(escaped);
+
+ return result;
+}
+
+const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
+{
+ int i, num = 0;
+ va_list ap;
+ const char **result;
+
+ va_start(ap, mem_ctx);
+ while (va_arg(ap, const char *) != NULL)
+ num += 1;
+ va_end(ap);
+
+ result = TALLOC_ARRAY(mem_ctx, const char *, num+1);
+
+ va_start(ap, mem_ctx);
+ for (i=0; i<num; i++)
+ result[i] = talloc_strdup(mem_ctx, va_arg(ap, const char*));
+ va_end(ap);
+
+ result[num] = NULL;
+ return result;
+}
+
+struct ldap_search_state {
+ struct smbldap_state *connection;
+
+ uint16 acct_flags;
+ uint16 group_type;
+
+ const char *base;
+ int scope;
+ const char *filter;
+ const char **attrs;
+ int attrsonly;
+ void *pagedresults_cookie;
+
+ LDAPMessage *entries, *current_entry;
+ BOOL (*ldap2displayentry)(struct ldap_search_state *state,
+ TALLOC_CTX *mem_ctx,
+ LDAP *ld, LDAPMessage *entry,
+ struct samr_displayentry *result);
+};
+
+static BOOL ldapsam_search_firstpage(struct pdb_search *search)
+{
+ struct ldap_search_state *state = search->private_data;
+ LDAP *ld;
+ int rc = LDAP_OPERATIONS_ERROR;
+
+ state->entries = NULL;
+
+ if (state->connection->paged_results) {
+ rc = smbldap_search_paged(state->connection, state->base,
+ state->scope, state->filter,
+ state->attrs, state->attrsonly,
+ lp_ldap_page_size(), &state->entries,
+ &state->pagedresults_cookie);
+ }
+
+ if ((rc != LDAP_SUCCESS) || (state->entries == NULL)) {
+
+ if (state->entries != NULL) {
+ /* Left over from unsuccessful paged attempt */
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ rc = smbldap_search(state->connection, state->base,
+ state->scope, state->filter, state->attrs,
+ state->attrsonly, &state->entries);
+
+ if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
+ return False;
+
+ /* Ok, the server was lying. It told us it could do paged
+ * searches when it could not. */
+ state->connection->paged_results = False;
+ }
+
+ ld = state->connection->ldap_struct;
+ if ( ld == NULL) {
+ DEBUG(5, ("Don't have an LDAP connection right after a "
+ "search\n"));
+ return False;
+ }
+ state->current_entry = ldap_first_entry(ld, state->entries);
+
+ if (state->current_entry == NULL) {
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_search_nextpage(struct pdb_search *search)
+{
+ struct ldap_search_state *state = search->private_data;
+ LDAP *ld = state->connection->ldap_struct;
+ int rc;
+
+ if (!state->connection->paged_results) {
+ /* There is no next page when there are no paged results */
+ return False;
+ }
+
+ rc = smbldap_search_paged(state->connection, state->base,
+ state->scope, state->filter, state->attrs,
+ state->attrsonly, lp_ldap_page_size(),
+ &state->entries,
+ &state->pagedresults_cookie);
+
+ if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
+ return False;
+
+ state->current_entry = ldap_first_entry(ld, state->entries);
+
+ if (state->current_entry == NULL) {
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_search_next_entry(struct pdb_search *search,
+ struct samr_displayentry *entry)
+{
+ struct ldap_search_state *state = search->private_data;
+ LDAP *ld = state->connection->ldap_struct;
+ BOOL result;
+
+ retry:
+ if ((state->entries == NULL) && (state->pagedresults_cookie == NULL))
+ return False;
+
+ if ((state->entries == NULL) &&
+ !ldapsam_search_nextpage(search))
+ return False;
+
+ result = state->ldap2displayentry(state, search->mem_ctx, ld,
+ state->current_entry, entry);
+
+ if (!result) {
+ char *dn;
+ dn = ldap_get_dn(ld, state->current_entry);
+ DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
+ if (dn != NULL) ldap_memfree(dn);
+ }
+
+ state->current_entry = ldap_next_entry(ld, state->current_entry);
+
+ if (state->current_entry == NULL) {
+ ldap_msgfree(state->entries);
+ state->entries = NULL;
+ }
+
+ if (!result) goto retry;
+
+ return True;
+}
+
+static void ldapsam_search_end(struct pdb_search *search)
+{
+ struct ldap_search_state *state = search->private_data;
+ int rc;
+
+ if (state->pagedresults_cookie == NULL)
+ return;
+
+ if (state->entries != NULL)
+ ldap_msgfree(state->entries);
+
+ state->entries = NULL;
+ state->current_entry = NULL;
+
+ if (!state->connection->paged_results)
+ return;
+
+ /* Tell the LDAP server we're not interested in the rest anymore. */
+
+ rc = smbldap_search_paged(state->connection, state->base, state->scope,
+ state->filter, state->attrs,
+ state->attrsonly, 0, &state->entries,
+ &state->pagedresults_cookie);
+
+ if (rc != LDAP_SUCCESS)
+ DEBUG(5, ("Could not end search properly\n"));
+
+ return;
+}
+
+static BOOL ldapuser2displayentry(struct ldap_search_state *state,
+ TALLOC_CTX *mem_ctx,
+ LDAP *ld, LDAPMessage *entry,
+ struct samr_displayentry *result)
+{
+ char **vals;
+ DOM_SID sid;
+ uint16 acct_flags;
+
+ vals = ldap_get_values(ld, entry, "sambaAcctFlags");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"sambaAcctFlags\" not found\n"));
+ return False;
+ }
+ acct_flags = pdb_decode_acct_ctrl(vals[0]);
+ ldap_value_free(vals);
+
+ if ((state->acct_flags != 0) &&
+ ((state->acct_flags & acct_flags) == 0))
+ return False;
+
+ result->acct_flags = acct_flags;
+ result->account_name = "";
+ result->fullname = "";
+ result->description = "";
+
+ vals = ldap_get_values(ld, entry, "uid");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"uid\" not found\n"));
+ return False;
+ }
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
+ ldap_value_free(vals);
+
+ vals = ldap_get_values(ld, entry, "displayName");
+ if ((vals == NULL) || (vals[0] == NULL))
+ DEBUG(8, ("\"displayName\" not found\n"));
+ else
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->fullname),
+ vals[0]);
+ ldap_value_free(vals);
+
+ vals = ldap_get_values(ld, entry, "description");
+ if ((vals == NULL) || (vals[0] == NULL))
+ DEBUG(8, ("\"description\" not found\n"));
+ else
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->description),
+ vals[0]);
+ ldap_value_free(vals);
+
+ if ((result->account_name == NULL) ||
+ (result->fullname == NULL) ||
+ (result->description == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ vals = ldap_get_values(ld, entry, "sambaSid");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(0, ("\"objectSid\" not found\n"));
+ return False;
+ }
+
+ if (!string_to_sid(&sid, vals[0])) {
+ DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
+ ldap_value_free(vals);
+ return False;
+ }
+ ldap_value_free(vals);
+
+ if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
+ DEBUG(0, ("sid %s does not belong to our domain\n", sid_string_static(&sid)));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL ldapsam_search_users(struct pdb_methods *methods,
+ struct pdb_search *search,
+ uint16 acct_flags)
+{
+ struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldap_search_state *state;
+
+ state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
+ if (state == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ state->connection = ldap_state->smbldap_state;
+
+ if ((acct_flags != 0) && ((acct_flags & ACB_NORMAL) != 0))
+ state->base = lp_ldap_user_suffix();
+ else if ((acct_flags != 0) &&
+ ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))
+ state->base = lp_ldap_machine_suffix();
+ else
+ state->base = lp_ldap_suffix();
+
+ state->acct_flags = acct_flags;
+ state->base = talloc_strdup(search->mem_ctx, state->base);
+ state->scope = LDAP_SCOPE_SUBTREE;
+ state->filter = get_ldap_filter(search->mem_ctx, "*");
+ state->attrs = talloc_attrs(search->mem_ctx, "uid", "sambaSid",
+ "displayName", "description",
+ "sambaAcctFlags", NULL);
+ state->attrsonly = 0;
+ state->pagedresults_cookie = NULL;
+ state->entries = NULL;
+ state->ldap2displayentry = ldapuser2displayentry;
+
+ if ((state->filter == NULL) || (state->attrs == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ search->private_data = state;
+ search->next_entry = ldapsam_search_next_entry;
+ search->search_end = ldapsam_search_end;
+
+ return ldapsam_search_firstpage(search);
+}
+
+static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
+ TALLOC_CTX *mem_ctx,
+ LDAP *ld, LDAPMessage *entry,
+ struct samr_displayentry *result)
+{
+ char **vals;
+ DOM_SID sid;
+ uint16 group_type;
+
+ result->account_name = "";
+ result->fullname = "";
+ result->description = "";
+
+
+ vals = ldap_get_values(ld, entry, "sambaGroupType");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"sambaGroupType\" not found\n"));
+ return False;
+ }
+
+ group_type = atoi(vals[0]);
+
+ if ((state->group_type != 0) &&
+ ((state->group_type != group_type))) {
+ return False;
+ }
+
+ /* display name is the NT group name */
+
+ vals = ldap_get_values(ld, entry, "displayName");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(8, ("\"displayName\" not found\n"));
+
+ /* fallback to the 'cn' attribute */
+ vals = ldap_get_values(ld, entry, "cn");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"cn\" not found\n"));
+ return False;
+ }
+ pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+ }
+ else {
+ pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+ }
+
+ ldap_value_free(vals);
+
+ vals = ldap_get_values(ld, entry, "description");
+ if ((vals == NULL) || (vals[0] == NULL))
+ DEBUG(8, ("\"description\" not found\n"));
+ else
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->description),
+ vals[0]);
+ ldap_value_free(vals);
+
+ if ((result->account_name == NULL) ||
+ (result->fullname == NULL) ||
+ (result->description == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ vals = ldap_get_values(ld, entry, "sambaSid");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(0, ("\"objectSid\" not found\n"));
+ return False;
+ }
+
+ if (!string_to_sid(&sid, vals[0])) {
+ DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
+ return False;
+ }
+
+ ldap_value_free(vals);
+
+ switch (group_type) {
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_ALIAS:
+
+ if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
+ DEBUG(0, ("%s is not in our domain\n", sid_string_static(&sid)));
+ return False;
+ }
+ break;
+
+ case SID_NAME_WKN_GRP:
+
+ if (!sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid)) {
+
+ DEBUG(0, ("%s is not in builtin sid\n", sid_string_static(&sid)));
+ return False;
+ }
+ break;
+
+ default:
+ DEBUG(0,("unkown group type: %d\n", group_type));
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
+ struct pdb_search *search,
+ enum SID_NAME_USE type)
+{
+ struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldap_search_state *state;
+
+ state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
+ if (state == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ state->connection = ldap_state->smbldap_state;
+
+ state->base = talloc_strdup(search->mem_ctx, lp_ldap_group_suffix());
+ state->connection = ldap_state->smbldap_state;
+ state->scope = LDAP_SCOPE_SUBTREE;
+ state->filter = talloc_asprintf(search->mem_ctx,
+ "(&(objectclass=sambaGroupMapping)"
+ "(sambaGroupType=%d))", type);
+ state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
+ "displayName", "description", "sambaGroupType", NULL);
+ state->attrsonly = 0;
+ state->pagedresults_cookie = NULL;
+ state->entries = NULL;
+ state->group_type = type;
+ state->ldap2displayentry = ldapgroup2displayentry;
+
+ if ((state->filter == NULL) || (state->attrs == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+
+ search->private_data = state;
+ search->next_entry = ldapsam_search_next_entry;
+ search->search_end = ldapsam_search_end;
+
+ return ldapsam_search_firstpage(search);
+}
+
+static BOOL ldapsam_search_groups(struct pdb_methods *methods,
+ struct pdb_search *search)
+{
+ return ldapsam_search_grouptype(methods, search, SID_NAME_DOM_GRP);
+}
+
+static BOOL ldapsam_search_aliases(struct pdb_methods *methods,
+ struct pdb_search *search,
+ const DOM_SID *sid)
+{
+ if (sid_check_is_domain(sid))
+ return ldapsam_search_grouptype(methods, search,
+ SID_NAME_ALIAS);
+
+ if (sid_check_is_builtin(sid))
+ return ldapsam_search_grouptype(methods, search,
+ SID_NAME_WKN_GRP);
+
+ DEBUG(5, ("Don't know SID %s\n", sid_string_static(sid)));
+ return False;
+}
+
+/**********************************************************************
+ Housekeeping
+ *********************************************************************/
+
+static void free_private_data(void **vp)
+{
+ struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
+
smbldap_free_struct(&(*ldap_state)->smbldap_state);
if ((*ldap_state)->result != NULL) {
ldap_msgfree((*ldap_state)->result);
(*ldap_state)->result = NULL;
}
+ if ((*ldap_state)->domain_dn != NULL) {
+ SAFE_FREE((*ldap_state)->domain_dn);
+ }
*ldap_state = NULL;
(*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
(*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
(*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
+ (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
(*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
+ (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
+
+ (*pdb_method)->get_account_policy = ldapsam_get_account_policy;
+ (*pdb_method)->set_account_policy = ldapsam_set_account_policy;
+
+ (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
/* TODO: Setup private data and free */
Initialise the 'compat' mode for pdb_ldap
*********************************************************************/
-static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
Initialise the normal mode for pdb_ldap
*********************************************************************/
-static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
DOM_SID ldap_domain_sid;
DOM_SID secrets_domain_sid;
pstring domain_sid_string;
+ char *dn;
if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
return nt_status;
(*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
(*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
(*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
+ (*pdb_method)->search_users = ldapsam_search_users;
+ (*pdb_method)->search_groups = ldapsam_search_groups;
+ (*pdb_method)->search_aliases = ldapsam_search_aliases;
ldap_state = (*pdb_method)->private_data;
ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
return NT_STATUS_UNSUCCESSFUL;
}
+ dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ if (!dn) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ldap_state->domain_dn = smb_xstrdup(dn);
+ ldap_memfree(dn);
+
if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
domain_sid_string)) {
if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
return nt_status;
+ /* Let pdb_nds register backends */
+ pdb_nds_init();
+
return NT_STATUS_OK;
}