1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This module contains smbadm CLI which offers smb configuration 30 * functionalities. 31 */ 32 #include <stdlib.h> 33 #include <stdio.h> 34 #include <syslog.h> 35 #include <strings.h> 36 #include <limits.h> 37 #include <getopt.h> 38 #include <libintl.h> 39 #include <zone.h> 40 #include <grp.h> 41 #include <libgen.h> 42 43 #include <smbsrv/libsmb.h> 44 #include <smbsrv/libmlsvc.h> 45 46 typedef enum { 47 HELP_ADD_MEMBER, 48 HELP_CREATE, 49 HELP_DELETE, 50 HELP_DEL_MEMBER, 51 HELP_GET, 52 HELP_JOIN, 53 HELP_LIST, 54 HELP_RENAME, 55 HELP_SET, 56 HELP_SHOW, 57 HELP_UDISABLE, 58 HELP_UENABLE 59 } smbadm_help_t; 60 61 typedef struct smbadm_cmdinfo { 62 char *name; 63 int (*func)(int, char **); 64 smbadm_help_t usage; 65 } smbadm_cmdinfo_t; 66 67 smbadm_cmdinfo_t *curcmd; 68 static char *progname; 69 70 static int smbadm_join(int, char **); 71 static int smbadm_list(int, char **); 72 static int smbadm_group_create(int, char **); 73 static int smbadm_group_delete(int, char **); 74 static int smbadm_group_rename(int, char **); 75 static int smbadm_group_show(int, char **); 76 static int smbadm_group_getprop(int, char **); 77 static int smbadm_group_setprop(int, char **); 78 static int smbadm_group_addmember(int, char **); 79 static int smbadm_group_delmember(int, char **); 80 static int smbadm_user_disable(int, char **); 81 static int smbadm_user_enable(int, char **); 82 83 static smbadm_cmdinfo_t smbadm_cmdtable[] = 84 { 85 { "add-member", smbadm_group_addmember, HELP_ADD_MEMBER }, 86 { "create", smbadm_group_create, HELP_CREATE }, 87 { "delete", smbadm_group_delete, HELP_DELETE }, 88 { "disable-user", smbadm_user_disable, HELP_UDISABLE }, 89 { "enable-user", smbadm_user_enable, HELP_UENABLE }, 90 { "get", smbadm_group_getprop, HELP_GET }, 91 { "join", smbadm_join, HELP_JOIN }, 92 { "list", smbadm_list, HELP_LIST }, 93 { "remove-member", smbadm_group_delmember, HELP_DEL_MEMBER }, 94 { "rename", smbadm_group_rename, HELP_RENAME }, 95 { "set", smbadm_group_setprop, HELP_SET }, 96 { "show", smbadm_group_show, HELP_SHOW }, 97 }; 98 99 #define SMBADM_NCMD (sizeof (smbadm_cmdtable) / sizeof (smbadm_cmdtable[0])) 100 101 typedef struct smbadm_prop { 102 char *p_name; 103 char *p_value; 104 } smbadm_prop_t; 105 106 typedef struct smbadm_prop_handle { 107 char *p_name; 108 char *p_dispvalue; 109 int (*p_setfn)(char *, smbadm_prop_t *); 110 int (*p_getfn)(char *, smbadm_prop_t *); 111 boolean_t (*p_chkfn)(smbadm_prop_t *); 112 } smbadm_prop_handle_t; 113 114 static boolean_t smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval); 115 static int smbadm_prop_parse(char *arg, smbadm_prop_t *prop); 116 static smbadm_prop_handle_t *smbadm_prop_gethandle(char *pname); 117 118 static boolean_t smbadm_chkprop_priv(smbadm_prop_t *prop); 119 static int smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop); 120 static int smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop); 121 static int smbadm_setprop_backup(char *gname, smbadm_prop_t *prop); 122 static int smbadm_getprop_backup(char *gname, smbadm_prop_t *prop); 123 static int smbadm_setprop_restore(char *gname, smbadm_prop_t *prop); 124 static int smbadm_getprop_restore(char *gname, smbadm_prop_t *prop); 125 static int smbadm_setprop_desc(char *gname, smbadm_prop_t *prop); 126 static int smbadm_getprop_desc(char *gname, smbadm_prop_t *prop); 127 128 static smbadm_prop_handle_t smbadm_ptable[] = { 129 {"backup", "on | off", smbadm_setprop_backup, 130 smbadm_getprop_backup, smbadm_chkprop_priv }, 131 {"restore", "on | off", smbadm_setprop_restore, 132 smbadm_getprop_restore, smbadm_chkprop_priv }, 133 {"take-ownership", "on | off", smbadm_setprop_tkowner, 134 smbadm_getprop_tkowner, smbadm_chkprop_priv }, 135 {"description", "<string>", smbadm_setprop_desc, 136 smbadm_getprop_desc, NULL }, 137 }; 138 139 static const char *smbadm_pwd_strerror(int error); 140 141 /* 142 * Number of supported properties 143 */ 144 #define SMBADM_NPROP (sizeof (smbadm_ptable) / sizeof (smbadm_ptable[0])) 145 146 static void 147 smbadm_cmdusage(FILE *fp, smbadm_cmdinfo_t *cmd) 148 { 149 switch (cmd->usage) { 150 case HELP_ADD_MEMBER: 151 (void) fprintf(fp, 152 gettext("\t%s -m member [[-m member] ...] group\n"), 153 cmd->name); 154 return; 155 156 case HELP_CREATE: 157 (void) fprintf(fp, gettext("\t%s [-d description] group\n"), 158 cmd->name); 159 return; 160 161 case HELP_DELETE: 162 (void) fprintf(fp, gettext("\t%s group\n"), cmd->name); 163 return; 164 165 case HELP_UDISABLE: 166 case HELP_UENABLE: 167 (void) fprintf(fp, gettext("\t%s user\n"), cmd->name); 168 return; 169 170 case HELP_GET: 171 (void) fprintf(fp, gettext("\t%s [[-p property] ...] group\n"), 172 cmd->name); 173 return; 174 175 case HELP_JOIN: 176 (void) fprintf(fp, gettext("\t%s -u username domain\n" 177 "\t%s -w workgroup\n"), cmd->name, cmd->name); 178 return; 179 180 case HELP_LIST: 181 (void) fprintf(fp, gettext("\t%s\n"), cmd->name); 182 return; 183 184 case HELP_DEL_MEMBER: 185 (void) fprintf(fp, 186 gettext("\t%s -m member [[-m member] ...] group\n"), 187 cmd->name); 188 return; 189 190 case HELP_RENAME: 191 (void) fprintf(fp, gettext("\t%s group new-group\n"), 192 cmd->name); 193 return; 194 195 case HELP_SET: 196 (void) fprintf(fp, gettext("\t%s -p property=value " 197 "[[-p property=value] ...] group\n"), cmd->name); 198 return; 199 200 case HELP_SHOW: 201 (void) fprintf(fp, gettext("\t%s [-m] [-p] [group]\n"), 202 cmd->name); 203 return; 204 205 } 206 207 abort(); 208 /* NOTREACHED */ 209 } 210 211 static void 212 smbadm_usage(boolean_t requested) 213 { 214 FILE *fp = requested ? stdout : stderr; 215 boolean_t show_props = B_FALSE; 216 int i; 217 218 if (curcmd == NULL) { 219 (void) fprintf(fp, 220 gettext("usage: %s [-h | <command> [options]]\n"), 221 progname); 222 (void) fprintf(fp, 223 gettext("where 'command' is one of the following:\n\n")); 224 225 for (i = 0; i < SMBADM_NCMD; i++) 226 smbadm_cmdusage(fp, &smbadm_cmdtable[i]); 227 228 (void) fprintf(fp, 229 gettext("\nFor property list, run %s %s|%s\n"), 230 progname, "get", "set"); 231 232 exit(requested ? 0 : 2); 233 } 234 235 (void) fprintf(fp, gettext("usage:\n")); 236 smbadm_cmdusage(fp, curcmd); 237 238 if (strcmp(curcmd->name, "get") == 0 || 239 strcmp(curcmd->name, "set") == 0) 240 show_props = B_TRUE; 241 242 if (show_props) { 243 (void) fprintf(fp, 244 gettext("\nThe following properties are supported:\n")); 245 246 (void) fprintf(fp, "\n\t%-16s %s\n\n", 247 "PROPERTY", "VALUES"); 248 249 for (i = 0; i < SMBADM_NPROP; i++) { 250 (void) fprintf(fp, "\t%-16s %s\n", 251 smbadm_ptable[i].p_name, 252 smbadm_ptable[i].p_dispvalue); 253 } 254 } 255 256 exit(requested ? 0 : 2); 257 } 258 259 /* 260 * smbadm_join 261 * 262 * Join the given domain/workgroup 263 */ 264 static int 265 smbadm_join(int argc, char **argv) 266 { 267 char option; 268 smb_joininfo_t jdi; 269 boolean_t join_w = B_FALSE; 270 boolean_t join_d = B_FALSE; 271 uint32_t status; 272 273 bzero(&jdi, sizeof (jdi)); 274 275 while ((option = getopt(argc, argv, "u:w:")) != -1) { 276 switch (option) { 277 case 'w': 278 (void) strlcpy(jdi.domain_name, optarg, 279 sizeof (jdi.domain_name)); 280 jdi.mode = SMB_SECMODE_WORKGRP; 281 join_w = B_TRUE; 282 break; 283 284 case 'u': 285 /* admin username */ 286 (void) strlcpy(jdi.domain_username, optarg, 287 sizeof (jdi.domain_username)); 288 jdi.mode = SMB_SECMODE_DOMAIN; 289 join_d = B_TRUE; 290 break; 291 292 default: 293 smbadm_usage(B_FALSE); 294 } 295 } 296 297 if (join_w && join_d) { 298 (void) fprintf(stderr, 299 gettext("domain and workgroup " 300 "can not be specified together\n")); 301 smbadm_usage(B_FALSE); 302 } 303 304 if (join_d && (argv[optind] != NULL)) { 305 (void) strlcpy(jdi.domain_name, argv[optind], 306 sizeof (jdi.domain_name)); 307 } 308 309 if (*jdi.domain_name == '\0') { 310 (void) fprintf(stderr, gettext("missing %s name\n"), 311 (join_d) ? "domain" : "workgroup"); 312 smbadm_usage(B_FALSE); 313 } 314 315 if (join_d && *jdi.domain_username == '\0') { 316 (void) fprintf(stderr, gettext("missing username\n")); 317 smbadm_usage(B_FALSE); 318 } 319 320 if (join_w) { 321 status = smb_join(&jdi); 322 if (status == NT_STATUS_SUCCESS) { 323 (void) printf( 324 gettext("Successfully joined workgroup '%s'\n"), 325 jdi.domain_name); 326 return (0); 327 } 328 329 (void) fprintf(stderr, 330 gettext("failed to join workgroup '%s' (%s)\n"), 331 jdi.domain_name, xlate_nt_status(status)); 332 333 return (1); 334 } 335 336 /* Join the domain */ 337 if (*jdi.domain_passwd == '\0') { 338 char *p = NULL; 339 char *prompt = gettext("Enter domain password: "); 340 p = getpassphrase(prompt); 341 if (!p) { 342 (void) fprintf(stderr, gettext("missing password\n")); 343 smbadm_usage(B_FALSE); 344 } 345 346 (void) strlcpy(jdi.domain_passwd, p, 347 sizeof (jdi.domain_passwd)); 348 } 349 350 (void) printf(gettext("Joining '%s' ... this may take a minute ...\n"), 351 jdi.domain_name); 352 353 status = smb_join(&jdi); 354 355 switch (status) { 356 case NT_STATUS_SUCCESS: 357 (void) printf(gettext("Successfully joined domain '%s'\n"), 358 jdi.domain_name); 359 return (0); 360 361 case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND: 362 (void) fprintf(stderr, gettext("failed to find " 363 "any domain controllers for '%s'\n"), 364 jdi.domain_name); 365 break; 366 367 default: 368 (void) fprintf(stderr, 369 gettext("failed to join domain '%s' (%s)\n"), 370 jdi.domain_name, xlate_nt_status(status)); 371 } 372 373 return (1); 374 } 375 376 /* 377 * smbadm_list 378 * 379 * Displays current security mode and domain/workgroup name. 380 */ 381 /*ARGSUSED*/ 382 static int 383 smbadm_list(int argc, char **argv) 384 { 385 char resource_domain[SMB_PI_MAX_DOMAIN]; 386 int sec_mode; 387 char *modename; 388 389 if (smbd_get_security_mode(&sec_mode)) { 390 (void) fprintf(stderr, 391 gettext("failed to get the security mode\n")); 392 return (1); 393 } 394 395 modename = (sec_mode == SMB_SECMODE_DOMAIN) ? "domain" : "workgroup"; 396 397 (void) printf(gettext("security mode: %s\n"), 398 smb_config_secmode_tostr(sec_mode)); 399 400 if (smbd_get_param(SMB_CI_DOMAIN_NAME, resource_domain) != 0) { 401 (void) fprintf(stderr, 402 gettext("failed to get the %s name\n"), modename); 403 return (1); 404 } 405 406 (void) printf(gettext("%s name: %s\n"), 407 modename, resource_domain); 408 409 return (0); 410 } 411 412 /* 413 * smbadm_group_create 414 * 415 * Creates a local SMB group 416 */ 417 static int 418 smbadm_group_create(int argc, char **argv) 419 { 420 char *gname = NULL; 421 char *desc = NULL; 422 char option; 423 uint32_t status; 424 425 while ((option = getopt(argc, argv, "d:")) != -1) { 426 switch (option) { 427 case 'd': 428 desc = optarg; 429 break; 430 431 default: 432 smbadm_usage(B_FALSE); 433 } 434 } 435 436 gname = argv[optind]; 437 if (optind >= argc || gname == NULL || *gname == '\0') { 438 (void) fprintf(stderr, gettext("missing group name\n")); 439 smbadm_usage(B_FALSE); 440 } 441 442 if (getgrnam(gname) == NULL) { 443 (void) fprintf(stderr, 444 gettext("failed to get the Solaris group\n")); 445 (void) fprintf(stderr, 446 gettext("use 'groupadd' to add the Solaris group\n")); 447 return (1); 448 } 449 450 status = smb_group_add(gname, desc); 451 if (status != NT_STATUS_SUCCESS) { 452 (void) fprintf(stderr, 453 gettext("failed to create the group (%s)\n"), 454 xlate_nt_status(status)); 455 } else { 456 (void) printf(gettext("Successfully created group '%s'\n"), 457 gname); 458 } 459 460 return (status); 461 } 462 463 /* 464 * smbadm_group_dump_members 465 * 466 * Dump group members details. 467 */ 468 static void 469 smbadm_group_dump_members(char *gname) 470 { 471 ntgrp_member_list_t *members = NULL; 472 int mem_cnt = 0; 473 int offset = 0; 474 uint32_t status; 475 int i; 476 477 status = smb_group_member_count(gname, &mem_cnt); 478 if (mem_cnt < 0) { 479 (void) fprintf(stderr, 480 gettext("failed to get the group members (%s)\n"), 481 xlate_nt_status(status)); 482 } 483 484 if (mem_cnt == 0) { 485 (void) printf(gettext("\tNo members\n")); 486 return; 487 } 488 489 (void) printf(gettext("\tMembers:\n")); 490 while (smb_group_member_list(gname, offset, &members) == 0) { 491 if (members == NULL) 492 break; 493 494 for (i = 0; i < members->cnt; i++) 495 (void) printf(gettext("\t\t%s\n"), members->members[i]); 496 497 offset += members->cnt; 498 smb_group_free_memberlist(members, 0); 499 if (offset >= mem_cnt) 500 break; 501 } 502 } 503 504 /* 505 * smbadm_group_dump_privs 506 * 507 * Dump group privilege details. 508 */ 509 static void 510 smbadm_group_dump_privs(char *gname, ntpriv_list_t *privs) 511 { 512 int privcnt = 0; 513 uint32_t privval; 514 char *name = NULL; 515 int i; 516 517 (void) printf(gettext("\tPrivileges: \n")); 518 519 for (i = 0; i < privs->cnt; i++) { 520 name = privs->privs[i]->name; 521 if (name == NULL) 522 continue; 523 524 if (smb_group_priv_get(gname, privs->privs[i]->id, 525 &privval) != 0) { 526 continue; 527 } 528 529 if (privval == SE_PRIVILEGE_ENABLED) { 530 (void) printf(gettext("\t\t%s: On\n"), name); 531 } else if (privval == SE_PRIVILEGE_DISABLED) { 532 (void) printf(gettext("\t\t%s: Off\n"), name); 533 } else { 534 (void) printf(gettext("\t\t%s: %d\n"), 535 name, privval); 536 } 537 538 name = NULL; 539 privcnt++; 540 } 541 542 if (privcnt == 0) 543 (void) printf(gettext("\t\tNo privileges\n")); 544 } 545 546 /* 547 * smbadm_group_dump 548 * 549 * Dump group details. 550 */ 551 static int 552 smbadm_group_dump(ntgrp_list_t *list, boolean_t show_mem, boolean_t show_privs) 553 { 554 ntpriv_list_t *privs = NULL; 555 char *gname; 556 uint32_t status; 557 int i; 558 559 if (show_privs) { 560 if ((status = smb_group_priv_list(&privs)) != 0) { 561 (void) fprintf(stderr, 562 gettext("failed to get privileges (%s)\n"), 563 xlate_nt_status(status)); 564 return (1); 565 } 566 } 567 568 for (i = 0; i < list->cnt; i++) { 569 gname = list->groups[i].name; 570 571 (void) printf(gettext("%s (%s)\n"), gname, 572 list->groups[i].desc); 573 (void) printf(gettext("\tType: %s, Attr: %X\n"), 574 list->groups[i].type, list->groups[i].attr); 575 (void) printf(gettext("\tSID: %s\n"), 576 list->groups[i].sid); 577 578 if (show_privs) 579 smbadm_group_dump_privs(gname, privs); 580 581 if (show_mem) 582 smbadm_group_dump_members(list->groups[i].name); 583 } 584 585 return (0); 586 } 587 588 /* 589 * smbadm_group_show 590 * 591 */ 592 static int 593 smbadm_group_show(int argc, char **argv) 594 { 595 char *gname = NULL; 596 int cnt = 0; 597 int offset = 0; 598 boolean_t show_privs; 599 boolean_t show_members; 600 char option; 601 uint32_t status; 602 ntgrp_list_t *list = NULL; 603 int ret = 0; 604 605 show_privs = show_members = B_FALSE; 606 607 while ((option = getopt(argc, argv, "mp")) != -1) { 608 switch (option) { 609 case 'm': 610 show_members = B_TRUE; 611 break; 612 case 'p': 613 show_privs = B_TRUE; 614 break; 615 616 default: 617 smbadm_usage(B_FALSE); 618 } 619 } 620 621 gname = argv[optind]; 622 if (optind >= argc || gname == NULL || *gname == '\0') 623 gname = "*"; 624 625 status = smb_group_count(&cnt); 626 if ((status != NT_STATUS_SUCCESS) || (cnt < 0)) { 627 (void) fprintf(stderr, 628 gettext("failed to get the number of group(s) (%s)\n"), 629 xlate_nt_status(status)); 630 return (1); 631 } 632 633 while ((offset < cnt)) { 634 status = smb_group_list(offset, &list, gname, 0); 635 if (status != NT_STATUS_SUCCESS) { 636 (void) fprintf(stderr, 637 gettext("failed to get the group(s) (%s)\n"), 638 xlate_nt_status(status)); 639 return (1); 640 } 641 642 if ((list == NULL) || (list->cnt <= 0)) 643 break; 644 645 ret = smbadm_group_dump(list, show_members, show_privs); 646 if (ret) 647 break; 648 649 offset += list->cnt; 650 smb_group_free_list(list, 0); 651 list = NULL; 652 } 653 654 return (ret); 655 } 656 657 /* 658 * smbadm_group_delete 659 * 660 */ 661 static int 662 smbadm_group_delete(int argc, char **argv) 663 { 664 uint32_t status; 665 char *gname = NULL; 666 667 gname = argv[optind]; 668 if (optind >= argc || gname == NULL || *gname == '\0') { 669 (void) fprintf(stderr, gettext("missing group name\n")); 670 smbadm_usage(B_FALSE); 671 } 672 673 status = smb_group_delete(gname); 674 if (status != NT_STATUS_SUCCESS) { 675 (void) fprintf(stderr, 676 gettext("failed to delete the group (%s)\n"), 677 xlate_nt_status(status)); 678 } else { 679 (void) printf(gettext("Successfully deleted group '%s'\n"), 680 gname); 681 } 682 683 return (status); 684 } 685 686 /* 687 * smbadm_group_rename 688 * 689 */ 690 static int 691 smbadm_group_rename(int argc, char **argv) 692 { 693 char *gname = NULL; 694 char *ngname = NULL; 695 uint32_t status; 696 697 gname = argv[optind]; 698 if (optind++ >= argc || gname == NULL || *gname == '\0') { 699 (void) fprintf(stderr, gettext("missing group name\n")); 700 smbadm_usage(B_FALSE); 701 } 702 703 ngname = argv[optind]; 704 if (optind >= argc || ngname == NULL || *ngname == '\0') { 705 (void) fprintf(stderr, gettext("missing new group name\n")); 706 smbadm_usage(B_FALSE); 707 } 708 709 if (getgrnam(gname) == NULL) { 710 (void) fprintf(stderr, 711 gettext("failed to get the Solaris group\n")); 712 (void) fprintf(stderr, 713 gettext("use 'groupadd' to add the Solaris group\n")); 714 return (1); 715 } 716 717 status = smb_group_modify(gname, ngname, NULL); 718 if (status != NT_STATUS_SUCCESS) { 719 (void) fprintf(stderr, 720 gettext("failed to modify the group (%s)\n"), 721 xlate_nt_status(status)); 722 } else { 723 (void) printf(gettext("Successfully modified " 724 "group '%s'\n"), gname); 725 } 726 727 return (status); 728 } 729 730 /* 731 * smbadm_group_setprop 732 * 733 * Set the group properties. 734 */ 735 static int 736 smbadm_group_setprop(int argc, char **argv) 737 { 738 char *gname = NULL; 739 smbadm_prop_t props[SMBADM_NPROP]; 740 smbadm_prop_handle_t *phandle; 741 char option; 742 int pcnt = 0; 743 int ret; 744 int p; 745 746 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 747 748 while ((option = getopt(argc, argv, "p:")) != -1) { 749 switch (option) { 750 case 'p': 751 if (pcnt >= SMBADM_NPROP) { 752 (void) fprintf(stderr, 753 gettext("exceeded number of supported" 754 " properties\n")); 755 smbadm_usage(B_FALSE); 756 } 757 758 ret = smbadm_prop_parse(optarg, &props[pcnt++]); 759 if (ret) { 760 if (ret == 1) 761 exit(1); 762 763 if (ret == 2) 764 smbadm_usage(B_FALSE); 765 } 766 break; 767 768 default: 769 smbadm_usage(B_FALSE); 770 } 771 } 772 773 if (pcnt == 0) { 774 (void) fprintf(stderr, 775 gettext("missing property=value argument\n")); 776 smbadm_usage(B_FALSE); 777 } 778 779 gname = argv[optind]; 780 if (optind >= argc || gname == NULL || *gname == '\0') { 781 (void) fprintf(stderr, gettext("missing group name\n")); 782 smbadm_usage(B_FALSE); 783 } 784 785 for (p = 0; p < pcnt; p++) { 786 phandle = smbadm_prop_gethandle(props[p].p_name); 787 if (phandle) { 788 if (phandle->p_setfn(gname, &props[p]) != 0) 789 ret = 1; 790 } 791 } 792 793 return (ret); 794 } 795 796 /* 797 * smbadm_group_getprop 798 * 799 * Get the group properties. 800 */ 801 static int 802 smbadm_group_getprop(int argc, char **argv) 803 { 804 char *gname = NULL; 805 smbadm_prop_t props[SMBADM_NPROP]; 806 smbadm_prop_handle_t *phandle; 807 char option; 808 int pcnt = 0; 809 int ret; 810 int p; 811 812 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 813 814 while ((option = getopt(argc, argv, "p:")) != -1) { 815 switch (option) { 816 case 'p': 817 if (pcnt >= SMBADM_NPROP) { 818 (void) fprintf(stderr, 819 gettext("exceeded number of supported" 820 " properties\n")); 821 smbadm_usage(B_FALSE); 822 } 823 824 ret = smbadm_prop_parse(optarg, &props[pcnt++]); 825 if (ret) { 826 if (ret == 1) 827 exit(1); 828 829 if (ret == 2) 830 smbadm_usage(B_FALSE); 831 } 832 break; 833 834 default: 835 smbadm_usage(B_FALSE); 836 } 837 } 838 839 gname = argv[optind]; 840 if (optind >= argc || gname == NULL || *gname == '\0') { 841 (void) fprintf(stderr, gettext("missing group name\n")); 842 smbadm_usage(B_FALSE); 843 } 844 845 if (pcnt == 0) { 846 /* 847 * If no property has be specified then get 848 * all the properties. 849 */ 850 pcnt = SMBADM_NPROP; 851 for (p = 0; p < pcnt; p++) 852 props[p].p_name = smbadm_ptable[p].p_name; 853 } 854 855 for (p = 0; p < pcnt; p++) { 856 phandle = smbadm_prop_gethandle(props[p].p_name); 857 if (phandle) { 858 if (phandle->p_getfn(gname, &props[p]) != 0) 859 ret = 1; 860 } 861 } 862 863 return (ret); 864 } 865 866 /* 867 * smbadm_group_addmember 868 * 869 */ 870 static int 871 smbadm_group_addmember(int argc, char **argv) 872 { 873 char *gname = NULL; 874 char **mname; 875 char option; 876 uint32_t status; 877 int mcnt = 0; 878 int ret = 0; 879 int i; 880 881 882 mname = (char **)malloc(argc * sizeof (char *)); 883 if (mname == NULL) { 884 (void) fprintf(stderr, gettext("out of memory\n")); 885 return (1); 886 } 887 bzero(mname, argc * sizeof (char *)); 888 889 while ((option = getopt(argc, argv, "m:")) != -1) { 890 switch (option) { 891 case 'm': 892 mname[mcnt++] = optarg; 893 break; 894 895 default: 896 free(mname); 897 smbadm_usage(B_FALSE); 898 } 899 } 900 901 if (mcnt == 0) { 902 (void) fprintf(stderr, gettext("missing member name\n")); 903 free(mname); 904 smbadm_usage(B_FALSE); 905 } 906 907 gname = argv[optind]; 908 if (optind >= argc || gname == NULL || *gname == 0) { 909 (void) fprintf(stderr, gettext("missing group name\n")); 910 free(mname); 911 smbadm_usage(B_FALSE); 912 } 913 914 915 for (i = 0; i < mcnt; i++) { 916 if (mname[i] == NULL) 917 continue; 918 919 status = smb_group_member_add(gname, mname[i]); 920 if (status != NT_STATUS_SUCCESS) { 921 (void) fprintf(stderr, 922 gettext("failed to add %s (%s)\n"), 923 mname[i], xlate_nt_status(status)); 924 ret = 1; 925 } 926 else 927 (void) printf(gettext("Successfully added %s to %s\n"), 928 mname[i], gname); 929 } 930 931 free(mname); 932 return (ret); 933 } 934 935 /* 936 * smbadm_group_delmember 937 */ 938 static int 939 smbadm_group_delmember(int argc, char **argv) 940 { 941 char *gname = NULL; 942 char **mname; 943 char option; 944 uint32_t status; 945 int mcnt = 0; 946 int ret = 0; 947 int i; 948 949 mname = (char **)malloc(argc * sizeof (char *)); 950 if (mname == NULL) { 951 (void) fprintf(stderr, gettext("out of memory\n")); 952 return (1); 953 } 954 bzero(mname, argc * sizeof (char *)); 955 956 while ((option = getopt(argc, argv, "m:")) != -1) { 957 switch (option) { 958 case 'm': 959 mname[mcnt++] = optarg; 960 break; 961 962 default: 963 free(mname); 964 smbadm_usage(B_FALSE); 965 } 966 } 967 968 if (mcnt == 0) { 969 (void) fprintf(stderr, gettext("missing member name\n")); 970 free(mname); 971 smbadm_usage(B_FALSE); 972 } 973 974 gname = argv[optind]; 975 if (optind >= argc || gname == NULL || *gname == 0) { 976 (void) fprintf(stderr, gettext("missing group name\n")); 977 free(mname); 978 smbadm_usage(B_FALSE); 979 } 980 981 982 for (i = 0; i < mcnt; i++) { 983 if (mname[i] == NULL) 984 continue; 985 986 status = smb_group_member_remove(gname, mname[i]); 987 if (status != NT_STATUS_SUCCESS) { 988 (void) fprintf(stderr, 989 gettext("failed to remove %s (%s)\n"), 990 mname[i], xlate_nt_status(status)); 991 ret = 1; 992 } else { 993 (void) printf( 994 gettext("Successfully removed %s from %s\n"), 995 mname[i], gname); 996 } 997 } 998 999 return (ret); 1000 } 1001 1002 static int 1003 smbadm_user_disable(int argc, char **argv) 1004 { 1005 int error; 1006 char *user = NULL; 1007 1008 user = argv[optind]; 1009 if (optind >= argc || user == NULL || *user == '\0') { 1010 (void) fprintf(stderr, gettext("missing user name\n")); 1011 smbadm_usage(B_FALSE); 1012 } 1013 1014 error = smb_pwd_setcntl(user, SMB_PWC_DISABLE); 1015 if (error == SMB_PWE_SUCCESS) 1016 (void) printf(gettext("%s is disabled.\n"), user); 1017 else 1018 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1019 1020 return (error); 1021 } 1022 1023 static int 1024 smbadm_user_enable(int argc, char **argv) 1025 { 1026 int error; 1027 char *user = NULL; 1028 1029 user = argv[optind]; 1030 if (optind >= argc || user == NULL || *user == '\0') { 1031 (void) fprintf(stderr, gettext("missing user name\n")); 1032 smbadm_usage(B_FALSE); 1033 } 1034 1035 error = smb_pwd_setcntl(user, SMB_PWC_ENABLE); 1036 if (error == SMB_PWE_SUCCESS) 1037 (void) printf(gettext("%s is enabled.\n"), user); 1038 else 1039 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1040 1041 return (error); 1042 } 1043 1044 1045 int 1046 main(int argc, char **argv) 1047 { 1048 int i; 1049 1050 (void) malloc(0); /* satisfy libumem dependency */ 1051 1052 progname = basename(argv[0]); 1053 1054 if (getzoneid() != GLOBAL_ZONEID) { 1055 (void) fprintf(stderr, 1056 gettext("cannot execute in non-global zone\n")); 1057 return (0); 1058 } 1059 1060 if (is_system_labeled()) { 1061 (void) fprintf(stderr, 1062 gettext("Trusted Extensions not supported\n")); 1063 return (0); 1064 } 1065 1066 if (argc < 2) { 1067 (void) fprintf(stderr, gettext("missing command\n")); 1068 smbadm_usage(B_FALSE); 1069 } 1070 1071 /* 1072 * Special case "cmd --help/-?" 1073 */ 1074 if (strcmp(argv[1], "-?") == 0 || 1075 strcmp(argv[1], "--help") == 0 || 1076 strcmp(argv[1], "-h") == 0) 1077 smbadm_usage(B_TRUE); 1078 1079 for (i = 0; i < SMBADM_NCMD; ++i) { 1080 curcmd = &smbadm_cmdtable[i]; 1081 if (strcasecmp(argv[1], curcmd->name) == 0) { 1082 if (argc > 2) { 1083 /* cmd subcmd --help/-? */ 1084 if (strcmp(argv[2], "-?") == 0 || 1085 strcmp(argv[2], "--help") == 0 || 1086 strcmp(argv[2], "-h") == 0) 1087 smbadm_usage(B_TRUE); 1088 } 1089 1090 return (curcmd->func(argc - 1, &argv[1])); 1091 } 1092 } 1093 1094 curcmd = NULL; 1095 (void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]); 1096 smbadm_usage(B_FALSE); 1097 return (2); 1098 } 1099 1100 static boolean_t 1101 smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 1102 { 1103 smbadm_prop_handle_t *pinfo; 1104 int i; 1105 1106 for (i = 0; i < SMBADM_NPROP; i++) { 1107 pinfo = &smbadm_ptable[i]; 1108 if (strcmp(pinfo->p_name, prop->p_name) == 0) { 1109 if (pinfo->p_chkfn && chkval) 1110 return (pinfo->p_chkfn(prop)); 1111 1112 return (B_TRUE); 1113 } 1114 } 1115 1116 (void) fprintf(stderr, 1117 gettext("unrecognized property '%s'\n"), prop->p_name); 1118 1119 return (B_FALSE); 1120 } 1121 1122 static int 1123 smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 1124 { 1125 boolean_t parse_value; 1126 char *equal; 1127 1128 if (arg == NULL) 1129 return (2); 1130 1131 prop->p_name = prop->p_value = NULL; 1132 1133 if (strcmp(curcmd->name, "set") == 0) 1134 parse_value = B_TRUE; 1135 else 1136 parse_value = B_FALSE; 1137 1138 prop->p_name = arg; 1139 1140 if (parse_value) { 1141 equal = strchr(arg, '='); 1142 if (equal == NULL) 1143 return (2); 1144 1145 *equal++ = '\0'; 1146 prop->p_value = equal; 1147 } 1148 1149 if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 1150 return (2); 1151 1152 return (0); 1153 } 1154 1155 static smbadm_prop_handle_t * 1156 smbadm_prop_gethandle(char *pname) 1157 { 1158 int i; 1159 1160 for (i = 0; i < SMBADM_NPROP; i++) 1161 if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 1162 return (&smbadm_ptable[i]); 1163 1164 return (NULL); 1165 } 1166 1167 static int 1168 smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 1169 { 1170 uint32_t status; 1171 1172 status = smb_group_modify(gname, gname, prop->p_value); 1173 if (status != NT_STATUS_SUCCESS) { 1174 (void) fprintf(stderr, 1175 gettext("failed to modify the group description (%s)\n"), 1176 xlate_nt_status(status)); 1177 return (1); 1178 } 1179 1180 (void) printf(gettext("Successfully modified " 1181 "'%s' description\n"), gname); 1182 1183 return (0); 1184 } 1185 1186 static int 1187 smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 1188 { 1189 uint32_t status; 1190 ntgrp_list_t *list = NULL; 1191 1192 status = smb_group_list(0, &list, gname, 0); 1193 if (status != NT_STATUS_SUCCESS) { 1194 (void) fprintf(stderr, 1195 gettext("failed to get the %s (%s)\n"), 1196 prop->p_name, xlate_nt_status(status)); 1197 return (1); 1198 } 1199 1200 if ((list == NULL) || (list->cnt <= 0)) { 1201 (void) fprintf(stderr, gettext("%s: no such group\n"), gname); 1202 return (1); 1203 } 1204 1205 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 1206 list->groups[0].desc); 1207 smb_group_free_list(list, 0); 1208 return (0); 1209 } 1210 1211 static int 1212 smbadm_group_setpriv(char *gname, uint32_t priv_id, smbadm_prop_t *prop) 1213 { 1214 uint32_t priv_attr; 1215 uint32_t status; 1216 int ret; 1217 1218 if (strcasecmp(prop->p_value, "on") == 0) { 1219 (void) printf(gettext("Enabling %s privilege "), prop->p_name); 1220 priv_attr = SE_PRIVILEGE_ENABLED; 1221 } else { 1222 (void) printf(gettext("Disabling %s privilege "), prop->p_name); 1223 priv_attr = SE_PRIVILEGE_DISABLED; 1224 } 1225 1226 status = smb_group_priv_set(gname, priv_id, priv_attr); 1227 1228 if (status == NT_STATUS_SUCCESS) { 1229 (void) printf(gettext("succeeded\n")); 1230 ret = 0; 1231 } else { 1232 (void) printf(gettext("failed: %s\n"), xlate_nt_status(status)); 1233 ret = 1; 1234 } 1235 1236 return (ret); 1237 } 1238 1239 static int 1240 smbadm_group_getpriv(char *gname, uint32_t priv_id, smbadm_prop_t *prop) 1241 { 1242 uint32_t priv_attr; 1243 uint32_t status; 1244 1245 status = smb_group_priv_get(gname, priv_id, &priv_attr); 1246 if (status != NT_STATUS_SUCCESS) { 1247 (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 1248 prop->p_name, xlate_nt_status(status)); 1249 return (1); 1250 } 1251 1252 if (priv_attr == SE_PRIVILEGE_ENABLED) 1253 (void) printf(gettext("\t%s: %s\n"), prop->p_name, "On"); 1254 else if (priv_attr == SE_PRIVILEGE_DISABLED) 1255 (void) printf(gettext("\t%s: %s\n"), prop->p_name, "Off"); 1256 else 1257 (void) printf(gettext("\t%s: %s\n"), prop->p_name, "Unknown"); 1258 1259 return (0); 1260 } 1261 1262 static int 1263 smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 1264 { 1265 return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1266 } 1267 1268 static int 1269 smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 1270 { 1271 return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1272 } 1273 1274 static int 1275 smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 1276 { 1277 return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 1278 } 1279 1280 static int 1281 smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 1282 { 1283 return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 1284 } 1285 1286 static int 1287 smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 1288 { 1289 return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 1290 } 1291 1292 static int 1293 smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 1294 { 1295 return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 1296 } 1297 1298 static boolean_t 1299 smbadm_chkprop_priv(smbadm_prop_t *prop) 1300 { 1301 if (prop->p_value == NULL || *prop->p_value == '\0') { 1302 (void) fprintf(stderr, 1303 gettext("missing value for '%s'\n"), prop->p_name); 1304 return (B_FALSE); 1305 } 1306 1307 if (strcasecmp(prop->p_value, "on") == 0) 1308 return (B_TRUE); 1309 1310 if (strcasecmp(prop->p_value, "off") == 0) 1311 return (B_TRUE); 1312 1313 (void) fprintf(stderr, 1314 gettext("%s: unrecognized value for '%s' property\n"), 1315 prop->p_value, prop->p_name); 1316 1317 return (B_FALSE); 1318 } 1319 1320 static const char * 1321 smbadm_pwd_strerror(int error) 1322 { 1323 switch (error) { 1324 case SMB_PWE_SUCCESS: 1325 return (gettext("Success.")); 1326 1327 case SMB_PWE_USER_UNKNOWN: 1328 return (gettext("User does not exist.")); 1329 1330 case SMB_PWE_USER_DISABLE: 1331 return (gettext("User is disable.")); 1332 1333 case SMB_PWE_CLOSE_FAILED: 1334 case SMB_PWE_OPEN_FAILED: 1335 case SMB_PWE_WRITE_FAILED: 1336 case SMB_PWE_UPDATE_FAILED: 1337 return (gettext("Unexpected failure. " 1338 "SMB password database unchanged.")); 1339 1340 case SMB_PWE_STAT_FAILED: 1341 return (gettext("stat of SMB password file failed.")); 1342 1343 case SMB_PWE_BUSY: 1344 return (gettext("SMB password database busy. " 1345 "Try again later.")); 1346 1347 case SMB_PWE_DENIED: 1348 return (gettext("Operation not permitted.")); 1349 1350 case SMB_PWE_SYSTEM_ERROR: 1351 return (gettext("System error.")); 1352 } 1353 1354 return (gettext("Unknown error code.")); 1355 } 1356 1357 /* 1358 * Enable libumem debugging by default on DEBUG builds. 1359 */ 1360 #ifdef DEBUG 1361 const char * 1362 _umem_debug_init(void) 1363 { 1364 return ("default,verbose"); /* $UMEM_DEBUG setting */ 1365 } 1366 1367 const char * 1368 _umem_logging_init(void) 1369 { 1370 return ("fail,contents"); /* $UMEM_LOGGING setting */ 1371 } 1372 #endif 1373