From 30ef8fe1e85c0ca229b54f3f1595c4330f7191d1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 29 Feb 2004 16:48:19 +0000 Subject: [PATCH] Apply my experimental aliases support to HEAD. This will be a bit difficult to merge to 3_0, as the pdb interfaces has changed a bit between the two. This has not been tested too severly (which means it's completely broken ;-), but I want it in for review. Feel free to revert it :-) TODO: make 'net groupmap' a bit more friendly for alias members. Put that stuff into pdb_ldap. Getting the information over to winbind. One plan without linking pdb into winbind would be to fill group_mapping.tdb with the membership information and have that as a cache (or use gencache.tdb?). smbd on a PDC or stand-alone could trigger that itself, the problem is a BDC using LDAP. This needs to do it on a regular basis. The BDC smbd needs to be informed about SAM changes somehow... Volker --- source/auth/auth_util.c | 66 ++++++++++ source/groupdb/mapping.c | 282 +++++++++++++++++++++++++++++++++++++++- source/include/passdb.h | 28 ++++ source/passdb/pdb_interface.c | 121 +++++++++++++++++ source/rpc_server/srv_samr_nt.c | 9 +- source/utils/net_groupmap.c | 112 ++++++++++++++++ 6 files changed, 614 insertions(+), 4 deletions(-) diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c index 0f945b33cb3..912432b98f8 100644 --- a/source/auth/auth_util.c +++ b/source/auth/auth_util.c @@ -635,6 +635,70 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, return token; } +static void add_gid_to_array_unique(gid_t gid, gid_t **groups, int *ngroups) +{ + int i; + + if ((*ngroups) >= groups_max()) + return; + + for (i=0; i<*ngroups; i++) { + if ((*groups)[i] == gid) + return; + } + + *groups = Realloc(*groups, ((*ngroups)+1) * sizeof(gid_t)); + + if (*groups == NULL) + return; + + (*groups)[*ngroups] = gid; + *ngroups += 1; +} + +static void add_foreign_gids_from_sid(const DOM_SID *sid, gid_t **groups, + int *ngroups) +{ + DOM_SID *aliases; + int j, num_aliases; + + if (!pdb_enum_alias_memberships(sid, &aliases, &num_aliases)) + return; + + for (j=0; jsid_name_use != SID_NAME_ALIAS) + if ( ( (map->sid_name_use != SID_NAME_ALIAS) && + (map->sid_name_use != SID_NAME_WKN_GRP) ) || (map->gid == -1) || (getgrgid(map->gid) == NULL) ) { @@ -704,6 +946,9 @@ BOOL get_sid_list_of_group(gid_t gid, DOM_SID **sids, int *num_sids) int i=0; char *gr; DOM_SID *s; + DOM_SID sid; + DOM_SID *members; + int num_members; struct sys_pwent *userlist; struct sys_pwent *user; @@ -803,6 +1048,15 @@ BOOL get_sid_list_of_group(gid_t gid, DOM_SID **sids, int *num_sids) DEBUG(10, ("got primary groups, members: [%d]\n", *num_sids)); winbind_on(); + + if ( NT_STATUS_IS_OK(gid_to_sid(&sid, gid)) && + NT_STATUS_IS_OK(enum_aliasmem(&sid, &members, &num_members)) ) { + + for (i=0; ipdb_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); +} + static NTSTATUS context_gettrustpwent(struct pdb_context *context, SAM_TRUST_PASSWD *trust) { @@ -641,6 +702,10 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry; (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry; (*context)->pdb_enum_group_mapping = context_enum_group_mapping; + (*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)->pdb_gettrustpwent = context_gettrustpwent; (*context)->pdb_gettrustpwsid = context_gettrustpwsid; (*context)->pdb_add_trust_passwd = context_add_trust_passwd; @@ -955,6 +1020,58 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, rmap, num_entries, unix_only)); } +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_add_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). @@ -1065,6 +1182,10 @@ 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)->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; (*methods)->gettrustpwent = pdb_default_gettrustpwent; (*methods)->gettrustpwsid = pdb_default_gettrustpwsid; diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index a8176271278..b50d44d9e36 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -3381,7 +3381,8 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD if (check != True) { pdb_free_sam(&sam_user); - return NT_STATUS_NO_SUCH_USER; + return pdb_add_aliasmem(&alias_sid, &q_u->sid.sid) ? + NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } /* check a real user exist before we run the script to add a user to a group */ @@ -3457,7 +3458,8 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE return NT_STATUS_NO_SUCH_ALIAS; } - if( !get_local_group_from_sid(&alias_sid, &map)) + if( !get_local_group_from_sid(&alias_sid, &map) && + !get_builtin_group_from_sid(&alias_sid, &map) ) return NT_STATUS_NO_SUCH_ALIAS; if ((grp=getgrgid(map.gid)) == NULL) @@ -3471,7 +3473,8 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE if(!pdb_getsampwsid(sam_pass, &q_u->sid.sid)) { DEBUG(5,("_samr_del_aliasmem:User %s doesn't exist.\n", pdb_get_username(sam_pass))); pdb_free_sam(&sam_pass); - return NT_STATUS_NO_SUCH_USER; + return pdb_del_aliasmem(&alias_sid, &q_u->sid.sid) ? + NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } /* if the user is not in the group */ diff --git a/source/utils/net_groupmap.c b/source/utils/net_groupmap.c index 2b487ef17b4..48406f72b88 100644 --- a/source/utils/net_groupmap.c +++ b/source/utils/net_groupmap.c @@ -608,6 +608,104 @@ static int net_groupmap_cleanup(int argc, const char **argv) return 0; } +static int net_groupmap_addmem(int argc, const char **argv) +{ + DOM_SID alias, member; + NTSTATUS result; + + if ( (argc != 2) || + !string_to_sid(&alias, argv[0]) || + !string_to_sid(&member, argv[1]) ) { + d_printf("Usage: net groupmap addmem alias-sid member-sid\n"); + return -1; + } + + if (!pdb_add_aliasmem(&alias, &member)) { + d_printf("Could not add sid %s to alias %s: %s\n", + argv[1], argv[0], nt_errstr(result)); + return -1; + } + + return 0; +} + +static int net_groupmap_delmem(int argc, const char **argv) +{ + DOM_SID alias, member; + NTSTATUS result; + + if ( (argc != 2) || + !string_to_sid(&alias, argv[0]) || + !string_to_sid(&member, argv[1]) ) { + d_printf("Usage: net groupmap delmem alias-sid member-sid\n"); + return -1; + } + + if (!pdb_del_aliasmem(&alias, &member)) { + d_printf("Could not delete sid %s from alias %s: %s\n", + argv[1], argv[0], nt_errstr(result)); + return -1; + } + + return 0; +} + +static int net_groupmap_listmem(int argc, const char **argv) +{ + DOM_SID alias; + DOM_SID *members; + int i, num; + NTSTATUS result; + + if ( (argc != 1) || + !string_to_sid(&alias, argv[0]) ) { + d_printf("Usage: net groupmap listmem alias-sid\n"); + return -1; + } + + if (!pdb_enum_aliasmem(&alias, &members, &num)) { + d_printf("Could not list members for sid %s: %s\n", + argv[0], nt_errstr(result)); + return -1; + } + + for (i = 0; i < num; i++) { + printf("%s\n", sid_string_static(&(members[i]))); + } + + SAFE_FREE(members); + + return 0; +} + +static int net_groupmap_memberships(int argc, const char **argv) +{ + DOM_SID member; + DOM_SID *aliases; + int i, num; + NTSTATUS result; + + if ( (argc != 1) || + !string_to_sid(&member, argv[0]) ) { + d_printf("Usage: net groupmap memberof sid\n"); + return -1; + } + + if (!pdb_enum_alias_memberships(&member, &aliases, &num)) { + d_printf("Could not list memberships for sid %s: %s\n", + argv[0], nt_errstr(result)); + return -1; + } + + for (i = 0; i < num; i++) { + printf("%s\n", sid_string_static(&(aliases[i]))); + } + + SAFE_FREE(aliases); + + return 0; +} + int net_help_groupmap(int argc, const char **argv) { d_printf("net groupmap add"\ @@ -616,6 +714,14 @@ int net_help_groupmap(int argc, const char **argv) "\n Update a group mapping\n"); d_printf("net groupmap delete"\ "\n Remove a group mapping\n"); + d_printf("net groupmap addmember"\ + "\n Add a foreign alias member\n"); + d_printf("net groupmap delmember"\ + "\n Delete a foreign alias member\n"); + d_printf("net groupmap listmembers"\ + "\n List foreign group members\n"); + d_printf("net groupmap memberships"\ + "\n List foreign group memberships\n"); d_printf("net groupmap list"\ "\n List current group map\n"); d_printf("net groupmap set"\ @@ -638,16 +744,22 @@ int net_groupmap(int argc, const char **argv) {"delete", net_groupmap_delete}, {"set", net_groupmap_set}, {"cleanup", net_groupmap_cleanup}, + {"addmem", net_groupmap_addmem}, + {"delmem", net_groupmap_delmem}, + {"listmem", net_groupmap_listmem}, + {"memberships", net_groupmap_memberships}, {"list", net_groupmap_list}, {"help", net_help_groupmap}, {NULL, NULL} }; /* we shouldn't have silly checks like this */ +#if 0 if (getuid() != 0) { d_printf("You must be root to edit group mappings.\nExiting...\n"); return -1; } +#endif if ( argc ) return net_run_function(argc, argv, func, net_help_groupmap); -- 2.11.4.GIT