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