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_UDISABLE, 57 HELP_UENABLE 58 } smbadm_help_t; 59 60 #define SMBADM_CMDF_GROUP 0x01 61 62 typedef struct smbadm_cmdinfo { 63 char *name; 64 int (*func)(int, char **); 65 smbadm_help_t usage; 66 uint32_t flags; 67 } smbadm_cmdinfo_t; 68 69 smbadm_cmdinfo_t *curcmd; 70 static char *progname; 71 72 static int smbadm_join(int, char **); 73 static int smbadm_list(int, char **); 74 static int smbadm_group_create(int, char **); 75 static int smbadm_group_delete(int, char **); 76 static int smbadm_group_rename(int, char **); 77 static int smbadm_group_show(int, char **); 78 static int smbadm_group_getprop(int, char **); 79 static int smbadm_group_setprop(int, char **); 80 static int smbadm_group_addmember(int, char **); 81 static int smbadm_group_delmember(int, char **); 82 static int smbadm_user_disable(int, char **); 83 static int smbadm_user_enable(int, char **); 84 85 static smbadm_cmdinfo_t smbadm_cmdtable[] = 86 { 87 { "add-member", smbadm_group_addmember, HELP_ADD_MEMBER, 88 SMBADM_CMDF_GROUP }, 89 { "create", smbadm_group_create, HELP_CREATE, 90 SMBADM_CMDF_GROUP }, 91 { "delete", smbadm_group_delete, HELP_DELETE, 92 SMBADM_CMDF_GROUP }, 93 { "disable-user", smbadm_user_disable, HELP_UDISABLE, 0 }, 94 { "enable-user", smbadm_user_enable, HELP_UENABLE, 0 }, 95 { "get", smbadm_group_getprop, HELP_GET, 96 SMBADM_CMDF_GROUP }, 97 { "join", smbadm_join, HELP_JOIN, 0 }, 98 { "list", smbadm_list, HELP_LIST, 0 }, 99 { "remove-member", smbadm_group_delmember, HELP_DEL_MEMBER, 100 SMBADM_CMDF_GROUP }, 101 { "rename", smbadm_group_rename, HELP_RENAME, 102 SMBADM_CMDF_GROUP }, 103 { "set", smbadm_group_setprop, HELP_SET, 104 SMBADM_CMDF_GROUP }, 105 { "show", smbadm_group_show, HELP_SHOW, 106 SMBADM_CMDF_GROUP }, 107 }; 108 109 #define SMBADM_NCMD (sizeof (smbadm_cmdtable) / sizeof (smbadm_cmdtable[0])) 110 111 typedef struct smbadm_prop { 112 char *p_name; 113 char *p_value; 114 } smbadm_prop_t; 115 116 typedef struct smbadm_prop_handle { 117 char *p_name; 118 char *p_dispvalue; 119 int (*p_setfn)(char *, smbadm_prop_t *); 120 int (*p_getfn)(char *, smbadm_prop_t *); 121 boolean_t (*p_chkfn)(smbadm_prop_t *); 122 } smbadm_prop_handle_t; 123 124 static boolean_t smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval); 125 static int smbadm_prop_parse(char *arg, smbadm_prop_t *prop); 126 static smbadm_prop_handle_t *smbadm_prop_gethandle(char *pname); 127 128 static boolean_t smbadm_chkprop_priv(smbadm_prop_t *prop); 129 static int smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop); 130 static int smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop); 131 static int smbadm_setprop_backup(char *gname, smbadm_prop_t *prop); 132 static int smbadm_getprop_backup(char *gname, smbadm_prop_t *prop); 133 static int smbadm_setprop_restore(char *gname, smbadm_prop_t *prop); 134 static int smbadm_getprop_restore(char *gname, smbadm_prop_t *prop); 135 static int smbadm_setprop_desc(char *gname, smbadm_prop_t *prop); 136 static int smbadm_getprop_desc(char *gname, smbadm_prop_t *prop); 137 138 static smbadm_prop_handle_t smbadm_ptable[] = { 139 {"backup", "on | off", smbadm_setprop_backup, 140 smbadm_getprop_backup, smbadm_chkprop_priv }, 141 {"restore", "on | off", smbadm_setprop_restore, 142 smbadm_getprop_restore, smbadm_chkprop_priv }, 143 {"take-ownership", "on | off", smbadm_setprop_tkowner, 144 smbadm_getprop_tkowner, smbadm_chkprop_priv }, 145 {"description", "<string>", smbadm_setprop_desc, 146 smbadm_getprop_desc, NULL }, 147 }; 148 149 static int smbadm_grpcmd_init(void); 150 static void smbadm_grpcmd_fini(void); 151 static const char *smbadm_pwd_strerror(int error); 152 153 /* 154 * Number of supported properties 155 */ 156 #define SMBADM_NPROP (sizeof (smbadm_ptable) / sizeof (smbadm_ptable[0])) 157 158 static void 159 smbadm_cmdusage(FILE *fp, smbadm_cmdinfo_t *cmd) 160 { 161 switch (cmd->usage) { 162 case HELP_ADD_MEMBER: 163 (void) fprintf(fp, 164 gettext("\t%s -m member [[-m member] ...] group\n"), 165 cmd->name); 166 return; 167 168 case HELP_CREATE: 169 (void) fprintf(fp, gettext("\t%s [-d description] group\n"), 170 cmd->name); 171 return; 172 173 case HELP_DELETE: 174 (void) fprintf(fp, gettext("\t%s group\n"), cmd->name); 175 return; 176 177 case HELP_UDISABLE: 178 case HELP_UENABLE: 179 (void) fprintf(fp, gettext("\t%s user\n"), cmd->name); 180 return; 181 182 case HELP_GET: 183 (void) fprintf(fp, gettext("\t%s [[-p property] ...] group\n"), 184 cmd->name); 185 return; 186 187 case HELP_JOIN: 188 (void) fprintf(fp, gettext("\t%s -u username domain\n" 189 "\t%s -w workgroup\n"), cmd->name, cmd->name); 190 return; 191 192 case HELP_LIST: 193 (void) fprintf(fp, gettext("\t%s\n"), cmd->name); 194 return; 195 196 case HELP_DEL_MEMBER: 197 (void) fprintf(fp, 198 gettext("\t%s -m member [[-m member] ...] group\n"), 199 cmd->name); 200 return; 201 202 case HELP_RENAME: 203 (void) fprintf(fp, gettext("\t%s group new-group\n"), 204 cmd->name); 205 return; 206 207 case HELP_SET: 208 (void) fprintf(fp, gettext("\t%s -p property=value " 209 "[[-p property=value] ...] group\n"), cmd->name); 210 return; 211 212 case HELP_SHOW: 213 (void) fprintf(fp, gettext("\t%s [-m] [-p] [group]\n"), 214 cmd->name); 215 return; 216 217 } 218 219 abort(); 220 /* NOTREACHED */ 221 } 222 223 static void 224 smbadm_usage(boolean_t requested) 225 { 226 FILE *fp = requested ? stdout : stderr; 227 boolean_t show_props = B_FALSE; 228 int i; 229 230 if (curcmd == NULL) { 231 (void) fprintf(fp, 232 gettext("usage: %s [-h | <command> [options]]\n"), 233 progname); 234 (void) fprintf(fp, 235 gettext("where 'command' is one of the following:\n\n")); 236 237 for (i = 0; i < SMBADM_NCMD; i++) 238 smbadm_cmdusage(fp, &smbadm_cmdtable[i]); 239 240 (void) fprintf(fp, 241 gettext("\nFor property list, run %s %s|%s\n"), 242 progname, "get", "set"); 243 244 exit(requested ? 0 : 2); 245 } 246 247 (void) fprintf(fp, gettext("usage:\n")); 248 smbadm_cmdusage(fp, curcmd); 249 250 if (strcmp(curcmd->name, "get") == 0 || 251 strcmp(curcmd->name, "set") == 0) 252 show_props = B_TRUE; 253 254 if (show_props) { 255 (void) fprintf(fp, 256 gettext("\nThe following properties are supported:\n")); 257 258 (void) fprintf(fp, "\n\t%-16s %s\n\n", 259 "PROPERTY", "VALUES"); 260 261 for (i = 0; i < SMBADM_NPROP; i++) { 262 (void) fprintf(fp, "\t%-16s %s\n", 263 smbadm_ptable[i].p_name, 264 smbadm_ptable[i].p_dispvalue); 265 } 266 } 267 268 exit(requested ? 0 : 2); 269 } 270 271 /* 272 * smbadm_join 273 * 274 * Join the given domain/workgroup 275 */ 276 static int 277 smbadm_join(int argc, char **argv) 278 { 279 char option; 280 smb_joininfo_t jdi; 281 boolean_t join_w = B_FALSE; 282 boolean_t join_d = B_FALSE; 283 uint32_t status; 284 char kdom[MAXHOSTNAMELEN]; 285 boolean_t override = B_FALSE; 286 287 bzero(&jdi, sizeof (jdi)); 288 289 while ((option = getopt(argc, argv, "u:w:")) != -1) { 290 switch (option) { 291 case 'w': 292 (void) strlcpy(jdi.domain_name, optarg, 293 sizeof (jdi.domain_name)); 294 jdi.mode = SMB_SECMODE_WORKGRP; 295 join_w = B_TRUE; 296 break; 297 298 case 'u': 299 /* admin username */ 300 (void) strlcpy(jdi.domain_username, optarg, 301 sizeof (jdi.domain_username)); 302 jdi.mode = SMB_SECMODE_DOMAIN; 303 join_d = B_TRUE; 304 break; 305 306 default: 307 smbadm_usage(B_FALSE); 308 } 309 } 310 311 if (join_w && join_d) { 312 (void) fprintf(stderr, 313 gettext("domain and workgroup " 314 "can not be specified together\n")); 315 smbadm_usage(B_FALSE); 316 } 317 318 if (join_d && (argv[optind] != NULL)) { 319 (void) strlcpy(jdi.domain_name, argv[optind], 320 sizeof (jdi.domain_name)); 321 } 322 323 if (*jdi.domain_name == '\0') { 324 (void) fprintf(stderr, gettext("missing %s name\n"), 325 (join_d) ? "domain" : "workgroup"); 326 smbadm_usage(B_FALSE); 327 } 328 329 if (join_d && *jdi.domain_username == '\0') { 330 (void) fprintf(stderr, gettext("missing username\n")); 331 smbadm_usage(B_FALSE); 332 } 333 334 if (join_w) { 335 status = smb_join(&jdi); 336 if (status == NT_STATUS_SUCCESS) { 337 (void) printf( 338 gettext("Successfully joined workgroup '%s'\n"), 339 jdi.domain_name); 340 return (0); 341 } 342 343 (void) fprintf(stderr, 344 gettext("failed to join workgroup '%s' (%s)\n"), 345 jdi.domain_name, xlate_nt_status(status)); 346 347 return (1); 348 } 349 350 if ((smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kdom, sizeof (kdom)) 351 == SMBD_SMF_OK) && (*kdom != 0)) { 352 if (strncasecmp(jdi.domain_name, kdom, 353 strlen(jdi.domain_name))) { 354 char reply[8]; 355 356 (void) printf(gettext("The system has already " 357 "joined to a different domain %s by another " 358 "program.\nWould you like to continue [yes/no]? "), 359 kdom); 360 (void) scanf("%8s", reply); 361 (void) trim_whitespace(reply); 362 if (strncasecmp(reply, "yes", 3) != 0) 363 return (0); 364 365 override = B_TRUE; 366 } 367 } 368 369 /* Join the domain */ 370 if (*jdi.domain_passwd == '\0') { 371 char *p = NULL; 372 char *prompt = gettext("Enter domain password: "); 373 p = getpassphrase(prompt); 374 if (!p) { 375 (void) fprintf(stderr, gettext("missing password\n")); 376 smbadm_usage(B_FALSE); 377 } 378 379 (void) strlcpy(jdi.domain_passwd, p, 380 sizeof (jdi.domain_passwd)); 381 } 382 383 (void) printf(gettext("Joining '%s' ... this may take a minute ...\n"), 384 jdi.domain_name); 385 386 status = smb_join(&jdi); 387 388 switch (status) { 389 case NT_STATUS_SUCCESS: 390 (void) printf(gettext("Successfully joined domain '%s'\n"), 391 jdi.domain_name); 392 393 if (override) { 394 if (smb_getfqdomainname(kdom, sizeof (kdom)) == -1) 395 (void) strlcpy(kdom, jdi.domain_name, 396 sizeof (kdom)); 397 398 (void) smb_config_setstr(SMB_CI_KPASSWD_DOMAIN, kdom); 399 } 400 return (0); 401 402 case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND: 403 (void) fprintf(stderr, gettext("failed to find " 404 "any domain controllers for '%s'\n"), 405 jdi.domain_name); 406 break; 407 408 default: 409 (void) fprintf(stderr, 410 gettext("failed to join domain '%s' (%s)\n"), 411 jdi.domain_name, xlate_nt_status(status)); 412 } 413 414 return (1); 415 } 416 417 /* 418 * smbadm_list 419 * 420 * Displays current security mode and domain/workgroup name. 421 */ 422 /*ARGSUSED*/ 423 static int 424 smbadm_list(int argc, char **argv) 425 { 426 char domain[MAXHOSTNAMELEN]; 427 char modename[16]; 428 int rc; 429 430 rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename)); 431 if (rc != SMBD_SMF_OK) { 432 (void) fprintf(stderr, 433 gettext("failed to get the security mode\n")); 434 return (1); 435 } 436 437 (void) printf(gettext("security mode: %s\n"), modename); 438 439 if (smb_getdomainname(domain, sizeof (domain)) != 0) { 440 (void) fprintf(stderr, gettext("failed to get the %s name\n"), 441 modename); 442 return (1); 443 } 444 445 (void) printf(gettext("%s name: %s\n"), modename, domain); 446 return (0); 447 } 448 449 /* 450 * smbadm_group_create 451 * 452 * Creates a local SMB group 453 */ 454 static int 455 smbadm_group_create(int argc, char **argv) 456 { 457 char *gname = NULL; 458 char *desc = NULL; 459 char option; 460 int status; 461 462 while ((option = getopt(argc, argv, "d:")) != -1) { 463 switch (option) { 464 case 'd': 465 desc = optarg; 466 break; 467 468 default: 469 smbadm_usage(B_FALSE); 470 } 471 } 472 473 gname = argv[optind]; 474 if (optind >= argc || gname == NULL || *gname == '\0') { 475 (void) fprintf(stderr, gettext("missing group name\n")); 476 smbadm_usage(B_FALSE); 477 } 478 479 if (getgrnam(gname) == NULL) { 480 (void) fprintf(stderr, 481 gettext("failed to get the Solaris group '%s'\n"), gname); 482 (void) fprintf(stderr, 483 gettext("use 'groupadd' to add '%s'\n"), gname); 484 return (1); 485 } 486 487 status = smb_lgrp_add(gname, desc); 488 if (status != SMB_LGRP_SUCCESS) { 489 (void) fprintf(stderr, 490 gettext("failed to create the group (%s)\n"), 491 smb_lgrp_strerror(status)); 492 } else { 493 (void) printf(gettext("'%s' created.\n"), 494 gname); 495 } 496 497 return (status); 498 } 499 500 /* 501 * smbadm_group_dump_members 502 * 503 * Dump group members details. 504 */ 505 static void 506 smbadm_group_dump_members(smb_gsid_t *members, int num) 507 { 508 char sidstr[SMB_SID_STRSZ]; 509 int i; 510 511 if (num == 0) { 512 (void) printf(gettext("\tNo members\n")); 513 return; 514 } 515 516 (void) printf(gettext("\tMembers:\n")); 517 for (i = 0; i < num; i++) { 518 (void) smb_lookup_sid(members[i].gs_sid, sidstr, 519 sizeof (sidstr)); 520 (void) printf(gettext("\t\t%s\n"), sidstr); 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_grpcmd_init()) != 0) 1100 return (ret); 1101 1102 ret = curcmd->func(argc - 1, &argv[1]); 1103 1104 smbadm_grpcmd_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_grpcmd_init(void) 1117 { 1118 int rc; 1119 1120 if (curcmd->flags & SMBADM_CMDF_GROUP) { 1121 if (smb_idmap_start() != 0) { 1122 (void) fprintf(stderr, 1123 gettext("failed to contact idmap service\n")); 1124 return (1); 1125 } 1126 1127 if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { 1128 (void) fprintf(stderr, 1129 gettext("failed to initialize (%s)\n"), 1130 smb_lgrp_strerror(rc)); 1131 smb_idmap_stop(); 1132 return (1); 1133 } 1134 } 1135 1136 return (0); 1137 } 1138 1139 static void 1140 smbadm_grpcmd_fini(void) 1141 { 1142 if (curcmd->flags & SMBADM_CMDF_GROUP) { 1143 smb_lgrp_stop(); 1144 smb_idmap_stop(); 1145 } 1146 } 1147 1148 static boolean_t 1149 smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 1150 { 1151 smbadm_prop_handle_t *pinfo; 1152 int i; 1153 1154 for (i = 0; i < SMBADM_NPROP; i++) { 1155 pinfo = &smbadm_ptable[i]; 1156 if (strcmp(pinfo->p_name, prop->p_name) == 0) { 1157 if (pinfo->p_chkfn && chkval) 1158 return (pinfo->p_chkfn(prop)); 1159 1160 return (B_TRUE); 1161 } 1162 } 1163 1164 (void) fprintf(stderr, 1165 gettext("unrecognized property '%s'\n"), prop->p_name); 1166 1167 return (B_FALSE); 1168 } 1169 1170 static int 1171 smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 1172 { 1173 boolean_t parse_value; 1174 char *equal; 1175 1176 if (arg == NULL) 1177 return (2); 1178 1179 prop->p_name = prop->p_value = NULL; 1180 1181 if (strcmp(curcmd->name, "set") == 0) 1182 parse_value = B_TRUE; 1183 else 1184 parse_value = B_FALSE; 1185 1186 prop->p_name = arg; 1187 1188 if (parse_value) { 1189 equal = strchr(arg, '='); 1190 if (equal == NULL) 1191 return (2); 1192 1193 *equal++ = '\0'; 1194 prop->p_value = equal; 1195 } 1196 1197 if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 1198 return (2); 1199 1200 return (0); 1201 } 1202 1203 static smbadm_prop_handle_t * 1204 smbadm_prop_gethandle(char *pname) 1205 { 1206 int i; 1207 1208 for (i = 0; i < SMBADM_NPROP; i++) 1209 if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 1210 return (&smbadm_ptable[i]); 1211 1212 return (NULL); 1213 } 1214 1215 static int 1216 smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 1217 { 1218 int status; 1219 1220 status = smb_lgrp_setcmnt(gname, prop->p_value); 1221 if (status != SMB_LGRP_SUCCESS) { 1222 (void) fprintf(stderr, 1223 gettext("failed to modify the group description (%s)\n"), 1224 smb_lgrp_strerror(status)); 1225 return (1); 1226 } 1227 1228 (void) printf(gettext("Successfully modified " 1229 "'%s' description\n"), gname); 1230 1231 return (0); 1232 } 1233 1234 static int 1235 smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 1236 { 1237 char *cmnt = NULL; 1238 int status; 1239 1240 status = smb_lgrp_getcmnt(gname, &cmnt); 1241 if (status != SMB_LGRP_SUCCESS) { 1242 (void) fprintf(stderr, 1243 gettext("failed to get the group description (%s)\n"), 1244 smb_lgrp_strerror(status)); 1245 return (1); 1246 } 1247 1248 (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); 1249 free(cmnt); 1250 return (0); 1251 } 1252 1253 static int 1254 smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1255 { 1256 boolean_t enable; 1257 int status; 1258 int ret; 1259 1260 if (strcasecmp(prop->p_value, "on") == 0) { 1261 (void) printf(gettext("Enabling %s privilege "), prop->p_name); 1262 enable = B_TRUE; 1263 } else { 1264 (void) printf(gettext("Disabling %s privilege "), prop->p_name); 1265 enable = B_FALSE; 1266 } 1267 1268 status = smb_lgrp_setpriv(gname, priv_id, enable); 1269 if (status == SMB_LGRP_SUCCESS) { 1270 (void) printf(gettext("succeeded\n")); 1271 ret = 0; 1272 } else { 1273 (void) printf(gettext("failed: %s\n"), 1274 smb_lgrp_strerror(status)); 1275 ret = 1; 1276 } 1277 1278 return (ret); 1279 } 1280 1281 static int 1282 smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1283 { 1284 boolean_t enable; 1285 int status; 1286 1287 status = smb_lgrp_getpriv(gname, priv_id, &enable); 1288 if (status != SMB_LGRP_SUCCESS) { 1289 (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 1290 prop->p_name, smb_lgrp_strerror(status)); 1291 return (1); 1292 } 1293 1294 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 1295 (enable) ? "On" : "Off"); 1296 1297 return (0); 1298 } 1299 1300 static int 1301 smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 1302 { 1303 return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1304 } 1305 1306 static int 1307 smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 1308 { 1309 return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1310 } 1311 1312 static int 1313 smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 1314 { 1315 return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 1316 } 1317 1318 static int 1319 smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 1320 { 1321 return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 1322 } 1323 1324 static int 1325 smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 1326 { 1327 return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 1328 } 1329 1330 static int 1331 smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 1332 { 1333 return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 1334 } 1335 1336 static boolean_t 1337 smbadm_chkprop_priv(smbadm_prop_t *prop) 1338 { 1339 if (prop->p_value == NULL || *prop->p_value == '\0') { 1340 (void) fprintf(stderr, 1341 gettext("missing value for '%s'\n"), prop->p_name); 1342 return (B_FALSE); 1343 } 1344 1345 if (strcasecmp(prop->p_value, "on") == 0) 1346 return (B_TRUE); 1347 1348 if (strcasecmp(prop->p_value, "off") == 0) 1349 return (B_TRUE); 1350 1351 (void) fprintf(stderr, 1352 gettext("%s: unrecognized value for '%s' property\n"), 1353 prop->p_value, prop->p_name); 1354 1355 return (B_FALSE); 1356 } 1357 1358 static const char * 1359 smbadm_pwd_strerror(int error) 1360 { 1361 switch (error) { 1362 case SMB_PWE_SUCCESS: 1363 return (gettext("Success.")); 1364 1365 case SMB_PWE_USER_UNKNOWN: 1366 return (gettext("User does not exist.")); 1367 1368 case SMB_PWE_USER_DISABLE: 1369 return (gettext("User is disable.")); 1370 1371 case SMB_PWE_CLOSE_FAILED: 1372 case SMB_PWE_OPEN_FAILED: 1373 case SMB_PWE_WRITE_FAILED: 1374 case SMB_PWE_UPDATE_FAILED: 1375 return (gettext("Unexpected failure. " 1376 "SMB password database unchanged.")); 1377 1378 case SMB_PWE_STAT_FAILED: 1379 return (gettext("stat of SMB password file failed.")); 1380 1381 case SMB_PWE_BUSY: 1382 return (gettext("SMB password database busy. " 1383 "Try again later.")); 1384 1385 case SMB_PWE_DENIED: 1386 return (gettext("Operation not permitted.")); 1387 1388 case SMB_PWE_SYSTEM_ERROR: 1389 return (gettext("System error.")); 1390 } 1391 1392 return (gettext("Unknown error code.")); 1393 } 1394 1395 /* 1396 * Enable libumem debugging by default on DEBUG builds. 1397 */ 1398 #ifdef DEBUG 1399 const char * 1400 _umem_debug_init(void) 1401 { 1402 return ("default,verbose"); /* $UMEM_DEBUG setting */ 1403 } 1404 1405 const char * 1406 _umem_logging_init(void) 1407 { 1408 return ("fail,contents"); /* $UMEM_LOGGING setting */ 1409 } 1410 #endif 1411