Use rpccli_lsa_LookupPrivDisplayName() in net and rpcclient.
[kai/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 static void init_lsa_String(struct lsa_String *name, const char *s)
23 {
24         name->string = s;
25 }
26
27 /********************************************************************
28 ********************************************************************/
29
30 static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd,
31                                 TALLOC_CTX *mem_ctx,
32                                 DOM_SID *sid,
33                                 fstring name)
34 {
35         POLICY_HND pol;
36         enum lsa_SidType *sid_types = NULL;
37         NTSTATUS result;
38         char **domains = NULL, **names = NULL;
39
40         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
41                 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
42                 
43         if ( !NT_STATUS_IS_OK(result) )
44                 return result;
45
46         result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types);
47         
48         if ( NT_STATUS_IS_OK(result) ) {
49                 if ( *domains[0] )
50                         fstr_sprintf( name, "%s\\%s", domains[0], names[0] );
51                 else
52                         fstrcpy( name, names[0] );
53         }
54
55         rpccli_lsa_Close(pipe_hnd, mem_ctx, &pol);
56         return result;
57 }
58
59 /********************************************************************
60 ********************************************************************/
61
62 static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
63                             TALLOC_CTX *mem_ctx,
64                             DOM_SID *sid, const char *name)
65 {
66         POLICY_HND pol;
67         enum lsa_SidType *sid_types;
68         NTSTATUS result;
69         DOM_SID *sids;
70
71         /* maybe its a raw SID */
72         if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) {
73                 return NT_STATUS_OK;
74         }
75
76         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
77                 SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
78                 
79         if ( !NT_STATUS_IS_OK(result) )
80                 return result;
81
82         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name,
83                                          NULL, 1, &sids, &sid_types);
84         
85         if ( NT_STATUS_IS_OK(result) )
86                 sid_copy( sid, &sids[0] );
87
88         rpccli_lsa_Close(pipe_hnd, mem_ctx, &pol);
89         return result;
90 }
91
92 /********************************************************************
93 ********************************************************************/
94
95 static NTSTATUS enum_privileges(struct rpc_pipe_client *pipe_hnd,
96                                 TALLOC_CTX *ctx,
97                                 POLICY_HND *pol )
98 {
99         NTSTATUS result;
100         uint32 enum_context = 0;
101         uint32 pref_max_length=0x1000;
102         int i;
103         uint16 lang_id=0;
104         uint16 lang_id_sys=0;
105         uint16 lang_id_desc;
106         struct lsa_StringLarge *description = NULL;
107         struct lsa_PrivArray priv_array;
108
109         result = rpccli_lsa_EnumPrivs(pipe_hnd, ctx,
110                                       pol,
111                                       &enum_context,
112                                       &priv_array,
113                                       pref_max_length);
114
115         if ( !NT_STATUS_IS_OK(result) )
116                 return result;
117
118         /* Print results */
119
120         for (i = 0; i < priv_array.count; i++) {
121
122                 struct lsa_String lsa_name;
123
124                 d_printf("%30s  ",
125                         priv_array.privs[i].name.string ? priv_array.privs[i].name.string : "*unknown*" );
126
127                 /* try to get the description */
128
129                 init_lsa_String(&lsa_name, priv_array.privs[i].name.string);
130
131                 result = rpccli_lsa_LookupPrivDisplayName(pipe_hnd, ctx,
132                                                           pol,
133                                                           &lsa_name,
134                                                           lang_id,
135                                                           lang_id_sys,
136                                                           &description,
137                                                           &lang_id_desc);
138
139                 if (!NT_STATUS_IS_OK(result)) {
140                         d_printf("??????\n");
141                         continue;
142                 }
143
144                 d_printf("%s\n", description->string);
145         }
146
147         return NT_STATUS_OK;
148 }
149
150 /********************************************************************
151 ********************************************************************/
152
153 static NTSTATUS check_privilege_for_user(struct rpc_pipe_client *pipe_hnd,
154                                         TALLOC_CTX *ctx,
155                                         POLICY_HND *pol,
156                                         DOM_SID *sid,
157                                         const char *right)
158 {
159         NTSTATUS result;
160         uint32 count;
161         char **rights;
162         int i;
163
164         result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
165
166         if (!NT_STATUS_IS_OK(result)) {
167                 return result;
168         }
169
170         if (count == 0) {
171                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
172         }
173                 
174         for (i = 0; i < count; i++) {
175                 if (StrCaseCmp(rights[i], right) == 0) {
176                         return NT_STATUS_OK;
177                 }
178         }
179
180         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
181 }
182
183 /********************************************************************
184 ********************************************************************/
185
186 static NTSTATUS enum_privileges_for_user(struct rpc_pipe_client *pipe_hnd,
187                                         TALLOC_CTX *ctx,
188                                         POLICY_HND *pol,
189                                         DOM_SID *sid )
190 {
191         NTSTATUS result;
192         uint32 count;
193         char **rights;
194         int i;
195
196         result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
197
198         if (!NT_STATUS_IS_OK(result))
199                 return result;
200
201         if ( count == 0 )
202                 d_printf("No privileges assigned\n");
203                 
204         for (i = 0; i < count; i++) {
205                 printf("%s\n", rights[i]);
206         }
207
208         return NT_STATUS_OK;
209 }
210
211 /********************************************************************
212 ********************************************************************/
213
214 static NTSTATUS enum_accounts_for_privilege(struct rpc_pipe_client *pipe_hnd,
215                                                 TALLOC_CTX *ctx,
216                                                 POLICY_HND *pol,
217                                                 const char *privilege)
218 {
219         NTSTATUS result;
220         uint32 enum_context=0;
221         uint32 pref_max_length=0x1000;
222         DOM_SID *sids = NULL;
223         uint32 count=0;
224         int i;
225         fstring name;
226
227         result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
228                 pref_max_length, &count, &sids);
229
230         if (!NT_STATUS_IS_OK(result))
231                 return result;
232                 
233         d_printf("%s:\n", privilege);
234
235         for ( i=0; i<count; i++ ) {
236         
237                    
238                 result = check_privilege_for_user( pipe_hnd, ctx, pol, &sids[i], privilege);
239                 
240                 if ( ! NT_STATUS_IS_OK(result)) {
241                         if ( ! NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
242                                 return result;
243                         }
244                         continue;
245                 }
246
247                 /* try to convert the SID to a name.  Fall back to 
248                    printing the raw SID if necessary */
249                 result = sid_to_name( pipe_hnd, ctx, &sids[i], name );
250                 if ( !NT_STATUS_IS_OK (result) )
251                         sid_to_fstring(name, &sids[i]);
252
253                 d_printf("  %s\n", name);
254         }
255
256         return NT_STATUS_OK;
257 }
258
259 /********************************************************************
260 ********************************************************************/
261
262 static NTSTATUS enum_privileges_for_accounts(struct rpc_pipe_client *pipe_hnd,
263                                                 TALLOC_CTX *ctx,
264                                                 POLICY_HND *pol)
265 {
266         NTSTATUS result;
267         uint32 enum_context=0;
268         uint32 pref_max_length=0x1000;
269         DOM_SID *sids;
270         uint32 count=0;
271         int i;
272         fstring name;
273
274         result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
275                 pref_max_length, &count, &sids);
276
277         if (!NT_STATUS_IS_OK(result))
278                 return result;
279                 
280         for ( i=0; i<count; 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, &sids[i], name );
286                 if ( !NT_STATUS_IS_OK (result) )
287                         sid_to_fstring(name, &sids[i]);
288                         
289                 d_printf("%s\n", name);
290                 
291                 result = enum_privileges_for_user(pipe_hnd, ctx, pol, &sids[i] );
292                 
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