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