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