diff options
Diffstat (limited to 'source3/passdb/pdb_interface.c')
-rw-r--r-- | source3/passdb/pdb_interface.c | 444 |
1 files changed, 388 insertions, 56 deletions
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 4808af3908..d8afff2111 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -36,7 +36,10 @@ static void lazy_initialize_passdb(void) } static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name); - +static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, + const char **name, + enum SID_NAME_USE *psid_name_use, + union unid_t *unix_id); /******************************************************************* Clean up uninitialised passwords. The only way to tell that these values are not 'real' is that they do not @@ -526,9 +529,10 @@ static NTSTATUS context_enum_group_members(struct pdb_context *context, } static NTSTATUS context_enum_group_memberships(struct pdb_context *context, - const char *username, - gid_t primary_gid, - DOM_SID **pp_sids, gid_t **pp_gids, + TALLOC_CTX *mem_ctx, + SAM_ACCOUNT *user, + DOM_SID **pp_sids, + gid_t **pp_gids, size_t *p_num_groups) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -539,8 +543,8 @@ static NTSTATUS context_enum_group_memberships(struct pdb_context *context, } return context->pdb_methods-> - enum_group_memberships(context->pdb_methods, username, - primary_gid, pp_sids, pp_gids, p_num_groups); + enum_group_memberships(context->pdb_methods, mem_ctx, user, + pp_sids, pp_gids, p_num_groups); } static NTSTATUS context_find_alias(struct pdb_context *context, @@ -757,6 +761,63 @@ static NTSTATUS context_get_seq_num(struct pdb_context *context, time_t *seq_num return context->pdb_methods->get_seq_num(context->pdb_methods, seq_num); } + +static BOOL context_uid_to_rid(struct pdb_context *context, uid_t uid, + uint32 *rid) +{ + if ((context == NULL) || (context->pdb_methods == NULL)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->uid_to_rid(context->pdb_methods, uid, + rid); +} + +static BOOL context_gid_to_sid(struct pdb_context *context, gid_t gid, + DOM_SID *sid) +{ + if ((context == NULL) || (context->pdb_methods == NULL)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->gid_to_sid(context->pdb_methods, gid, + sid); +} + +static BOOL context_sid_to_id(struct pdb_context *context, + const DOM_SID *sid, + union unid_t *id, enum SID_NAME_USE *type) +{ + if ((context == NULL) || (context->pdb_methods == NULL)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->sid_to_id(context->pdb_methods, sid, + id, type); +} + +static BOOL context_rid_algorithm(struct pdb_context *context) +{ + if ((context == NULL) || (context->pdb_methods == NULL)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->rid_algorithm(context->pdb_methods); +} + +static BOOL context_new_rid(struct pdb_context *context, uint32 *rid) +{ + if ((context == NULL) || (context->pdb_methods == NULL)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->new_rid(context->pdb_methods, rid); +} /****************************************************************** Free and cleanup a pdb context, any associated data and anything @@ -936,6 +997,13 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_search_groups = context_search_groups; (*context)->pdb_search_aliases = context_search_aliases; + (*context)->pdb_uid_to_rid = context_uid_to_rid; + (*context)->pdb_gid_to_sid = context_gid_to_sid; + (*context)->pdb_sid_to_id = context_sid_to_id; + + (*context)->pdb_rid_algorithm = context_rid_algorithm; + (*context)->pdb_new_rid = context_new_rid; + (*context)->free_fn = free_pdb_context; return NT_STATUS_OK; @@ -1126,12 +1194,12 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct)); } -BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) +NTSTATUS pdb_update_sam_account(SAM_ACCOUNT *sam_acct) { struct pdb_context *pdb_context = pdb_get_static_context(False); if (!pdb_context) { - return False; + return NT_STATUS_UNSUCCESSFUL; } if (sam_account_cache != NULL) { @@ -1139,7 +1207,7 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) sam_account_cache = NULL; } - return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct)); + return pdb_context->pdb_update_sam_account(pdb_context, sam_acct); } BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) @@ -1221,28 +1289,26 @@ BOOL pdb_getgrnam(GROUP_MAP *map, const char *name) pdb_getgrnam(pdb_context, map, name)); } -BOOL pdb_add_group_mapping_entry(GROUP_MAP *map) +NTSTATUS pdb_add_group_mapping_entry(GROUP_MAP *map) { struct pdb_context *pdb_context = pdb_get_static_context(False); if (!pdb_context) { - return False; + return NT_STATUS_UNSUCCESSFUL; } - return NT_STATUS_IS_OK(pdb_context-> - pdb_add_group_mapping_entry(pdb_context, map)); + return pdb_context->pdb_add_group_mapping_entry(pdb_context, map); } -BOOL pdb_update_group_mapping_entry(GROUP_MAP *map) +NTSTATUS pdb_update_group_mapping_entry(GROUP_MAP *map) { struct pdb_context *pdb_context = pdb_get_static_context(False); if (!pdb_context) { - return False; + return NT_STATUS_UNSUCCESSFUL; } - return NT_STATUS_IS_OK(pdb_context-> - pdb_update_group_mapping_entry(pdb_context, map)); + return pdb_context->pdb_update_group_mapping_entry(pdb_context, map); } BOOL pdb_delete_group_mapping_entry(DOM_SID sid) @@ -1286,7 +1352,7 @@ NTSTATUS pdb_enum_group_members(TALLOC_CTX *mem_ctx, pp_member_rids, p_num_members); } -NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid, +NTSTATUS pdb_enum_group_memberships(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *user, DOM_SID **pp_sids, gid_t **pp_gids, size_t *p_num_groups) { @@ -1296,9 +1362,9 @@ NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid, return NT_STATUS_UNSUCCESSFUL; } - return pdb_context->pdb_enum_group_memberships(pdb_context, username, - primary_gid, pp_sids, pp_gids, - p_num_groups); + return pdb_context->pdb_enum_group_memberships( + pdb_context, mem_ctx, user, + pp_sids, pp_gids, p_num_groups); } BOOL pdb_find_alias(const char *name, DOM_SID *sid) @@ -1361,60 +1427,58 @@ BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info) info)); } -BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member) +NTSTATUS 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_UNSUCCESSFUL; } - return NT_STATUS_IS_OK(pdb_context-> - pdb_add_aliasmem(pdb_context, alias, member)); + return pdb_context->pdb_add_aliasmem(pdb_context, alias, member); } -BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member) +NTSTATUS 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_UNSUCCESSFUL; } - return NT_STATUS_IS_OK(pdb_context-> - pdb_del_aliasmem(pdb_context, alias, member)); + return pdb_context->pdb_del_aliasmem(pdb_context, alias, member); } -BOOL pdb_enum_aliasmem(const DOM_SID *alias, - DOM_SID **pp_members, size_t *p_num_members) +NTSTATUS pdb_enum_aliasmem(const DOM_SID *alias, + DOM_SID **pp_members, size_t *p_num_members) { struct pdb_context *pdb_context = pdb_get_static_context(False); if (!pdb_context) { - return False; + return NT_STATUS_UNSUCCESSFUL; } - return NT_STATUS_IS_OK(pdb_context-> - pdb_enum_aliasmem(pdb_context, alias, - pp_members, p_num_members)); + return pdb_context->pdb_enum_aliasmem(pdb_context, alias, + pp_members, p_num_members); } -BOOL pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, - const DOM_SID *members, size_t num_members, - uint32 **pp_alias_rids, size_t *p_num_alias_rids) +NTSTATUS pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + const DOM_SID *members, size_t num_members, + uint32 **pp_alias_rids, + size_t *p_num_alias_rids) { struct pdb_context *pdb_context = pdb_get_static_context(False); if (!pdb_context) { - return False; + return NT_STATUS_NOT_IMPLEMENTED; } - return NT_STATUS_IS_OK(pdb_context-> - pdb_enum_alias_memberships(pdb_context, mem_ctx, - domain_sid, - members, num_members, - pp_alias_rids, - p_num_alias_rids)); + return pdb_context->pdb_enum_alias_memberships(pdb_context, mem_ctx, + domain_sid, + members, num_members, + pp_alias_rids, + p_num_alias_rids); } NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid, @@ -1484,6 +1548,78 @@ BOOL pdb_get_seq_num(time_t *seq_num) return NT_STATUS_IS_OK(pdb_context-> pdb_get_seq_num(pdb_context, seq_num)); } + +BOOL pdb_uid_to_rid(uid_t uid, uint32 *rid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_uid_to_rid(pdb_context, uid, rid); +} + +BOOL pdb_gid_to_sid(gid_t gid, DOM_SID *sid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_gid_to_sid(pdb_context, gid, sid); +} + +BOOL pdb_sid_to_id(const DOM_SID *sid, union unid_t *id, + enum SID_NAME_USE *type) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_sid_to_id(pdb_context, sid, id, type); +} + +BOOL pdb_rid_algorithm(void) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return pdb_context->pdb_rid_algorithm(pdb_context); +} + +BOOL pdb_new_rid(uint32 *rid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + if (pdb_rid_algorithm()) { + DEBUG(0, ("Trying to allocate a RID when algorithmic RIDs " + "are active\n")); + return False; + } + + if (algorithmic_rid_base() != BASE_RID) { + DEBUG(0, ("'algorithmic rid base' is set but a passdb backend " + "without algorithmic RIDs is chosen.\n")); + DEBUGADD(0, ("Please map all used groups using 'net groupmap " + "add', set the maximum used RID using\n")); + DEBUGADD(0, ("'net setmaxrid' and remove the parameter\n")); + return False; + } + + return pdb_context->pdb_new_rid(pdb_context, rid); +} + /*************************************************************** Initialize the static context (at smbd startup etc). @@ -1567,6 +1703,117 @@ static NTSTATUS pdb_default_get_seq_num(struct pdb_methods *methods, time_t *seq return NT_STATUS_OK; } +static BOOL pdb_default_uid_to_rid(struct pdb_methods *methods, uid_t uid, + uint32 *rid) +{ + SAM_ACCOUNT *sampw = NULL; + struct passwd *unix_pw; + BOOL ret; + + unix_pw = sys_getpwuid( uid ); + + if ( !unix_pw ) { + DEBUG(4,("pdb_default_uid_to_rid: host has no idea of uid " + "%lu\n", (unsigned long)uid)); + return False; + } + + if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) { + DEBUG(0,("pdb_default_uid_to_rid: failed to allocate " + "SAM_ACCOUNT object\n")); + return False; + } + + become_root(); + ret = NT_STATUS_IS_OK( + methods->getsampwnam(methods, sampw, unix_pw->pw_name )); + unbecome_root(); + + if (!ret) { + DEBUG(5, ("pdb_default_uid_to_rid: Did not find user " + "%s (%d)\n", unix_pw->pw_name, uid)); + pdb_free_sam(&sampw); + return False; + } + + ret = sid_peek_check_rid(get_global_sam_sid(), + pdb_get_user_sid(sampw), rid); + + if (!ret) { + DEBUG(1, ("Could not peek rid out of sid %s\n", + sid_string_static(pdb_get_user_sid(sampw)))); + } + + pdb_free_sam(&sampw); + return ret; +} + +static BOOL pdb_default_gid_to_sid(struct pdb_methods *methods, gid_t gid, + DOM_SID *sid) +{ + GROUP_MAP map; + + if (!NT_STATUS_IS_OK(methods->getgrgid(methods, &map, gid))) { + return False; + } + + sid_copy(sid, &map.sid); + return True; +} + +static BOOL pdb_default_sid_to_id(struct pdb_methods *methods, + const DOM_SID *sid, + union unid_t *id, enum SID_NAME_USE *type) +{ + TALLOC_CTX *mem_ctx; + BOOL ret = False; + const char *name; + uint32 rid; + + mem_ctx = talloc_new(NULL); + + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_new failed\n")); + return False; + } + + if (sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) { + /* Here we might have users as well as groups and aliases */ + ret = lookup_global_sam_rid(mem_ctx, rid, &name, type, id); + goto done; + } + + if (sid_peek_check_rid(&global_sid_Builtin, sid, &rid)) { + /* Here we only have aliases */ + GROUP_MAP map; + if (!NT_STATUS_IS_OK(methods->getgrsid(methods, &map, *sid))) { + DEBUG(10, ("Could not find map for sid %s\n", + sid_string_static(sid))); + goto done; + } + if ((map.sid_name_use != SID_NAME_ALIAS) && + (map.sid_name_use != SID_NAME_WKN_GRP)) { + DEBUG(10, ("Map for sid %s is a %s, expected an " + "alias\n", sid_string_static(sid), + sid_type_lookup(map.sid_name_use))); + goto done; + } + + id->gid = map.gid; + *type = SID_NAME_ALIAS; + ret = True; + goto done; + } + + DEBUG(5, ("Sid %s is neither ours nor builtin, don't know it\n", + sid_string_static(sid))); + + done: + + talloc_free(mem_ctx); + return ret; +} + static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, uid_t **pp_uids, size_t *p_num) { @@ -1644,7 +1891,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, *pp_member_rids = NULL; *p_num_members = 0; - if (!NT_STATUS_IS_OK(sid_to_gid(group, &gid))) + if (!sid_to_gid(group, &gid)) return NT_STATUS_NO_SUCH_GROUP; if(!get_memberuids(mem_ctx, gid, &uids, &num_uids)) @@ -1658,10 +1905,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, for (i=0; i<num_uids; i++) { DOM_SID sid; - if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) { - DEBUG(1, ("Could not map member uid to SID\n")); - continue; - } + uid_to_sid(&sid, uids[i]); if (!sid_check_is_in_our_domain(&sid)) { DEBUG(1, ("Inconsistent SAM -- group member uid not " @@ -1676,6 +1920,92 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, return NT_STATUS_OK; } +/******************************************************************* + Look up a rid in the SAM we're responsible for (i.e. passdb) + ********************************************************************/ + +static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, + const char **name, + enum SID_NAME_USE *psid_name_use, + union unid_t *unix_id) +{ + SAM_ACCOUNT *sam_account = NULL; + GROUP_MAP map; + BOOL ret; + DOM_SID sid; + + *psid_name_use = SID_NAME_UNKNOWN; + + DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n", + (unsigned int)rid)); + + sid_copy(&sid, get_global_sam_sid()); + sid_append_rid(&sid, rid); + + /* see if the passdb can help us with the name of the user */ + if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { + return False; + } + + /* BEING ROOT BLLOCK */ + become_root(); + if (pdb_getsampwsid(sam_account, &sid)) { + struct passwd *pw; + + unbecome_root(); /* -----> EXIT BECOME_ROOT() */ + *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account)); + *psid_name_use = SID_NAME_USER; + + pdb_free_sam(&sam_account); + + if (unix_id == NULL) { + return True; + } + + pw = Get_Pwnam(*name); + if (pw == NULL) { + return False; + } + unix_id->uid = pw->pw_uid; + return True; + } + pdb_free_sam(&sam_account); + + ret = pdb_getgrsid(&map, sid); + unbecome_root(); + /* END BECOME_ROOT BLOCK */ + + if ( ret ) { + if (map.gid!=(gid_t)-1) { + DEBUG(5,("lookup_global_sam_rid: mapped group %s to " + "gid %u\n", map.nt_name, + (unsigned int)map.gid)); + } else { + DEBUG(5,("lookup_global_sam_rid: mapped group %s to " + "no unix gid. Returning name.\n", + map.nt_name)); + } + + *name = talloc_strdup(mem_ctx, map.nt_name); + *psid_name_use = map.sid_name_use; + + if (unix_id == NULL) { + return True; + } + + if (map.gid == (gid_t)-1) { + DEBUG(5, ("Can't find a unix id for an unmapped " + "group\n")); + return False; + } + + unix_id->gid = map.gid; + return True; + } + + return False; +} + NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, const DOM_SID *domain_sid, int num_rids, @@ -1715,7 +2045,8 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, for (i = 0; i < num_rids; i++) { const char *name; - if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) { + if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i], + NULL)) { names[i] = name; DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); have_mapped = True; @@ -1772,11 +2103,9 @@ NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods, } for (i = 0; i < num_names; i++) { - const char *name; - - if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) { - names[i] = name; - DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i])); + if (lookup_global_sam_name(names[i], 0, &rids[i], &attrs[i])) { + DEBUG(5,("lookup_names: %s-> %d:%d\n", names[i], + rids[i], attrs[i])); have_mapped = True; } else { have_unmapped = True; @@ -2157,6 +2486,9 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) (*methods)->get_account_policy = pdb_default_get_account_policy; (*methods)->set_account_policy = pdb_default_set_account_policy; (*methods)->get_seq_num = pdb_default_get_seq_num; + (*methods)->uid_to_rid = pdb_default_uid_to_rid; + (*methods)->gid_to_sid = pdb_default_gid_to_sid; + (*methods)->sid_to_id = pdb_default_sid_to_id; (*methods)->search_users = pdb_default_search_users; (*methods)->search_groups = pdb_default_search_groups; |