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