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