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