Globally replace 'global_sam_sid' with get_global_sam_sid(), a self
[kai/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 extern pstring global_myname;
25 extern pstring global_myworkgroup;
26
27 /*
28  * Next two lines needed for SunOS and don't
29  * hurt anything else...
30  */
31 extern char *optarg;
32 extern int optind;
33
34 /*********************************************************
35  Print command usage on stderr and die.
36 **********************************************************/
37 static void usage(void)
38 {
39         if (getuid() == 0) {
40                 printf("smbgroupedit options\n");
41         } else {
42                 printf("You need to be root to use this tool!\n");
43         }
44         printf("options:\n");
45         printf("  -a group             create new group\n");
46         printf("    -n group           NT group name\n");
47         printf("    -p privilege       only local\n");
48         printf("  -v                   list groups\n");
49         printf("    -l                 long list (include details)\n");
50         printf("    -s                 short list (default)\n");
51         printf("  -c SID               change group\n");
52         printf("     -u unix 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 (!get_group_map_from_ntname(input, &map, 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(char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcomment, char *privilege)
88 {
89         PRIVILEGE_SET se_priv;
90         gid_t gid;
91         DOM_SID sid;
92         fstring string_sid;
93         fstring name, comment;
94
95         gid=nametogid(group);
96         if (gid==-1) {
97                 printf("unix group %s doesn't exist!\n", group);
98                 return -1;
99         }
100
101         local_gid_to_sid(&sid, gid);
102
103         sid_to_string(string_sid, &sid);
104         
105         if (ntgroup==NULL)
106                 fstrcpy(name, group);
107         else
108                 fstrcpy(name, ntgroup);
109         
110         if (ntcomment==NULL)
111                 fstrcpy(comment, "Local Unix group");
112         else
113                 fstrcpy(comment, ntcomment);
114
115         init_privilege(&se_priv);
116         if (privilege!=NULL)
117                 convert_priv_from_text(&se_priv, privilege);
118
119         if(!add_initial_entry(gid, string_sid, sid_type, name, comment, se_priv, PR_ACCESS_FROM_NETWORK)) {
120                 printf("adding entry for group %s failed!\n", group);
121                 free_privilege(&se_priv);
122                 return -1;
123         }
124
125         free_privilege(&se_priv);
126         return 0;
127 }
128
129 /*********************************************************
130  Change a group.
131 **********************************************************/
132 static int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *groupdesc, char *privilege)
133 {
134         DOM_SID sid;
135         GROUP_MAP map;
136         gid_t gid;
137
138         if (!get_sid_from_input(&sid, sid_string)) {
139                 return -1;
140         }
141
142         /* Get the current mapping from the database */
143         if(!get_group_map_from_sid(sid, &map, MAPPING_WITH_PRIV)) {
144                 printf("This SID does not exist in the database\n");
145                 return -1;
146         }
147
148         /* If a new Unix group is specified, check and change */
149         if (group!=NULL) {
150                 gid=nametogid(group);
151                 if (gid==-1) {
152                         printf("The UNIX group does not exist\n");
153                         return -1;
154                 } else
155                         map.gid=gid;
156         }
157         
158         /*
159          * Allow changing of group type only between domain and local
160          * We disallow changing Builtin groups !!! (SID problem)
161          */ 
162         if (sid_type==SID_NAME_ALIAS 
163             || sid_type==SID_NAME_DOM_GRP 
164             || sid_type==SID_NAME_UNKNOWN) {
165                 if (map.sid_name_use==SID_NAME_ALIAS 
166                     || map.sid_name_use==SID_NAME_DOM_GRP
167                     || map.sid_name_use==SID_NAME_UNKNOWN) {
168                         map.sid_name_use=sid_type;
169                 } else {
170                         printf("cannot change group type to builtin\n");
171                 };
172         } else {
173                 printf("cannot change group type from builtin\n");
174         }
175
176         if (ntgroup!=NULL)
177                 fstrcpy(map.nt_name, ntgroup);
178
179         /* Change comment if new one */
180         if (groupdesc!=NULL)
181                 fstrcpy(map.comment, groupdesc);
182
183         /* Change the privilege if new one */
184         if (privilege!=NULL)
185                 convert_priv_from_text(&map.priv_set, privilege);
186
187         if (!add_mapping_entry(&map, TDB_REPLACE)) {
188                 printf("Count not update group database\n");
189                 free_privilege(&map.priv_set);
190                 return -1;
191         }
192         
193         free_privilege(&map.priv_set);
194         return 0;
195 }
196
197 /*********************************************************
198  Delete the group.
199 **********************************************************/
200 static int deletegroup(char *group)
201 {
202         DOM_SID sid;
203
204         if (!get_sid_from_input(&sid, group)) {
205                 return -1;
206         }
207
208         if(!group_map_remove(sid)) {
209                 printf("removing group %s from the mapping db failed!\n", group);
210                 return -1;
211         }
212
213         return 0;
214 }
215
216 /*********************************************************
217  List the groups.
218 **********************************************************/
219 static int listgroup(enum SID_NAME_USE sid_type, BOOL long_list)
220 {
221         int entries,i;
222         GROUP_MAP *map=NULL;
223         fstring string_sid;
224         fstring group_type;
225         fstring priv_text;
226
227         if (!long_list)
228                 printf("NT group (SID) -> Unix group\n");
229                 
230         if (!enum_group_mapping(sid_type, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV))
231                 return -1;
232         
233         for (i=0; i<entries; i++) {
234                 decode_sid_name_use(group_type, (map[i]).sid_name_use);
235                 sid_to_string(string_sid, &map[i].sid);
236                 convert_priv_to_text(&(map[i].priv_set), priv_text);
237                 free_privilege(&(map[i].priv_set));
238                 
239                 if (!long_list)
240                         printf("%s (%s) -> %s\n", map[i].nt_name, string_sid, gidtoname(map[i].gid));
241                 else {
242                         printf("%s\n", map[i].nt_name);
243                         printf("\tSID       : %s\n", string_sid);
244                         printf("\tUnix group: %s\n", gidtoname(map[i].gid));
245                         printf("\tGroup type: %s\n", group_type);
246                         printf("\tComment   : %s\n", map[i].comment);
247                         printf("\tPrivilege : %s\n\n", priv_text);
248                 }
249         }
250
251         return 0;
252 }
253
254 /*********************************************************
255  Start here.
256 **********************************************************/
257 int main (int argc, char **argv)
258 {
259         int ch;
260         BOOL add_group = False;
261         BOOL view_group = False;
262         BOOL change_group = False;
263         BOOL delete_group = False;
264         BOOL nt_group = False;
265         BOOL priv = False;
266         BOOL group_type = False;
267         BOOL long_list = False;
268
269         char *group = NULL;
270         char *sid = NULL;
271         char *ntgroup = NULL;
272         char *privilege = NULL;
273         char *groupt = NULL;
274         char *group_desc = NULL;
275
276         enum SID_NAME_USE sid_type;
277
278         setup_logging("groupedit", True);
279
280         if (argc < 2) {
281                 usage();
282                 return 0;
283         }
284         
285         if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
286                 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
287                         dyn_CONFIGFILE);
288                 exit(1);
289         }
290
291         if (!*global_myname) {
292                 char *p;
293                 pstrcpy( global_myname, myhostname() );
294                 p = strchr_m(global_myname, '.' );
295                 if (p) 
296                         *p = 0;
297         }
298
299         strupper(global_myname);
300
301         fstrcpy(global_myworkgroup, lp_workgroup());
302         
303         if(!initialize_password_db(True)) {
304                 fprintf(stderr, "Can't setup password database vectors.\n");
305                 exit(1);
306         }
307         
308         if(get_global_sam_sid()==False) {
309                 fprintf(stderr, "Can not read machine SID\n");
310                 return 0;
311         }
312
313         while ((ch = getopt(argc, argv, "a:c:d:ln:p:st:u:vx:")) != EOF) {
314                 switch(ch) {
315                 case 'a':
316                         add_group = True;
317                         group=optarg;
318                         break;
319                 case 'c':
320                         change_group = True;
321                         sid=optarg;
322                         break;
323                 case 'd':
324                         group_desc=optarg;
325                         break;
326                 case 'l':
327                         long_list = True;
328                         break;
329                 case 'n':
330                         nt_group = True;
331                         ntgroup=optarg;
332                         break;
333                 case 'p':
334                         priv = True;
335                         privilege=optarg;
336                         break;
337                 case 's':
338                         long_list = False;
339                         break;
340                 case 't':
341                         group_type = True;
342                         groupt=optarg;
343                         break;
344                 case 'u':
345                         group=optarg;
346                         break;
347                 case 'v':
348                         view_group = True;
349                         break;
350                 case 'x':
351                         delete_group = True;
352                         group=optarg;
353                         break;
354                 /*default:
355                         usage();*/
356                 }
357         }
358         
359         
360         if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) > 1) {
361                 fprintf (stderr, "Incompatible options on command line!\n");
362                 usage();
363                 exit(1);
364         }
365
366         /* no option on command line -> list groups */  
367         if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) == 0)
368                 view_group = True;
369
370         
371         if (group_type==False)
372                 sid_type=SID_NAME_UNKNOWN;
373         else {
374                 switch (groupt[0]) {
375                         case 'l':
376                         case 'L':
377                                 sid_type=SID_NAME_ALIAS;
378                                 break;
379                         case 'd':
380                         case 'D':
381                                 sid_type=SID_NAME_DOM_GRP;
382                                 break;
383                         case 'b':
384                         case 'B':
385                                 sid_type=SID_NAME_WKN_GRP;
386                                 break;
387                         default:
388                                 sid_type=SID_NAME_UNKNOWN;
389                                 break;
390                 }
391         }
392
393         if (add_group)
394                 return addgroup(group, sid_type, ntgroup, group_desc, privilege);
395
396         if (view_group)
397                 return listgroup(sid_type, long_list);
398
399         if (delete_group)
400                 return deletegroup(group);
401         
402         if (change_group) {             
403                 return changegroup(sid, group, sid_type, ntgroup, group_desc, privilege);
404         }
405         
406         usage();
407
408         return 0;
409 }