first public release of samba4 code
[jelmer/samba4-debian.git] / source / utils / smbgroupedit.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2001.
6  *  
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include "includes.h"
23
24 /*
25  * Next two lines needed for SunOS and don't
26  * hurt anything else...
27  */
28 extern char *optarg;
29 extern int optind;
30
31 /*********************************************************
32  Print command usage on stderr and die.
33 **********************************************************/
34 static void usage(void)
35 {
36         if (getuid() == 0) {
37                 printf("smbgroupedit options\n");
38         } else {
39                 printf("You need to be root to use this tool!\n");
40         }
41         printf("options:\n");
42         printf("  -a group             create new group\n");
43         printf("    -n group           NT group name\n");
44         printf("    -p privilege       only local\n");
45         printf("    -d description     group description\n");
46         printf("  -v                   list groups\n");
47         printf("    -l                 long list (include details)\n");
48         printf("    -s                 short list (default)\n");
49         printf("  -c SID               change group\n");
50         printf("     -u unix group\n");
51         printf("     -d description    group description\n");
52         printf("  -r rid               RID of new group\n");
53         printf("  -x group             delete this group\n");
54         printf("\n");
55         printf("    -t[b|d|l]          type: builtin, domain, local \n");
56         exit(1);
57 }
58
59 /*********************************************************
60  Figure out if the input was an NT group or a SID string.  
61  Return the SID.
62 **********************************************************/
63 static BOOL get_sid_from_input(DOM_SID *sid, char *input) 
64 {
65         GROUP_MAP map;
66         
67         if (StrnCaseCmp( input, "S-", 2)) {
68                 /* Perhaps its the NT group name? */
69                 if (!pdb_getgrnam(&map, input, MAPPING_WITHOUT_PRIV)) {
70                         printf("NT Group %s doesn't exist in mapping DB\n", input);
71                         return False;
72                 } else {
73                         *sid = map.sid;
74                 }
75         } else {
76                 if (!string_to_sid(sid, input)) {
77                         printf("converting sid %s from a string failed!\n", input);
78                         return False;
79                 }
80         }
81         return True;
82 }
83
84 /*********************************************************
85  add a group.
86 **********************************************************/
87 static int addgroup(gid_t gid, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcomment, char *privilege, uint32 rid)
88 {
89         PRIVILEGE_SET se_priv;
90         DOM_SID sid;
91         fstring string_sid;
92         fstring comment;
93
94         sid_copy(&sid, get_global_sam_sid());
95         sid_append_rid(&sid, rid);
96         
97         sid_to_string(string_sid, &sid);
98         
99         if (ntcomment==NULL)
100                 fstrcpy(comment, "Local Unix group");
101         else
102                 fstrcpy(comment, ntcomment);
103
104         init_privilege(&se_priv);
105         if (privilege!=NULL)
106                 convert_priv_from_text(&se_priv, privilege);
107
108         if(!add_initial_entry(gid, string_sid, sid_type, ntgroup,
109                               comment, se_priv, PR_ACCESS_FROM_NETWORK)) {
110                 printf("adding entry for group %s failed!\n", ntgroup);
111                 free_privilege(&se_priv);
112                 return -1;
113         }
114
115         free_privilege(&se_priv);
116         return 0;
117 }
118
119 /*********************************************************
120  Change a group.
121 **********************************************************/
122 static int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *groupdesc, char *privilege)
123 {
124         DOM_SID sid;
125         GROUP_MAP map;
126         gid_t gid;
127
128         if (!get_sid_from_input(&sid, sid_string)) {
129                 return -1;
130         }
131
132         /* Get the current mapping from the database */
133         if(!pdb_getgrsid(&map, sid, MAPPING_WITH_PRIV)) {
134                 printf("This SID does not exist in the database\n");
135                 return -1;
136         }
137
138         /* If a new Unix group is specified, check and change */
139         if (group!=NULL) {
140                 gid=nametogid(group);
141                 if (gid==-1) {
142                         printf("The UNIX group does not exist\n");
143                         return -1;
144                 } else
145                         map.gid=gid;
146         }
147         
148         /*
149          * Allow changing of group type only between domain and local
150          * We disallow changing Builtin groups !!! (SID problem)
151          */ 
152         if (sid_type==SID_NAME_ALIAS 
153             || sid_type==SID_NAME_DOM_GRP 
154             || sid_type==SID_NAME_UNKNOWN) {
155                 if (map.sid_name_use==SID_NAME_ALIAS 
156                     || map.sid_name_use==SID_NAME_DOM_GRP
157                     || map.sid_name_use==SID_NAME_UNKNOWN) {
158                         map.sid_name_use=sid_type;
159                 } else {
160                         printf("cannot change group type to builtin\n");
161                 };
162         } else {
163                 printf("cannot change group type from builtin\n");
164         }
165
166         if (ntgroup!=NULL)
167                 fstrcpy(map.nt_name, ntgroup);
168
169         /* Change comment if new one */
170         if (groupdesc!=NULL)
171                 fstrcpy(map.comment, groupdesc);
172
173         /* Change the privilege if new one */
174         if (privilege!=NULL)
175                 convert_priv_from_text(&map.priv_set, privilege);
176
177         if (!pdb_update_group_mapping_entry(&map)) {
178                 printf("Could not update group database\n");
179                 free_privilege(&map.priv_set);
180                 return -1;
181         }
182         
183         free_privilege(&map.priv_set);
184         return 0;
185 }
186
187 /*********************************************************
188  Delete the group.
189 **********************************************************/
190 static int deletegroup(char *group)
191 {
192         DOM_SID sid;
193
194         if (!get_sid_from_input(&sid, group)) {
195                 return -1;
196         }
197
198         if(!pdb_delete_group_mapping_entry(sid)) {
199                 printf("removing group %s from the mapping db failed!\n", group);
200                 return -1;
201         }
202
203         return 0;
204 }
205
206 /*********************************************************
207  List the groups.
208 **********************************************************/
209 static int listgroup(enum SID_NAME_USE sid_type, BOOL long_list)
210 {
211         int entries,i;
212         TALLOC_CTX *mem_ctx;
213         GROUP_MAP *map=NULL;
214         fstring string_sid;
215         fstring group_type;
216         fstring priv_text;
217
218         if (!long_list)
219                 printf("NT group (SID) -> Unix group\n");
220                 
221         if (!pdb_enum_group_mapping(sid_type, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV))
222                 return -1;
223         
224         mem_ctx = talloc_init("smbgroupedit talloc");
225         if (!mem_ctx) return -1;
226         for (i=0; i<entries; i++) {
227                 decode_sid_name_use(group_type, (map[i]).sid_name_use);
228                 sid_to_string(string_sid, &map[i].sid);
229                 convert_priv_to_text(&(map[i].priv_set), priv_text);
230                 free_privilege(&(map[i].priv_set));
231                 
232                 if (!long_list)
233                         printf("%s (%s) -> %s\n", map[i].nt_name, string_sid, 
234                                 gidtoname(mem_ctx, map[i].gid));
235                 else {
236                         printf("%s\n", map[i].nt_name);
237                         printf("\tSID       : %s\n", string_sid);
238                         printf("\tUnix group: %s\n", gidtoname(mem_ctx, map[i].gid));
239                         printf("\tGroup type: %s\n", group_type);
240                         printf("\tComment   : %s\n", map[i].comment);
241                         printf("\tPrivilege : %s\n\n", priv_text);
242                 }
243         }
244         talloc_destroy(mem_ctx);
245
246         return 0;
247 }
248
249 /*********************************************************
250  Start here.
251 **********************************************************/
252 int main (int argc, char **argv)
253 {
254         int ch;
255         BOOL add_group = False;
256         BOOL view_group = False;
257         BOOL change_group = False;
258         BOOL delete_group = False;
259         BOOL nt_group = False;
260         BOOL priv = False;
261         BOOL group_type = False;
262         BOOL long_list = False;
263
264         char *group = NULL;
265         char *sid = NULL;
266         char *ntgroup = NULL;
267         char *privilege = NULL;
268         char *groupt = NULL;
269         char *group_desc = NULL;
270
271         enum SID_NAME_USE sid_type;
272         uint32 rid = -1;
273
274         setup_logging("groupedit", True);
275
276         if (argc < 2) {
277                 usage();
278                 return 0;
279         }
280         
281         if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
282                 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
283                         dyn_CONFIGFILE);
284                 exit(1);
285         }
286
287         if (!init_names())
288                 exit(1);
289         
290         if(!initialize_password_db(True)) {
291                 fprintf(stderr, "Can't setup password database vectors.\n");
292                 exit(1);
293         }
294         
295         if(get_global_sam_sid()==False) {
296                 fprintf(stderr, "Can not read machine SID\n");
297                 return 0;
298         }
299
300         while ((ch = getopt(argc, argv, "a:c:d:ln:p:r:st:u:vx:")) != EOF) {
301                 switch(ch) {
302                 case 'a':
303                         add_group = True;
304                         group=optarg;
305                         break;
306                 case 'c':
307                         change_group = True;
308                         sid=optarg;
309                         break;
310                 case 'd':
311                         group_desc=optarg;
312                         break;
313                 case 'l':
314                         long_list = True;
315                         break;
316                 case 'n':
317                         nt_group = True;
318                         ntgroup=optarg;
319                         break;
320                 case 'p':
321                         priv = True;
322                         privilege=optarg;
323                         break;
324                 case 'r':
325                         rid = atoi(optarg);
326                         break;
327                 case 's':
328                         long_list = False;
329                         break;
330                 case 't':
331                         group_type = True;
332                         groupt=optarg;
333                         break;
334                 case 'u':
335                         group=optarg;
336                         break;
337                 case 'v':
338                         view_group = True;
339                         break;
340                 case 'x':
341                         delete_group = True;
342                         group=optarg;
343                         break;
344                 /*default:
345                         usage();*/
346                 }
347         }
348         
349         
350         if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) > 1) {
351                 fprintf (stderr, "Incompatible options on command line!\n");
352                 usage();
353                 exit(1);
354         }
355
356         /* no option on command line -> list groups */  
357         if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) == 0)
358                 view_group = True;
359
360         
361         if (group_type==False)
362                 sid_type=SID_NAME_UNKNOWN;
363         else {
364                 switch (groupt[0]) {
365                         case 'l':
366                         case 'L':
367                                 sid_type=SID_NAME_ALIAS;
368                                 break;
369                         case 'd':
370                         case 'D':
371                                 sid_type=SID_NAME_DOM_GRP;
372                                 break;
373                         case 'b':
374                         case 'B':
375                                 sid_type=SID_NAME_WKN_GRP;
376                                 break;
377                         default:
378                                 sid_type=SID_NAME_UNKNOWN;
379                                 break;
380                 }
381         }
382
383         if (add_group) {
384                 gid_t gid=nametogid(group);
385                 if (gid==-1) {
386                         printf("unix group %s doesn't exist!\n", group);
387                         return -1;
388                 }
389
390                 if (rid == -1) {
391                         rid = pdb_gid_to_group_rid(gid);
392                 }
393                 return addgroup(gid, sid_type, ntgroup?ntgroup:group,
394                                 group_desc, privilege, rid);
395         }
396
397         if (view_group)
398                 return listgroup(sid_type, long_list);
399
400         if (delete_group)
401                 return deletegroup(group);
402         
403         if (change_group) {             
404                 return changegroup(sid, group, sid_type, ntgroup, group_desc, privilege);
405         }
406         
407         usage();
408
409         return 0;
410 }