e0dc57c7345f1567d12e43f4920b26365cdd6f38
[ira/wip.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;
32         NTSTATUS result;
33         char **domains, **names;
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         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)\n", 
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 }
563
564 static NTSTATUS rpc_sh_rights_list(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
565                                    struct rpc_pipe_client *pipe_hnd,
566                                    int argc, const char **argv)
567 {
568         return rpc_rights_list_internal(ctx->domain_sid, ctx->domain_name,
569                                         ctx->cli, pipe_hnd, mem_ctx,
570                                         argc, argv);
571 }
572
573 static NTSTATUS rpc_sh_rights_grant(TALLOC_CTX *mem_ctx,
574                                     struct rpc_sh_ctx *ctx,
575                                     struct rpc_pipe_client *pipe_hnd,
576                                     int argc, const char **argv)
577 {
578         return rpc_rights_grant_internal(ctx->domain_sid, ctx->domain_name,
579                                          ctx->cli, pipe_hnd, mem_ctx,
580                                          argc, argv);
581 }
582
583 static NTSTATUS rpc_sh_rights_revoke(TALLOC_CTX *mem_ctx,
584                                      struct rpc_sh_ctx *ctx,
585                                      struct rpc_pipe_client *pipe_hnd,
586                                      int argc, const char **argv)
587 {
588         return rpc_rights_revoke_internal(ctx->domain_sid, ctx->domain_name,
589                                           ctx->cli, pipe_hnd, mem_ctx,
590                                           argc, argv);
591 }
592
593 struct rpc_sh_cmd *net_rpc_rights_cmds(TALLOC_CTX *mem_ctx,
594                                        struct rpc_sh_ctx *ctx)
595 {
596         static struct rpc_sh_cmd cmds[] = {
597
598         { "list", NULL, PI_LSARPC, rpc_sh_rights_list,
599           "View available or assigned privileges" },
600
601         { "grant", NULL, PI_LSARPC, rpc_sh_rights_grant,
602           "Assign privilege[s]" },
603
604         { "revoke", NULL, PI_LSARPC, rpc_sh_rights_revoke,
605           "Revoke privilege[s]" },
606
607         { NULL, NULL, 0, NULL, NULL }
608         };
609
610         return cmds;
611 }
612