Removed global_myworkgroup, global_myname, global_myscope. Added liberal
[samba.git] / source3 / 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         GROUP_MAP *map=NULL;
213         fstring string_sid;
214         fstring group_type;
215         fstring priv_text;
216
217         if (!long_list)
218                 printf("NT group (SID) -> Unix group\n");
219                 
220         if (!pdb_enum_group_mapping(sid_type, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV))
221                 return -1;
222         
223         for (i=0; i<entries; i++) {
224                 decode_sid_name_use(group_type, (map[i]).sid_name_use);
225                 sid_to_string(string_sid, &map[i].sid);
226                 convert_priv_to_text(&(map[i].priv_set), priv_text);
227                 free_privilege(&(map[i].priv_set));
228                 
229                 if (!long_list)
230                         printf("%s (%s) -> %s\n", map[i].nt_name, string_sid, gidtoname(map[i].gid));
231                 else {
232                         printf("%s\n", map[i].nt_name);
233                         printf("\tSID       : %s\n", string_sid);
234                         printf("\tUnix group: %s\n", gidtoname(map[i].gid));
235                         printf("\tGroup type: %s\n", group_type);
236                         printf("\tComment   : %s\n", map[i].comment);
237                         printf("\tPrivilege : %s\n\n", priv_text);
238                 }
239         }
240
241         return 0;
242 }
243
244 /*********************************************************
245  Start here.
246 **********************************************************/
247 int main (int argc, char **argv)
248 {
249         int ch;
250         BOOL add_group = False;
251         BOOL view_group = False;
252         BOOL change_group = False;
253         BOOL delete_group = False;
254         BOOL nt_group = False;
255         BOOL priv = False;
256         BOOL group_type = False;
257         BOOL long_list = False;
258
259         char *group = NULL;
260         char *sid = NULL;
261         char *ntgroup = NULL;
262         char *privilege = NULL;
263         char *groupt = NULL;
264         char *group_desc = NULL;
265
266         enum SID_NAME_USE sid_type;
267         uint32 rid = -1;
268
269         setup_logging("groupedit", True);
270
271         if (argc < 2) {
272                 usage();
273                 return 0;
274         }
275         
276         if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
277                 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
278                         dyn_CONFIGFILE);
279                 exit(1);
280         }
281
282         if (!init_names())
283                 exit(1);
284         
285         if(!initialize_password_db(True)) {
286                 fprintf(stderr, "Can't setup password database vectors.\n");
287                 exit(1);
288         }
289         
290         if(get_global_sam_sid()==False) {
291                 fprintf(stderr, "Can not read machine SID\n");
292                 return 0;
293         }
294
295         while ((ch = getopt(argc, argv, "a:c:d:ln:p:r:st:u:vx:")) != EOF) {
296                 switch(ch) {
297                 case 'a':
298                         add_group = True;
299                         group=optarg;
300                         break;
301                 case 'c':
302                         change_group = True;
303                         sid=optarg;
304                         break;
305                 case 'd':
306                         group_desc=optarg;
307                         break;
308                 case 'l':
309                         long_list = True;
310                         break;
311                 case 'n':
312                         nt_group = True;
313                         ntgroup=optarg;
314                         break;
315                 case 'p':
316                         priv = True;
317                         privilege=optarg;
318                         break;
319                 case 'r':
320                         rid = atoi(optarg);
321                         break;
322                 case 's':
323                         long_list = False;
324                         break;
325                 case 't':
326                         group_type = True;
327                         groupt=optarg;
328                         break;
329                 case 'u':
330                         group=optarg;
331                         break;
332                 case 'v':
333                         view_group = True;
334                         break;
335                 case 'x':
336                         delete_group = True;
337                         group=optarg;
338                         break;
339                 /*default:
340                         usage();*/
341                 }
342         }
343         
344         
345         if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) > 1) {
346                 fprintf (stderr, "Incompatible options on command line!\n");
347                 usage();
348                 exit(1);
349         }
350
351         /* no option on command line -> list groups */  
352         if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) == 0)
353                 view_group = True;
354
355         
356         if (group_type==False)
357                 sid_type=SID_NAME_UNKNOWN;
358         else {
359                 switch (groupt[0]) {
360                         case 'l':
361                         case 'L':
362                                 sid_type=SID_NAME_ALIAS;
363                                 break;
364                         case 'd':
365                         case 'D':
366                                 sid_type=SID_NAME_DOM_GRP;
367                                 break;
368                         case 'b':
369                         case 'B':
370                                 sid_type=SID_NAME_WKN_GRP;
371                                 break;
372                         default:
373                                 sid_type=SID_NAME_UNKNOWN;
374                                 break;
375                 }
376         }
377
378         if (add_group) {
379                 gid_t gid=nametogid(group);
380                 if (gid==-1) {
381                         printf("unix group %s doesn't exist!\n", group);
382                         return -1;
383                 }
384
385                 if (rid == -1) {
386                         rid = pdb_gid_to_group_rid(gid);
387                 }
388                 return addgroup(gid, sid_type, ntgroup?ntgroup:group,
389                                 group_desc, privilege, rid);
390         }
391
392         if (view_group)
393                 return listgroup(sid_type, long_list);
394
395         if (delete_group)
396                 return deletegroup(group);
397         
398         if (change_group) {             
399                 return changegroup(sid, group, sid_type, ntgroup, group_desc, privilege);
400         }
401         
402         usage();
403
404         return 0;
405 }