diff options
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/pdb_interface.c | 300 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 288 | ||||
-rw-r--r-- | source3/passdb/util_sam_sid.c | 13 |
3 files changed, 599 insertions, 2 deletions
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 06097d3557..a3b2706c35 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -452,6 +452,156 @@ static NTSTATUS context_enum_group_mapping(struct pdb_context *context, num_entries, unix_only); } +static NTSTATUS context_find_alias(struct pdb_context *context, + const char *name, DOM_SID *sid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->find_alias(context->pdb_methods, + name, sid); +} + +static NTSTATUS context_create_alias(struct pdb_context *context, + const char *name, uint32 *rid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->create_alias(context->pdb_methods, + name, rid); +} + +static NTSTATUS context_delete_alias(struct pdb_context *context, + const DOM_SID *sid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->delete_alias(context->pdb_methods, sid); +} + +static NTSTATUS context_enum_aliases(struct pdb_context *context, + const DOM_SID *sid, + uint32 start_idx, uint32 max_entries, + uint32 *num_aliases, + struct acct_info **info) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->enum_aliases(context->pdb_methods, + sid, start_idx, max_entries, + num_aliases, info); +} + +static NTSTATUS context_get_aliasinfo(struct pdb_context *context, + const DOM_SID *sid, + struct acct_info *info) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->get_aliasinfo(context->pdb_methods, + sid, info); +} + +static NTSTATUS context_set_aliasinfo(struct pdb_context *context, + const DOM_SID *sid, + struct acct_info *info) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->set_aliasinfo(context->pdb_methods, + sid, info); +} + +static NTSTATUS context_add_aliasmem(struct pdb_context *context, + const DOM_SID *alias, + const DOM_SID *member) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->add_aliasmem(context->pdb_methods, + alias, member); +} + +static NTSTATUS context_del_aliasmem(struct pdb_context *context, + const DOM_SID *alias, + const DOM_SID *member) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->del_aliasmem(context->pdb_methods, + alias, member); +} + +static NTSTATUS context_enum_aliasmem(struct pdb_context *context, + const DOM_SID *alias, DOM_SID **members, + int *num) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->enum_aliasmem(context->pdb_methods, + alias, members, num); +} + +static NTSTATUS context_enum_alias_memberships(struct pdb_context *context, + const DOM_SID *sid, + DOM_SID **aliases, int *num) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods-> + enum_alias_memberships(context->pdb_methods, sid, aliases, + num); +} + /****************************************************************** Free and cleanup a pdb context, any associated data and anything that the attached modules might have associated. @@ -568,6 +718,17 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry; (*context)->pdb_enum_group_mapping = context_enum_group_mapping; + (*context)->pdb_find_alias = context_find_alias; + (*context)->pdb_create_alias = context_create_alias; + (*context)->pdb_delete_alias = context_delete_alias; + (*context)->pdb_enum_aliases = context_enum_aliases; + (*context)->pdb_get_aliasinfo = context_get_aliasinfo; + (*context)->pdb_set_aliasinfo = context_set_aliasinfo; + (*context)->pdb_add_aliasmem = context_add_aliasmem; + (*context)->pdb_del_aliasmem = context_del_aliasmem; + (*context)->pdb_enum_aliasmem = context_enum_aliasmem; + (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships; + (*context)->free_fn = free_pdb_context; return NT_STATUS_OK; @@ -850,6 +1011,135 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, rmap, num_entries, unix_only)); } +BOOL pdb_find_alias(const char *name, DOM_SID *sid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context->pdb_find_alias(pdb_context, + name, sid)); +} + +BOOL pdb_create_alias(const char *name, uint32 *rid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context->pdb_create_alias(pdb_context, + name, rid)); +} + +BOOL pdb_delete_alias(const DOM_SID *sid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context->pdb_delete_alias(pdb_context, + sid)); + +} + +BOOL pdb_enum_aliases(const DOM_SID *sid, uint32 start_idx, uint32 max_entries, + uint32 *num_aliases, struct acct_info **info) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context->pdb_enum_aliases(pdb_context, sid, + start_idx, + max_entries, + num_aliases, + info)); +} + +BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context->pdb_get_aliasinfo(pdb_context, sid, + info)); +} + +BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context->pdb_set_aliasinfo(pdb_context, sid, + info)); +} + +BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_add_aliasmem(pdb_context, alias, member)); +} + +BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_del_aliasmem(pdb_context, alias, member)); +} + +BOOL pdb_enum_aliasmem(const DOM_SID *alias, + DOM_SID **members, int *num_members) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_enum_aliasmem(pdb_context, alias, + members, num_members)); +} + +BOOL pdb_enum_alias_memberships(const DOM_SID *sid, + DOM_SID **aliases, int *num) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_enum_alias_memberships(pdb_context, sid, + aliases, num)); +} + /*************************************************************** Initialize the static context (at smbd startup etc). @@ -933,6 +1223,16 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry; (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry; (*methods)->enum_group_mapping = pdb_default_enum_group_mapping; + (*methods)->find_alias = pdb_default_find_alias; + (*methods)->create_alias = pdb_default_create_alias; + (*methods)->delete_alias = pdb_default_delete_alias; + (*methods)->enum_aliases = pdb_default_enum_aliases; + (*methods)->get_aliasinfo = pdb_default_get_aliasinfo; + (*methods)->set_aliasinfo = pdb_default_set_aliasinfo; + (*methods)->add_aliasmem = pdb_default_add_aliasmem; + (*methods)->del_aliasmem = pdb_default_del_aliasmem; + (*methods)->enum_aliasmem = pdb_default_enum_aliasmem; + (*methods)->enum_alias_memberships = pdb_default_alias_memberships; return NT_STATUS_OK; } diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 307d187f66..15635a034c 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -1989,8 +1989,8 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state, { pstring filter; - pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", - LDAP_OBJ_POSIXGROUP, + pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))", + LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), (unsigned long)gid); @@ -2032,6 +2032,37 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if ( count == 0 ) { + /* There's no posixGroup account, let's try to find an + * appropriate idmap entry for aliases */ + + pstring suffix; + pstring filter; + char **attr_list; + + ldap_msgfree(result); + + pstrcpy( suffix, lp_ldap_idmap_suffix() ); + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))", + LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER, + map->gid); + + attr_list = get_attr_list( sidmap_attr_list ); + rc = smbldap_search(ldap_state->smbldap_state, suffix, + LDAP_SCOPE_SUBTREE, filter, attr_list, + 0, &result); + + free_attr_list(attr_list); + + if (rc != LDAP_SUCCESS) { + DEBUG(3,("Failure looking up entry (%s)\n", + ldap_err2string(rc) )); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + } + + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); + if ( count == 0 ) { ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -2306,6 +2337,254 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, return NT_STATUS_OK; } +static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods, + const DOM_SID *alias, + const DOM_SID *member, + int modop) +{ + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + char *dn; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + int count; + LDAPMod **mods = NULL; + int rc; + + pstring filter; + + pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))", + LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY, + get_attr_key2string(groupmap_attr_list, + LDAP_ATTR_GROUP_SID), + sid_string_static(alias)); + + if (ldapsam_search_one_group(ldap_state, filter, + &result) != LDAP_SUCCESS) + return NT_STATUS_NO_SUCH_ALIAS; + + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, + result); + + if (count < 1) { + DEBUG(4, ("ldapsam_add_aliasmem: Did not find alias\n")); + ldap_msgfree(result); + return NT_STATUS_NO_SUCH_ALIAS; + } + + if (count > 1) { + DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: " + "count=%d\n", filter, count)); + ldap_msgfree(result); + return NT_STATUS_NO_SUCH_ALIAS; + } + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, + result); + + if (!entry) { + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + if (!dn) { + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + smbldap_set_mod(&mods, modop, + get_attr_key2string(groupmap_attr_list, + LDAP_ATTR_SID_LIST), + sid_string_static(member)); + + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); + + ldap_mods_free(mods, True); + ldap_msgfree(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_delete_entry: Could not delete attributes " + "for %s, error: %s (%s)\n", dn, ldap_err2string(rc), + ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); + SAFE_FREE(dn); + return NT_STATUS_UNSUCCESSFUL; + } + + SAFE_FREE(dn); + + return NT_STATUS_OK; +} + +static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods, + const DOM_SID *alias, + const DOM_SID *member) +{ + return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD); +} + +static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods, + const DOM_SID *alias, + const DOM_SID *member) +{ + return ldapsam_modify_aliasmem(methods, alias, member, + LDAP_MOD_DELETE); +} + +static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods, + const DOM_SID *alias, DOM_SID **members, + int *num_members) +{ + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + int count; + char **values; + int i; + pstring filter; + + *members = NULL; + *num_members = 0; + + pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))", + LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY, + get_attr_key2string(groupmap_attr_list, + LDAP_ATTR_GROUP_SID), + sid_string_static(alias)); + + if (ldapsam_search_one_group(ldap_state, filter, + &result) != LDAP_SUCCESS) + return NT_STATUS_NO_SUCH_ALIAS; + + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, + result); + + if (count < 1) { + DEBUG(4, ("ldapsam_add_aliasmem: Did not find alias\n")); + ldap_msgfree(result); + return NT_STATUS_NO_SUCH_ALIAS; + } + + if (count > 1) { + DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: " + "count=%d\n", filter, count)); + ldap_msgfree(result); + return NT_STATUS_NO_SUCH_ALIAS; + } + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, + result); + + if (!entry) { + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, + entry, + get_attr_key2string(groupmap_attr_list, + LDAP_ATTR_SID_LIST)); + + if (values == NULL) { + ldap_msgfree(result); + return NT_STATUS_OK; + } + + count = ldap_count_values(values); + + for (i=0; i<count; i++) { + DOM_SID member; + + if (!string_to_sid(&member, values[i])) + continue; + + add_sid_to_array(&member, members, num_members); + } + + ldap_value_free(values); + ldap_msgfree(result); + + return NT_STATUS_OK; +} + +static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, + const DOM_SID *sid, + DOM_SID **aliases, int *num) +{ + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + + fstring sid_string; + const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL }; + + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + int count; + int rc; + pstring filter; + + sid_to_string(sid_string, sid); + pstr_sprintf(filter, "(&(|(objectclass=%s)(objectclass=%s))(%s=%s))", + LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY, + get_attr_key2string(groupmap_attr_list, + LDAP_ATTR_SID_LIST), sid_string); + + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(), + LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); + + if (rc != LDAP_SUCCESS) + return NT_STATUS_UNSUCCESSFUL; + + *aliases = NULL; + *num = 0; + + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, + result); + + if (count < 1) { + ldap_msgfree(result); + return NT_STATUS_OK; + } + + + for (entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, + result); + entry != NULL; + entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, + entry)) + { + DOM_SID alias; + char **vals; + vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, + entry, LDAP_ATTRIBUTE_SID); + + if (vals == NULL) + continue; + + if (vals[0] == NULL) { + ldap_value_free(vals); + continue; + } + + if (!string_to_sid(&alias, vals[0])) { + ldap_value_free(vals); + continue; + } + + add_sid_to_array(&alias, aliases, num); + ldap_value_free(vals); + } + + ldap_msgfree(result); + return NT_STATUS_OK; +} + /********************************************************************** Housekeeping *********************************************************************/ @@ -2444,6 +2723,11 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met (*pdb_method)->name = "ldapsam"; + (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem; + (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem; + (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem; + (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships; + ldap_state = (*pdb_method)->private_data; ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT; diff --git a/source3/passdb/util_sam_sid.c b/source3/passdb/util_sam_sid.c index f6cc2491a8..63ef5914af 100644 --- a/source3/passdb/util_sam_sid.c +++ b/source3/passdb/util_sam_sid.c @@ -305,3 +305,16 @@ BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char return False; } + +void add_sid_to_array(const DOM_SID *sid, DOM_SID **sids, int *num) +{ + *sids = Realloc(*sids, ((*num)+1) * sizeof(DOM_SID)); + + if (*sids == NULL) + return; + + sid_copy(&((*sids)[*num]), sid); + *num += 1; + + return; +} |