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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * This module contains smbadm CLI which offers smb configuration 27 * functionalities. 28 */ 29 #include <errno.h> 30 #include <err.h> 31 #include <ctype.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <stdio.h> 35 #include <syslog.h> 36 #include <strings.h> 37 #include <limits.h> 38 #include <getopt.h> 39 #include <libintl.h> 40 #include <zone.h> 41 #include <pwd.h> 42 #include <grp.h> 43 #include <libgen.h> 44 #include <netinet/in.h> 45 #include <auth_attr.h> 46 #include <locale.h> 47 #include <smbsrv/libsmb.h> 48 49 #if !defined(TEXT_DOMAIN) 50 #define TEXT_DOMAIN "SYS_TEST" 51 #endif 52 53 typedef enum { 54 HELP_ADD_MEMBER, 55 HELP_CREATE, 56 HELP_DELETE, 57 HELP_DEL_MEMBER, 58 HELP_GET, 59 HELP_JOIN, 60 HELP_LIST, 61 HELP_RENAME, 62 HELP_SET, 63 HELP_SHOW, 64 HELP_USER_DISABLE, 65 HELP_USER_ENABLE 66 } smbadm_help_t; 67 68 #define SMBADM_CMDF_NONE 0x00 69 #define SMBADM_CMDF_USER 0x01 70 #define SMBADM_CMDF_GROUP 0x02 71 #define SMBADM_CMDF_TYPEMASK 0x0F 72 73 #define SMBADM_ANSBUFSIZ 64 74 75 typedef struct smbadm_cmdinfo { 76 char *name; 77 int (*func)(int, char **); 78 smbadm_help_t usage; 79 uint32_t flags; 80 char *auth; 81 } smbadm_cmdinfo_t; 82 83 smbadm_cmdinfo_t *curcmd; 84 static char *progname; 85 86 #define SMBADM_ACTION_AUTH "solaris.smf.manage.smb" 87 #define SMBADM_VALUE_AUTH "solaris.smf.value.smb" 88 #define SMBADM_BASIC_AUTH "solaris.network.hosts.read" 89 90 static boolean_t smbadm_checkauth(const char *); 91 92 static void smbadm_usage(boolean_t); 93 static int smbadm_join_workgroup(const char *); 94 static int smbadm_join_domain(const char *, const char *); 95 static void smbadm_extract_domain(char *, char **, char **); 96 97 static int smbadm_join(int, char **); 98 static int smbadm_list(int, char **); 99 static int smbadm_group_create(int, char **); 100 static int smbadm_group_delete(int, char **); 101 static int smbadm_group_rename(int, char **); 102 static int smbadm_group_show(int, char **); 103 static void smbadm_group_show_name(const char *, const char *); 104 static int smbadm_group_getprop(int, char **); 105 static int smbadm_group_setprop(int, char **); 106 static int smbadm_group_addmember(int, char **); 107 static int smbadm_group_delmember(int, char **); 108 static int smbadm_user_disable(int, char **); 109 static int smbadm_user_enable(int, char **); 110 111 static smbadm_cmdinfo_t smbadm_cmdtable[] = 112 { 113 { "add-member", smbadm_group_addmember, HELP_ADD_MEMBER, 114 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 115 { "create", smbadm_group_create, HELP_CREATE, 116 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 117 { "delete", smbadm_group_delete, HELP_DELETE, 118 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 119 { "disable-user", smbadm_user_disable, HELP_USER_DISABLE, 120 SMBADM_CMDF_USER, SMBADM_ACTION_AUTH }, 121 { "enable-user", smbadm_user_enable, HELP_USER_ENABLE, 122 SMBADM_CMDF_USER, SMBADM_ACTION_AUTH }, 123 { "get", smbadm_group_getprop, HELP_GET, 124 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 125 { "join", smbadm_join, HELP_JOIN, 126 SMBADM_CMDF_NONE, SMBADM_VALUE_AUTH }, 127 { "list", smbadm_list, HELP_LIST, 128 SMBADM_CMDF_NONE, SMBADM_BASIC_AUTH }, 129 { "remove-member", smbadm_group_delmember, HELP_DEL_MEMBER, 130 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 131 { "rename", smbadm_group_rename, HELP_RENAME, 132 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 133 { "set", smbadm_group_setprop, HELP_SET, 134 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 135 { "show", smbadm_group_show, HELP_SHOW, 136 SMBADM_CMDF_GROUP, SMBADM_ACTION_AUTH }, 137 }; 138 139 #define SMBADM_NCMD (sizeof (smbadm_cmdtable) / sizeof (smbadm_cmdtable[0])) 140 141 typedef struct smbadm_prop { 142 char *p_name; 143 char *p_value; 144 } smbadm_prop_t; 145 146 typedef struct smbadm_prop_handle { 147 char *p_name; 148 char *p_dispvalue; 149 int (*p_setfn)(char *, smbadm_prop_t *); 150 int (*p_getfn)(char *, smbadm_prop_t *); 151 boolean_t (*p_chkfn)(smbadm_prop_t *); 152 } smbadm_prop_handle_t; 153 154 static boolean_t smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval); 155 static int smbadm_prop_parse(char *arg, smbadm_prop_t *prop); 156 static smbadm_prop_handle_t *smbadm_prop_gethandle(char *pname); 157 158 static boolean_t smbadm_chkprop_priv(smbadm_prop_t *prop); 159 static int smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop); 160 static int smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop); 161 static int smbadm_setprop_backup(char *gname, smbadm_prop_t *prop); 162 static int smbadm_getprop_backup(char *gname, smbadm_prop_t *prop); 163 static int smbadm_setprop_restore(char *gname, smbadm_prop_t *prop); 164 static int smbadm_getprop_restore(char *gname, smbadm_prop_t *prop); 165 static int smbadm_setprop_desc(char *gname, smbadm_prop_t *prop); 166 static int smbadm_getprop_desc(char *gname, smbadm_prop_t *prop); 167 168 static smbadm_prop_handle_t smbadm_ptable[] = { 169 {"backup", "on | off", smbadm_setprop_backup, 170 smbadm_getprop_backup, smbadm_chkprop_priv }, 171 {"restore", "on | off", smbadm_setprop_restore, 172 smbadm_getprop_restore, smbadm_chkprop_priv }, 173 {"take-ownership", "on | off", smbadm_setprop_tkowner, 174 smbadm_getprop_tkowner, smbadm_chkprop_priv }, 175 {"description", "<string>", smbadm_setprop_desc, 176 smbadm_getprop_desc, NULL }, 177 }; 178 179 static int smbadm_init(void); 180 static void smbadm_fini(void); 181 static const char *smbadm_pwd_strerror(int error); 182 183 /* 184 * Number of supported properties 185 */ 186 #define SMBADM_NPROP (sizeof (smbadm_ptable) / sizeof (smbadm_ptable[0])) 187 188 static void 189 smbadm_cmdusage(FILE *fp, smbadm_cmdinfo_t *cmd) 190 { 191 switch (cmd->usage) { 192 case HELP_ADD_MEMBER: 193 (void) fprintf(fp, 194 gettext("\t%s -m member [[-m member] ...] group\n"), 195 cmd->name); 196 return; 197 198 case HELP_CREATE: 199 (void) fprintf(fp, gettext("\t%s [-d description] group\n"), 200 cmd->name); 201 return; 202 203 case HELP_DELETE: 204 (void) fprintf(fp, gettext("\t%s group\n"), cmd->name); 205 return; 206 207 case HELP_USER_DISABLE: 208 case HELP_USER_ENABLE: 209 (void) fprintf(fp, gettext("\t%s user\n"), cmd->name); 210 return; 211 212 case HELP_GET: 213 (void) fprintf(fp, gettext("\t%s [[-p property] ...] group\n"), 214 cmd->name); 215 return; 216 217 case HELP_JOIN: 218 (void) fprintf(fp, gettext("\t%s -u username domain\n" 219 "\t%s -w workgroup\n"), cmd->name, cmd->name); 220 return; 221 222 case HELP_LIST: 223 (void) fprintf(fp, gettext("\t%s\n"), cmd->name); 224 (void) fprintf(fp, 225 gettext("\t\t[*] primary domain\n")); 226 (void) fprintf(fp, gettext("\t\t[.] local domain\n")); 227 (void) fprintf(fp, gettext("\t\t[-] other domains\n")); 228 (void) fprintf(fp, 229 gettext("\t\t[+] selected domain controller\n")); 230 return; 231 232 case HELP_DEL_MEMBER: 233 (void) fprintf(fp, 234 gettext("\t%s -m member [[-m member] ...] group\n"), 235 cmd->name); 236 return; 237 238 case HELP_RENAME: 239 (void) fprintf(fp, gettext("\t%s group new-group\n"), 240 cmd->name); 241 return; 242 243 case HELP_SET: 244 (void) fprintf(fp, gettext("\t%s -p property=value " 245 "[[-p property=value] ...] group\n"), cmd->name); 246 return; 247 248 case HELP_SHOW: 249 (void) fprintf(fp, gettext("\t%s [-m] [-p] [group]\n"), 250 cmd->name); 251 return; 252 253 default: 254 break; 255 } 256 257 abort(); 258 /* NOTREACHED */ 259 } 260 261 static void 262 smbadm_usage(boolean_t requested) 263 { 264 FILE *fp = requested ? stdout : stderr; 265 boolean_t show_props = B_FALSE; 266 int i; 267 268 if (curcmd == NULL) { 269 (void) fprintf(fp, 270 gettext("usage: %s [-h | <command> [options]]\n"), 271 progname); 272 (void) fprintf(fp, 273 gettext("where 'command' is one of the following:\n\n")); 274 275 for (i = 0; i < SMBADM_NCMD; i++) 276 smbadm_cmdusage(fp, &smbadm_cmdtable[i]); 277 278 (void) fprintf(fp, 279 gettext("\nFor property list, run %s %s|%s\n"), 280 progname, "get", "set"); 281 282 exit(requested ? 0 : 2); 283 } 284 285 (void) fprintf(fp, gettext("usage:\n")); 286 smbadm_cmdusage(fp, curcmd); 287 288 if (strcmp(curcmd->name, "get") == 0 || 289 strcmp(curcmd->name, "set") == 0) 290 show_props = B_TRUE; 291 292 if (show_props) { 293 (void) fprintf(fp, 294 gettext("\nThe following properties are supported:\n")); 295 296 (void) fprintf(fp, "\n\t%-16s %s\n\n", 297 "PROPERTY", "VALUES"); 298 299 for (i = 0; i < SMBADM_NPROP; i++) { 300 (void) fprintf(fp, "\t%-16s %s\n", 301 smbadm_ptable[i].p_name, 302 smbadm_ptable[i].p_dispvalue); 303 } 304 } 305 306 exit(requested ? 0 : 2); 307 } 308 309 /* 310 * smbadm_strcasecmplist 311 * 312 * Find a string 's' within a list of strings. 313 * 314 * Returns the index of the matching string or -1 if there is no match. 315 */ 316 static int 317 smbadm_strcasecmplist(const char *s, ...) 318 { 319 va_list ap; 320 char *p; 321 int ndx; 322 323 va_start(ap, s); 324 325 for (ndx = 0; ((p = va_arg(ap, char *)) != NULL); ++ndx) { 326 if (strcasecmp(s, p) == 0) { 327 va_end(ap); 328 return (ndx); 329 } 330 } 331 332 va_end(ap); 333 return (-1); 334 } 335 336 /* 337 * smbadm_answer_prompt 338 * 339 * Prompt for the answer to a question. A default response must be 340 * specified, which will be used if the user presses <enter> without 341 * answering the question. 342 */ 343 static int 344 smbadm_answer_prompt(const char *prompt, char *answer, const char *dflt) 345 { 346 char buf[SMBADM_ANSBUFSIZ]; 347 char *p; 348 349 (void) printf(gettext("%s [%s]: "), prompt, dflt); 350 351 if (fgets(buf, SMBADM_ANSBUFSIZ, stdin) == NULL) 352 return (-1); 353 354 if ((p = strchr(buf, '\n')) != NULL) 355 *p = '\0'; 356 357 if (*buf == '\0') 358 (void) strlcpy(answer, dflt, SMBADM_ANSBUFSIZ); 359 else 360 (void) strlcpy(answer, buf, SMBADM_ANSBUFSIZ); 361 362 return (0); 363 } 364 365 /* 366 * smbadm_confirm 367 * 368 * Ask a question that requires a yes/no answer. 369 * A default response must be specified. 370 */ 371 static boolean_t 372 smbadm_confirm(const char *prompt, const char *dflt) 373 { 374 char buf[SMBADM_ANSBUFSIZ]; 375 376 for (;;) { 377 if (smbadm_answer_prompt(prompt, buf, dflt) < 0) 378 return (B_FALSE); 379 380 if (smbadm_strcasecmplist(buf, "n", "no", 0) >= 0) 381 return (B_FALSE); 382 383 if (smbadm_strcasecmplist(buf, "y", "yes", 0) >= 0) 384 return (B_TRUE); 385 386 (void) printf(gettext("Please answer yes or no.\n")); 387 } 388 } 389 390 static boolean_t 391 smbadm_join_prompt(const char *domain) 392 { 393 (void) printf(gettext("After joining %s the smb service will be " 394 "restarted automatically.\n"), domain); 395 396 return (smbadm_confirm("Would you like to continue?", "no")); 397 } 398 399 static void 400 smbadm_restart_service(void) 401 { 402 if (smb_smf_restart_service() != 0) { 403 (void) fprintf(stderr, 404 gettext("Unable to restart smb service. " 405 "Run 'svcs -xv smb/server' for more information.")); 406 } 407 } 408 409 /* 410 * smbadm_join 411 * 412 * Join a domain or workgroup. 413 * 414 * When joining a domain, we may receive the username, password and 415 * domain name in any of the following combinations. Note that the 416 * password is optional on the command line: if it is not provided, 417 * we will prompt for it later. 418 * 419 * username+password domain 420 * domain\username+password 421 * domain/username+password 422 * username@domain 423 * 424 * We allow domain\name+password or domain/name+password but not 425 * name+password@domain because @ is a valid password character. 426 * 427 * If the username and domain name are passed as separate command 428 * line arguments, we process them directly. Otherwise we separate 429 * them and continue as if they were separate command line arguments. 430 */ 431 static int 432 smbadm_join(int argc, char **argv) 433 { 434 char buf[MAXHOSTNAMELEN * 2]; 435 char *domain = NULL; 436 char *username = NULL; 437 uint32_t mode = 0; 438 char option; 439 440 while ((option = getopt(argc, argv, "u:w:")) != -1) { 441 switch (option) { 442 case 'w': 443 if (mode != 0) { 444 (void) fprintf(stderr, 445 gettext("-u and -w must only appear " 446 "once and are mutually exclusive\n")); 447 smbadm_usage(B_FALSE); 448 } 449 450 mode = SMB_SECMODE_WORKGRP; 451 domain = optarg; 452 break; 453 454 case 'u': 455 if (mode != 0) { 456 (void) fprintf(stderr, 457 gettext("-u and -w must only appear " 458 "once and are mutually exclusive\n")); 459 smbadm_usage(B_FALSE); 460 } 461 462 mode = SMB_SECMODE_DOMAIN; 463 username = optarg; 464 465 if ((domain = argv[optind]) == NULL) { 466 /* 467 * The domain was not specified as a separate 468 * argument, check for the combination forms. 469 */ 470 (void) strlcpy(buf, username, sizeof (buf)); 471 smbadm_extract_domain(buf, &username, &domain); 472 } 473 474 if ((username == NULL) || (*username == '\0')) { 475 (void) fprintf(stderr, 476 gettext("missing username\n")); 477 smbadm_usage(B_FALSE); 478 } 479 break; 480 481 default: 482 smbadm_usage(B_FALSE); 483 break; 484 } 485 } 486 487 if ((domain == NULL) || (*domain == '\0')) { 488 (void) fprintf(stderr, gettext("missing %s name\n"), 489 (mode == SMB_SECMODE_WORKGRP) ? "workgroup" : "domain"); 490 smbadm_usage(B_FALSE); 491 } 492 493 if (mode == SMB_SECMODE_WORKGRP) 494 return (smbadm_join_workgroup(domain)); 495 else 496 return (smbadm_join_domain(domain, username)); 497 } 498 499 /* 500 * Workgroups comprise a collection of standalone, independently administered 501 * computers that use a common workgroup name. This is a peer-to-peer model 502 * with no formal membership mechanism. 503 */ 504 static int 505 smbadm_join_workgroup(const char *workgroup) 506 { 507 smb_joininfo_t jdi; 508 uint32_t status; 509 510 bzero(&jdi, sizeof (jdi)); 511 jdi.mode = SMB_SECMODE_WORKGRP; 512 (void) strlcpy(jdi.domain_name, workgroup, sizeof (jdi.domain_name)); 513 (void) strtrim(jdi.domain_name, " \t\n"); 514 515 if (smb_name_validate_workgroup(jdi.domain_name) != ERROR_SUCCESS) { 516 (void) fprintf(stderr, gettext("workgroup name is invalid\n")); 517 smbadm_usage(B_FALSE); 518 } 519 520 if (!smbadm_join_prompt(jdi.domain_name)) 521 return (0); 522 523 if ((status = smb_join(&jdi)) != NT_STATUS_SUCCESS) { 524 (void) fprintf(stderr, gettext("failed to join %s: %s\n"), 525 jdi.domain_name, xlate_nt_status(status)); 526 return (1); 527 } 528 529 (void) printf(gettext("Successfully joined %s\n"), jdi.domain_name); 530 smbadm_restart_service(); 531 return (0); 532 } 533 534 /* 535 * Domains comprise a centrally administered group of computers and accounts 536 * that share a common security and administration policy and database. 537 * Computers must join a domain and become domain members, which requires 538 * an administrator level account name. 539 * 540 * The '+' character is invalid within a username. We allow the password 541 * to be appended to the username using '+' as a scripting convenience. 542 */ 543 static int 544 smbadm_join_domain(const char *domain, const char *username) 545 { 546 smb_joininfo_t jdi; 547 uint32_t status; 548 char *prompt; 549 char *p; 550 int len; 551 552 bzero(&jdi, sizeof (jdi)); 553 jdi.mode = SMB_SECMODE_DOMAIN; 554 (void) strlcpy(jdi.domain_name, domain, sizeof (jdi.domain_name)); 555 (void) strtrim(jdi.domain_name, " \t\n"); 556 557 if (smb_name_validate_domain(jdi.domain_name) != ERROR_SUCCESS) { 558 (void) fprintf(stderr, gettext("domain name is invalid\n")); 559 smbadm_usage(B_FALSE); 560 } 561 562 if (!smbadm_join_prompt(jdi.domain_name)) 563 return (0); 564 565 if ((p = strchr(username, '+')) != NULL) { 566 ++p; 567 568 len = (int)(p - username); 569 if (len > sizeof (jdi.domain_name)) 570 len = sizeof (jdi.domain_name); 571 572 (void) strlcpy(jdi.domain_username, username, len); 573 (void) strlcpy(jdi.domain_passwd, p, 574 sizeof (jdi.domain_passwd)); 575 } else { 576 (void) strlcpy(jdi.domain_username, username, 577 sizeof (jdi.domain_username)); 578 } 579 580 if (smb_name_validate_account(jdi.domain_username) != ERROR_SUCCESS) { 581 (void) fprintf(stderr, 582 gettext("username contains invalid characters\n")); 583 smbadm_usage(B_FALSE); 584 } 585 586 if (*jdi.domain_passwd == '\0') { 587 prompt = gettext("Enter domain password: "); 588 589 if ((p = getpassphrase(prompt)) == NULL) { 590 (void) fprintf(stderr, gettext("missing password\n")); 591 smbadm_usage(B_FALSE); 592 } 593 594 (void) strlcpy(jdi.domain_passwd, p, 595 sizeof (jdi.domain_passwd)); 596 } 597 598 (void) printf(gettext("Joining %s ... this may take a minute ...\n"), 599 jdi.domain_name); 600 601 status = smb_join(&jdi); 602 603 switch (status) { 604 case NT_STATUS_SUCCESS: 605 (void) printf(gettext("Successfully joined %s\n"), 606 jdi.domain_name); 607 bzero(&jdi, sizeof (jdi)); 608 smbadm_restart_service(); 609 return (0); 610 611 case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND: 612 (void) fprintf(stderr, 613 gettext("failed to find any domain controllers for %s\n"), 614 jdi.domain_name); 615 bzero(&jdi, sizeof (jdi)); 616 return (1); 617 618 default: 619 (void) fprintf(stderr, gettext("failed to join %s: %s\n"), 620 jdi.domain_name, xlate_nt_status(status)); 621 (void) fprintf(stderr, gettext("Please refer to the system log" 622 " for more information.\n")); 623 bzero(&jdi, sizeof (jdi)); 624 return (1); 625 } 626 } 627 628 /* 629 * We want to process the user and domain names as separate strings. 630 * Check for names of the forms below and separate the components as 631 * required. 632 * 633 * name@domain 634 * domain\name 635 * domain/name 636 * 637 * If we encounter any of the forms above in arg, the @, / or \ 638 * separator is replaced by \0 and the username and domain pointers 639 * are changed to point to the appropriate components (in arg). 640 * 641 * If none of the separators are encountered, the username and domain 642 * pointers remain unchanged. 643 */ 644 static void 645 smbadm_extract_domain(char *arg, char **username, char **domain) 646 { 647 char *p; 648 649 if ((p = strpbrk(arg, "/\\@")) != NULL) { 650 if (*p == '@') { 651 *p = '\0'; 652 ++p; 653 654 if (strchr(arg, '+') != NULL) 655 return; 656 657 *domain = p; 658 *username = arg; 659 } else { 660 *p = '\0'; 661 ++p; 662 *username = p; 663 *domain = arg; 664 } 665 } 666 } 667 668 /* 669 * smbadm_list 670 * 671 * Displays current security mode and domain/workgroup name. 672 */ 673 /*ARGSUSED*/ 674 static int 675 smbadm_list(int argc, char **argv) 676 { 677 char domain[MAXHOSTNAMELEN]; 678 char fqdn[MAXHOSTNAMELEN]; 679 char srvname[MAXHOSTNAMELEN]; 680 char modename[16]; 681 int rc; 682 smb_inaddr_t srvipaddr; 683 char ipstr[INET6_ADDRSTRLEN]; 684 685 rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename)); 686 if (rc != SMBD_SMF_OK) { 687 (void) fprintf(stderr, 688 gettext("cannot determine the operational mode\n")); 689 return (1); 690 } 691 692 if (smb_getdomainname(domain, sizeof (domain)) != 0) { 693 (void) fprintf(stderr, gettext("failed to get the %s name\n"), 694 modename); 695 return (1); 696 } 697 698 if (strcmp(modename, "workgroup") == 0) { 699 (void) printf(gettext("[*] [%s]\n"), domain); 700 return (0); 701 } 702 703 (void) printf(gettext("[*] [%s]\n"), domain); 704 if ((smb_getfqdomainname(fqdn, sizeof (fqdn)) == 0) && (*fqdn != '\0')) 705 (void) printf(gettext("[*] [%s]\n"), fqdn); 706 707 if ((smb_get_dcinfo(srvname, MAXHOSTNAMELEN, &srvipaddr) 708 == NT_STATUS_SUCCESS) && (*srvname != '\0') && 709 (!smb_inet_iszero(&srvipaddr))) { 710 (void) smb_inet_ntop(&srvipaddr, ipstr, 711 SMB_IPSTRLEN(srvipaddr.a_family)); 712 (void) printf(gettext("\t[+%s.%s] [%s]\n"), 713 srvname, fqdn, ipstr); 714 } 715 716 smb_domain_show(); 717 return (0); 718 } 719 720 /* 721 * smbadm_group_create 722 * 723 * Creates a local SMB group 724 */ 725 static int 726 smbadm_group_create(int argc, char **argv) 727 { 728 char *gname = NULL; 729 char *desc = NULL; 730 char option; 731 int status; 732 733 while ((option = getopt(argc, argv, "d:")) != -1) { 734 switch (option) { 735 case 'd': 736 desc = optarg; 737 break; 738 739 default: 740 smbadm_usage(B_FALSE); 741 } 742 } 743 744 gname = argv[optind]; 745 if (optind >= argc || gname == NULL || *gname == '\0') { 746 (void) fprintf(stderr, gettext("missing group name\n")); 747 smbadm_usage(B_FALSE); 748 } 749 750 status = smb_lgrp_add(gname, desc); 751 if (status != SMB_LGRP_SUCCESS) { 752 (void) fprintf(stderr, 753 gettext("failed to create %s (%s)\n"), gname, 754 smb_lgrp_strerror(status)); 755 } else { 756 (void) printf(gettext("%s created\n"), gname); 757 } 758 759 return (status); 760 } 761 762 /* 763 * smbadm_group_dump_members 764 * 765 * Dump group members details. 766 */ 767 static void 768 smbadm_group_dump_members(smb_gsid_t *members, int num) 769 { 770 char sidstr[SMB_SID_STRSZ]; 771 lsa_account_t acct; 772 int i; 773 774 if (num == 0) { 775 (void) printf(gettext("\tNo members\n")); 776 return; 777 } 778 779 (void) printf(gettext("\tMembers:\n")); 780 for (i = 0; i < num; i++) { 781 smb_sid_tostr(members[i].gs_sid, sidstr); 782 783 if (smb_lookup_sid(sidstr, &acct) == 0) { 784 if (acct.a_status == NT_STATUS_SUCCESS) 785 smbadm_group_show_name(acct.a_domain, 786 acct.a_name); 787 else 788 (void) printf(gettext("\t\t%s [%s]\n"), 789 sidstr, xlate_nt_status(acct.a_status)); 790 } else { 791 (void) printf(gettext("\t\t%s\n"), sidstr); 792 } 793 } 794 } 795 796 static void 797 smbadm_group_show_name(const char *domain, const char *name) 798 { 799 if (strchr(domain, '.') != NULL) 800 (void) printf(gettext("\t\t%s@%s\n"), name, domain); 801 else 802 (void) printf(gettext("\t\t%s\\%s\n"), domain, name); 803 } 804 805 /* 806 * smbadm_group_dump_privs 807 * 808 * Dump group privilege details. 809 */ 810 static void 811 smbadm_group_dump_privs(smb_privset_t *privs) 812 { 813 smb_privinfo_t *pinfo; 814 char *pstatus; 815 int i; 816 817 (void) printf(gettext("\tPrivileges: \n")); 818 819 for (i = 0; i < privs->priv_cnt; i++) { 820 pinfo = smb_priv_getbyvalue(privs->priv[i].luid.lo_part); 821 if ((pinfo == NULL) || (pinfo->flags & PF_PRESENTABLE) == 0) 822 continue; 823 824 switch (privs->priv[i].attrs) { 825 case SE_PRIVILEGE_ENABLED: 826 pstatus = "On"; 827 break; 828 case SE_PRIVILEGE_DISABLED: 829 pstatus = "Off"; 830 break; 831 default: 832 pstatus = "Unknown"; 833 break; 834 } 835 (void) printf(gettext("\t\t%s: %s\n"), pinfo->name, pstatus); 836 } 837 838 if (privs->priv_cnt == 0) 839 (void) printf(gettext("\t\tNo privileges\n")); 840 } 841 842 /* 843 * smbadm_group_dump 844 * 845 * Dump group details. 846 */ 847 static void 848 smbadm_group_dump(smb_group_t *grp, boolean_t show_mem, boolean_t show_privs) 849 { 850 char sidstr[SMB_SID_STRSZ]; 851 852 (void) printf(gettext("%s (%s)\n"), grp->sg_name, grp->sg_cmnt); 853 854 smb_sid_tostr(grp->sg_id.gs_sid, sidstr); 855 (void) printf(gettext("\tSID: %s\n"), sidstr); 856 857 if (show_privs) 858 smbadm_group_dump_privs(grp->sg_privs); 859 860 if (show_mem) 861 smbadm_group_dump_members(grp->sg_members, grp->sg_nmembers); 862 } 863 864 /* 865 * smbadm_group_show 866 * 867 */ 868 static int 869 smbadm_group_show(int argc, char **argv) 870 { 871 char *gname = NULL; 872 boolean_t show_privs; 873 boolean_t show_members; 874 char option; 875 int status; 876 smb_group_t grp; 877 smb_giter_t gi; 878 879 show_privs = show_members = B_FALSE; 880 881 while ((option = getopt(argc, argv, "mp")) != -1) { 882 switch (option) { 883 case 'm': 884 show_members = B_TRUE; 885 break; 886 case 'p': 887 show_privs = B_TRUE; 888 break; 889 890 default: 891 smbadm_usage(B_FALSE); 892 } 893 } 894 895 gname = argv[optind]; 896 if (optind >= argc || gname == NULL || *gname == '\0') 897 gname = "*"; 898 899 if (strcmp(gname, "*")) { 900 status = smb_lgrp_getbyname(gname, &grp); 901 if (status == SMB_LGRP_SUCCESS) { 902 smbadm_group_dump(&grp, show_members, show_privs); 903 smb_lgrp_free(&grp); 904 } else { 905 (void) fprintf(stderr, 906 gettext("failed to find %s (%s)\n"), 907 gname, smb_lgrp_strerror(status)); 908 } 909 return (status); 910 } 911 912 if ((status = smb_lgrp_iteropen(&gi)) != SMB_LGRP_SUCCESS) { 913 (void) fprintf(stderr, gettext("failed to list groups (%s)\n"), 914 smb_lgrp_strerror(status)); 915 return (status); 916 } 917 918 while ((status = smb_lgrp_iterate(&gi, &grp)) == SMB_LGRP_SUCCESS) { 919 smbadm_group_dump(&grp, show_members, show_privs); 920 smb_lgrp_free(&grp); 921 } 922 923 smb_lgrp_iterclose(&gi); 924 925 if ((status != SMB_LGRP_NO_MORE) || smb_lgrp_itererror(&gi)) { 926 if (status != SMB_LGRP_NO_MORE) 927 syslog(LOG_ERR, "smb_lgrp_iterate: %s", 928 smb_lgrp_strerror(status)); 929 930 (void) fprintf(stderr, 931 gettext("\nAn error occurred while retrieving group data.\n" 932 "Check the system log for more information.\n")); 933 return (status); 934 } 935 936 return (0); 937 } 938 939 /* 940 * smbadm_group_delete 941 */ 942 static int 943 smbadm_group_delete(int argc, char **argv) 944 { 945 char *gname = NULL; 946 int status; 947 948 gname = argv[optind]; 949 if (optind >= argc || gname == NULL || *gname == '\0') { 950 (void) fprintf(stderr, gettext("missing group name\n")); 951 smbadm_usage(B_FALSE); 952 } 953 954 status = smb_lgrp_delete(gname); 955 if (status != SMB_LGRP_SUCCESS) { 956 (void) fprintf(stderr, 957 gettext("failed to delete %s (%s)\n"), gname, 958 smb_lgrp_strerror(status)); 959 } else { 960 (void) printf(gettext("%s deleted\n"), gname); 961 } 962 963 return (status); 964 } 965 966 /* 967 * smbadm_group_rename 968 */ 969 static int 970 smbadm_group_rename(int argc, char **argv) 971 { 972 char *gname = NULL; 973 char *ngname = NULL; 974 int status; 975 976 gname = argv[optind]; 977 if (optind++ >= argc || gname == NULL || *gname == '\0') { 978 (void) fprintf(stderr, gettext("missing group name\n")); 979 smbadm_usage(B_FALSE); 980 } 981 982 ngname = argv[optind]; 983 if (optind >= argc || ngname == NULL || *ngname == '\0') { 984 (void) fprintf(stderr, gettext("missing new group name\n")); 985 smbadm_usage(B_FALSE); 986 } 987 988 status = smb_lgrp_rename(gname, ngname); 989 if (status != SMB_LGRP_SUCCESS) { 990 if (status == SMB_LGRP_EXISTS) 991 (void) fprintf(stderr, 992 gettext("failed to rename '%s' (%s already " 993 "exists)\n"), gname, ngname); 994 else 995 (void) fprintf(stderr, 996 gettext("failed to rename '%s' (%s)\n"), gname, 997 smb_lgrp_strerror(status)); 998 } else { 999 (void) printf(gettext("'%s' renamed to '%s'\n"), gname, ngname); 1000 } 1001 1002 return (status); 1003 } 1004 1005 /* 1006 * smbadm_group_setprop 1007 * 1008 * Set the group properties. 1009 */ 1010 static int 1011 smbadm_group_setprop(int argc, char **argv) 1012 { 1013 char *gname = NULL; 1014 smbadm_prop_t props[SMBADM_NPROP]; 1015 smbadm_prop_handle_t *phandle; 1016 char option; 1017 int pcnt = 0; 1018 int ret; 1019 int p; 1020 1021 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 1022 1023 while ((option = getopt(argc, argv, "p:")) != -1) { 1024 switch (option) { 1025 case 'p': 1026 if (pcnt >= SMBADM_NPROP) { 1027 (void) fprintf(stderr, 1028 gettext("exceeded number of supported" 1029 " properties\n")); 1030 smbadm_usage(B_FALSE); 1031 } 1032 1033 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 1034 smbadm_usage(B_FALSE); 1035 break; 1036 1037 default: 1038 smbadm_usage(B_FALSE); 1039 } 1040 } 1041 1042 if (pcnt == 0) { 1043 (void) fprintf(stderr, 1044 gettext("missing property=value argument\n")); 1045 smbadm_usage(B_FALSE); 1046 } 1047 1048 gname = argv[optind]; 1049 if (optind >= argc || gname == NULL || *gname == '\0') { 1050 (void) fprintf(stderr, gettext("missing group name\n")); 1051 smbadm_usage(B_FALSE); 1052 } 1053 1054 for (p = 0; p < pcnt; p++) { 1055 phandle = smbadm_prop_gethandle(props[p].p_name); 1056 if (phandle) { 1057 if (phandle->p_setfn(gname, &props[p]) != 0) 1058 ret = 1; 1059 } 1060 } 1061 1062 return (ret); 1063 } 1064 1065 /* 1066 * smbadm_group_getprop 1067 * 1068 * Get the group properties. 1069 */ 1070 static int 1071 smbadm_group_getprop(int argc, char **argv) 1072 { 1073 char *gname = NULL; 1074 smbadm_prop_t props[SMBADM_NPROP]; 1075 smbadm_prop_handle_t *phandle; 1076 char option; 1077 int pcnt = 0; 1078 int ret; 1079 int p; 1080 1081 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 1082 1083 while ((option = getopt(argc, argv, "p:")) != -1) { 1084 switch (option) { 1085 case 'p': 1086 if (pcnt >= SMBADM_NPROP) { 1087 (void) fprintf(stderr, 1088 gettext("exceeded number of supported" 1089 " properties\n")); 1090 smbadm_usage(B_FALSE); 1091 } 1092 1093 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 1094 smbadm_usage(B_FALSE); 1095 break; 1096 1097 default: 1098 smbadm_usage(B_FALSE); 1099 } 1100 } 1101 1102 gname = argv[optind]; 1103 if (optind >= argc || gname == NULL || *gname == '\0') { 1104 (void) fprintf(stderr, gettext("missing group name\n")); 1105 smbadm_usage(B_FALSE); 1106 } 1107 1108 if (pcnt == 0) { 1109 /* 1110 * If no property has be specified then get 1111 * all the properties. 1112 */ 1113 pcnt = SMBADM_NPROP; 1114 for (p = 0; p < pcnt; p++) 1115 props[p].p_name = smbadm_ptable[p].p_name; 1116 } 1117 1118 for (p = 0; p < pcnt; p++) { 1119 phandle = smbadm_prop_gethandle(props[p].p_name); 1120 if (phandle) { 1121 if (phandle->p_getfn(gname, &props[p]) != 0) 1122 ret = 1; 1123 } 1124 } 1125 1126 return (ret); 1127 } 1128 1129 /* 1130 * smbadm_group_addmember 1131 * 1132 */ 1133 static int 1134 smbadm_group_addmember(int argc, char **argv) 1135 { 1136 lsa_account_t acct; 1137 char *gname = NULL; 1138 char **mname; 1139 char option; 1140 smb_gsid_t msid; 1141 int status; 1142 int mcnt = 0; 1143 int ret = 0; 1144 int i; 1145 1146 1147 mname = (char **)malloc(argc * sizeof (char *)); 1148 if (mname == NULL) { 1149 warn(gettext("failed to add group member")); 1150 return (1); 1151 } 1152 bzero(mname, argc * sizeof (char *)); 1153 1154 while ((option = getopt(argc, argv, "m:")) != -1) { 1155 switch (option) { 1156 case 'm': 1157 mname[mcnt++] = optarg; 1158 break; 1159 1160 default: 1161 free(mname); 1162 smbadm_usage(B_FALSE); 1163 } 1164 } 1165 1166 if (mcnt == 0) { 1167 (void) fprintf(stderr, gettext("missing member name\n")); 1168 free(mname); 1169 smbadm_usage(B_FALSE); 1170 } 1171 1172 gname = argv[optind]; 1173 if (optind >= argc || gname == NULL || *gname == 0) { 1174 (void) fprintf(stderr, gettext("missing group name\n")); 1175 free(mname); 1176 smbadm_usage(B_FALSE); 1177 } 1178 1179 1180 for (i = 0; i < mcnt; i++) { 1181 ret = 0; 1182 if (mname[i] == NULL) 1183 continue; 1184 1185 ret = smb_lookup_name(mname[i], SidTypeUnknown, &acct); 1186 if ((ret != 0) || (acct.a_status != NT_STATUS_SUCCESS)) { 1187 (void) fprintf(stderr, 1188 gettext("failed to add %s: unable to obtain SID\n"), 1189 mname[i]); 1190 continue; 1191 } 1192 1193 msid.gs_type = acct.a_sidtype; 1194 1195 if ((msid.gs_sid = smb_sid_fromstr(acct.a_sid)) == NULL) { 1196 (void) fprintf(stderr, 1197 gettext("failed to add %s: no memory\n"), mname[i]); 1198 continue; 1199 } 1200 1201 status = smb_lgrp_add_member(gname, msid.gs_sid, msid.gs_type); 1202 smb_sid_free(msid.gs_sid); 1203 if (status != SMB_LGRP_SUCCESS) { 1204 (void) fprintf(stderr, 1205 gettext("failed to add %s (%s)\n"), 1206 mname[i], smb_lgrp_strerror(status)); 1207 ret = 1; 1208 } else { 1209 (void) printf(gettext("'%s' is now a member of '%s'\n"), 1210 mname[i], gname); 1211 } 1212 } 1213 1214 free(mname); 1215 return (ret); 1216 } 1217 1218 /* 1219 * smbadm_group_delmember 1220 */ 1221 static int 1222 smbadm_group_delmember(int argc, char **argv) 1223 { 1224 lsa_account_t acct; 1225 char *gname = NULL; 1226 char **mname; 1227 char option; 1228 smb_gsid_t msid; 1229 int status; 1230 int mcnt = 0; 1231 int ret = 0; 1232 int i; 1233 1234 mname = (char **)malloc(argc * sizeof (char *)); 1235 if (mname == NULL) { 1236 warn(gettext("failed to delete group member")); 1237 return (1); 1238 } 1239 bzero(mname, argc * sizeof (char *)); 1240 1241 while ((option = getopt(argc, argv, "m:")) != -1) { 1242 switch (option) { 1243 case 'm': 1244 mname[mcnt++] = optarg; 1245 break; 1246 1247 default: 1248 free(mname); 1249 smbadm_usage(B_FALSE); 1250 } 1251 } 1252 1253 if (mcnt == 0) { 1254 (void) fprintf(stderr, gettext("missing member name\n")); 1255 free(mname); 1256 smbadm_usage(B_FALSE); 1257 } 1258 1259 gname = argv[optind]; 1260 if (optind >= argc || gname == NULL || *gname == 0) { 1261 (void) fprintf(stderr, gettext("missing group name\n")); 1262 free(mname); 1263 smbadm_usage(B_FALSE); 1264 } 1265 1266 1267 for (i = 0; i < mcnt; i++) { 1268 ret = 0; 1269 if (mname[i] == NULL) 1270 continue; 1271 1272 ret = smb_lookup_name(mname[i], SidTypeUnknown, &acct); 1273 if ((ret != 0) || (acct.a_status != NT_STATUS_SUCCESS)) { 1274 (void) fprintf(stderr, 1275 gettext("failed to remove %s: " 1276 "unable to obtain SID\n"), 1277 mname[i]); 1278 continue; 1279 } 1280 1281 msid.gs_type = acct.a_sidtype; 1282 1283 if ((msid.gs_sid = smb_sid_fromstr(acct.a_sid)) == NULL) { 1284 (void) fprintf(stderr, 1285 gettext("failed to remove %s: no memory\n"), 1286 mname[i]); 1287 continue; 1288 } 1289 1290 status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type); 1291 smb_sid_free(msid.gs_sid); 1292 if (status != SMB_LGRP_SUCCESS) { 1293 (void) fprintf(stderr, 1294 gettext("failed to remove %s (%s)\n"), 1295 mname[i], smb_lgrp_strerror(status)); 1296 ret = 1; 1297 } else { 1298 (void) printf( 1299 gettext("'%s' has been removed from %s\n"), 1300 mname[i], gname); 1301 } 1302 } 1303 1304 return (ret); 1305 } 1306 1307 static int 1308 smbadm_user_disable(int argc, char **argv) 1309 { 1310 int error; 1311 char *user = NULL; 1312 1313 user = argv[optind]; 1314 if (optind >= argc || user == NULL || *user == '\0') { 1315 (void) fprintf(stderr, gettext("missing user name\n")); 1316 smbadm_usage(B_FALSE); 1317 } 1318 1319 error = smb_pwd_setcntl(user, SMB_PWC_DISABLE); 1320 if (error == SMB_PWE_SUCCESS) 1321 (void) printf(gettext("%s is disabled.\n"), user); 1322 else 1323 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1324 1325 return (error); 1326 } 1327 1328 static int 1329 smbadm_user_enable(int argc, char **argv) 1330 { 1331 int error; 1332 char *user = NULL; 1333 1334 user = argv[optind]; 1335 if (optind >= argc || user == NULL || *user == '\0') { 1336 (void) fprintf(stderr, gettext("missing user name\n")); 1337 smbadm_usage(B_FALSE); 1338 } 1339 1340 error = smb_pwd_setcntl(user, SMB_PWC_ENABLE); 1341 if (error == SMB_PWE_SUCCESS) 1342 (void) printf(gettext("%s is enabled.\n"), user); 1343 else 1344 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1345 1346 return (error); 1347 } 1348 1349 1350 int 1351 main(int argc, char **argv) 1352 { 1353 int ret; 1354 int i; 1355 1356 (void) setlocale(LC_ALL, ""); 1357 (void) textdomain(TEXT_DOMAIN); 1358 1359 (void) malloc(0); /* satisfy libumem dependency */ 1360 1361 progname = basename(argv[0]); 1362 1363 if (getzoneid() != GLOBAL_ZONEID) { 1364 (void) fprintf(stderr, 1365 gettext("cannot execute in non-global zone\n")); 1366 return (0); 1367 } 1368 1369 if (is_system_labeled()) { 1370 (void) fprintf(stderr, 1371 gettext("Trusted Extensions not supported\n")); 1372 return (0); 1373 } 1374 1375 if (argc < 2) { 1376 (void) fprintf(stderr, gettext("missing command\n")); 1377 smbadm_usage(B_FALSE); 1378 } 1379 1380 /* 1381 * Special case "cmd --help/-?" 1382 */ 1383 if (strcmp(argv[1], "-?") == 0 || 1384 strcmp(argv[1], "--help") == 0 || 1385 strcmp(argv[1], "-h") == 0) 1386 smbadm_usage(B_TRUE); 1387 1388 for (i = 0; i < SMBADM_NCMD; ++i) { 1389 curcmd = &smbadm_cmdtable[i]; 1390 if (strcasecmp(argv[1], curcmd->name) == 0) { 1391 if (argc > 2) { 1392 /* cmd subcmd --help/-? */ 1393 if (strcmp(argv[2], "-?") == 0 || 1394 strcmp(argv[2], "--help") == 0 || 1395 strcmp(argv[2], "-h") == 0) 1396 smbadm_usage(B_TRUE); 1397 } 1398 1399 if (!smbadm_checkauth(curcmd->auth)) { 1400 (void) fprintf(stderr, 1401 gettext("%s: %s: authorization denied\n"), 1402 progname, curcmd->name); 1403 return (1); 1404 } 1405 1406 if ((ret = smbadm_init()) != 0) 1407 return (ret); 1408 1409 ret = curcmd->func(argc - 1, &argv[1]); 1410 1411 smbadm_fini(); 1412 return (ret); 1413 } 1414 } 1415 1416 curcmd = NULL; 1417 (void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]); 1418 smbadm_usage(B_FALSE); 1419 return (2); 1420 } 1421 1422 static int 1423 smbadm_init(void) 1424 { 1425 int rc; 1426 1427 switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 1428 case SMBADM_CMDF_GROUP: 1429 if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { 1430 (void) fprintf(stderr, 1431 gettext("failed to initialize (%s)\n"), 1432 smb_lgrp_strerror(rc)); 1433 return (1); 1434 } 1435 break; 1436 1437 case SMBADM_CMDF_USER: 1438 smb_pwd_init(B_FALSE); 1439 break; 1440 1441 default: 1442 break; 1443 } 1444 1445 return (0); 1446 } 1447 1448 static void 1449 smbadm_fini(void) 1450 { 1451 switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 1452 case SMBADM_CMDF_GROUP: 1453 smb_lgrp_stop(); 1454 break; 1455 1456 case SMBADM_CMDF_USER: 1457 smb_pwd_fini(); 1458 break; 1459 1460 default: 1461 break; 1462 } 1463 } 1464 1465 static boolean_t 1466 smbadm_checkauth(const char *auth) 1467 { 1468 struct passwd *pw; 1469 1470 if ((pw = getpwuid(getuid())) == NULL) 1471 return (B_FALSE); 1472 1473 if (chkauthattr(auth, pw->pw_name) == 0) 1474 return (B_FALSE); 1475 1476 return (B_TRUE); 1477 } 1478 1479 static boolean_t 1480 smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 1481 { 1482 smbadm_prop_handle_t *pinfo; 1483 int i; 1484 1485 for (i = 0; i < SMBADM_NPROP; i++) { 1486 pinfo = &smbadm_ptable[i]; 1487 if (strcmp(pinfo->p_name, prop->p_name) == 0) { 1488 if (pinfo->p_chkfn && chkval) 1489 return (pinfo->p_chkfn(prop)); 1490 1491 return (B_TRUE); 1492 } 1493 } 1494 1495 (void) fprintf(stderr, gettext("unrecognized property '%s'\n"), 1496 prop->p_name); 1497 1498 return (B_FALSE); 1499 } 1500 1501 static int 1502 smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 1503 { 1504 boolean_t parse_value; 1505 char *equal; 1506 1507 if (arg == NULL) 1508 return (2); 1509 1510 prop->p_name = prop->p_value = NULL; 1511 1512 if (strcmp(curcmd->name, "set") == 0) 1513 parse_value = B_TRUE; 1514 else 1515 parse_value = B_FALSE; 1516 1517 prop->p_name = arg; 1518 1519 if (parse_value) { 1520 equal = strchr(arg, '='); 1521 if (equal == NULL) 1522 return (2); 1523 1524 *equal++ = '\0'; 1525 prop->p_value = equal; 1526 } 1527 1528 if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 1529 return (2); 1530 1531 return (0); 1532 } 1533 1534 static smbadm_prop_handle_t * 1535 smbadm_prop_gethandle(char *pname) 1536 { 1537 int i; 1538 1539 for (i = 0; i < SMBADM_NPROP; i++) 1540 if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 1541 return (&smbadm_ptable[i]); 1542 1543 return (NULL); 1544 } 1545 1546 static int 1547 smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 1548 { 1549 int status; 1550 1551 status = smb_lgrp_setcmnt(gname, prop->p_value); 1552 if (status != SMB_LGRP_SUCCESS) { 1553 (void) fprintf(stderr, 1554 gettext("failed to modify the group description (%s)\n"), 1555 smb_lgrp_strerror(status)); 1556 return (1); 1557 } 1558 1559 (void) printf(gettext("%s: description modified\n"), gname); 1560 return (0); 1561 } 1562 1563 static int 1564 smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 1565 { 1566 char *cmnt = NULL; 1567 int status; 1568 1569 status = smb_lgrp_getcmnt(gname, &cmnt); 1570 if (status != SMB_LGRP_SUCCESS) { 1571 (void) fprintf(stderr, 1572 gettext("failed to get the group description (%s)\n"), 1573 smb_lgrp_strerror(status)); 1574 return (1); 1575 } 1576 1577 (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); 1578 free(cmnt); 1579 return (0); 1580 } 1581 1582 static int 1583 smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1584 { 1585 boolean_t enable; 1586 int status; 1587 int ret; 1588 1589 if (strcasecmp(prop->p_value, "on") == 0) { 1590 (void) printf(gettext("Enabling %s privilege "), prop->p_name); 1591 enable = B_TRUE; 1592 } else { 1593 (void) printf(gettext("Disabling %s privilege "), prop->p_name); 1594 enable = B_FALSE; 1595 } 1596 1597 status = smb_lgrp_setpriv(gname, priv_id, enable); 1598 if (status == SMB_LGRP_SUCCESS) { 1599 (void) printf(gettext("succeeded\n")); 1600 ret = 0; 1601 } else { 1602 (void) printf(gettext("failed: %s\n"), 1603 smb_lgrp_strerror(status)); 1604 ret = 1; 1605 } 1606 1607 return (ret); 1608 } 1609 1610 static int 1611 smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1612 { 1613 boolean_t enable; 1614 int status; 1615 1616 status = smb_lgrp_getpriv(gname, priv_id, &enable); 1617 if (status != SMB_LGRP_SUCCESS) { 1618 (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 1619 prop->p_name, smb_lgrp_strerror(status)); 1620 return (1); 1621 } 1622 1623 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 1624 (enable) ? "On" : "Off"); 1625 1626 return (0); 1627 } 1628 1629 static int 1630 smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 1631 { 1632 return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1633 } 1634 1635 static int 1636 smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 1637 { 1638 return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1639 } 1640 1641 static int 1642 smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 1643 { 1644 return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 1645 } 1646 1647 static int 1648 smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 1649 { 1650 return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 1651 } 1652 1653 static int 1654 smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 1655 { 1656 return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 1657 } 1658 1659 static int 1660 smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 1661 { 1662 return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 1663 } 1664 1665 static boolean_t 1666 smbadm_chkprop_priv(smbadm_prop_t *prop) 1667 { 1668 if (prop->p_value == NULL || *prop->p_value == '\0') { 1669 (void) fprintf(stderr, 1670 gettext("missing value for '%s'\n"), prop->p_name); 1671 return (B_FALSE); 1672 } 1673 1674 if (strcasecmp(prop->p_value, "on") == 0) 1675 return (B_TRUE); 1676 1677 if (strcasecmp(prop->p_value, "off") == 0) 1678 return (B_TRUE); 1679 1680 (void) fprintf(stderr, 1681 gettext("%s: unrecognized value for '%s' property\n"), 1682 prop->p_value, prop->p_name); 1683 1684 return (B_FALSE); 1685 } 1686 1687 static const char * 1688 smbadm_pwd_strerror(int error) 1689 { 1690 switch (error) { 1691 case SMB_PWE_SUCCESS: 1692 return (gettext("Success.")); 1693 1694 case SMB_PWE_USER_UNKNOWN: 1695 return (gettext("User does not exist.")); 1696 1697 case SMB_PWE_USER_DISABLE: 1698 return (gettext("User is disabled.")); 1699 1700 case SMB_PWE_CLOSE_FAILED: 1701 case SMB_PWE_OPEN_FAILED: 1702 case SMB_PWE_WRITE_FAILED: 1703 case SMB_PWE_UPDATE_FAILED: 1704 return (gettext("Unexpected failure. " 1705 "SMB password database unchanged.")); 1706 1707 case SMB_PWE_STAT_FAILED: 1708 return (gettext("stat of SMB password file failed.")); 1709 1710 case SMB_PWE_BUSY: 1711 return (gettext("SMB password database busy. " 1712 "Try again later.")); 1713 1714 case SMB_PWE_DENIED: 1715 return (gettext("Operation not permitted.")); 1716 1717 case SMB_PWE_SYSTEM_ERROR: 1718 return (gettext("System error.")); 1719 1720 default: 1721 break; 1722 } 1723 1724 return (gettext("Unknown error code.")); 1725 } 1726 1727 /* 1728 * Enable libumem debugging by default on DEBUG builds. 1729 */ 1730 #ifdef DEBUG 1731 const char * 1732 _umem_debug_init(void) 1733 { 1734 return ("default,verbose"); /* $UMEM_DEBUG setting */ 1735 } 1736 1737 const char * 1738 _umem_logging_init(void) 1739 { 1740 return ("fail,contents"); /* $UMEM_LOGGING setting */ 1741 } 1742 #endif 1743