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