/* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-2000, * Copyright (C) Jean François Micouleau 1998-2001. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" /* * Next two lines needed for SunOS and don't * hurt anything else... */ extern char *optarg; extern int optind; /********************************************************* Print command usage on stderr and die. **********************************************************/ static void usage(void) { if (getuid() == 0) { printf("smbgroupedit options\n"); } else { printf("You need to be root to use this tool!\n"); } printf("options:\n"); printf(" -a group create new group\n"); printf(" -n group NT group name\n"); printf(" -p privilege only local\n"); printf(" -d description group description\n"); printf(" -v list groups\n"); printf(" -l long list (include details)\n"); printf(" -s short list (default)\n"); printf(" -c SID change group\n"); printf(" -u unix group\n"); printf(" -d description group description\n"); printf(" -r rid RID of new group\n"); printf(" -x group delete this group\n"); printf("\n"); printf(" -t[b|d|l] type: builtin, domain, local \n"); exit(1); } /********************************************************* Figure out if the input was an NT group or a SID string. Return the SID. **********************************************************/ static BOOL get_sid_from_input(DOM_SID *sid, char *input) { GROUP_MAP map; if (StrnCaseCmp( input, "S-", 2)) { /* Perhaps its the NT group name? */ if (!pdb_getgrnam(&map, input, MAPPING_WITHOUT_PRIV)) { printf("NT Group %s doesn't exist in mapping DB\n", input); return False; } else { *sid = map.sid; } } else { if (!string_to_sid(sid, input)) { printf("converting sid %s from a string failed!\n", input); return False; } } return True; } /********************************************************* add a group. **********************************************************/ static int addgroup(gid_t gid, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcomment, char *privilege, uint32 rid) { PRIVILEGE_SET se_priv; DOM_SID sid; fstring string_sid; fstring comment; sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, rid); sid_to_string(string_sid, &sid); if (ntcomment==NULL) fstrcpy(comment, "Local Unix group"); else fstrcpy(comment, ntcomment); init_privilege(&se_priv); if (privilege!=NULL) convert_priv_from_text(&se_priv, privilege); if(!add_initial_entry(gid, string_sid, sid_type, ntgroup, comment, se_priv, PR_ACCESS_FROM_NETWORK)) { printf("adding entry for group %s failed!\n", ntgroup); free_privilege(&se_priv); return -1; } free_privilege(&se_priv); return 0; } /********************************************************* Change a group. **********************************************************/ static int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *groupdesc, char *privilege) { DOM_SID sid; GROUP_MAP map; gid_t gid; if (!get_sid_from_input(&sid, sid_string)) { return -1; } /* Get the current mapping from the database */ if(!pdb_getgrsid(&map, sid, MAPPING_WITH_PRIV)) { printf("This SID does not exist in the database\n"); return -1; } /* If a new Unix group is specified, check and change */ if (group!=NULL) { gid=nametogid(group); if (gid==-1) { printf("The UNIX group does not exist\n"); return -1; } else map.gid=gid; } /* * Allow changing of group type only between domain and local * We disallow changing Builtin groups !!! (SID problem) */ if (sid_type==SID_NAME_ALIAS || sid_type==SID_NAME_DOM_GRP || sid_type==SID_NAME_UNKNOWN) { if (map.sid_name_use==SID_NAME_ALIAS || map.sid_name_use==SID_NAME_DOM_GRP || map.sid_name_use==SID_NAME_UNKNOWN) { map.sid_name_use=sid_type; } else { printf("cannot change group type to builtin\n"); }; } else { printf("cannot change group type from builtin\n"); } if (ntgroup!=NULL) fstrcpy(map.nt_name, ntgroup); /* Change comment if new one */ if (groupdesc!=NULL) fstrcpy(map.comment, groupdesc); /* Change the privilege if new one */ if (privilege!=NULL) convert_priv_from_text(&map.priv_set, privilege); if (!pdb_update_group_mapping_entry(&map)) { printf("Could not update group database\n"); free_privilege(&map.priv_set); return -1; } free_privilege(&map.priv_set); return 0; } /********************************************************* Delete the group. **********************************************************/ static int deletegroup(char *group) { DOM_SID sid; if (!get_sid_from_input(&sid, group)) { return -1; } if(!pdb_delete_group_mapping_entry(sid)) { printf("removing group %s from the mapping db failed!\n", group); return -1; } return 0; } /********************************************************* List the groups. **********************************************************/ static int listgroup(enum SID_NAME_USE sid_type, BOOL long_list) { int entries,i; TALLOC_CTX *mem_ctx; GROUP_MAP *map=NULL; fstring string_sid; fstring group_type; fstring priv_text; if (!long_list) printf("NT group (SID) -> Unix group\n"); if (!pdb_enum_group_mapping(sid_type, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV)) return -1; mem_ctx = talloc_init("smbgroupedit talloc"); if (!mem_ctx) return -1; for (i=0; i %s\n", map[i].nt_name, string_sid, gidtoname(mem_ctx, map[i].gid)); else { printf("%s\n", map[i].nt_name); printf("\tSID : %s\n", string_sid); printf("\tUnix group: %s\n", gidtoname(mem_ctx, map[i].gid)); printf("\tGroup type: %s\n", group_type); printf("\tComment : %s\n", map[i].comment); printf("\tPrivilege : %s\n\n", priv_text); } } talloc_destroy(mem_ctx); return 0; } /********************************************************* Start here. **********************************************************/ int main (int argc, char **argv) { int ch; BOOL add_group = False; BOOL view_group = False; BOOL change_group = False; BOOL delete_group = False; BOOL nt_group = False; BOOL priv = False; BOOL group_type = False; BOOL long_list = False; char *group = NULL; char *sid = NULL; char *ntgroup = NULL; char *privilege = NULL; char *groupt = NULL; char *group_desc = NULL; enum SID_NAME_USE sid_type; uint32 rid = -1; setup_logging("groupedit", DEBUG_STDOUT); if (argc < 2) { usage(); return 0; } if (!lp_load(dyn_CONFIGFILE,True,False,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); exit(1); } if (!init_names()) exit(1); if(!initialize_password_db(True)) { fprintf(stderr, "Can't setup password database vectors.\n"); exit(1); } if(get_global_sam_sid()==False) { fprintf(stderr, "Can not read machine SID\n"); return 0; } while ((ch = getopt(argc, argv, "a:c:d:ln:p:r:st:u:vx:")) != EOF) { switch(ch) { case 'a': add_group = True; group=optarg; break; case 'c': change_group = True; sid=optarg; break; case 'd': group_desc=optarg; break; case 'l': long_list = True; break; case 'n': nt_group = True; ntgroup=optarg; break; case 'p': priv = True; privilege=optarg; break; case 'r': rid = atoi(optarg); break; case 's': long_list = False; break; case 't': group_type = True; groupt=optarg; break; case 'u': group=optarg; break; case 'v': view_group = True; break; case 'x': delete_group = True; group=optarg; break; /*default: usage();*/ } } if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) > 1) { fprintf (stderr, "Incompatible options on command line!\n"); usage(); exit(1); } /* no option on command line -> list groups */ if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) == 0) view_group = True; if (group_type==False) sid_type=SID_NAME_UNKNOWN; else { switch (groupt[0]) { case 'l': case 'L': sid_type=SID_NAME_ALIAS; break; case 'd': case 'D': sid_type=SID_NAME_DOM_GRP; break; case 'b': case 'B': sid_type=SID_NAME_WKN_GRP; break; default: sid_type=SID_NAME_UNKNOWN; break; } } if (add_group) { gid_t gid=nametogid(group); if (gid==-1) { printf("unix group %s doesn't exist!\n", group); return -1; } if (rid == -1) { rid = pdb_gid_to_group_rid(gid); } return addgroup(gid, sid_type, ntgroup?ntgroup:group, group_desc, privilege, rid); } if (view_group) return listgroup(sid_type, long_list); if (delete_group) return deletegroup(group); if (change_group) { return changegroup(sid, group, sid_type, ntgroup, group_desc, privilege); } usage(); return 0; }