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