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