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