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 286 bzero(&jdi, sizeof (jdi)); 287 288 while ((option = getopt(argc, argv, "u:w:")) != -1) { 289 switch (option) { 290 case 'w': 291 (void) strlcpy(jdi.domain_name, optarg, 292 sizeof (jdi.domain_name)); 293 jdi.mode = SMB_SECMODE_WORKGRP; 294 join_w = B_TRUE; 295 break; 296 297 case 'u': 298 /* admin username */ 299 (void) strlcpy(jdi.domain_username, optarg, 300 sizeof (jdi.domain_username)); 301 jdi.mode = SMB_SECMODE_DOMAIN; 302 join_d = B_TRUE; 303 break; 304 305 default: 306 smbadm_usage(B_FALSE); 307 } 308 } 309 310 if (join_w && join_d) { 311 (void) fprintf(stderr, 312 gettext("domain and workgroup " 313 "can not be specified together\n")); 314 smbadm_usage(B_FALSE); 315 } 316 317 if (join_d && (argv[optind] != NULL)) { 318 (void) strlcpy(jdi.domain_name, argv[optind], 319 sizeof (jdi.domain_name)); 320 } 321 322 if (*jdi.domain_name == '\0') { 323 (void) fprintf(stderr, gettext("missing %s name\n"), 324 (join_d) ? "domain" : "workgroup"); 325 smbadm_usage(B_FALSE); 326 } 327 328 if (join_d && *jdi.domain_username == '\0') { 329 (void) fprintf(stderr, gettext("missing username\n")); 330 smbadm_usage(B_FALSE); 331 } 332 333 if (join_w) { 334 status = smb_join(&jdi); 335 if (status == NT_STATUS_SUCCESS) { 336 (void) printf( 337 gettext("Successfully joined workgroup '%s'\n"), 338 jdi.domain_name); 339 return (0); 340 } 341 342 (void) fprintf(stderr, 343 gettext("failed to join workgroup '%s' (%s)\n"), 344 jdi.domain_name, xlate_nt_status(status)); 345 346 return (1); 347 } 348 349 if ((smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kdom, sizeof (kdom)) 350 == SMBD_SMF_OK) && (*kdom != 0)) { 351 if (strncasecmp(jdi.domain_name, kdom, 352 strlen(jdi.domain_name))) { 353 char reply[8]; 354 355 (void) printf(gettext("The system has already " 356 "joined to a different domain %s by another " 357 "program.\nWould you like to continue [yes/no]? "), 358 kdom); 359 (void) scanf("%8s", reply); 360 (void) trim_whitespace(reply); 361 if (strncasecmp(reply, "yes", 3) != 0) 362 return (0); 363 } 364 } 365 366 /* Join the domain */ 367 if (*jdi.domain_passwd == '\0') { 368 char *p = NULL; 369 char *prompt = gettext("Enter domain password: "); 370 p = getpassphrase(prompt); 371 if (!p) { 372 (void) fprintf(stderr, gettext("missing password\n")); 373 smbadm_usage(B_FALSE); 374 } 375 376 (void) strlcpy(jdi.domain_passwd, p, 377 sizeof (jdi.domain_passwd)); 378 } 379 380 (void) printf(gettext("Joining '%s' ... this may take a minute ...\n"), 381 jdi.domain_name); 382 383 status = smb_join(&jdi); 384 385 switch (status) { 386 case NT_STATUS_SUCCESS: 387 (void) printf(gettext("Successfully joined domain '%s'\n"), 388 jdi.domain_name); 389 return (0); 390 391 case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND: 392 (void) fprintf(stderr, gettext("failed to find " 393 "any domain controllers for '%s'\n"), 394 jdi.domain_name); 395 break; 396 397 default: 398 (void) fprintf(stderr, 399 gettext("failed to join domain '%s' (%s)\n"), 400 jdi.domain_name, xlate_nt_status(status)); 401 } 402 403 return (1); 404 } 405 406 /* 407 * smbadm_list 408 * 409 * Displays current security mode and domain/workgroup name. 410 */ 411 /*ARGSUSED*/ 412 static int 413 smbadm_list(int argc, char **argv) 414 { 415 char domain[MAXHOSTNAMELEN]; 416 char modename[16]; 417 int rc; 418 419 rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename)); 420 if (rc != SMBD_SMF_OK) { 421 (void) fprintf(stderr, 422 gettext("failed to get the security mode\n")); 423 return (1); 424 } 425 426 (void) printf(gettext("security mode: %s\n"), modename); 427 428 if (smb_getdomainname(domain, sizeof (domain)) != 0) { 429 (void) fprintf(stderr, gettext("failed to get the %s name\n"), 430 modename); 431 return (1); 432 } 433 434 (void) printf(gettext("%s name: %s\n"), modename, domain); 435 return (0); 436 } 437 438 /* 439 * smbadm_group_create 440 * 441 * Creates a local SMB group 442 */ 443 static int 444 smbadm_group_create(int argc, char **argv) 445 { 446 char *gname = NULL; 447 char *desc = NULL; 448 char option; 449 int status; 450 451 while ((option = getopt(argc, argv, "d:")) != -1) { 452 switch (option) { 453 case 'd': 454 desc = optarg; 455 break; 456 457 default: 458 smbadm_usage(B_FALSE); 459 } 460 } 461 462 gname = argv[optind]; 463 if (optind >= argc || gname == NULL || *gname == '\0') { 464 (void) fprintf(stderr, gettext("missing group name\n")); 465 smbadm_usage(B_FALSE); 466 } 467 468 if (getgrnam(gname) == NULL) { 469 (void) fprintf(stderr, 470 gettext("failed to get the Solaris group '%s'\n"), gname); 471 (void) fprintf(stderr, 472 gettext("use 'groupadd' to add '%s'\n"), gname); 473 return (1); 474 } 475 476 status = smb_lgrp_add(gname, desc); 477 if (status != SMB_LGRP_SUCCESS) { 478 (void) fprintf(stderr, 479 gettext("failed to create the group (%s)\n"), 480 smb_lgrp_strerror(status)); 481 } else { 482 (void) printf(gettext("'%s' created.\n"), 483 gname); 484 } 485 486 return (status); 487 } 488 489 /* 490 * smbadm_group_dump_members 491 * 492 * Dump group members details. 493 */ 494 static void 495 smbadm_group_dump_members(smb_gsid_t *members, int num) 496 { 497 char sidstr[NT_SID_FMTBUF_SIZE]; 498 int i; 499 500 if (num == 0) { 501 (void) printf(gettext("\tNo members\n")); 502 return; 503 } 504 505 (void) printf(gettext("\tMembers:\n")); 506 for (i = 0; i < num; i++) { 507 (void) smb_lookup_sid(members[i].gs_sid, sidstr, 508 sizeof (sidstr)); 509 (void) printf(gettext("\t\t%s\n"), sidstr); 510 } 511 } 512 513 /* 514 * smbadm_group_dump_privs 515 * 516 * Dump group privilege details. 517 */ 518 static void 519 smbadm_group_dump_privs(smb_privset_t *privs) 520 { 521 smb_privinfo_t *pinfo; 522 char *pstatus; 523 int i; 524 525 (void) printf(gettext("\tPrivileges: \n")); 526 527 for (i = 0; i < privs->priv_cnt; i++) { 528 pinfo = smb_priv_getbyvalue(privs->priv[i].luid.lo_part); 529 if ((pinfo == NULL) || (pinfo->flags & PF_PRESENTABLE) == 0) 530 continue; 531 532 switch (privs->priv[i].attrs) { 533 case SE_PRIVILEGE_ENABLED: 534 pstatus = "On"; 535 break; 536 case SE_PRIVILEGE_DISABLED: 537 pstatus = "Off"; 538 break; 539 default: 540 pstatus = "Unknown"; 541 break; 542 } 543 (void) printf(gettext("\t\t%s: %s\n"), pinfo->name, pstatus); 544 } 545 546 if (privs->priv_cnt == 0) 547 (void) printf(gettext("\t\tNo privileges\n")); 548 } 549 550 /* 551 * smbadm_group_dump 552 * 553 * Dump group details. 554 */ 555 static void 556 smbadm_group_dump(smb_group_t *grp, boolean_t show_mem, boolean_t show_privs) 557 { 558 char sidstr[NT_SID_FMTBUF_SIZE]; 559 560 (void) printf(gettext("%s (%s)\n"), grp->sg_name, grp->sg_cmnt); 561 562 nt_sid_format2(grp->sg_id.gs_sid, sidstr); 563 (void) printf(gettext("\tSID: %s\n"), sidstr); 564 565 if (show_privs) 566 smbadm_group_dump_privs(grp->sg_privs); 567 568 if (show_mem) 569 smbadm_group_dump_members(grp->sg_members, grp->sg_nmembers); 570 } 571 572 /* 573 * smbadm_group_show 574 * 575 */ 576 static int 577 smbadm_group_show(int argc, char **argv) 578 { 579 char *gname = NULL; 580 boolean_t show_privs; 581 boolean_t show_members; 582 char option; 583 int status; 584 smb_group_t grp; 585 smb_giter_t gi; 586 587 show_privs = show_members = B_FALSE; 588 589 while ((option = getopt(argc, argv, "mp")) != -1) { 590 switch (option) { 591 case 'm': 592 show_members = B_TRUE; 593 break; 594 case 'p': 595 show_privs = B_TRUE; 596 break; 597 598 default: 599 smbadm_usage(B_FALSE); 600 } 601 } 602 603 gname = argv[optind]; 604 if (optind >= argc || gname == NULL || *gname == '\0') 605 gname = "*"; 606 607 if (strcmp(gname, "*")) { 608 status = smb_lgrp_getbyname(gname, &grp); 609 if (status == SMB_LGRP_SUCCESS) { 610 smbadm_group_dump(&grp, show_members, show_privs); 611 smb_lgrp_free(&grp); 612 } else { 613 (void) fprintf(stderr, 614 gettext("failed to find '%s' (%s)\n"), 615 gname, smb_lgrp_strerror(status)); 616 } 617 return (status); 618 } 619 620 status = smb_lgrp_iteropen(&gi); 621 if (status != SMB_LGRP_SUCCESS) { 622 (void) fprintf(stderr, 623 gettext("failed to list groups (%s)\n"), 624 smb_lgrp_strerror(status)); 625 return (status); 626 } 627 628 while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { 629 smbadm_group_dump(&grp, show_members, show_privs); 630 smb_lgrp_free(&grp); 631 } 632 smb_lgrp_iterclose(&gi); 633 634 return (0); 635 } 636 637 /* 638 * smbadm_group_delete 639 */ 640 static int 641 smbadm_group_delete(int argc, char **argv) 642 { 643 char *gname = NULL; 644 int status; 645 646 gname = argv[optind]; 647 if (optind >= argc || gname == NULL || *gname == '\0') { 648 (void) fprintf(stderr, gettext("missing group name\n")); 649 smbadm_usage(B_FALSE); 650 } 651 652 status = smb_lgrp_delete(gname); 653 if (status != SMB_LGRP_SUCCESS) { 654 (void) fprintf(stderr, 655 gettext("failed to delete the group (%s)\n"), 656 smb_lgrp_strerror(status)); 657 } else { 658 (void) printf(gettext("'%s' deleted.\n"), 659 gname); 660 } 661 662 return (status); 663 } 664 665 /* 666 * smbadm_group_rename 667 */ 668 static int 669 smbadm_group_rename(int argc, char **argv) 670 { 671 char *gname = NULL; 672 char *ngname = NULL; 673 int status; 674 675 gname = argv[optind]; 676 if (optind++ >= argc || gname == NULL || *gname == '\0') { 677 (void) fprintf(stderr, gettext("missing group name\n")); 678 smbadm_usage(B_FALSE); 679 } 680 681 ngname = argv[optind]; 682 if (optind >= argc || ngname == NULL || *ngname == '\0') { 683 (void) fprintf(stderr, gettext("missing new group name\n")); 684 smbadm_usage(B_FALSE); 685 } 686 687 if (getgrnam(ngname) == NULL) { 688 (void) fprintf(stderr, 689 gettext("failed to get the Solaris group '%s'\n"), ngname); 690 (void) fprintf(stderr, 691 gettext("use 'groupadd' to add '%s'\n"), ngname); 692 return (1); 693 } 694 695 status = smb_lgrp_rename(gname, ngname); 696 if (status != SMB_LGRP_SUCCESS) { 697 if (status == SMB_LGRP_EXISTS) 698 (void) fprintf(stderr, 699 gettext("failed to rename '%s' (%s already " 700 "exists)\n"), gname, ngname); 701 else 702 (void) fprintf(stderr, 703 gettext("failed to rename '%s' (%s)\n"), gname, 704 smb_lgrp_strerror(status)); 705 } else { 706 (void) printf(gettext("'%s' renamed to '%s'\n"), gname, ngname); 707 } 708 709 return (status); 710 } 711 712 /* 713 * smbadm_group_setprop 714 * 715 * Set the group properties. 716 */ 717 static int 718 smbadm_group_setprop(int argc, char **argv) 719 { 720 char *gname = NULL; 721 smbadm_prop_t props[SMBADM_NPROP]; 722 smbadm_prop_handle_t *phandle; 723 char option; 724 int pcnt = 0; 725 int ret; 726 int p; 727 728 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 729 730 while ((option = getopt(argc, argv, "p:")) != -1) { 731 switch (option) { 732 case 'p': 733 if (pcnt >= SMBADM_NPROP) { 734 (void) fprintf(stderr, 735 gettext("exceeded number of supported" 736 " properties\n")); 737 smbadm_usage(B_FALSE); 738 } 739 740 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 741 smbadm_usage(B_FALSE); 742 break; 743 744 default: 745 smbadm_usage(B_FALSE); 746 } 747 } 748 749 if (pcnt == 0) { 750 (void) fprintf(stderr, 751 gettext("missing property=value argument\n")); 752 smbadm_usage(B_FALSE); 753 } 754 755 gname = argv[optind]; 756 if (optind >= argc || gname == NULL || *gname == '\0') { 757 (void) fprintf(stderr, gettext("missing group name\n")); 758 smbadm_usage(B_FALSE); 759 } 760 761 for (p = 0; p < pcnt; p++) { 762 phandle = smbadm_prop_gethandle(props[p].p_name); 763 if (phandle) { 764 if (phandle->p_setfn(gname, &props[p]) != 0) 765 ret = 1; 766 } 767 } 768 769 return (ret); 770 } 771 772 /* 773 * smbadm_group_getprop 774 * 775 * Get the group properties. 776 */ 777 static int 778 smbadm_group_getprop(int argc, char **argv) 779 { 780 char *gname = NULL; 781 smbadm_prop_t props[SMBADM_NPROP]; 782 smbadm_prop_handle_t *phandle; 783 char option; 784 int pcnt = 0; 785 int ret; 786 int p; 787 788 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 789 790 while ((option = getopt(argc, argv, "p:")) != -1) { 791 switch (option) { 792 case 'p': 793 if (pcnt >= SMBADM_NPROP) { 794 (void) fprintf(stderr, 795 gettext("exceeded number of supported" 796 " properties\n")); 797 smbadm_usage(B_FALSE); 798 } 799 800 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 801 smbadm_usage(B_FALSE); 802 break; 803 804 default: 805 smbadm_usage(B_FALSE); 806 } 807 } 808 809 gname = argv[optind]; 810 if (optind >= argc || gname == NULL || *gname == '\0') { 811 (void) fprintf(stderr, gettext("missing group name\n")); 812 smbadm_usage(B_FALSE); 813 } 814 815 if (pcnt == 0) { 816 /* 817 * If no property has be specified then get 818 * all the properties. 819 */ 820 pcnt = SMBADM_NPROP; 821 for (p = 0; p < pcnt; p++) 822 props[p].p_name = smbadm_ptable[p].p_name; 823 } 824 825 for (p = 0; p < pcnt; p++) { 826 phandle = smbadm_prop_gethandle(props[p].p_name); 827 if (phandle) { 828 if (phandle->p_getfn(gname, &props[p]) != 0) 829 ret = 1; 830 } 831 } 832 833 return (ret); 834 } 835 836 /* 837 * smbadm_group_addmember 838 * 839 */ 840 static int 841 smbadm_group_addmember(int argc, char **argv) 842 { 843 char *gname = NULL; 844 char **mname; 845 char option; 846 smb_gsid_t msid; 847 int status; 848 int mcnt = 0; 849 int ret = 0; 850 int i; 851 852 853 mname = (char **)malloc(argc * sizeof (char *)); 854 if (mname == NULL) { 855 (void) fprintf(stderr, gettext("out of memory\n")); 856 return (1); 857 } 858 bzero(mname, argc * sizeof (char *)); 859 860 while ((option = getopt(argc, argv, "m:")) != -1) { 861 switch (option) { 862 case 'm': 863 mname[mcnt++] = optarg; 864 break; 865 866 default: 867 free(mname); 868 smbadm_usage(B_FALSE); 869 } 870 } 871 872 if (mcnt == 0) { 873 (void) fprintf(stderr, gettext("missing member name\n")); 874 free(mname); 875 smbadm_usage(B_FALSE); 876 } 877 878 gname = argv[optind]; 879 if (optind >= argc || gname == NULL || *gname == 0) { 880 (void) fprintf(stderr, gettext("missing group name\n")); 881 free(mname); 882 smbadm_usage(B_FALSE); 883 } 884 885 886 for (i = 0; i < mcnt; i++) { 887 if (mname[i] == NULL) 888 continue; 889 890 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 891 (void) fprintf(stderr, 892 gettext("failed to add %s " 893 "(could not obtain the SID)\n"), 894 mname[i]); 895 continue; 896 } 897 898 status = smb_lgrp_add_member(gname, msid.gs_sid, msid.gs_type); 899 free(msid.gs_sid); 900 if (status != SMB_LGRP_SUCCESS) { 901 (void) fprintf(stderr, 902 gettext("failed to add %s (%s)\n"), 903 mname[i], smb_lgrp_strerror(status)); 904 ret = 1; 905 } else { 906 (void) printf(gettext("'%s' is now a member of '%s'\n"), 907 mname[i], gname); 908 } 909 } 910 911 free(mname); 912 return (ret); 913 } 914 915 /* 916 * smbadm_group_delmember 917 */ 918 static int 919 smbadm_group_delmember(int argc, char **argv) 920 { 921 char *gname = NULL; 922 char **mname; 923 char option; 924 smb_gsid_t msid; 925 int status; 926 int mcnt = 0; 927 int ret = 0; 928 int i; 929 930 mname = (char **)malloc(argc * sizeof (char *)); 931 if (mname == NULL) { 932 (void) fprintf(stderr, gettext("out of memory\n")); 933 return (1); 934 } 935 bzero(mname, argc * sizeof (char *)); 936 937 while ((option = getopt(argc, argv, "m:")) != -1) { 938 switch (option) { 939 case 'm': 940 mname[mcnt++] = optarg; 941 break; 942 943 default: 944 free(mname); 945 smbadm_usage(B_FALSE); 946 } 947 } 948 949 if (mcnt == 0) { 950 (void) fprintf(stderr, gettext("missing member name\n")); 951 free(mname); 952 smbadm_usage(B_FALSE); 953 } 954 955 gname = argv[optind]; 956 if (optind >= argc || gname == NULL || *gname == 0) { 957 (void) fprintf(stderr, gettext("missing group name\n")); 958 free(mname); 959 smbadm_usage(B_FALSE); 960 } 961 962 963 for (i = 0; i < mcnt; i++) { 964 if (mname[i] == NULL) 965 continue; 966 967 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 968 (void) fprintf(stderr, 969 gettext("failed to remove %s " 970 "(could not obtain the SID)\n"), 971 mname[i]); 972 continue; 973 } 974 975 status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type); 976 free(msid.gs_sid); 977 if (status != SMB_LGRP_SUCCESS) { 978 (void) fprintf(stderr, 979 gettext("failed to remove %s (%s)\n"), 980 mname[i], smb_lgrp_strerror(status)); 981 ret = 1; 982 } else { 983 (void) printf( 984 gettext("'%s' has been removed from %s\n"), 985 mname[i], gname); 986 } 987 } 988 989 return (ret); 990 } 991 992 static int 993 smbadm_user_disable(int argc, char **argv) 994 { 995 int error; 996 char *user = NULL; 997 998 user = argv[optind]; 999 if (optind >= argc || user == NULL || *user == '\0') { 1000 (void) fprintf(stderr, gettext("missing user name\n")); 1001 smbadm_usage(B_FALSE); 1002 } 1003 1004 error = smb_pwd_setcntl(user, SMB_PWC_DISABLE); 1005 if (error == SMB_PWE_SUCCESS) 1006 (void) printf(gettext("%s is disabled.\n"), user); 1007 else 1008 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1009 1010 return (error); 1011 } 1012 1013 static int 1014 smbadm_user_enable(int argc, char **argv) 1015 { 1016 int error; 1017 char *user = NULL; 1018 1019 user = argv[optind]; 1020 if (optind >= argc || user == NULL || *user == '\0') { 1021 (void) fprintf(stderr, gettext("missing user name\n")); 1022 smbadm_usage(B_FALSE); 1023 } 1024 1025 error = smb_pwd_setcntl(user, SMB_PWC_ENABLE); 1026 if (error == SMB_PWE_SUCCESS) 1027 (void) printf(gettext("%s is enabled.\n"), user); 1028 else 1029 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1030 1031 return (error); 1032 } 1033 1034 1035 int 1036 main(int argc, char **argv) 1037 { 1038 int ret; 1039 int i; 1040 1041 (void) malloc(0); /* satisfy libumem dependency */ 1042 1043 progname = basename(argv[0]); 1044 1045 if (getzoneid() != GLOBAL_ZONEID) { 1046 (void) fprintf(stderr, 1047 gettext("cannot execute in non-global zone\n")); 1048 return (0); 1049 } 1050 1051 if (is_system_labeled()) { 1052 (void) fprintf(stderr, 1053 gettext("Trusted Extensions not supported\n")); 1054 return (0); 1055 } 1056 1057 if (argc < 2) { 1058 (void) fprintf(stderr, gettext("missing command\n")); 1059 smbadm_usage(B_FALSE); 1060 } 1061 1062 /* 1063 * Special case "cmd --help/-?" 1064 */ 1065 if (strcmp(argv[1], "-?") == 0 || 1066 strcmp(argv[1], "--help") == 0 || 1067 strcmp(argv[1], "-h") == 0) 1068 smbadm_usage(B_TRUE); 1069 1070 for (i = 0; i < SMBADM_NCMD; ++i) { 1071 curcmd = &smbadm_cmdtable[i]; 1072 if (strcasecmp(argv[1], curcmd->name) == 0) { 1073 if (argc > 2) { 1074 /* cmd subcmd --help/-? */ 1075 if (strcmp(argv[2], "-?") == 0 || 1076 strcmp(argv[2], "--help") == 0 || 1077 strcmp(argv[2], "-h") == 0) 1078 smbadm_usage(B_TRUE); 1079 } 1080 1081 if ((ret = smbadm_grpcmd_init()) != 0) 1082 return (ret); 1083 1084 ret = curcmd->func(argc - 1, &argv[1]); 1085 1086 smbadm_grpcmd_fini(); 1087 return (ret); 1088 } 1089 } 1090 1091 curcmd = NULL; 1092 (void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]); 1093 smbadm_usage(B_FALSE); 1094 return (2); 1095 } 1096 1097 static int 1098 smbadm_grpcmd_init(void) 1099 { 1100 int rc; 1101 1102 if (curcmd->flags & SMBADM_CMDF_GROUP) { 1103 if (smb_idmap_start() != 0) { 1104 (void) fprintf(stderr, 1105 gettext("failed to contact idmap service\n")); 1106 return (1); 1107 } 1108 1109 if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { 1110 (void) fprintf(stderr, 1111 gettext("failed to initialize (%s)\n"), 1112 smb_lgrp_strerror(rc)); 1113 smb_idmap_stop(); 1114 return (1); 1115 } 1116 } 1117 1118 return (0); 1119 } 1120 1121 static void 1122 smbadm_grpcmd_fini(void) 1123 { 1124 if (curcmd->flags & SMBADM_CMDF_GROUP) { 1125 smb_lgrp_stop(); 1126 smb_idmap_stop(); 1127 } 1128 } 1129 1130 static boolean_t 1131 smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 1132 { 1133 smbadm_prop_handle_t *pinfo; 1134 int i; 1135 1136 for (i = 0; i < SMBADM_NPROP; i++) { 1137 pinfo = &smbadm_ptable[i]; 1138 if (strcmp(pinfo->p_name, prop->p_name) == 0) { 1139 if (pinfo->p_chkfn && chkval) 1140 return (pinfo->p_chkfn(prop)); 1141 1142 return (B_TRUE); 1143 } 1144 } 1145 1146 (void) fprintf(stderr, 1147 gettext("unrecognized property '%s'\n"), prop->p_name); 1148 1149 return (B_FALSE); 1150 } 1151 1152 static int 1153 smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 1154 { 1155 boolean_t parse_value; 1156 char *equal; 1157 1158 if (arg == NULL) 1159 return (2); 1160 1161 prop->p_name = prop->p_value = NULL; 1162 1163 if (strcmp(curcmd->name, "set") == 0) 1164 parse_value = B_TRUE; 1165 else 1166 parse_value = B_FALSE; 1167 1168 prop->p_name = arg; 1169 1170 if (parse_value) { 1171 equal = strchr(arg, '='); 1172 if (equal == NULL) 1173 return (2); 1174 1175 *equal++ = '\0'; 1176 prop->p_value = equal; 1177 } 1178 1179 if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 1180 return (2); 1181 1182 return (0); 1183 } 1184 1185 static smbadm_prop_handle_t * 1186 smbadm_prop_gethandle(char *pname) 1187 { 1188 int i; 1189 1190 for (i = 0; i < SMBADM_NPROP; i++) 1191 if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 1192 return (&smbadm_ptable[i]); 1193 1194 return (NULL); 1195 } 1196 1197 static int 1198 smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 1199 { 1200 int status; 1201 1202 status = smb_lgrp_setcmnt(gname, prop->p_value); 1203 if (status != SMB_LGRP_SUCCESS) { 1204 (void) fprintf(stderr, 1205 gettext("failed to modify the group description (%s)\n"), 1206 smb_lgrp_strerror(status)); 1207 return (1); 1208 } 1209 1210 (void) printf(gettext("Successfully modified " 1211 "'%s' description\n"), gname); 1212 1213 return (0); 1214 } 1215 1216 static int 1217 smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 1218 { 1219 char *cmnt = NULL; 1220 int status; 1221 1222 status = smb_lgrp_getcmnt(gname, &cmnt); 1223 if (status != SMB_LGRP_SUCCESS) { 1224 (void) fprintf(stderr, 1225 gettext("failed to get the group description (%s)\n"), 1226 smb_lgrp_strerror(status)); 1227 return (1); 1228 } 1229 1230 (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); 1231 free(cmnt); 1232 return (0); 1233 } 1234 1235 static int 1236 smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1237 { 1238 boolean_t enable; 1239 int status; 1240 int ret; 1241 1242 if (strcasecmp(prop->p_value, "on") == 0) { 1243 (void) printf(gettext("Enabling %s privilege "), prop->p_name); 1244 enable = B_TRUE; 1245 } else { 1246 (void) printf(gettext("Disabling %s privilege "), prop->p_name); 1247 enable = B_FALSE; 1248 } 1249 1250 status = smb_lgrp_setpriv(gname, priv_id, enable); 1251 if (status == SMB_LGRP_SUCCESS) { 1252 (void) printf(gettext("succeeded\n")); 1253 ret = 0; 1254 } else { 1255 (void) printf(gettext("failed: %s\n"), 1256 smb_lgrp_strerror(status)); 1257 ret = 1; 1258 } 1259 1260 return (ret); 1261 } 1262 1263 static int 1264 smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1265 { 1266 boolean_t enable; 1267 int status; 1268 1269 status = smb_lgrp_getpriv(gname, priv_id, &enable); 1270 if (status != SMB_LGRP_SUCCESS) { 1271 (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 1272 prop->p_name, smb_lgrp_strerror(status)); 1273 return (1); 1274 } 1275 1276 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 1277 (enable) ? "On" : "Off"); 1278 1279 return (0); 1280 } 1281 1282 static int 1283 smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 1284 { 1285 return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1286 } 1287 1288 static int 1289 smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 1290 { 1291 return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1292 } 1293 1294 static int 1295 smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 1296 { 1297 return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 1298 } 1299 1300 static int 1301 smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 1302 { 1303 return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 1304 } 1305 1306 static int 1307 smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 1308 { 1309 return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 1310 } 1311 1312 static int 1313 smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 1314 { 1315 return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 1316 } 1317 1318 static boolean_t 1319 smbadm_chkprop_priv(smbadm_prop_t *prop) 1320 { 1321 if (prop->p_value == NULL || *prop->p_value == '\0') { 1322 (void) fprintf(stderr, 1323 gettext("missing value for '%s'\n"), prop->p_name); 1324 return (B_FALSE); 1325 } 1326 1327 if (strcasecmp(prop->p_value, "on") == 0) 1328 return (B_TRUE); 1329 1330 if (strcasecmp(prop->p_value, "off") == 0) 1331 return (B_TRUE); 1332 1333 (void) fprintf(stderr, 1334 gettext("%s: unrecognized value for '%s' property\n"), 1335 prop->p_value, prop->p_name); 1336 1337 return (B_FALSE); 1338 } 1339 1340 static const char * 1341 smbadm_pwd_strerror(int error) 1342 { 1343 switch (error) { 1344 case SMB_PWE_SUCCESS: 1345 return (gettext("Success.")); 1346 1347 case SMB_PWE_USER_UNKNOWN: 1348 return (gettext("User does not exist.")); 1349 1350 case SMB_PWE_USER_DISABLE: 1351 return (gettext("User is disable.")); 1352 1353 case SMB_PWE_CLOSE_FAILED: 1354 case SMB_PWE_OPEN_FAILED: 1355 case SMB_PWE_WRITE_FAILED: 1356 case SMB_PWE_UPDATE_FAILED: 1357 return (gettext("Unexpected failure. " 1358 "SMB password database unchanged.")); 1359 1360 case SMB_PWE_STAT_FAILED: 1361 return (gettext("stat of SMB password file failed.")); 1362 1363 case SMB_PWE_BUSY: 1364 return (gettext("SMB password database busy. " 1365 "Try again later.")); 1366 1367 case SMB_PWE_DENIED: 1368 return (gettext("Operation not permitted.")); 1369 1370 case SMB_PWE_SYSTEM_ERROR: 1371 return (gettext("System error.")); 1372 } 1373 1374 return (gettext("Unknown error code.")); 1375 } 1376 1377 /* 1378 * Enable libumem debugging by default on DEBUG builds. 1379 */ 1380 #ifdef DEBUG 1381 const char * 1382 _umem_debug_init(void) 1383 { 1384 return ("default,verbose"); /* $UMEM_DEBUG setting */ 1385 } 1386 1387 const char * 1388 _umem_logging_init(void) 1389 { 1390 return ("fail,contents"); /* $UMEM_LOGGING setting */ 1391 } 1392 #endif 1393