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
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.
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.
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/>.
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"
29 /********************************************************************
30 ********************************************************************/
32 static NTSTATUS
sid_to_name(struct rpc_pipe_client
*pipe_hnd
,
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
;
43 status
= rpccli_lsa_open_policy(pipe_hnd
, mem_ctx
, true,
44 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
46 if ( !NT_STATUS_IS_OK(status
) )
49 status
= rpccli_lsa_lookup_sids(pipe_hnd
, mem_ctx
, &pol
, 1, sid
, &domains
, &names
, &sid_types
);
51 if ( NT_STATUS_IS_OK(status
) ) {
53 fstr_sprintf( name
, "%s\\%s", domains
[0], names
[0] );
55 fstrcpy( name
, names
[0] );
58 dcerpc_lsa_Close(b
, mem_ctx
, &pol
, &result
);
62 /********************************************************************
63 ********************************************************************/
65 static NTSTATUS
name_to_sid(struct rpc_pipe_client
*pipe_hnd
,
67 struct dom_sid
*sid
, const char *name
)
69 struct policy_handle pol
;
70 enum lsa_SidType
*sid_types
;
71 NTSTATUS status
, result
;
73 struct dcerpc_binding_handle
*b
= pipe_hnd
->binding_handle
;
75 /* maybe its a raw SID */
76 if (dom_sid_parse(name
, sid
)) {
80 status
= rpccli_lsa_open_policy(pipe_hnd
, mem_ctx
, true,
81 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
83 if ( !NT_STATUS_IS_OK(status
) )
86 status
= rpccli_lsa_lookup_names(pipe_hnd
, mem_ctx
, &pol
, 1, &name
,
87 NULL
, 1, &sids
, &sid_types
);
89 if ( NT_STATUS_IS_OK(status
) )
90 sid_copy( sid
, &sids
[0] );
92 dcerpc_lsa_Close(b
, mem_ctx
, &pol
, &result
);
96 /********************************************************************
97 ********************************************************************/
99 static NTSTATUS
enum_privileges(struct rpc_pipe_client
*pipe_hnd
,
101 struct policy_handle
*pol
)
103 NTSTATUS status
, result
;
104 uint32_t enum_context
= 0;
105 uint32_t pref_max_length
=0x1000;
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
;
114 status
= dcerpc_lsa_EnumPrivs(b
, ctx
,
121 if ( !NT_STATUS_IS_OK(status
) )
123 if (!NT_STATUS_IS_OK(result
)) {
129 for (i
= 0; i
< priv_array
.count
; i
++) {
131 struct lsa_String lsa_name
;
134 priv_array
.privs
[i
].name
.string
? priv_array
.privs
[i
].name
.string
: "*unknown*" );
136 /* try to get the description */
138 init_lsa_String(&lsa_name
, priv_array
.privs
[i
].name
.string
);
140 status
= dcerpc_lsa_LookupPrivDisplayName(b
, ctx
,
148 if (!NT_STATUS_IS_OK(status
)) {
149 d_printf("??????\n");
152 if (!NT_STATUS_IS_OK(result
)) {
153 d_printf("??????\n");
157 d_printf("%s\n", description
? description
->string
: "??????");
163 /********************************************************************
164 ********************************************************************/
166 static NTSTATUS
check_privilege_for_user(struct rpc_pipe_client
*pipe_hnd
,
168 struct policy_handle
*pol
,
172 NTSTATUS status
, result
;
173 struct lsa_RightSet rights
;
175 struct dcerpc_binding_handle
*b
= pipe_hnd
->binding_handle
;
177 status
= dcerpc_lsa_EnumAccountRights(b
, ctx
,
182 if (!NT_STATUS_IS_OK(status
)) {
185 if (!NT_STATUS_IS_OK(result
)) {
189 if (rights
.count
== 0) {
190 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
193 for (i
= 0; i
< rights
.count
; i
++) {
194 if (strcasecmp_m(rights
.names
[i
].string
, right
) == 0) {
199 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
202 /********************************************************************
203 ********************************************************************/
205 static NTSTATUS
enum_privileges_for_user(struct rpc_pipe_client
*pipe_hnd
,
207 struct policy_handle
*pol
,
208 struct dom_sid
*sid
)
210 NTSTATUS status
, result
;
211 struct lsa_RightSet rights
;
213 struct dcerpc_binding_handle
*b
= pipe_hnd
->binding_handle
;
215 status
= dcerpc_lsa_EnumAccountRights(b
, ctx
,
220 if (!NT_STATUS_IS_OK(status
))
222 if (!NT_STATUS_IS_OK(result
))
225 if (rights
.count
== 0) {
226 d_printf(_("No privileges assigned\n"));
229 for (i
= 0; i
< rights
.count
; i
++) {
230 printf("%s\n", rights
.names
[i
].string
);
236 /********************************************************************
237 ********************************************************************/
239 static NTSTATUS
enum_accounts_for_privilege(struct rpc_pipe_client
*pipe_hnd
,
241 struct policy_handle
*pol
,
242 const char *privilege
)
244 NTSTATUS status
, result
;
245 uint32_t enum_context
=0;
246 uint32_t pref_max_length
=0x1000;
247 struct lsa_SidArray sid_array
;
250 struct dcerpc_binding_handle
*b
= pipe_hnd
->binding_handle
;
252 status
= dcerpc_lsa_EnumAccounts(b
, ctx
,
258 if (!NT_STATUS_IS_OK(status
))
260 if (!NT_STATUS_IS_OK(result
))
263 d_printf("%s:\n", privilege
);
265 for ( i
=0; i
<sid_array
.num_sids
; i
++ ) {
267 status
= check_privilege_for_user(pipe_hnd
, ctx
, pol
,
268 sid_array
.sids
[i
].sid
,
271 if ( ! NT_STATUS_IS_OK(status
)) {
272 if ( ! NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
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
);
284 d_printf(" %s\n", name
);
290 /********************************************************************
291 ********************************************************************/
293 static NTSTATUS
enum_privileges_for_accounts(struct rpc_pipe_client
*pipe_hnd
,
295 struct policy_handle
*pol
)
297 NTSTATUS status
, result
;
298 uint32_t enum_context
=0;
299 uint32_t pref_max_length
=0x1000;
300 struct lsa_SidArray sid_array
;
303 struct dcerpc_binding_handle
*b
= pipe_hnd
->binding_handle
;
305 status
= dcerpc_lsa_EnumAccounts(b
, ctx
,
311 if (!NT_STATUS_IS_OK(status
))
313 if (!NT_STATUS_IS_OK(result
))
316 for ( i
=0; i
<sid_array
.num_sids
; i
++ ) {
318 /* try to convert the SID to a name. Fall back to
319 printing the raw SID if necessary */
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
);
325 d_printf("%s\n", name
);
327 status
= enum_privileges_for_user(pipe_hnd
, ctx
, pol
,
328 sid_array
.sids
[i
].sid
);
329 if ( !NT_STATUS_IS_OK(status
) )
338 /********************************************************************
339 ********************************************************************/
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
,
350 struct policy_handle pol
;
351 NTSTATUS status
, result
;
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
;
361 status
= rpccli_lsa_open_policy(pipe_hnd
, mem_ctx
, true,
362 SEC_FLAG_MAXIMUM_ALLOWED
, &pol
);
364 if ( !NT_STATUS_IS_OK(status
) )
367 /* backwards compatibility; just list available privileges if no argument */
370 status
= enum_privileges(pipe_hnd
, mem_ctx
, &pol
);
374 if (strequal(argv
[0], "privileges")) {
377 if (argv
[1] == NULL
) {
378 status
= enum_privileges(pipe_hnd
, mem_ctx
, &pol
);
382 while ( argv
[i
] != NULL
) {
383 fstrcpy(privname
, argv
[i
]);
384 init_lsa_String(&lsa_name
, argv
[i
]);
387 /* verify that this is a valid privilege for error reporting */
388 status
= dcerpc_lsa_LookupPrivDisplayName(b
, mem_ctx
,
396 if (!NT_STATUS_IS_OK(status
)) {
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
);
405 d_fprintf(stderr
, _("Error resolving "
406 "privilege display name "
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
));
423 /* special case to enumerate all privileged SIDs with associated rights */
425 if (strequal( argv
[0], "accounts")) {
428 if (argv
[1] == NULL
) {
429 status
= enum_privileges_for_accounts(pipe_hnd
, mem_ctx
, &pol
);
433 while (argv
[i
] != NULL
) {
434 status
= name_to_sid(pipe_hnd
, mem_ctx
, &sid
, argv
[i
]);
435 if (!NT_STATUS_IS_OK(status
)) {
438 status
= enum_privileges_for_user(pipe_hnd
, mem_ctx
, &pol
, &sid
);
439 if (!NT_STATUS_IS_OK(status
)) {
447 /* backward compatibility: if no keyword provided, treat the key
448 as an account name */
450 d_printf("%s net rpc rights list [[accounts|privileges] "
451 "[name|SID]]\n", _("Usage:"));
452 status
= NT_STATUS_OK
;
456 status
= name_to_sid(pipe_hnd
, mem_ctx
, &sid
, argv
[0]);
457 if (!NT_STATUS_IS_OK(status
)) {
460 status
= enum_privileges_for_user(pipe_hnd
, mem_ctx
, &pol
, &sid
);
463 dcerpc_lsa_Close(b
, mem_ctx
, &pol
, &result
);
468 /********************************************************************
469 ********************************************************************/
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
,
480 struct policy_handle dom_pol
= {
483 NTSTATUS status
, result
;
484 struct lsa_RightSet rights
;
486 struct dcerpc_binding_handle
*b
= pipe_hnd
->binding_handle
;
487 union lsa_revision_info out_revision_info
= {
492 uint32_t out_version
= 0;
499 _(" net rpc rights grant <name|SID> <rights...>\n"));
503 status
= name_to_sid(pipe_hnd
, mem_ctx
, &sid
, argv
[0]);
504 if (NT_STATUS_EQUAL(status
, NT_STATUS_NONE_MAPPED
))
505 status
= NT_STATUS_NO_SUCH_USER
;
507 if (!NT_STATUS_IS_OK(status
))
510 status
= dcerpc_lsa_open_policy_fallback(b
,
512 pipe_hnd
->srv_name_slash
,
514 SEC_FLAG_MAXIMUM_ALLOWED
,
519 if (any_nt_status_not_ok(status
, result
, &status
)) {
520 DBG_DEBUG("Couldn't open policy handle: %s\n",
525 rights
.count
= argc
-1;
526 rights
.names
= talloc_array(mem_ctx
, struct lsa_StringLarge
,
528 if (rights
.names
== NULL
) {
529 status
= NT_STATUS_NO_MEMORY
;
533 for (i
=0; i
<argc
-1; i
++) {
534 init_lsa_StringLarge(&rights
.names
[i
], argv
[i
+1]);
537 status
= dcerpc_lsa_AddAccountRights(b
, mem_ctx
,
542 if (any_nt_status_not_ok(status
, result
, &status
)) {
546 d_printf(_("Successfully granted rights.\n"));
549 if ( !NT_STATUS_IS_OK(status
) ) {
550 d_fprintf(stderr
, _("Failed to grant privileges for %s (%s)\n"),
551 argv
[0], nt_errstr(status
));
554 dcerpc_lsa_Close(b
, mem_ctx
, &dom_pol
, &result
);
559 /********************************************************************
560 ********************************************************************/
562 static NTSTATUS
rpc_rights_revoke_internal(struct net_context
*c
,
563 const struct dom_sid
*domain_sid
,
564 const char *domain_name
,
565 struct cli_state
*cli
,
566 struct rpc_pipe_client
*pipe_hnd
,
571 struct policy_handle dom_pol
;
572 NTSTATUS status
, result
;
573 struct lsa_RightSet rights
;
576 struct dcerpc_binding_handle
*b
= pipe_hnd
->binding_handle
;
577 union lsa_revision_info out_revision_info
= {
583 uint32_t out_version
= 0;
588 _(" net rpc rights revoke <name|SID> <rights...>\n"));
592 status
= name_to_sid(pipe_hnd
, mem_ctx
, &sid
, argv
[0]);
593 if (!NT_STATUS_IS_OK(status
))
596 status
= dcerpc_lsa_open_policy_fallback(b
,
598 pipe_hnd
->srv_name_slash
,
600 SEC_FLAG_MAXIMUM_ALLOWED
,
605 if (any_nt_status_not_ok(status
, result
, &status
)) {
606 DBG_DEBUG("Couldn't open policy handle: %s\n",
611 rights
.count
= argc
-1;
612 rights
.names
= talloc_array(mem_ctx
, struct lsa_StringLarge
,
615 return NT_STATUS_NO_MEMORY
;
618 for (i
=0; i
<argc
-1; i
++) {
619 init_lsa_StringLarge(&rights
.names
[i
], argv
[i
+1]);
622 status
= dcerpc_lsa_RemoveAccountRights(b
, mem_ctx
,
628 if (!NT_STATUS_IS_OK(status
))
630 if (!NT_STATUS_IS_OK(result
)) {
635 d_printf(_("Successfully revoked rights.\n"));
638 if ( !NT_STATUS_IS_OK(status
) ) {
639 d_fprintf(stderr
,_("Failed to revoke privileges for %s (%s)\n"),
640 argv
[0], nt_errstr(status
));
643 dcerpc_lsa_Close(b
, mem_ctx
, &dom_pol
, &result
);
649 /********************************************************************
650 ********************************************************************/
652 static int rpc_rights_list(struct net_context
*c
, int argc
, const char **argv
)
654 if (c
->display_usage
) {
657 _("net rpc rights list [{accounts|privileges} "
659 " View available/assigned privileges\n"));
663 return run_rpc_command(c
, NULL
, &ndr_table_lsarpc
, 0,
664 rpc_rights_list_internal
, argc
, argv
);
667 /********************************************************************
668 ********************************************************************/
670 static int rpc_rights_grant(struct net_context
*c
, int argc
, const char **argv
)
672 if (c
->display_usage
) {
675 _("net rpc rights grant <name|SID> <right>\n"
676 " Assign privilege[s]\n"));
677 d_printf(_("For example:\n"
678 " net rpc rights grant 'VALE\\biddle' "
679 "SePrintOperatorPrivilege SeDiskOperatorPrivilege\n"
680 " would grant the printer admin and disk manager "
681 "rights to the user 'VALE\\biddle'\n"));
685 return run_rpc_command(c
, NULL
, &ndr_table_lsarpc
, 0,
686 rpc_rights_grant_internal
, argc
, argv
);
689 /********************************************************************
690 ********************************************************************/
692 static int rpc_rights_revoke(struct net_context
*c
, int argc
, const char **argv
)
694 if (c
->display_usage
) {
697 _("net rpc rights revoke <name|SID> <right>\n"
698 " Revoke privilege[s]\n"));
699 d_printf(_("For example:\n"
700 " net rpc rights revoke 'VALE\\biddle' "
701 "SePrintOperatorPrivilege SeDiskOperatorPrivilege\n"
702 " would revoke the printer admin and disk manager"
703 " rights from the user 'VALE\\biddle'\n"));
707 return run_rpc_command(c
, NULL
, &ndr_table_lsarpc
, 0,
708 rpc_rights_revoke_internal
, argc
, argv
);
711 /********************************************************************
712 ********************************************************************/
714 int net_rpc_rights(struct net_context
*c
, int argc
, const char **argv
)
716 struct functable func
[] = {
721 N_("View available/assigned privileges"),
722 N_("net rpc rights list\n"
723 " View available/assigned privileges")
729 N_("Assign privilege[s]"),
730 N_("net rpc rights grant\n"
731 " Assign privilege[s]")
737 N_("Revoke privilege[s]"),
738 N_("net rpc rights revoke\n"
739 " Revoke privilege[s]")
741 {NULL
, NULL
, 0, NULL
, NULL
}
744 return net_run_function(c
, argc
, argv
, "net rpc rights", func
);
747 static NTSTATUS
rpc_sh_rights_list(struct net_context
*c
,
748 TALLOC_CTX
*mem_ctx
, struct rpc_sh_ctx
*ctx
,
749 struct rpc_pipe_client
*pipe_hnd
,
750 int argc
, const char **argv
)
752 return rpc_rights_list_internal(c
, ctx
->domain_sid
, ctx
->domain_name
,
753 ctx
->cli
, pipe_hnd
, mem_ctx
,
757 static NTSTATUS
rpc_sh_rights_grant(struct net_context
*c
,
759 struct rpc_sh_ctx
*ctx
,
760 struct rpc_pipe_client
*pipe_hnd
,
761 int argc
, const char **argv
)
763 return rpc_rights_grant_internal(c
, ctx
->domain_sid
, ctx
->domain_name
,
764 ctx
->cli
, pipe_hnd
, mem_ctx
,
768 static NTSTATUS
rpc_sh_rights_revoke(struct net_context
*c
,
770 struct rpc_sh_ctx
*ctx
,
771 struct rpc_pipe_client
*pipe_hnd
,
772 int argc
, const char **argv
)
774 return rpc_rights_revoke_internal(c
, ctx
->domain_sid
, ctx
->domain_name
,
775 ctx
->cli
, pipe_hnd
, mem_ctx
,
779 struct rpc_sh_cmd
*net_rpc_rights_cmds(struct net_context
*c
, TALLOC_CTX
*mem_ctx
,
780 struct rpc_sh_ctx
*ctx
)
782 static struct rpc_sh_cmd cmds
[] = {
784 { "list", NULL
, &ndr_table_lsarpc
, rpc_sh_rights_list
,
785 N_("View available or assigned privileges") },
787 { "grant", NULL
, &ndr_table_lsarpc
, rpc_sh_rights_grant
,
788 N_("Assign privilege[s]") },
790 { "revoke", NULL
, &ndr_table_lsarpc
, rpc_sh_rights_revoke
,
791 N_("Revoke privilege[s]") },
793 { NULL
, NULL
, 0, NULL
, NULL
}