Initial import
[samba] / source / utils / net_rpc_rights.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) Gerald (Jerry) Carter          2004
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19  
20 #include "includes.h"
21 #include "utils/net.h"
22
23 /********************************************************************
24 ********************************************************************/
25
26 static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd,
27                                 TALLOC_CTX *mem_ctx,
28                                 DOM_SID *sid,
29                                 fstring name)
30 {
31         POLICY_HND pol;
32         uint32 *sid_types;
33         NTSTATUS result;
34         char **domains, **names;
35
36         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
37                 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
38                 
39         if ( !NT_STATUS_IS_OK(result) )
40                 return result;
41
42         result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types);
43         
44         if ( NT_STATUS_IS_OK(result) ) {
45                 if ( *domains[0] )
46                         fstr_sprintf( name, "%s\\%s", domains[0], names[0] );
47                 else
48                         fstrcpy( name, names[0] );
49         }
50
51         rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
52         return result;
53 }
54
55 /********************************************************************
56 ********************************************************************/
57
58 static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
59                             TALLOC_CTX *mem_ctx,
60                             DOM_SID *sid, const char *name)
61 {
62         POLICY_HND pol;
63         uint32 *sid_types;
64         NTSTATUS result;
65         DOM_SID *sids;
66
67         /* maybe its a raw SID */
68         if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) {
69                 return NT_STATUS_OK;
70         }
71
72         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
73                 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
74                 
75         if ( !NT_STATUS_IS_OK(result) )
76                 return result;
77
78         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, &sids, &sid_types);
79         
80         if ( NT_STATUS_IS_OK(result) )
81                 sid_copy( sid, &sids[0] );
82
83         rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
84         return result;
85 }
86
87 /********************************************************************
88 ********************************************************************/
89
90 static NTSTATUS enum_privileges(struct rpc_pipe_client *pipe_hnd,
91                                 TALLOC_CTX *ctx,
92                                 POLICY_HND *pol )
93 {
94         NTSTATUS result;
95         uint32 enum_context = 0;
96         uint32 pref_max_length=0x1000;
97         uint32 count=0;
98         char   **privs_name;
99         uint32 *privs_high;
100         uint32 *privs_low;
101         int i;
102         uint16 lang_id=0;
103         uint16 lang_id_sys=0;
104         uint16 lang_id_desc;
105         fstring description;
106
107         result = rpccli_lsa_enum_privilege(pipe_hnd, ctx, pol, &enum_context, 
108                 pref_max_length, &count, &privs_name, &privs_high, &privs_low);
109
110         if ( !NT_STATUS_IS_OK(result) )
111                 return result;
112
113         /* Print results */
114         
115         for (i = 0; i < count; i++) {
116                 d_printf("%30s  ", privs_name[i] ? privs_name[i] : "*unknown*" );
117                 
118                 /* try to get the description */
119                 
120                 if ( !NT_STATUS_IS_OK(rpccli_lsa_get_dispname(pipe_hnd, ctx, pol, 
121                         privs_name[i], lang_id, lang_id_sys, description, &lang_id_desc)) )
122                 {
123                         d_printf("??????\n");
124                         continue;
125                 }
126                 
127                 d_printf("%s\n", description );         
128         }
129
130         return NT_STATUS_OK;
131 }
132
133 /********************************************************************
134 ********************************************************************/
135
136 static NTSTATUS check_privilege_for_user(struct rpc_pipe_client *pipe_hnd,
137                                         TALLOC_CTX *ctx,
138                                         POLICY_HND *pol,
139                                         DOM_SID *sid,
140                                         const char *right)
141 {
142         NTSTATUS result;
143         uint32 count;
144         char **rights;
145         int i;
146
147         result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
148
149         if (!NT_STATUS_IS_OK(result)) {
150                 return result;
151         }
152
153         if (count == 0) {
154                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
155         }
156                 
157         for (i = 0; i < count; i++) {
158                 if (StrCaseCmp(rights[i], right) == 0) {
159                         return NT_STATUS_OK;
160                 }
161         }
162
163         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
164 }
165
166 /********************************************************************
167 ********************************************************************/
168
169 static NTSTATUS enum_privileges_for_user(struct rpc_pipe_client *pipe_hnd,
170                                         TALLOC_CTX *ctx,
171                                         POLICY_HND *pol,
172                                         DOM_SID *sid )
173 {
174         NTSTATUS result;
175         uint32 count;
176         char **rights;
177         int i;
178
179         result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
180
181         if (!NT_STATUS_IS_OK(result))
182                 return result;
183
184         if ( count == 0 )
185                 d_printf("No privileges assigned\n");
186                 
187         for (i = 0; i < count; i++) {
188                 printf("%s\n", rights[i]);
189         }
190
191         return NT_STATUS_OK;
192 }
193
194 /********************************************************************
195 ********************************************************************/
196
197 static NTSTATUS enum_accounts_for_privilege(struct rpc_pipe_client *pipe_hnd,
198                                                 TALLOC_CTX *ctx,
199                                                 POLICY_HND *pol,
200                                                 const char *privilege)
201 {
202         NTSTATUS result;
203         uint32 enum_context=0;
204         uint32 pref_max_length=0x1000;
205         DOM_SID *sids;
206         uint32 count=0;
207         int i;
208         fstring name;
209
210         result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
211                 pref_max_length, &count, &sids);
212
213         if (!NT_STATUS_IS_OK(result))
214                 return result;
215                 
216         d_printf("%s:\n", privilege);
217
218         for ( i=0; i<count; i++ ) {
219         
220                    
221                 result = check_privilege_for_user( pipe_hnd, ctx, pol, &sids[i], privilege);
222                 
223                 if ( ! NT_STATUS_IS_OK(result)) {
224                         if ( ! NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
225                                 return result;
226                         }
227                         continue;
228                 }
229
230                 /* try to convert the SID to a name.  Fall back to 
231                    printing the raw SID if necessary */
232                 result = sid_to_name( pipe_hnd, ctx, &sids[i], name );
233                 if ( !NT_STATUS_IS_OK (result) )
234                         fstrcpy( name, sid_string_static(&sids[i]) );
235                         
236                 d_printf("  %s\n", name);
237         }
238
239         return NT_STATUS_OK;
240 }
241
242 /********************************************************************
243 ********************************************************************/
244
245 static NTSTATUS enum_privileges_for_accounts(struct rpc_pipe_client *pipe_hnd,
246                                                 TALLOC_CTX *ctx,
247                                                 POLICY_HND *pol)
248 {
249         NTSTATUS result;
250         uint32 enum_context=0;
251         uint32 pref_max_length=0x1000;
252         DOM_SID *sids;
253         uint32 count=0;
254         int i;
255         fstring name;
256
257         result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
258                 pref_max_length, &count, &sids);
259
260         if (!NT_STATUS_IS_OK(result))
261                 return result;
262                 
263         for ( i=0; i<count; i++ ) {
264         
265                 /* try to convert the SID to a name.  Fall back to 
266                    printing the raw SID if necessary */
267                    
268                 result = sid_to_name(pipe_hnd, ctx, &sids[i], name );
269                 if ( !NT_STATUS_IS_OK (result) )
270                         fstrcpy( name, sid_string_static(&sids[i]) );
271                         
272                 d_printf("%s\n", name);
273                 
274                 result = enum_privileges_for_user(pipe_hnd, ctx, pol, &sids[i] );
275                 
276                 if ( !NT_STATUS_IS_OK(result) )
277                         return result;
278
279                 d_printf("\n");
280         }
281
282         return NT_STATUS_OK;
283 }
284
285 /********************************************************************
286 ********************************************************************/
287
288 static NTSTATUS rpc_rights_list_internal(const DOM_SID *domain_sid,
289                                         const char *domain_name, 
290                                         struct cli_state *cli,
291                                         struct rpc_pipe_client *pipe_hnd,
292                                         TALLOC_CTX *mem_ctx, 
293                                         int argc,
294                                         const char **argv )
295 {
296         POLICY_HND pol;
297         NTSTATUS result;
298         DOM_SID sid;
299         fstring privname;
300         fstring description;
301         uint16 lang_id = 0;
302         uint16 lang_id_sys = 0;
303         uint16 lang_id_desc;
304         
305         
306         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
307                 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
308
309         if ( !NT_STATUS_IS_OK(result) )
310                 return result;
311         
312         /* backwards compatibility; just list available privileges if no arguement */
313            
314         if (argc == 0) {
315                 result = enum_privileges(pipe_hnd, mem_ctx, &pol );
316                 goto done;
317         }
318
319         if (strequal(argv[0], "privileges")) {
320                 int i = 1;
321
322                 if (argv[1] == NULL) {
323                         result = enum_privileges(pipe_hnd, mem_ctx, &pol );
324                         goto done;
325                 }
326
327                 while ( argv[i] != NULL ) {
328                         fstrcpy( privname, argv[i] );
329                         i++;
330                 
331                         /* verify that this is a valid privilege for error reporting */
332                         
333                         result = rpccli_lsa_get_dispname(pipe_hnd, mem_ctx, &pol, privname, lang_id, 
334                                 lang_id_sys, description, &lang_id_desc);
335                         
336                         if ( !NT_STATUS_IS_OK(result) ) {
337                                 if ( NT_STATUS_EQUAL( result, NT_STATUS_NO_SUCH_PRIVILEGE ) ) 
338                                         d_fprintf(stderr, "No such privilege exists: %s.\n", privname);
339                                 else
340                                         d_fprintf(stderr, "Error resolving privilege display name [%s].\n", nt_errstr(result));
341                                 continue;
342                         }
343                         
344                         result = enum_accounts_for_privilege(pipe_hnd, mem_ctx, &pol, privname);
345                         if (!NT_STATUS_IS_OK(result)) {
346                                 d_fprintf(stderr, "Error enumerating accounts for privilege %s [%s].\n", 
347                                         privname, nt_errstr(result));
348                                 continue;
349                         }
350                 }
351                 goto done;
352         }
353
354         /* special case to enumerate all privileged SIDs with associated rights */
355         
356         if (strequal( argv[0], "accounts")) {
357                 int i = 1;
358
359                 if (argv[1] == NULL) {
360                         result = enum_privileges_for_accounts(pipe_hnd, mem_ctx, &pol);
361                         goto done;
362                 }
363
364                 while (argv[i] != NULL) {
365                         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[i]);
366                         if (!NT_STATUS_IS_OK(result)) {
367                                 goto done;
368                         }
369                         result = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid);
370                         if (!NT_STATUS_IS_OK(result)) {
371                                 goto done;
372                         }
373                         i++;
374                 }
375                 goto done;
376         }
377
378         /* backward comaptibility: if no keyword provided, treat the key
379            as an account name */
380         if (argc > 1) {
381                 d_printf("Usage: net rpc rights list [[accounts|privileges] [name|SID]]\n");
382                 result = NT_STATUS_OK;
383                 goto done;
384         }
385
386         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
387         if (!NT_STATUS_IS_OK(result)) {
388                 goto done;
389         }
390         result = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid );
391
392 done:
393         rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
394
395         return result;
396 }
397
398 /********************************************************************
399 ********************************************************************/
400
401 static NTSTATUS rpc_rights_grant_internal(const DOM_SID *domain_sid,
402                                         const char *domain_name, 
403                                         struct cli_state *cli,
404                                         struct rpc_pipe_client *pipe_hnd,
405                                         TALLOC_CTX *mem_ctx, 
406                                         int argc,
407                                         const char **argv )
408 {
409         POLICY_HND dom_pol;
410         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
411
412         DOM_SID sid;
413
414         if (argc < 2 ) {
415                 d_printf("Usage: net rpc rights grant <name|SID> <rights...>\n");
416                 return NT_STATUS_OK;
417         }
418
419         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
420         if (!NT_STATUS_IS_OK(result))
421                 return result;  
422
423         result = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, 
424                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
425                                      &dom_pol);
426
427         if (!NT_STATUS_IS_OK(result))
428                 return result;  
429
430         result = rpccli_lsa_add_account_rights(pipe_hnd, mem_ctx, &dom_pol, sid, 
431                                             argc-1, argv+1);
432
433         if (!NT_STATUS_IS_OK(result))
434                 goto done;
435                 
436         d_printf("Successfully granted rights.\n");
437
438  done:
439         if ( !NT_STATUS_IS_OK(result) ) {
440                 d_fprintf(stderr, "Failed to grant privileges for %s (%s)\n", 
441                         argv[0], nt_errstr(result));
442         }
443                 
444         rpccli_lsa_close(pipe_hnd, mem_ctx, &dom_pol);
445         
446         return result;
447 }
448
449 /********************************************************************
450 ********************************************************************/
451
452 static NTSTATUS rpc_rights_revoke_internal(const DOM_SID *domain_sid,
453                                         const char *domain_name, 
454                                         struct cli_state *cli,
455                                         struct rpc_pipe_client *pipe_hnd,
456                                         TALLOC_CTX *mem_ctx, 
457                                         int argc,
458                                         const char **argv )
459 {
460         POLICY_HND dom_pol;
461         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
462
463         DOM_SID sid;
464
465         if (argc < 2 ) {
466                 d_printf("Usage: net rpc rights revoke <name|SID> <rights...>\n");
467                 return NT_STATUS_OK;
468         }
469
470         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
471         if (!NT_STATUS_IS_OK(result))
472                 return result;  
473
474         result = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, 
475                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
476                                      &dom_pol);
477
478         if (!NT_STATUS_IS_OK(result))
479                 return result;  
480
481         result = rpccli_lsa_remove_account_rights(pipe_hnd, mem_ctx, &dom_pol, sid, 
482                                                False, argc-1, argv+1);
483
484         if (!NT_STATUS_IS_OK(result))
485                 goto done;
486
487         d_printf("Successfully revoked rights.\n");
488
489 done:
490         if ( !NT_STATUS_IS_OK(result) ) {
491                 d_fprintf(stderr, "Failed to revoke privileges for %s (%s)", 
492                         argv[0], nt_errstr(result));
493         }
494         
495         rpccli_lsa_close(pipe_hnd, mem_ctx, &dom_pol);
496
497         return result;
498 }       
499
500
501 /********************************************************************
502 ********************************************************************/
503
504 static int rpc_rights_list( int argc, const char **argv )
505 {
506         return run_rpc_command( NULL, PI_LSARPC, 0, 
507                 rpc_rights_list_internal, argc, argv );
508 }
509
510 /********************************************************************
511 ********************************************************************/
512
513 static int rpc_rights_grant( int argc, const char **argv )
514 {
515         return run_rpc_command( NULL, PI_LSARPC, 0, 
516                 rpc_rights_grant_internal, argc, argv );
517 }
518
519 /********************************************************************
520 ********************************************************************/
521
522 static int rpc_rights_revoke( int argc, const char **argv )
523 {
524         return run_rpc_command( NULL, PI_LSARPC, 0, 
525                 rpc_rights_revoke_internal, argc, argv );
526 }
527
528 /********************************************************************
529 ********************************************************************/
530
531 static int net_help_rights( int argc, const char **argv )
532 {
533         d_printf("net rpc rights list [{accounts|privileges} [name|SID]]   View available or assigned privileges\n");
534         d_printf("net rpc rights grant <name|SID> <right>                  Assign privilege[s]\n");
535         d_printf("net rpc rights revoke <name|SID> <right>                 Revoke privilege[s]\n");
536         
537         d_printf("\nBoth 'grant' and 'revoke' require a SID and a list of privilege names.\n");
538         d_printf("For example\n");
539         d_printf("\n  net rpc rights grant 'VALE\\biddle' SePrintOperatorPrivilege SeDiskOperatorPrivilege\n");
540         d_printf("\nwould grant the printer admin and disk manager rights to the user 'VALE\\biddle'\n\n");
541         
542         
543         return -1;
544 }
545
546 /********************************************************************
547 ********************************************************************/
548
549 int net_rpc_rights(int argc, const char **argv) 
550 {
551         struct functable func[] = {
552                 {"list", rpc_rights_list},
553                 {"grant", rpc_rights_grant},
554                 {"revoke", rpc_rights_revoke},
555                 {NULL, NULL}
556         };
557         
558         if ( argc )
559                 return net_run_function( argc, argv, func, net_help_rights );
560                 
561         return net_help_rights( argc, argv );
562 }