#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;
-
- char *domain_dn;
-};
-
/**********************************************************************
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 const char** get_userattr_list( int schema_ver )
+const char** get_userattr_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,
const char **attr)
* 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));
/*
(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;
/*
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));
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));
(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);
}
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 );
*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,
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"));
+ 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;
}
- sid_peek_rid(&sid, &rid);
-
add_rid_to_array_unique(mem_ctx, rid, member_rids,
num_members);
}
goto done;
}
- sid_filter = strdup("(&(objectClass=sambaSamAccount)(|");
+ sid_filter = SMB_STRDUP("(&(objectClass=sambaSamAccount)(|");
if (sid_filter == NULL) {
result = NT_STATUS_NO_MEMORY;
goto done;
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 (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 (!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;
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;
-
- 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;
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ int rc;
+ LDAPMod **mods = NULL;
+ fstring value_string;
+ const char *policy_attr = NULL;
- /* No need to free any further, as it is talloc()ed */
-}
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
-/**********************************************************************
- Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
- *********************************************************************/
+ const char *attrs[2];
-static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
- const char *location)
-{
- NTSTATUS nt_status;
- struct ldapsam_privates *ldap_state;
+ DEBUG(10,("ldapsam_set_account_policy\n"));
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
- return nt_status;
+ if (!ldap_state->domain_dn) {
+ return NT_STATUS_INVALID_PARAMETER;
}
- (*pdb_method)->name = "ldapsam";
+ policy_attr = get_account_policy_attr(policy_index);
+ if (policy_attr == NULL) {
+ DEBUG(0,("ldapsam_set_account_policy: invalid policy\n"));
+ return ntstatus;
+ }
- (*pdb_method)->setsampwent = ldapsam_setsampwent;
- (*pdb_method)->endsampwent = ldapsam_endsampwent;
- (*pdb_method)->getsampwent = ldapsam_getsampwent;
- (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
- (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
- (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
- (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
- (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
+ attrs[0] = policy_attr;
+ attrs[1] = NULL;
- (*pdb_method)->getgrsid = ldapsam_getgrsid;
- (*pdb_method)->getgrgid = ldapsam_getgrgid;
- (*pdb_method)->getgrnam = ldapsam_getgrnam;
- (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
- (*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;
+ slprintf(value_string, sizeof(value_string) - 1, "%i", value);
- /* TODO: Setup private data and free */
+ smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
- ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
- if (!ldap_state) {
- DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
- return NT_STATUS_NO_MEMORY;
- }
+ rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn, mods);
- if (!NT_STATUS_IS_OK(nt_status =
- smbldap_init(pdb_context->mem_ctx, location,
- &ldap_state->smbldap_state)));
+ ldap_mods_free(mods, True);
- ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
- if (!ldap_state->domain_name) {
- return NT_STATUS_NO_MEMORY;
+ 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;
}
- (*pdb_method)->private_data = ldap_state;
-
- (*pdb_method)->free_private_data = free_private_data;
+ 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;
}
-/**********************************************************************
- Initialise the 'compat' mode for pdb_ldap
- *********************************************************************/
-
-static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, int policy_index, uint32 *value)
{
- NTSTATUS nt_status;
- struct ldapsam_privates *ldap_state;
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int count;
+ int rc;
+ char **vals = NULL;
+ const char *policy_attr = NULL;
-#ifdef WITH_LDAP_SAMCONFIG
- if (!location) {
- int ldap_port = lp_ldap_port();
-
- /* remap default port if not using SSL (ie clear or TLS) */
- if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
- ldap_port = 389;
- }
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
- location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
- if (!location) {
- return NT_STATUS_NO_MEMORY;
- }
+ const char *attrs[2];
+
+ DEBUG(10,("ldapsam_get_account_policy_from_ldap\n"));
+
+ if (!ldap_state->domain_dn) {
+ return NT_STATUS_INVALID_PARAMETER;
}
-#endif
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
- return nt_status;
+ 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;
}
- (*pdb_method)->name = "ldapsam_compat";
+ attrs[0] = policy_attr;
+ attrs[1] = NULL;
- ldap_state = (*pdb_method)->private_data;
- ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
+ rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
+ LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &result);
- sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
+ 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;
+
+ /* No need to free any further, as it is talloc()ed */
+}
+
+/**********************************************************************
+ Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
+ *********************************************************************/
+
+static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
+ const char *location)
+{
+ NTSTATUS nt_status;
+ struct ldapsam_privates *ldap_state;
+
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+ return nt_status;
+ }
+
+ (*pdb_method)->name = "ldapsam";
+
+ (*pdb_method)->setsampwent = ldapsam_setsampwent;
+ (*pdb_method)->endsampwent = ldapsam_endsampwent;
+ (*pdb_method)->getsampwent = ldapsam_getsampwent;
+ (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
+ (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
+ (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
+ (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
+ (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
+
+ (*pdb_method)->getgrsid = ldapsam_getgrsid;
+ (*pdb_method)->getgrgid = ldapsam_getgrgid;
+ (*pdb_method)->getgrnam = ldapsam_getgrnam;
+ (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
+ (*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 */
+
+ ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
+ if (!ldap_state) {
+ DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status =
+ smbldap_init(pdb_context->mem_ctx, location,
+ &ldap_state->smbldap_state)));
+
+ ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
+ if (!ldap_state->domain_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*pdb_method)->private_data = ldap_state;
+
+ (*pdb_method)->free_private_data = free_private_data;
+
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ Initialise the 'compat' mode for pdb_ldap
+ *********************************************************************/
+
+NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct ldapsam_privates *ldap_state;
+
+#ifdef WITH_LDAP_SAMCONFIG
+ if (!location) {
+ int ldap_port = lp_ldap_port();
+
+ /* remap default port if not using SSL (ie clear or TLS) */
+ if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
+ ldap_port = 389;
+ }
+
+ location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
+ if (!location) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+#endif
+
+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
+ return nt_status;
+ }
+
+ (*pdb_method)->name = "ldapsam_compat";
+
+ ldap_state = (*pdb_method)->private_data;
+ ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
+
+ sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
return NT_STATUS_OK;
}
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;
(*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;
}
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;
}