84661479b52be5372e46d24ec0aa1e1863d80dc3
[bbaumbach/samba-autobuild/.git] / source3 / 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 3 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         enum lsa_SidType *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         enum lsa_SidType *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,
79                                          NULL, 1, &sids, &sid_types);
80         
81         if ( NT_STATUS_IS_OK(result) )
82                 sid_copy( sid, &sids[0] );
83
84         rpccli_lsa_Close(pipe_hnd, mem_ctx, &pol);
85         return result;
86 }
87
88 /********************************************************************
89 ********************************************************************/
90
91 static NTSTATUS enum_privileges(struct rpc_pipe_client *pipe_hnd,
92                                 TALLOC_CTX *ctx,
93                                 POLICY_HND *pol )
94 {
95         NTSTATUS result;
96         uint32 enum_context = 0;
97         uint32 pref_max_length=0x1000;
98         uint32 count=0;
99         char   **privs_name;
100         uint32 *privs_high;
101         uint32 *privs_low;
102         int i;
103         uint16 lang_id=0;
104         uint16 lang_id_sys=0;
105         uint16 lang_id_desc;
106         fstring description;
107
108         result = rpccli_lsa_enum_privilege(pipe_hnd, ctx, pol, &enum_context, 
109                 pref_max_length, &count, &privs_name, &privs_high, &privs_low);
110
111         if ( !NT_STATUS_IS_OK(result) )
112                 return result;
113
114         /* Print results */
115         
116         for (i = 0; i < count; i++) {
117                 d_printf("%30s  ", privs_name[i] ? privs_name[i] : "*unknown*" );
118                 
119                 /* try to get the description */
120                 
121                 if ( !NT_STATUS_IS_OK(rpccli_lsa_get_dispname(pipe_hnd, ctx, pol, 
122                         privs_name[i], lang_id, lang_id_sys, description, &lang_id_desc)) )
123                 {
124                         d_printf("??????\n");
125                         continue;
126                 }
127                 
128                 d_printf("%s\n", description );         
129         }
130
131         return NT_STATUS_OK;
132 }
133
134 /********************************************************************
135 ********************************************************************/
136
137 static NTSTATUS check_privilege_for_user(struct rpc_pipe_client *pipe_hnd,
138                                         TALLOC_CTX *ctx,
139                                         POLICY_HND *pol,
140                                         DOM_SID *sid,
141                                         const char *right)
142 {
143         NTSTATUS result;
144         uint32 count;
145         char **rights;
146         int i;
147
148         result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
149
150         if (!NT_STATUS_IS_OK(result)) {
151                 return result;
152         }
153
154         if (count == 0) {
155                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
156         }
157                 
158         for (i = 0; i < count; i++) {
159                 if (StrCaseCmp(rights[i], right) == 0) {
160                         return NT_STATUS_OK;
161                 }
162         }
163
164         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
165 }
166
167 /********************************************************************
168 ********************************************************************/
169
170 static NTSTATUS enum_privileges_for_user(struct rpc_pipe_client *pipe_hnd,
171                                         TALLOC_CTX *ctx,
172                                         POLICY_HND *pol,
173                                         DOM_SID *sid )
174 {
175         NTSTATUS result;
176         uint32 count;
177         char **rights;
178         int i;
179
180         result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
181
182         if (!NT_STATUS_IS_OK(result))
183                 return result;
184
185         if ( count == 0 )
186                 d_printf("No privileges assigned\n");
187                 
188         for (i = 0; i < count; i++) {
189                 printf("%s\n", rights[i]);
190         }
191
192         return NT_STATUS_OK;
193 }
194
195 /********************************************************************
196 ********************************************************************/
197
198 static NTSTATUS enum_accounts_for_privilege(struct rpc_pipe_client *pipe_hnd,
199                                                 TALLOC_CTX *ctx,
200                                                 POLICY_HND *pol,
201                                                 const char *privilege)
202 {
203         NTSTATUS result;
204         uint32 enum_context=0;
205         uint32 pref_max_length=0x1000;
206         DOM_SID *sids;
207         uint32 count=0;
208         int i;
209         fstring name;
210
211         result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
212                 pref_max_length, &count, &sids);
213
214         if (!NT_STATUS_IS_OK(result))
215                 return result;
216                 
217         d_printf("%s:\n", privilege);
218
219         for ( i=0; i<count; i++ ) {
220         
221                    
222                 result = check_privilege_for_user( pipe_hnd, ctx, pol, &sids[i], privilege);
223                 
224                 if ( ! NT_STATUS_IS_OK(result)) {
225                         if ( ! NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
226                                 return result;
227                         }
228                         continue;
229                 }
230
231                 /* try to convert the SID to a name.  Fall back to 
232                    printing the raw SID if necessary */
233                 result = sid_to_name( pipe_hnd, ctx, &sids[i], name );
234                 if ( !NT_STATUS_IS_OK (result) )
235                         fstrcpy( name, sid_string_static(&sids[i]) );
236                         
237                 d_printf("  %s\n", name);
238         }
239
240         return NT_STATUS_OK;
241 }
242
243 /********************************************************************
244 ********************************************************************/
245
246 static NTSTATUS enum_privileges_for_accounts(struct rpc_pipe_client *pipe_hnd,
247                                                 TALLOC_CTX *ctx,
248                                                 POLICY_HND *pol)
249 {
250         NTSTATUS result;
251         uint32 enum_context=0;
252         uint32 pref_max_length=0x1000;
253         DOM_SID *sids;
254         uint32 count=0;
255         int i;
256         fstring name;
257
258         result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
259                 pref_max_length, &count, &sids);
260
261         if (!NT_STATUS_IS_OK(result))
262                 return result;
263                 
264         for ( i=0; i<count; i++ ) {
265         
266                 /* try to convert the SID to a name.  Fall back to 
267                    printing the raw SID if necessary */
268                    
269                 result = sid_to_name(pipe_hnd, ctx, &sids[i], name );
270                 if ( !NT_STATUS_IS_OK (result) )
271                         fstrcpy( name, sid_string_static(&sids[i]) );
272                         
273                 d_printf("%s\n", name);
274                 
275                 result = enum_privileges_for_user(pipe_hnd, ctx, pol, &sids[i] );
276                 
277                 if ( !NT_STATUS_IS_OK(result) )
278                         return result;
279
280                 d_printf("\n");
281         }
282
283         return NT_STATUS_OK;
284 }
285
286 /********************************************************************
287 ********************************************************************/
288
289 static NTSTATUS rpc_rights_list_internal(const DOM_SID *domain_sid,
290                                         const char *domain_name, 
291                                         struct cli_state *cli,
292                                         struct rpc_pipe_client *pipe_hnd,
293                                         TALLOC_CTX *mem_ctx, 
294                                         int argc,
295                                         const char **argv )
296 {
297         POLICY_HND pol;
298         NTSTATUS result;
299         DOM_SID sid;
300         fstring privname;
301         fstring description;
302         uint16 lang_id = 0;
303         uint16 lang_id_sys = 0;
304         uint16 lang_id_desc;
305         
306         
307         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
308                 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
309
310         if ( !NT_STATUS_IS_OK(result) )
311                 return result;
312         
313         /* backwards compatibility; just list available privileges if no arguement */
314            
315         if (argc == 0) {
316                 result = enum_privileges(pipe_hnd, mem_ctx, &pol );
317                 goto done;
318         }
319
320         if (strequal(argv[0], "privileges")) {
321                 int i = 1;
322
323                 if (argv[1] == NULL) {
324                         result = enum_privileges(pipe_hnd, mem_ctx, &pol );
325                         goto done;
326                 }
327
328                 while ( argv[i] != NULL ) {
329                         fstrcpy( privname, argv[i] );
330                         i++;
331                 
332                         /* verify that this is a valid privilege for error reporting */
333                         
334                         result = rpccli_lsa_get_dispname(pipe_hnd, mem_ctx, &pol, privname, lang_id, 
335                                 lang_id_sys, description, &lang_id_desc);
336                         
337                         if ( !NT_STATUS_IS_OK(result) ) {
338                                 if ( NT_STATUS_EQUAL( result, NT_STATUS_NO_SUCH_PRIVILEGE ) ) 
339                                         d_fprintf(stderr, "No such privilege exists: %s.\n", privname);
340                                 else
341                                         d_fprintf(stderr, "Error resolving privilege display name [%s].\n", nt_errstr(result));
342                                 continue;
343                         }
344                         
345                         result = enum_accounts_for_privilege(pipe_hnd, mem_ctx, &pol, privname);
346                         if (!NT_STATUS_IS_OK(result)) {
347                                 d_fprintf(stderr, "Error enumerating accounts for privilege %s [%s].\n", 
348                                         privname, nt_errstr(result));
349                                 continue;
350                         }
351                 }
352                 goto done;
353         }
354
355         /* special case to enumerate all privileged SIDs with associated rights */
356         
357         if (strequal( argv[0], "accounts")) {
358                 int i = 1;
359
360                 if (argv[1] == NULL) {
361                         result = enum_privileges_for_accounts(pipe_hnd, mem_ctx, &pol);
362                         goto done;
363                 }
364
365                 while (argv[i] != NULL) {
366                         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[i]);
367                         if (!NT_STATUS_IS_OK(result)) {
368                                 goto done;
369                         }
370                         result = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid);
371                         if (!NT_STATUS_IS_OK(result)) {
372                                 goto done;
373                         }
374                         i++;
375                 }
376                 goto done;
377         }
378
379         /* backward comaptibility: if no keyword provided, treat the key
380            as an account name */
381         if (argc > 1) {
382                 d_printf("Usage: net rpc rights list [[accounts|privileges] [name|SID]]\n");
383                 result = NT_STATUS_OK;
384                 goto done;
385         }
386
387         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
388         if (!NT_STATUS_IS_OK(result)) {
389                 goto done;
390         }
391         result = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid );
392
393 done:
394         rpccli_lsa_Close(pipe_hnd, mem_ctx, &pol);
395
396         return result;
397 }
398
399 /********************************************************************
400 ********************************************************************/
401
402 static NTSTATUS rpc_rights_grant_internal(const DOM_SID *domain_sid,
403                                         const char *domain_name, 
404                                         struct cli_state *cli,
405                                         struct rpc_pipe_client *pipe_hnd,
406                                         TALLOC_CTX *mem_ctx, 
407                                         int argc,
408                                         const char **argv )
409 {
410         POLICY_HND dom_pol;
411         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
412
413         DOM_SID sid;
414
415         if (argc < 2 ) {
416                 d_printf("Usage: net rpc rights grant <name|SID> <rights...>\n");
417                 return NT_STATUS_OK;
418         }
419
420         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
421         if (!NT_STATUS_IS_OK(result))
422                 return result;  
423
424         result = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, 
425                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
426                                      &dom_pol);
427
428         if (!NT_STATUS_IS_OK(result))
429                 return result;  
430
431         result = rpccli_lsa_add_account_rights(pipe_hnd, mem_ctx, &dom_pol, sid, 
432                                             argc-1, argv+1);
433
434         if (!NT_STATUS_IS_OK(result))
435                 goto done;
436                 
437         d_printf("Successfully granted rights.\n");
438
439  done:
440         if ( !NT_STATUS_IS_OK(result) ) {
441                 d_fprintf(stderr, "Failed to grant privileges for %s (%s)\n", 
442                         argv[0], nt_errstr(result));
443         }
444                 
445         rpccli_lsa_Close(pipe_hnd, mem_ctx, &dom_pol);
446         
447         return result;
448 }
449
450 /********************************************************************
451 ********************************************************************/
452
453 static NTSTATUS rpc_rights_revoke_internal(const DOM_SID *domain_sid,
454                                         const char *domain_name, 
455                                         struct cli_state *cli,
456                                         struct rpc_pipe_client *pipe_hnd,
457                                         TALLOC_CTX *mem_ctx, 
458                                         int argc,
459                                         const char **argv )
460 {
461         POLICY_HND dom_pol;
462         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
463
464         DOM_SID sid;
465
466         if (argc < 2 ) {
467                 d_printf("Usage: net rpc rights revoke <name|SID> <rights...>\n");
468                 return NT_STATUS_OK;
469         }
470
471         result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
472         if (!NT_STATUS_IS_OK(result))
473                 return result;  
474
475         result = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, 
476                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
477                                      &dom_pol);
478
479         if (!NT_STATUS_IS_OK(result))
480                 return result;  
481
482         result = rpccli_lsa_remove_account_rights(pipe_hnd, mem_ctx, &dom_pol, sid, 
483                                                False, argc-1, argv+1);
484
485         if (!NT_STATUS_IS_OK(result))
486                 goto done;
487
488         d_printf("Successfully revoked rights.\n");
489
490 done:
491         if ( !NT_STATUS_IS_OK(result) ) {
492                 d_fprintf(stderr, "Failed to revoke privileges for %s (%s)\n", 
493                         argv[0], nt_errstr(result));
494         }
495         
496         rpccli_lsa_Close(pipe_hnd, mem_ctx, &dom_pol);
497
498         return result;
499 }       
500
501
502 /********************************************************************
503 ********************************************************************/
504
505 static int rpc_rights_list( int argc, const char **argv )
506 {
507         return run_rpc_command( NULL, PI_LSARPC, 0, 
508                 rpc_rights_list_internal, argc, argv );
509 }
510
511 /********************************************************************
512 ********************************************************************/
513
514 static int rpc_rights_grant( int argc, const char **argv )
515 {
516         return run_rpc_command( NULL, PI_LSARPC, 0, 
517                 rpc_rights_grant_internal, argc, argv );
518 }
519
520 /********************************************************************
521 ********************************************************************/
522
523 static int rpc_rights_revoke( int argc, const char **argv )
524 {
525         return run_rpc_command( NULL, PI_LSARPC, 0, 
526                 rpc_rights_revoke_internal, argc, argv );
527 }
528
529 /********************************************************************
530 ********************************************************************/
531
532 static int net_help_rights( int argc, const char **argv )
533 {
534         d_printf("net rpc rights list [{accounts|privileges} [name|SID]]   View available or assigned privileges\n");
535         d_printf("net rpc rights grant <name|SID> <right>                  Assign privilege[s]\n");
536         d_printf("net rpc rights revoke <name|SID> <right>                 Revoke privilege[s]\n");
537         
538         d_printf("\nBoth 'grant' and 'revoke' require a SID and a list of privilege names.\n");
539         d_printf("For example\n");
540         d_printf("\n  net rpc rights grant 'VALE\\biddle' SePrintOperatorPrivilege SeDiskOperatorPrivilege\n");
541         d_printf("\nwould grant the printer admin and disk manager rights to the user 'VALE\\biddle'\n\n");
542         
543         
544         return -1;
545 }
546
547 /********************************************************************
548 ********************************************************************/
549
550 int net_rpc_rights(int argc, const char **argv) 
551 {
552         struct functable func[] = {
553                 {"list", rpc_rights_list},
554                 {"grant", rpc_rights_grant},
555                 {"revoke", rpc_rights_revoke},
556                 {NULL, NULL}
557         };
558         
559         if ( argc )
560                 return net_run_function( argc, argv, func, net_help_rights );
561                 
562         return net_help_rights( argc, argv );
563 }
564
565 static NTSTATUS rpc_sh_rights_list(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
566                                    struct rpc_pipe_client *pipe_hnd,
567                                    int argc, const char **argv)
568 {
569         return rpc_rights_list_internal(ctx->domain_sid, ctx->domain_name,
570                                         ctx->cli, pipe_hnd, mem_ctx,
571                                         argc, argv);
572 }
573
574 static NTSTATUS rpc_sh_rights_grant(TALLOC_CTX *mem_ctx,
575                                     struct rpc_sh_ctx *ctx,
576                                     struct rpc_pipe_client *pipe_hnd,
577                                     int argc, const char **argv)
578 {
579         return rpc_rights_grant_internal(ctx->domain_sid, ctx->domain_name,
580                                          ctx->cli, pipe_hnd, mem_ctx,
581                                          argc, argv);
582 }
583
584 static NTSTATUS rpc_sh_rights_revoke(TALLOC_CTX *mem_ctx,
585                                      struct rpc_sh_ctx *ctx,
586                                      struct rpc_pipe_client *pipe_hnd,
587                                      int argc, const char **argv)
588 {
589         return rpc_rights_revoke_internal(ctx->domain_sid, ctx->domain_name,
590                                           ctx->cli, pipe_hnd, mem_ctx,
591                                           argc, argv);
592 }
593
594 struct rpc_sh_cmd *net_rpc_rights_cmds(TALLOC_CTX *mem_ctx,
595                                        struct rpc_sh_ctx *ctx)
596 {
597         static struct rpc_sh_cmd cmds[] = {
598
599         { "list", NULL, PI_LSARPC, rpc_sh_rights_list,
600           "View available or assigned privileges" },
601
602         { "grant", NULL, PI_LSARPC, rpc_sh_rights_grant,
603           "Assign privilege[s]" },
604
605         { "revoke", NULL, PI_LSARPC, rpc_sh_rights_revoke,
606           "Revoke privilege[s]" },
607
608         { NULL, NULL, 0, NULL, NULL }
609         };
610
611         return cmds;
612 }
613