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) { 935 (void) fprintf(stderr, 936 gettext("failed to get all the groups (%s)\n"), 937 smb_lgrp_strerror(status)); 938 return (status); 939 } 940 941 return (0); 942 } 943 944 /* 945 * smbadm_group_delete 946 */ 947 static int 948 smbadm_group_delete(int argc, char **argv) 949 { 950 char *gname = NULL; 951 int status; 952 953 gname = argv[optind]; 954 if (optind >= argc || gname == NULL || *gname == '\0') { 955 (void) fprintf(stderr, gettext("missing group name\n")); 956 smbadm_usage(B_FALSE); 957 } 958 959 status = smb_lgrp_delete(gname); 960 if (status != SMB_LGRP_SUCCESS) { 961 (void) fprintf(stderr, 962 gettext("failed to delete %s (%s)\n"), gname, 963 smb_lgrp_strerror(status)); 964 } else { 965 (void) printf(gettext("%s deleted\n"), gname); 966 } 967 968 return (status); 969 } 970 971 /* 972 * smbadm_group_rename 973 */ 974 static int 975 smbadm_group_rename(int argc, char **argv) 976 { 977 char *gname = NULL; 978 char *ngname = NULL; 979 int status; 980 981 gname = argv[optind]; 982 if (optind++ >= argc || gname == NULL || *gname == '\0') { 983 (void) fprintf(stderr, gettext("missing group name\n")); 984 smbadm_usage(B_FALSE); 985 } 986 987 ngname = argv[optind]; 988 if (optind >= argc || ngname == NULL || *ngname == '\0') { 989 (void) fprintf(stderr, gettext("missing new group name\n")); 990 smbadm_usage(B_FALSE); 991 } 992 993 if (getgrnam(ngname) == NULL) { 994 (void) fprintf(stderr, 995 gettext("failed to get the Solaris group '%s'\n"), ngname); 996 (void) fprintf(stderr, 997 gettext("use 'groupadd' to add '%s'\n"), ngname); 998 return (1); 999 } 1000 1001 status = smb_lgrp_rename(gname, ngname); 1002 if (status != SMB_LGRP_SUCCESS) { 1003 if (status == SMB_LGRP_EXISTS) 1004 (void) fprintf(stderr, 1005 gettext("failed to rename '%s' (%s already " 1006 "exists)\n"), gname, ngname); 1007 else 1008 (void) fprintf(stderr, 1009 gettext("failed to rename '%s' (%s)\n"), gname, 1010 smb_lgrp_strerror(status)); 1011 } else { 1012 (void) printf(gettext("'%s' renamed to '%s'\n"), gname, ngname); 1013 } 1014 1015 return (status); 1016 } 1017 1018 /* 1019 * smbadm_group_setprop 1020 * 1021 * Set the group properties. 1022 */ 1023 static int 1024 smbadm_group_setprop(int argc, char **argv) 1025 { 1026 char *gname = NULL; 1027 smbadm_prop_t props[SMBADM_NPROP]; 1028 smbadm_prop_handle_t *phandle; 1029 char option; 1030 int pcnt = 0; 1031 int ret; 1032 int p; 1033 1034 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 1035 1036 while ((option = getopt(argc, argv, "p:")) != -1) { 1037 switch (option) { 1038 case 'p': 1039 if (pcnt >= SMBADM_NPROP) { 1040 (void) fprintf(stderr, 1041 gettext("exceeded number of supported" 1042 " properties\n")); 1043 smbadm_usage(B_FALSE); 1044 } 1045 1046 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 1047 smbadm_usage(B_FALSE); 1048 break; 1049 1050 default: 1051 smbadm_usage(B_FALSE); 1052 } 1053 } 1054 1055 if (pcnt == 0) { 1056 (void) fprintf(stderr, 1057 gettext("missing property=value argument\n")); 1058 smbadm_usage(B_FALSE); 1059 } 1060 1061 gname = argv[optind]; 1062 if (optind >= argc || gname == NULL || *gname == '\0') { 1063 (void) fprintf(stderr, gettext("missing group name\n")); 1064 smbadm_usage(B_FALSE); 1065 } 1066 1067 for (p = 0; p < pcnt; p++) { 1068 phandle = smbadm_prop_gethandle(props[p].p_name); 1069 if (phandle) { 1070 if (phandle->p_setfn(gname, &props[p]) != 0) 1071 ret = 1; 1072 } 1073 } 1074 1075 return (ret); 1076 } 1077 1078 /* 1079 * smbadm_group_getprop 1080 * 1081 * Get the group properties. 1082 */ 1083 static int 1084 smbadm_group_getprop(int argc, char **argv) 1085 { 1086 char *gname = NULL; 1087 smbadm_prop_t props[SMBADM_NPROP]; 1088 smbadm_prop_handle_t *phandle; 1089 char option; 1090 int pcnt = 0; 1091 int ret; 1092 int p; 1093 1094 bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 1095 1096 while ((option = getopt(argc, argv, "p:")) != -1) { 1097 switch (option) { 1098 case 'p': 1099 if (pcnt >= SMBADM_NPROP) { 1100 (void) fprintf(stderr, 1101 gettext("exceeded number of supported" 1102 " properties\n")); 1103 smbadm_usage(B_FALSE); 1104 } 1105 1106 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 1107 smbadm_usage(B_FALSE); 1108 break; 1109 1110 default: 1111 smbadm_usage(B_FALSE); 1112 } 1113 } 1114 1115 gname = argv[optind]; 1116 if (optind >= argc || gname == NULL || *gname == '\0') { 1117 (void) fprintf(stderr, gettext("missing group name\n")); 1118 smbadm_usage(B_FALSE); 1119 } 1120 1121 if (pcnt == 0) { 1122 /* 1123 * If no property has be specified then get 1124 * all the properties. 1125 */ 1126 pcnt = SMBADM_NPROP; 1127 for (p = 0; p < pcnt; p++) 1128 props[p].p_name = smbadm_ptable[p].p_name; 1129 } 1130 1131 for (p = 0; p < pcnt; p++) { 1132 phandle = smbadm_prop_gethandle(props[p].p_name); 1133 if (phandle) { 1134 if (phandle->p_getfn(gname, &props[p]) != 0) 1135 ret = 1; 1136 } 1137 } 1138 1139 return (ret); 1140 } 1141 1142 /* 1143 * smbadm_group_addmember 1144 * 1145 */ 1146 static int 1147 smbadm_group_addmember(int argc, char **argv) 1148 { 1149 lsa_account_t acct; 1150 char *gname = NULL; 1151 char **mname; 1152 char option; 1153 smb_gsid_t msid; 1154 int status; 1155 int mcnt = 0; 1156 int ret = 0; 1157 int i; 1158 1159 1160 mname = (char **)malloc(argc * sizeof (char *)); 1161 if (mname == NULL) { 1162 warn(gettext("failed to add group member")); 1163 return (1); 1164 } 1165 bzero(mname, argc * sizeof (char *)); 1166 1167 while ((option = getopt(argc, argv, "m:")) != -1) { 1168 switch (option) { 1169 case 'm': 1170 mname[mcnt++] = optarg; 1171 break; 1172 1173 default: 1174 free(mname); 1175 smbadm_usage(B_FALSE); 1176 } 1177 } 1178 1179 if (mcnt == 0) { 1180 (void) fprintf(stderr, gettext("missing member name\n")); 1181 free(mname); 1182 smbadm_usage(B_FALSE); 1183 } 1184 1185 gname = argv[optind]; 1186 if (optind >= argc || gname == NULL || *gname == 0) { 1187 (void) fprintf(stderr, gettext("missing group name\n")); 1188 free(mname); 1189 smbadm_usage(B_FALSE); 1190 } 1191 1192 1193 for (i = 0; i < mcnt; i++) { 1194 ret = 0; 1195 if (mname[i] == NULL) 1196 continue; 1197 1198 ret = smb_lookup_name(mname[i], SidTypeUnknown, &acct); 1199 if ((ret != 0) || (acct.a_status != NT_STATUS_SUCCESS)) { 1200 (void) fprintf(stderr, 1201 gettext("failed to add %s: unable to obtain SID\n"), 1202 mname[i]); 1203 continue; 1204 } 1205 1206 msid.gs_type = acct.a_sidtype; 1207 1208 if ((msid.gs_sid = smb_sid_fromstr(acct.a_sid)) == NULL) { 1209 (void) fprintf(stderr, 1210 gettext("failed to add %s: no memory\n"), mname[i]); 1211 continue; 1212 } 1213 1214 status = smb_lgrp_add_member(gname, msid.gs_sid, msid.gs_type); 1215 smb_sid_free(msid.gs_sid); 1216 if (status != SMB_LGRP_SUCCESS) { 1217 (void) fprintf(stderr, 1218 gettext("failed to add %s (%s)\n"), 1219 mname[i], smb_lgrp_strerror(status)); 1220 ret = 1; 1221 } else { 1222 (void) printf(gettext("'%s' is now a member of '%s'\n"), 1223 mname[i], gname); 1224 } 1225 } 1226 1227 free(mname); 1228 return (ret); 1229 } 1230 1231 /* 1232 * smbadm_group_delmember 1233 */ 1234 static int 1235 smbadm_group_delmember(int argc, char **argv) 1236 { 1237 lsa_account_t acct; 1238 char *gname = NULL; 1239 char **mname; 1240 char option; 1241 smb_gsid_t msid; 1242 int status; 1243 int mcnt = 0; 1244 int ret = 0; 1245 int i; 1246 1247 mname = (char **)malloc(argc * sizeof (char *)); 1248 if (mname == NULL) { 1249 warn(gettext("failed to delete group member")); 1250 return (1); 1251 } 1252 bzero(mname, argc * sizeof (char *)); 1253 1254 while ((option = getopt(argc, argv, "m:")) != -1) { 1255 switch (option) { 1256 case 'm': 1257 mname[mcnt++] = optarg; 1258 break; 1259 1260 default: 1261 free(mname); 1262 smbadm_usage(B_FALSE); 1263 } 1264 } 1265 1266 if (mcnt == 0) { 1267 (void) fprintf(stderr, gettext("missing member name\n")); 1268 free(mname); 1269 smbadm_usage(B_FALSE); 1270 } 1271 1272 gname = argv[optind]; 1273 if (optind >= argc || gname == NULL || *gname == 0) { 1274 (void) fprintf(stderr, gettext("missing group name\n")); 1275 free(mname); 1276 smbadm_usage(B_FALSE); 1277 } 1278 1279 1280 for (i = 0; i < mcnt; i++) { 1281 ret = 0; 1282 if (mname[i] == NULL) 1283 continue; 1284 1285 ret = smb_lookup_name(mname[i], SidTypeUnknown, &acct); 1286 if ((ret != 0) || (acct.a_status != NT_STATUS_SUCCESS)) { 1287 (void) fprintf(stderr, 1288 gettext("failed to remove %s: " 1289 "unable to obtain SID\n"), 1290 mname[i]); 1291 continue; 1292 } 1293 1294 msid.gs_type = acct.a_sidtype; 1295 1296 if ((msid.gs_sid = smb_sid_fromstr(acct.a_sid)) == NULL) { 1297 (void) fprintf(stderr, 1298 gettext("failed to remove %s: no memory\n"), 1299 mname[i]); 1300 continue; 1301 } 1302 1303 status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type); 1304 smb_sid_free(msid.gs_sid); 1305 if (status != SMB_LGRP_SUCCESS) { 1306 (void) fprintf(stderr, 1307 gettext("failed to remove %s (%s)\n"), 1308 mname[i], smb_lgrp_strerror(status)); 1309 ret = 1; 1310 } else { 1311 (void) printf( 1312 gettext("'%s' has been removed from %s\n"), 1313 mname[i], gname); 1314 } 1315 } 1316 1317 return (ret); 1318 } 1319 1320 static int 1321 smbadm_user_disable(int argc, char **argv) 1322 { 1323 int error; 1324 char *user = NULL; 1325 1326 user = argv[optind]; 1327 if (optind >= argc || user == NULL || *user == '\0') { 1328 (void) fprintf(stderr, gettext("missing user name\n")); 1329 smbadm_usage(B_FALSE); 1330 } 1331 1332 error = smb_pwd_setcntl(user, SMB_PWC_DISABLE); 1333 if (error == SMB_PWE_SUCCESS) 1334 (void) printf(gettext("%s is disabled.\n"), user); 1335 else 1336 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1337 1338 return (error); 1339 } 1340 1341 static int 1342 smbadm_user_enable(int argc, char **argv) 1343 { 1344 int error; 1345 char *user = NULL; 1346 1347 user = argv[optind]; 1348 if (optind >= argc || user == NULL || *user == '\0') { 1349 (void) fprintf(stderr, gettext("missing user name\n")); 1350 smbadm_usage(B_FALSE); 1351 } 1352 1353 error = smb_pwd_setcntl(user, SMB_PWC_ENABLE); 1354 if (error == SMB_PWE_SUCCESS) 1355 (void) printf(gettext("%s is enabled.\n"), user); 1356 else 1357 (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 1358 1359 return (error); 1360 } 1361 1362 1363 int 1364 main(int argc, char **argv) 1365 { 1366 int ret; 1367 int i; 1368 1369 (void) setlocale(LC_ALL, ""); 1370 (void) textdomain(TEXT_DOMAIN); 1371 1372 (void) malloc(0); /* satisfy libumem dependency */ 1373 1374 progname = basename(argv[0]); 1375 1376 if (getzoneid() != GLOBAL_ZONEID) { 1377 (void) fprintf(stderr, 1378 gettext("cannot execute in non-global zone\n")); 1379 return (0); 1380 } 1381 1382 if (is_system_labeled()) { 1383 (void) fprintf(stderr, 1384 gettext("Trusted Extensions not supported\n")); 1385 return (0); 1386 } 1387 1388 if (argc < 2) { 1389 (void) fprintf(stderr, gettext("missing command\n")); 1390 smbadm_usage(B_FALSE); 1391 } 1392 1393 /* 1394 * Special case "cmd --help/-?" 1395 */ 1396 if (strcmp(argv[1], "-?") == 0 || 1397 strcmp(argv[1], "--help") == 0 || 1398 strcmp(argv[1], "-h") == 0) 1399 smbadm_usage(B_TRUE); 1400 1401 for (i = 0; i < SMBADM_NCMD; ++i) { 1402 curcmd = &smbadm_cmdtable[i]; 1403 if (strcasecmp(argv[1], curcmd->name) == 0) { 1404 if (argc > 2) { 1405 /* cmd subcmd --help/-? */ 1406 if (strcmp(argv[2], "-?") == 0 || 1407 strcmp(argv[2], "--help") == 0 || 1408 strcmp(argv[2], "-h") == 0) 1409 smbadm_usage(B_TRUE); 1410 } 1411 1412 if (!smbadm_checkauth(curcmd->auth)) { 1413 (void) fprintf(stderr, 1414 gettext("%s: %s: authorization denied\n"), 1415 progname, curcmd->name); 1416 return (1); 1417 } 1418 1419 if ((ret = smbadm_init()) != 0) 1420 return (ret); 1421 1422 ret = curcmd->func(argc - 1, &argv[1]); 1423 1424 smbadm_fini(); 1425 return (ret); 1426 } 1427 } 1428 1429 curcmd = NULL; 1430 (void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]); 1431 smbadm_usage(B_FALSE); 1432 return (2); 1433 } 1434 1435 static int 1436 smbadm_init(void) 1437 { 1438 int rc; 1439 1440 switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 1441 case SMBADM_CMDF_GROUP: 1442 if (smb_idmap_start() != 0) { 1443 (void) fprintf(stderr, 1444 gettext("failed to contact idmap service\n")); 1445 return (1); 1446 } 1447 1448 if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { 1449 (void) fprintf(stderr, 1450 gettext("failed to initialize (%s)\n"), 1451 smb_lgrp_strerror(rc)); 1452 smb_idmap_stop(); 1453 return (1); 1454 } 1455 break; 1456 1457 case SMBADM_CMDF_USER: 1458 smb_pwd_init(B_FALSE); 1459 break; 1460 1461 default: 1462 break; 1463 } 1464 1465 return (0); 1466 } 1467 1468 static void 1469 smbadm_fini(void) 1470 { 1471 switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 1472 case SMBADM_CMDF_GROUP: 1473 smb_lgrp_stop(); 1474 smb_idmap_stop(); 1475 break; 1476 1477 case SMBADM_CMDF_USER: 1478 smb_pwd_fini(); 1479 break; 1480 1481 default: 1482 break; 1483 } 1484 } 1485 1486 static boolean_t 1487 smbadm_checkauth(const char *auth) 1488 { 1489 struct passwd *pw; 1490 1491 if ((pw = getpwuid(getuid())) == NULL) 1492 return (B_FALSE); 1493 1494 if (chkauthattr(auth, pw->pw_name) == 0) 1495 return (B_FALSE); 1496 1497 return (B_TRUE); 1498 } 1499 1500 static boolean_t 1501 smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 1502 { 1503 smbadm_prop_handle_t *pinfo; 1504 int i; 1505 1506 for (i = 0; i < SMBADM_NPROP; i++) { 1507 pinfo = &smbadm_ptable[i]; 1508 if (strcmp(pinfo->p_name, prop->p_name) == 0) { 1509 if (pinfo->p_chkfn && chkval) 1510 return (pinfo->p_chkfn(prop)); 1511 1512 return (B_TRUE); 1513 } 1514 } 1515 1516 (void) fprintf(stderr, gettext("unrecognized property '%s'\n"), 1517 prop->p_name); 1518 1519 return (B_FALSE); 1520 } 1521 1522 static int 1523 smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 1524 { 1525 boolean_t parse_value; 1526 char *equal; 1527 1528 if (arg == NULL) 1529 return (2); 1530 1531 prop->p_name = prop->p_value = NULL; 1532 1533 if (strcmp(curcmd->name, "set") == 0) 1534 parse_value = B_TRUE; 1535 else 1536 parse_value = B_FALSE; 1537 1538 prop->p_name = arg; 1539 1540 if (parse_value) { 1541 equal = strchr(arg, '='); 1542 if (equal == NULL) 1543 return (2); 1544 1545 *equal++ = '\0'; 1546 prop->p_value = equal; 1547 } 1548 1549 if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 1550 return (2); 1551 1552 return (0); 1553 } 1554 1555 static smbadm_prop_handle_t * 1556 smbadm_prop_gethandle(char *pname) 1557 { 1558 int i; 1559 1560 for (i = 0; i < SMBADM_NPROP; i++) 1561 if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 1562 return (&smbadm_ptable[i]); 1563 1564 return (NULL); 1565 } 1566 1567 static int 1568 smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 1569 { 1570 int status; 1571 1572 status = smb_lgrp_setcmnt(gname, prop->p_value); 1573 if (status != SMB_LGRP_SUCCESS) { 1574 (void) fprintf(stderr, 1575 gettext("failed to modify the group description (%s)\n"), 1576 smb_lgrp_strerror(status)); 1577 return (1); 1578 } 1579 1580 (void) printf(gettext("%s: description modified\n"), gname); 1581 return (0); 1582 } 1583 1584 static int 1585 smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 1586 { 1587 char *cmnt = NULL; 1588 int status; 1589 1590 status = smb_lgrp_getcmnt(gname, &cmnt); 1591 if (status != SMB_LGRP_SUCCESS) { 1592 (void) fprintf(stderr, 1593 gettext("failed to get the group description (%s)\n"), 1594 smb_lgrp_strerror(status)); 1595 return (1); 1596 } 1597 1598 (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); 1599 free(cmnt); 1600 return (0); 1601 } 1602 1603 static int 1604 smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1605 { 1606 boolean_t enable; 1607 int status; 1608 int ret; 1609 1610 if (strcasecmp(prop->p_value, "on") == 0) { 1611 (void) printf(gettext("Enabling %s privilege "), prop->p_name); 1612 enable = B_TRUE; 1613 } else { 1614 (void) printf(gettext("Disabling %s privilege "), prop->p_name); 1615 enable = B_FALSE; 1616 } 1617 1618 status = smb_lgrp_setpriv(gname, priv_id, enable); 1619 if (status == SMB_LGRP_SUCCESS) { 1620 (void) printf(gettext("succeeded\n")); 1621 ret = 0; 1622 } else { 1623 (void) printf(gettext("failed: %s\n"), 1624 smb_lgrp_strerror(status)); 1625 ret = 1; 1626 } 1627 1628 return (ret); 1629 } 1630 1631 static int 1632 smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 1633 { 1634 boolean_t enable; 1635 int status; 1636 1637 status = smb_lgrp_getpriv(gname, priv_id, &enable); 1638 if (status != SMB_LGRP_SUCCESS) { 1639 (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 1640 prop->p_name, smb_lgrp_strerror(status)); 1641 return (1); 1642 } 1643 1644 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 1645 (enable) ? "On" : "Off"); 1646 1647 return (0); 1648 } 1649 1650 static int 1651 smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 1652 { 1653 return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1654 } 1655 1656 static int 1657 smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 1658 { 1659 return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 1660 } 1661 1662 static int 1663 smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 1664 { 1665 return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 1666 } 1667 1668 static int 1669 smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 1670 { 1671 return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 1672 } 1673 1674 static int 1675 smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 1676 { 1677 return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 1678 } 1679 1680 static int 1681 smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 1682 { 1683 return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 1684 } 1685 1686 static boolean_t 1687 smbadm_chkprop_priv(smbadm_prop_t *prop) 1688 { 1689 if (prop->p_value == NULL || *prop->p_value == '\0') { 1690 (void) fprintf(stderr, 1691 gettext("missing value for '%s'\n"), prop->p_name); 1692 return (B_FALSE); 1693 } 1694 1695 if (strcasecmp(prop->p_value, "on") == 0) 1696 return (B_TRUE); 1697 1698 if (strcasecmp(prop->p_value, "off") == 0) 1699 return (B_TRUE); 1700 1701 (void) fprintf(stderr, 1702 gettext("%s: unrecognized value for '%s' property\n"), 1703 prop->p_value, prop->p_name); 1704 1705 return (B_FALSE); 1706 } 1707 1708 static const char * 1709 smbadm_pwd_strerror(int error) 1710 { 1711 switch (error) { 1712 case SMB_PWE_SUCCESS: 1713 return (gettext("Success.")); 1714 1715 case SMB_PWE_USER_UNKNOWN: 1716 return (gettext("User does not exist.")); 1717 1718 case SMB_PWE_USER_DISABLE: 1719 return (gettext("User is disabled.")); 1720 1721 case SMB_PWE_CLOSE_FAILED: 1722 case SMB_PWE_OPEN_FAILED: 1723 case SMB_PWE_WRITE_FAILED: 1724 case SMB_PWE_UPDATE_FAILED: 1725 return (gettext("Unexpected failure. " 1726 "SMB password database unchanged.")); 1727 1728 case SMB_PWE_STAT_FAILED: 1729 return (gettext("stat of SMB password file failed.")); 1730 1731 case SMB_PWE_BUSY: 1732 return (gettext("SMB password database busy. " 1733 "Try again later.")); 1734 1735 case SMB_PWE_DENIED: 1736 return (gettext("Operation not permitted.")); 1737 1738 case SMB_PWE_SYSTEM_ERROR: 1739 return (gettext("System error.")); 1740 1741 default: 1742 break; 1743 } 1744 1745 return (gettext("Unknown error code.")); 1746 } 1747 1748 /* 1749 * Enable libumem debugging by default on DEBUG builds. 1750 */ 1751 #ifdef DEBUG 1752 const char * 1753 _umem_debug_init(void) 1754 { 1755 return ("default,verbose"); /* $UMEM_DEBUG setting */ 1756 } 1757 1758 const char * 1759 _umem_logging_init(void) 1760 { 1761 return ("fail,contents"); /* $UMEM_LOGGING setting */ 1762 } 1763 #endif 1764