s3/utils: Use sddl_decode_err_msg instead of sddl_decode
[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    Copyright (C) Guenther Deschner              2008
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 #include "includes.h"
21 #include "utils/net.h"
22 #include "rpc_client/rpc_client.h"
23 #include "../librpc/gen_ndr/ndr_lsa_c.h"
24 #include "rpc_client/cli_lsarpc.h"
25 #include "rpc_client/init_lsa.h"
26 #include "../libcli/security/security.h"
27 #include "lib/util/string_wrappers.h"
28
29 /********************************************************************
30 ********************************************************************/
31
32 static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd,
33                                 TALLOC_CTX *mem_ctx,
34                                 struct dom_sid *sid,
35                                 fstring name)
36 {
37         struct policy_handle pol;
38         enum lsa_SidType *sid_types = NULL;
39         NTSTATUS status, result;
40         char **domains = NULL, **names = NULL;
41         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
42
43         status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
44                 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
45
46         if ( !NT_STATUS_IS_OK(status) )
47                 return status;
48
49         status = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types);
50
51         if ( NT_STATUS_IS_OK(status) ) {
52                 if ( *domains[0] )
53                         fstr_sprintf( name, "%s\\%s", domains[0], names[0] );
54                 else
55                         fstrcpy( name, names[0] );
56         }
57
58         dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
59         return status;
60 }
61
62 /********************************************************************
63 ********************************************************************/
64
65 static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
66                             TALLOC_CTX *mem_ctx,
67                             struct dom_sid *sid, const char *name)
68 {
69         struct policy_handle pol;
70         enum lsa_SidType *sid_types;
71         NTSTATUS status, result;
72         struct dom_sid *sids;
73         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
74
75         /* maybe its a raw SID */
76         if (dom_sid_parse(name, sid)) {
77                 return NT_STATUS_OK;
78         }
79
80         status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
81                 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
82
83         if ( !NT_STATUS_IS_OK(status) )
84                 return status;
85
86         status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name,
87                                          NULL, 1, &sids, &sid_types);
88
89         if ( NT_STATUS_IS_OK(status) )
90                 sid_copy( sid, &sids[0] );
91
92         dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
93         return status;
94 }
95
96 /********************************************************************
97 ********************************************************************/
98
99 static NTSTATUS enum_privileges(struct rpc_pipe_client *pipe_hnd,
100                                 TALLOC_CTX *ctx,
101                                 struct policy_handle *pol )
102 {
103         NTSTATUS status, result;
104         uint32_t enum_context = 0;
105         uint32_t pref_max_length=0x1000;
106         uint32_t i;
107         uint16_t lang_id=0;
108         uint16_t lang_id_sys=0;
109         uint16_t lang_id_desc;
110         struct lsa_StringLarge *description = NULL;
111         struct lsa_PrivArray priv_array;
112         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
113
114         status = dcerpc_lsa_EnumPrivs(b, ctx,
115                                       pol,
116                                       &enum_context,
117                                       &priv_array,
118                                       pref_max_length,
119                                       &result);
120
121         if ( !NT_STATUS_IS_OK(status) )
122                 return status;
123         if (!NT_STATUS_IS_OK(result)) {
124                 return result;
125         }
126
127         /* Print results */
128
129         for (i = 0; i < priv_array.count; i++) {
130
131                 struct lsa_String lsa_name;
132
133                 d_printf("%30s  ",
134                         priv_array.privs[i].name.string ? priv_array.privs[i].name.string : "*unknown*" );
135
136                 /* try to get the description */
137
138                 init_lsa_String(&lsa_name, priv_array.privs[i].name.string);
139
140                 status = dcerpc_lsa_LookupPrivDisplayName(b, ctx,
141                                                           pol,
142                                                           &lsa_name,
143                                                           lang_id,
144                                                           lang_id_sys,
145                                                           &description,
146                                                           &lang_id_desc,
147                                                           &result);
148                 if (!NT_STATUS_IS_OK(status)) {
149                         d_printf("??????\n");
150                         continue;
151                 }
152                 if (!NT_STATUS_IS_OK(result)) {
153                         d_printf("??????\n");
154                         continue;
155                 }
156
157                 d_printf("%s\n", description ? description->string : "??????");
158         }
159
160         return NT_STATUS_OK;
161 }
162
163 /********************************************************************
164 ********************************************************************/
165
166 static NTSTATUS check_privilege_for_user(struct rpc_pipe_client *pipe_hnd,
167                                         TALLOC_CTX *ctx,
168                                         struct policy_handle *pol,
169                                         struct dom_sid *sid,
170                                         const char *right)
171 {
172         NTSTATUS status, result;
173         struct lsa_RightSet rights;
174         uint32_t i;
175         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
176
177         status = dcerpc_lsa_EnumAccountRights(b, ctx,
178                                               pol,
179                                               sid,
180                                               &rights,
181                                               &result);
182         if (!NT_STATUS_IS_OK(status)) {
183                 return status;
184         }
185         if (!NT_STATUS_IS_OK(result)) {
186                 return result;
187         }
188
189         if (rights.count == 0) {
190                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
191         }
192
193         for (i = 0; i < rights.count; i++) {
194                 if (strcasecmp_m(rights.names[i].string, right) == 0) {
195                         return NT_STATUS_OK;
196                 }
197         }
198
199         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
200 }
201
202 /********************************************************************
203 ********************************************************************/
204
205 static NTSTATUS enum_privileges_for_user(struct rpc_pipe_client *pipe_hnd,
206                                         TALLOC_CTX *ctx,
207                                         struct policy_handle *pol,
208                                         struct dom_sid *sid )
209 {
210         NTSTATUS status, result;
211         struct lsa_RightSet rights;
212         uint32_t i;
213         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
214
215         status = dcerpc_lsa_EnumAccountRights(b, ctx,
216                                               pol,
217                                               sid,
218                                               &rights,
219                                               &result);
220         if (!NT_STATUS_IS_OK(status))
221                 return status;
222         if (!NT_STATUS_IS_OK(result))
223                 return result;
224
225         if (rights.count == 0) {
226                 d_printf(_("No privileges assigned\n"));
227         }
228
229         for (i = 0; i < rights.count; i++) {
230                 printf("%s\n", rights.names[i].string);
231         }
232
233         return NT_STATUS_OK;
234 }
235
236 /********************************************************************
237 ********************************************************************/
238
239 static NTSTATUS enum_accounts_for_privilege(struct rpc_pipe_client *pipe_hnd,
240                                                 TALLOC_CTX *ctx,
241                                                 struct policy_handle *pol,
242                                                 const char *privilege)
243 {
244         NTSTATUS status, result;
245         uint32_t enum_context=0;
246         uint32_t pref_max_length=0x1000;
247         struct lsa_SidArray sid_array;
248         uint32_t i;
249         fstring name;
250         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
251
252         status = dcerpc_lsa_EnumAccounts(b, ctx,
253                                          pol,
254                                          &enum_context,
255                                          &sid_array,
256                                          pref_max_length,
257                                          &result);
258         if (!NT_STATUS_IS_OK(status))
259                 return status;
260         if (!NT_STATUS_IS_OK(result))
261                 return result;
262
263         d_printf("%s:\n", privilege);
264
265         for ( i=0; i<sid_array.num_sids; i++ ) {
266
267                 status = check_privilege_for_user(pipe_hnd, ctx, pol,
268                                                   sid_array.sids[i].sid,
269                                                   privilege);
270
271                 if ( ! NT_STATUS_IS_OK(status)) {
272                         if ( ! NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
273                                 return status;
274                         }
275                         continue;
276                 }
277
278                 /* try to convert the SID to a name.  Fall back to
279                    printing the raw SID if necessary */
280                 status = sid_to_name( pipe_hnd, ctx, sid_array.sids[i].sid, name );
281                 if ( !NT_STATUS_IS_OK (status) )
282                         sid_to_fstring(name, sid_array.sids[i].sid);
283
284                 d_printf("  %s\n", name);
285         }
286
287         return NT_STATUS_OK;
288 }
289
290 /********************************************************************
291 ********************************************************************/
292
293 static NTSTATUS enum_privileges_for_accounts(struct rpc_pipe_client *pipe_hnd,
294                                                 TALLOC_CTX *ctx,
295                                                 struct policy_handle *pol)
296 {
297         NTSTATUS status, result;
298         uint32_t enum_context=0;
299         uint32_t pref_max_length=0x1000;
300         struct lsa_SidArray sid_array;
301         uint32_t i;
302         fstring name;
303         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
304
305         status = dcerpc_lsa_EnumAccounts(b, ctx,
306                                          pol,
307                                          &enum_context,
308                                          &sid_array,
309                                          pref_max_length,
310                                          &result);
311         if (!NT_STATUS_IS_OK(status))
312                 return status;
313         if (!NT_STATUS_IS_OK(result))
314                 return result;
315
316         for ( i=0; i<sid_array.num_sids; i++ ) {
317
318                 /* try to convert the SID to a name.  Fall back to
319                    printing the raw SID if necessary */
320
321                 status = sid_to_name(pipe_hnd, ctx, sid_array.sids[i].sid, name);
322                 if ( !NT_STATUS_IS_OK (status) )
323                         sid_to_fstring(name, sid_array.sids[i].sid);
324
325                 d_printf("%s\n", name);
326
327                 status = enum_privileges_for_user(pipe_hnd, ctx, pol,
328                                                   sid_array.sids[i].sid);
329                 if ( !NT_STATUS_IS_OK(status) )
330                         return status;
331
332                 d_printf("\n");
333         }
334
335         return NT_STATUS_OK;
336 }
337
338 /********************************************************************
339 ********************************************************************/
340
341 static NTSTATUS rpc_rights_list_internal(struct net_context *c,
342                                         const struct dom_sid *domain_sid,
343                                         const char *domain_name,
344                                         struct cli_state *cli,
345                                         struct rpc_pipe_client *pipe_hnd,
346                                         TALLOC_CTX *mem_ctx,
347                                         int argc,
348                                         const char **argv )
349 {
350         struct policy_handle pol;
351         NTSTATUS status, result;
352         struct dom_sid sid;
353         fstring privname;
354         struct lsa_String lsa_name;
355         struct lsa_StringLarge *description = NULL;
356         uint16_t lang_id = 0;
357         uint16_t lang_id_sys = 0;
358         uint16_t lang_id_desc;
359         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
360
361         status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
362                 SEC_FLAG_MAXIMUM_ALLOWED, &pol);
363
364         if ( !NT_STATUS_IS_OK(status) )
365                 return status;
366
367         /* backwards compatibility; just list available privileges if no argument */
368
369         if (argc == 0) {
370                 status = enum_privileges(pipe_hnd, mem_ctx, &pol );
371                 goto done;
372         }
373
374         if (strequal(argv[0], "privileges")) {
375                 int i = 1;
376
377                 if (argv[1] == NULL) {
378                         status = enum_privileges(pipe_hnd, mem_ctx, &pol );
379                         goto done;
380                 }
381
382                 while ( argv[i] != NULL ) {
383                         fstrcpy(privname, argv[i]);
384                         init_lsa_String(&lsa_name, argv[i]);
385                         i++;
386
387                         /* verify that this is a valid privilege for error reporting */
388                         status = dcerpc_lsa_LookupPrivDisplayName(b, mem_ctx,
389                                                                   &pol,
390                                                                   &lsa_name,
391                                                                   lang_id,
392                                                                   lang_id_sys,
393                                                                   &description,
394                                                                   &lang_id_desc,
395                                                                   &result);
396                         if (!NT_STATUS_IS_OK(status)) {
397                                 continue;
398                         }
399                         status = result;
400                         if ( !NT_STATUS_IS_OK(result) ) {
401                                 if ( NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_PRIVILEGE))
402                                         d_fprintf(stderr, _("No such privilege "
403                                                   "exists: %s.\n"), privname);
404                                 else
405                                         d_fprintf(stderr, _("Error resolving "
406                                                   "privilege display name "
407                                                   "[%s].\n"),
408                                                   nt_errstr(result));
409                                 continue;
410                         }
411
412                         status = enum_accounts_for_privilege(pipe_hnd, mem_ctx, &pol, privname);
413                         if (!NT_STATUS_IS_OK(status)) {
414                                 d_fprintf(stderr, _("Error enumerating "
415                                           "accounts for privilege %s [%s].\n"),
416                                           privname, nt_errstr(status));
417                                 continue;
418                         }
419                 }
420                 goto done;
421         }
422
423         /* special case to enumerate all privileged SIDs with associated rights */
424
425         if (strequal( argv[0], "accounts")) {
426                 int i = 1;
427
428                 if (argv[1] == NULL) {
429                         status = enum_privileges_for_accounts(pipe_hnd, mem_ctx, &pol);
430                         goto done;
431                 }
432
433                 while (argv[i] != NULL) {
434                         status = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[i]);
435                         if (!NT_STATUS_IS_OK(status)) {
436                                 goto done;
437                         }
438                         status = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid);
439                         if (!NT_STATUS_IS_OK(status)) {
440                                 goto done;
441                         }
442                         i++;
443                 }
444                 goto done;
445         }
446
447         /* backward compatibility: if no keyword provided, treat the key
448            as an account name */
449         if (argc > 1) {
450                 d_printf("%s net rpc rights list [[accounts|privileges] "
451                          "[name|SID]]\n", _("Usage:"));
452                 status = NT_STATUS_OK;
453                 goto done;
454         }
455
456         status = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
457         if (!NT_STATUS_IS_OK(status)) {
458                 goto done;
459         }
460         status = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid );
461
462 done:
463         dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
464
465         return status;
466 }
467
468 /********************************************************************
469 ********************************************************************/
470
471 static NTSTATUS rpc_rights_grant_internal(struct net_context *c,
472                                         const struct dom_sid *domain_sid,
473                                         const char *domain_name,
474                                         struct cli_state *cli,
475                                         struct rpc_pipe_client *pipe_hnd,
476                                         TALLOC_CTX *mem_ctx,
477                                         int argc,
478                                         const char **argv )
479 {
480         struct policy_handle dom_pol;
481         NTSTATUS status, result;
482         struct lsa_RightSet rights;
483         int i;
484         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
485
486         struct dom_sid sid;
487
488         if (argc < 2 ) {
489                 d_printf("%s\n%s",
490                          _("Usage:"),
491                          _(" net rpc rights grant <name|SID> <rights...>\n"));
492                 return NT_STATUS_OK;
493         }
494
495         status = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
496         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))
497                 status = NT_STATUS_NO_SUCH_USER;
498
499         if (!NT_STATUS_IS_OK(status))
500                 goto done;
501
502         status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true,
503                                      SEC_FLAG_MAXIMUM_ALLOWED,
504                                      &dom_pol);
505
506         if (!NT_STATUS_IS_OK(status))
507                 return status;
508
509         rights.count = argc-1;
510         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge,
511                                     rights.count);
512         if (!rights.names) {
513                 return NT_STATUS_NO_MEMORY;
514         }
515
516         for (i=0; i<argc-1; i++) {
517                 init_lsa_StringLarge(&rights.names[i], argv[i+1]);
518         }
519
520         status = dcerpc_lsa_AddAccountRights(b, mem_ctx,
521                                              &dom_pol,
522                                              &sid,
523                                              &rights,
524                                              &result);
525         if (!NT_STATUS_IS_OK(status))
526                 goto done;
527         if (!NT_STATUS_IS_OK(result)) {
528                 status = result;
529                 goto done;
530         }
531
532         d_printf(_("Successfully granted rights.\n"));
533
534  done:
535         if ( !NT_STATUS_IS_OK(status) ) {
536                 d_fprintf(stderr, _("Failed to grant privileges for %s (%s)\n"),
537                         argv[0], nt_errstr(status));
538         }
539
540         dcerpc_lsa_Close(b, mem_ctx, &dom_pol, &result);
541
542         return status;
543 }
544
545 /********************************************************************
546 ********************************************************************/
547
548 static NTSTATUS rpc_rights_revoke_internal(struct net_context *c,
549                                         const struct dom_sid *domain_sid,
550                                         const char *domain_name,
551                                         struct cli_state *cli,
552                                         struct rpc_pipe_client *pipe_hnd,
553                                         TALLOC_CTX *mem_ctx,
554                                         int argc,
555                                         const char **argv )
556 {
557         struct policy_handle dom_pol;
558         NTSTATUS status, result;
559         struct lsa_RightSet rights;
560         struct dom_sid sid;
561         int i;
562         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
563
564         if (argc < 2 ) {
565                 d_printf("%s\n%s",
566                          _("Usage:"),
567                          _(" net rpc rights revoke <name|SID> <rights...>\n"));
568                 return NT_STATUS_OK;
569         }
570
571         status = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
572         if (!NT_STATUS_IS_OK(status))
573                 return status;
574
575         status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true,
576                                      SEC_FLAG_MAXIMUM_ALLOWED,
577                                      &dom_pol);
578
579         if (!NT_STATUS_IS_OK(status))
580                 return status;
581
582         rights.count = argc-1;
583         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge,
584                                     rights.count);
585         if (!rights.names) {
586                 return NT_STATUS_NO_MEMORY;
587         }
588
589         for (i=0; i<argc-1; i++) {
590                 init_lsa_StringLarge(&rights.names[i], argv[i+1]);
591         }
592
593         status = dcerpc_lsa_RemoveAccountRights(b, mem_ctx,
594                                                 &dom_pol,
595                                                 &sid,
596                                                 false,
597                                                 &rights,
598                                                 &result);
599         if (!NT_STATUS_IS_OK(status))
600                 goto done;
601         if (!NT_STATUS_IS_OK(result)) {
602                 status = result;
603                 goto done;
604         }
605
606         d_printf(_("Successfully revoked rights.\n"));
607
608 done:
609         if ( !NT_STATUS_IS_OK(status) ) {
610                 d_fprintf(stderr,_("Failed to revoke privileges for %s (%s)\n"),
611                         argv[0], nt_errstr(status));
612         }
613
614         dcerpc_lsa_Close(b, mem_ctx, &dom_pol, &result);
615
616         return status;
617 }
618
619
620 /********************************************************************
621 ********************************************************************/
622
623 static int rpc_rights_list(struct net_context *c, int argc, const char **argv )
624 {
625         if (c->display_usage) {
626                 d_printf("%s\n%s",
627                          _("Usage:"),
628                          _("net rpc rights list [{accounts|privileges} "
629                            "[name|SID]]\n"
630                            "    View available/assigned privileges\n"));
631                 return 0;
632         }
633
634         return run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
635                 rpc_rights_list_internal, argc, argv );
636 }
637
638 /********************************************************************
639 ********************************************************************/
640
641 static int rpc_rights_grant(struct net_context *c, int argc, const char **argv )
642 {
643         if (c->display_usage) {
644                 d_printf("%s\n%s",
645                          _("Usage:"),
646                          _("net rpc rights grant <name|SID> <right>\n"
647                            "    Assign privilege[s]\n"));
648                 d_printf(_("For example:\n"
649                            "    net rpc rights grant 'VALE\\biddle' "
650                            "SePrintOperatorPrivilege SeDiskOperatorPrivilege\n"
651                            "    would grant the printer admin and disk manager "
652                            "rights to the user 'VALE\\biddle'\n"));
653                 return 0;
654         }
655
656         return run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
657                 rpc_rights_grant_internal, argc, argv );
658 }
659
660 /********************************************************************
661 ********************************************************************/
662
663 static int rpc_rights_revoke(struct net_context *c, int argc, const char **argv)
664 {
665         if (c->display_usage) {
666                 d_printf("%s\n%s",
667                          _("Usage:"),
668                          _("net rpc rights revoke <name|SID> <right>\n"
669                            "    Revoke privilege[s]\n"));
670                 d_printf(_("For example:\n"
671                            "    net rpc rights revoke 'VALE\\biddle' "
672                            "SePrintOperatorPrivilege SeDiskOperatorPrivilege\n"
673                            "    would revoke the printer admin and disk manager"
674                            " rights from the user 'VALE\\biddle'\n"));
675                 return 0;
676         }
677
678         return run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
679                 rpc_rights_revoke_internal, argc, argv );
680 }
681
682 /********************************************************************
683 ********************************************************************/
684
685 int net_rpc_rights(struct net_context *c, int argc, const char **argv)
686 {
687         struct functable func[] = {
688                 {
689                         "list",
690                         rpc_rights_list,
691                         NET_TRANSPORT_RPC,
692                         N_("View available/assigned privileges"),
693                         N_("net rpc rights list\n"
694                            "    View available/assigned privileges")
695                 },
696                 {
697                         "grant",
698                         rpc_rights_grant,
699                         NET_TRANSPORT_RPC,
700                         N_("Assign privilege[s]"),
701                         N_("net rpc rights grant\n"
702                            "    Assign privilege[s]")
703                 },
704                 {
705                         "revoke",
706                         rpc_rights_revoke,
707                         NET_TRANSPORT_RPC,
708                         N_("Revoke privilege[s]"),
709                         N_("net rpc rights revoke\n"
710                            "    Revoke privilege[s]")
711                 },
712                 {NULL, NULL, 0, NULL, NULL}
713         };
714
715         return net_run_function(c, argc, argv, "net rpc rights", func);
716 }
717
718 static NTSTATUS rpc_sh_rights_list(struct net_context *c,
719                                    TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
720                                    struct rpc_pipe_client *pipe_hnd,
721                                    int argc, const char **argv)
722 {
723         return rpc_rights_list_internal(c, ctx->domain_sid, ctx->domain_name,
724                                         ctx->cli, pipe_hnd, mem_ctx,
725                                         argc, argv);
726 }
727
728 static NTSTATUS rpc_sh_rights_grant(struct net_context *c,
729                                     TALLOC_CTX *mem_ctx,
730                                     struct rpc_sh_ctx *ctx,
731                                     struct rpc_pipe_client *pipe_hnd,
732                                     int argc, const char **argv)
733 {
734         return rpc_rights_grant_internal(c, ctx->domain_sid, ctx->domain_name,
735                                          ctx->cli, pipe_hnd, mem_ctx,
736                                          argc, argv);
737 }
738
739 static NTSTATUS rpc_sh_rights_revoke(struct net_context *c,
740                                      TALLOC_CTX *mem_ctx,
741                                      struct rpc_sh_ctx *ctx,
742                                      struct rpc_pipe_client *pipe_hnd,
743                                      int argc, const char **argv)
744 {
745         return rpc_rights_revoke_internal(c, ctx->domain_sid, ctx->domain_name,
746                                           ctx->cli, pipe_hnd, mem_ctx,
747                                           argc, argv);
748 }
749
750 struct rpc_sh_cmd *net_rpc_rights_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
751                                        struct rpc_sh_ctx *ctx)
752 {
753         static struct rpc_sh_cmd cmds[] = {
754
755         { "list", NULL, &ndr_table_lsarpc, rpc_sh_rights_list,
756           N_("View available or assigned privileges") },
757
758         { "grant", NULL, &ndr_table_lsarpc, rpc_sh_rights_grant,
759           N_("Assign privilege[s]") },
760
761         { "revoke", NULL, &ndr_table_lsarpc, rpc_sh_rights_revoke,
762           N_("Revoke privilege[s]") },
763
764         { NULL, NULL, 0, NULL, NULL }
765         };
766
767         return cmds;
768 }
769