15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 225772Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 26*7348SJose.Borrego@Sun.COM #pragma ident "@(#)smbadm.c 1.9 08/07/30 SMI" 275331Samw 285331Samw /* 295331Samw * This module contains smbadm CLI which offers smb configuration 305331Samw * functionalities. 315331Samw */ 325331Samw #include <stdlib.h> 335331Samw #include <stdio.h> 345331Samw #include <syslog.h> 355331Samw #include <strings.h> 365331Samw #include <limits.h> 375331Samw #include <getopt.h> 385331Samw #include <libintl.h> 395331Samw #include <zone.h> 405331Samw #include <grp.h> 415331Samw #include <libgen.h> 42*7348SJose.Borrego@Sun.COM #include <netinet/in.h> 435331Samw 445331Samw #include <smbsrv/libsmb.h> 455331Samw 465331Samw typedef enum { 475331Samw HELP_ADD_MEMBER, 485331Samw HELP_CREATE, 495331Samw HELP_DELETE, 505331Samw HELP_DEL_MEMBER, 515331Samw HELP_GET, 525331Samw HELP_JOIN, 535331Samw HELP_LIST, 545331Samw HELP_RENAME, 555331Samw HELP_SET, 565331Samw HELP_SHOW, 577052Samw HELP_USER_DISABLE, 587052Samw HELP_USER_ENABLE 595331Samw } smbadm_help_t; 605331Samw 617052Samw #define SMBADM_CMDF_USER 0x01 627052Samw #define SMBADM_CMDF_GROUP 0x02 637052Samw #define SMBADM_CMDF_TYPEMASK 0x0F 646139Sjb150015 65*7348SJose.Borrego@Sun.COM #define SMBADM_CHANGE_SECMODE 1 66*7348SJose.Borrego@Sun.COM #define SMBADM_CHANGE_DOMAIN 2 67*7348SJose.Borrego@Sun.COM 68*7348SJose.Borrego@Sun.COM #define SMBADM_ANSBUFSIZ 64 69*7348SJose.Borrego@Sun.COM 705331Samw typedef struct smbadm_cmdinfo { 715331Samw char *name; 725331Samw int (*func)(int, char **); 735331Samw smbadm_help_t usage; 746139Sjb150015 uint32_t flags; 755331Samw } smbadm_cmdinfo_t; 765331Samw 775331Samw smbadm_cmdinfo_t *curcmd; 785331Samw static char *progname; 795331Samw 805331Samw static int smbadm_join(int, char **); 815331Samw static int smbadm_list(int, char **); 825331Samw static int smbadm_group_create(int, char **); 835331Samw static int smbadm_group_delete(int, char **); 845331Samw static int smbadm_group_rename(int, char **); 855331Samw static int smbadm_group_show(int, char **); 865331Samw static int smbadm_group_getprop(int, char **); 875331Samw static int smbadm_group_setprop(int, char **); 885331Samw static int smbadm_group_addmember(int, char **); 895331Samw static int smbadm_group_delmember(int, char **); 905331Samw static int smbadm_user_disable(int, char **); 915331Samw static int smbadm_user_enable(int, char **); 925331Samw 935331Samw static smbadm_cmdinfo_t smbadm_cmdtable[] = 945331Samw { 956139Sjb150015 { "add-member", smbadm_group_addmember, HELP_ADD_MEMBER, 966139Sjb150015 SMBADM_CMDF_GROUP }, 976139Sjb150015 { "create", smbadm_group_create, HELP_CREATE, 986139Sjb150015 SMBADM_CMDF_GROUP }, 996139Sjb150015 { "delete", smbadm_group_delete, HELP_DELETE, 1006139Sjb150015 SMBADM_CMDF_GROUP }, 1017052Samw { "disable-user", smbadm_user_disable, HELP_USER_DISABLE, 1027052Samw SMBADM_CMDF_USER }, 1037052Samw { "enable-user", smbadm_user_enable, HELP_USER_ENABLE, 1047052Samw SMBADM_CMDF_USER }, 1056139Sjb150015 { "get", smbadm_group_getprop, HELP_GET, 1066139Sjb150015 SMBADM_CMDF_GROUP }, 1076139Sjb150015 { "join", smbadm_join, HELP_JOIN, 0 }, 1086139Sjb150015 { "list", smbadm_list, HELP_LIST, 0 }, 1096139Sjb150015 { "remove-member", smbadm_group_delmember, HELP_DEL_MEMBER, 1106139Sjb150015 SMBADM_CMDF_GROUP }, 1116139Sjb150015 { "rename", smbadm_group_rename, HELP_RENAME, 1126139Sjb150015 SMBADM_CMDF_GROUP }, 1136139Sjb150015 { "set", smbadm_group_setprop, HELP_SET, 1146139Sjb150015 SMBADM_CMDF_GROUP }, 1156139Sjb150015 { "show", smbadm_group_show, HELP_SHOW, 1166139Sjb150015 SMBADM_CMDF_GROUP }, 1175331Samw }; 1185331Samw 1195331Samw #define SMBADM_NCMD (sizeof (smbadm_cmdtable) / sizeof (smbadm_cmdtable[0])) 1205331Samw 1215331Samw typedef struct smbadm_prop { 1225331Samw char *p_name; 1235331Samw char *p_value; 1245331Samw } smbadm_prop_t; 1255331Samw 1265331Samw typedef struct smbadm_prop_handle { 1275331Samw char *p_name; 1285331Samw char *p_dispvalue; 1295331Samw int (*p_setfn)(char *, smbadm_prop_t *); 1305331Samw int (*p_getfn)(char *, smbadm_prop_t *); 1315331Samw boolean_t (*p_chkfn)(smbadm_prop_t *); 1325331Samw } smbadm_prop_handle_t; 1335331Samw 1345331Samw static boolean_t smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval); 1355331Samw static int smbadm_prop_parse(char *arg, smbadm_prop_t *prop); 1365331Samw static smbadm_prop_handle_t *smbadm_prop_gethandle(char *pname); 1375331Samw 1385331Samw static boolean_t smbadm_chkprop_priv(smbadm_prop_t *prop); 1395331Samw static int smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop); 1405331Samw static int smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop); 1415331Samw static int smbadm_setprop_backup(char *gname, smbadm_prop_t *prop); 1425331Samw static int smbadm_getprop_backup(char *gname, smbadm_prop_t *prop); 1435331Samw static int smbadm_setprop_restore(char *gname, smbadm_prop_t *prop); 1445331Samw static int smbadm_getprop_restore(char *gname, smbadm_prop_t *prop); 1455331Samw static int smbadm_setprop_desc(char *gname, smbadm_prop_t *prop); 1465331Samw static int smbadm_getprop_desc(char *gname, smbadm_prop_t *prop); 1475331Samw 1485331Samw static smbadm_prop_handle_t smbadm_ptable[] = { 1495331Samw {"backup", "on | off", smbadm_setprop_backup, 1505331Samw smbadm_getprop_backup, smbadm_chkprop_priv }, 1515331Samw {"restore", "on | off", smbadm_setprop_restore, 1525331Samw smbadm_getprop_restore, smbadm_chkprop_priv }, 1535331Samw {"take-ownership", "on | off", smbadm_setprop_tkowner, 1545331Samw smbadm_getprop_tkowner, smbadm_chkprop_priv }, 1555331Samw {"description", "<string>", smbadm_setprop_desc, 1565331Samw smbadm_getprop_desc, NULL }, 1575331Samw }; 1585331Samw 1597052Samw static int smbadm_init(void); 1607052Samw static void smbadm_fini(void); 1615331Samw static const char *smbadm_pwd_strerror(int error); 1625331Samw 1635331Samw /* 1645331Samw * Number of supported properties 1655331Samw */ 1665331Samw #define SMBADM_NPROP (sizeof (smbadm_ptable) / sizeof (smbadm_ptable[0])) 1675331Samw 1685331Samw static void 1695331Samw smbadm_cmdusage(FILE *fp, smbadm_cmdinfo_t *cmd) 1705331Samw { 1715331Samw switch (cmd->usage) { 1725331Samw case HELP_ADD_MEMBER: 1735331Samw (void) fprintf(fp, 1745331Samw gettext("\t%s -m member [[-m member] ...] group\n"), 1755331Samw cmd->name); 1765331Samw return; 1775331Samw 1785331Samw case HELP_CREATE: 1795331Samw (void) fprintf(fp, gettext("\t%s [-d description] group\n"), 1805331Samw cmd->name); 1815331Samw return; 1825331Samw 1835331Samw case HELP_DELETE: 1845331Samw (void) fprintf(fp, gettext("\t%s group\n"), cmd->name); 1855331Samw return; 1865331Samw 1877052Samw case HELP_USER_DISABLE: 1887052Samw case HELP_USER_ENABLE: 1895331Samw (void) fprintf(fp, gettext("\t%s user\n"), cmd->name); 1905331Samw return; 1915331Samw 1925331Samw case HELP_GET: 1935331Samw (void) fprintf(fp, gettext("\t%s [[-p property] ...] group\n"), 1945331Samw cmd->name); 1955331Samw return; 1965331Samw 1975331Samw case HELP_JOIN: 1985331Samw (void) fprintf(fp, gettext("\t%s -u username domain\n" 1995331Samw "\t%s -w workgroup\n"), cmd->name, cmd->name); 2005331Samw return; 2015331Samw 2025331Samw case HELP_LIST: 2035331Samw (void) fprintf(fp, gettext("\t%s\n"), cmd->name); 2045331Samw return; 2055331Samw 2065331Samw case HELP_DEL_MEMBER: 2075331Samw (void) fprintf(fp, 2085331Samw gettext("\t%s -m member [[-m member] ...] group\n"), 2095331Samw cmd->name); 2105331Samw return; 2115331Samw 2125331Samw case HELP_RENAME: 2135331Samw (void) fprintf(fp, gettext("\t%s group new-group\n"), 2145331Samw cmd->name); 2155331Samw return; 2165331Samw 2175331Samw case HELP_SET: 2185331Samw (void) fprintf(fp, gettext("\t%s -p property=value " 2195331Samw "[[-p property=value] ...] group\n"), cmd->name); 2205331Samw return; 2215331Samw 2225331Samw case HELP_SHOW: 2235331Samw (void) fprintf(fp, gettext("\t%s [-m] [-p] [group]\n"), 2245331Samw cmd->name); 2255331Samw return; 2265331Samw 2277052Samw default: 2287052Samw break; 2295331Samw } 2305331Samw 2315331Samw abort(); 2325331Samw /* NOTREACHED */ 2335331Samw } 2345331Samw 2355331Samw static void 2365331Samw smbadm_usage(boolean_t requested) 2375331Samw { 2385331Samw FILE *fp = requested ? stdout : stderr; 2395331Samw boolean_t show_props = B_FALSE; 2405331Samw int i; 2415331Samw 2425331Samw if (curcmd == NULL) { 2435331Samw (void) fprintf(fp, 2445331Samw gettext("usage: %s [-h | <command> [options]]\n"), 2455331Samw progname); 2465331Samw (void) fprintf(fp, 2475331Samw gettext("where 'command' is one of the following:\n\n")); 2485331Samw 2495331Samw for (i = 0; i < SMBADM_NCMD; i++) 2505331Samw smbadm_cmdusage(fp, &smbadm_cmdtable[i]); 2515331Samw 2525331Samw (void) fprintf(fp, 2535331Samw gettext("\nFor property list, run %s %s|%s\n"), 2545331Samw progname, "get", "set"); 2555331Samw 2565331Samw exit(requested ? 0 : 2); 2575331Samw } 2585331Samw 2595331Samw (void) fprintf(fp, gettext("usage:\n")); 2605331Samw smbadm_cmdusage(fp, curcmd); 2615331Samw 2625331Samw if (strcmp(curcmd->name, "get") == 0 || 2635331Samw strcmp(curcmd->name, "set") == 0) 2645331Samw show_props = B_TRUE; 2655331Samw 2665331Samw if (show_props) { 2675331Samw (void) fprintf(fp, 2685331Samw gettext("\nThe following properties are supported:\n")); 2695331Samw 2705331Samw (void) fprintf(fp, "\n\t%-16s %s\n\n", 2715331Samw "PROPERTY", "VALUES"); 2725331Samw 2735331Samw for (i = 0; i < SMBADM_NPROP; i++) { 2745331Samw (void) fprintf(fp, "\t%-16s %s\n", 2755331Samw smbadm_ptable[i].p_name, 2765331Samw smbadm_ptable[i].p_dispvalue); 2775331Samw } 2785331Samw } 2795331Samw 2805331Samw exit(requested ? 0 : 2); 2815331Samw } 2825331Samw 2835331Samw /* 284*7348SJose.Borrego@Sun.COM * smbadm_strcasecmplist 285*7348SJose.Borrego@Sun.COM * 286*7348SJose.Borrego@Sun.COM * Find a string 's' within a list of strings. 287*7348SJose.Borrego@Sun.COM * 288*7348SJose.Borrego@Sun.COM * Returns the index of the matching string or -1 if there is no match. 289*7348SJose.Borrego@Sun.COM */ 290*7348SJose.Borrego@Sun.COM static int 291*7348SJose.Borrego@Sun.COM smbadm_strcasecmplist(const char *s, ...) 292*7348SJose.Borrego@Sun.COM { 293*7348SJose.Borrego@Sun.COM va_list ap; 294*7348SJose.Borrego@Sun.COM char *p; 295*7348SJose.Borrego@Sun.COM int ndx; 296*7348SJose.Borrego@Sun.COM 297*7348SJose.Borrego@Sun.COM va_start(ap, s); 298*7348SJose.Borrego@Sun.COM 299*7348SJose.Borrego@Sun.COM for (ndx = 0; ((p = va_arg(ap, char *)) != NULL); ++ndx) { 300*7348SJose.Borrego@Sun.COM if (strcasecmp(s, p) == 0) { 301*7348SJose.Borrego@Sun.COM va_end(ap); 302*7348SJose.Borrego@Sun.COM return (ndx); 303*7348SJose.Borrego@Sun.COM } 304*7348SJose.Borrego@Sun.COM } 305*7348SJose.Borrego@Sun.COM 306*7348SJose.Borrego@Sun.COM va_end(ap); 307*7348SJose.Borrego@Sun.COM return (-1); 308*7348SJose.Borrego@Sun.COM } 309*7348SJose.Borrego@Sun.COM 310*7348SJose.Borrego@Sun.COM /* 311*7348SJose.Borrego@Sun.COM * smbadm_answer_prompt 312*7348SJose.Borrego@Sun.COM * 313*7348SJose.Borrego@Sun.COM * Prompt for the answer to a question. A default response must be 314*7348SJose.Borrego@Sun.COM * specified, which will be used if the user presses <enter> without 315*7348SJose.Borrego@Sun.COM * answering the question. 316*7348SJose.Borrego@Sun.COM */ 317*7348SJose.Borrego@Sun.COM static int 318*7348SJose.Borrego@Sun.COM smbadm_answer_prompt(const char *prompt, char *answer, const char *dflt) 319*7348SJose.Borrego@Sun.COM { 320*7348SJose.Borrego@Sun.COM char buf[SMBADM_ANSBUFSIZ]; 321*7348SJose.Borrego@Sun.COM char *p; 322*7348SJose.Borrego@Sun.COM 323*7348SJose.Borrego@Sun.COM (void) printf(gettext("%s [%s]: "), prompt, dflt); 324*7348SJose.Borrego@Sun.COM 325*7348SJose.Borrego@Sun.COM if (fgets(buf, SMBADM_ANSBUFSIZ, stdin) == NULL) 326*7348SJose.Borrego@Sun.COM return (-1); 327*7348SJose.Borrego@Sun.COM 328*7348SJose.Borrego@Sun.COM if ((p = strchr(buf, '\n')) != NULL) 329*7348SJose.Borrego@Sun.COM *p = '\0'; 330*7348SJose.Borrego@Sun.COM 331*7348SJose.Borrego@Sun.COM if (*buf == '\0') 332*7348SJose.Borrego@Sun.COM (void) strlcpy(answer, dflt, SMBADM_ANSBUFSIZ); 333*7348SJose.Borrego@Sun.COM else 334*7348SJose.Borrego@Sun.COM (void) strlcpy(answer, buf, SMBADM_ANSBUFSIZ); 335*7348SJose.Borrego@Sun.COM 336*7348SJose.Borrego@Sun.COM return (0); 337*7348SJose.Borrego@Sun.COM } 338*7348SJose.Borrego@Sun.COM 339*7348SJose.Borrego@Sun.COM /* 340*7348SJose.Borrego@Sun.COM * smbadm_confirm 341*7348SJose.Borrego@Sun.COM * 342*7348SJose.Borrego@Sun.COM * Ask a question that requires a yes/no answer. 343*7348SJose.Borrego@Sun.COM * A default response must be specified. 344*7348SJose.Borrego@Sun.COM */ 345*7348SJose.Borrego@Sun.COM static boolean_t 346*7348SJose.Borrego@Sun.COM smbadm_confirm(const char *prompt, const char *dflt) 347*7348SJose.Borrego@Sun.COM { 348*7348SJose.Borrego@Sun.COM char buf[SMBADM_ANSBUFSIZ]; 349*7348SJose.Borrego@Sun.COM 350*7348SJose.Borrego@Sun.COM for (;;) { 351*7348SJose.Borrego@Sun.COM if (smbadm_answer_prompt(prompt, buf, dflt) < 0) 352*7348SJose.Borrego@Sun.COM return (B_FALSE); 353*7348SJose.Borrego@Sun.COM 354*7348SJose.Borrego@Sun.COM if (smbadm_strcasecmplist(buf, "n", "no", 0) >= 0) 355*7348SJose.Borrego@Sun.COM return (B_FALSE); 356*7348SJose.Borrego@Sun.COM 357*7348SJose.Borrego@Sun.COM if (smbadm_strcasecmplist(buf, "y", "yes", 0) >= 0) 358*7348SJose.Borrego@Sun.COM return (B_TRUE); 359*7348SJose.Borrego@Sun.COM 360*7348SJose.Borrego@Sun.COM (void) printf(gettext("Please answer yes or no.\n")); 361*7348SJose.Borrego@Sun.COM } 362*7348SJose.Borrego@Sun.COM } 363*7348SJose.Borrego@Sun.COM 364*7348SJose.Borrego@Sun.COM static boolean_t 365*7348SJose.Borrego@Sun.COM smbadm_join_prompt(char *curdom, int prmpt_type) 366*7348SJose.Borrego@Sun.COM { 367*7348SJose.Borrego@Sun.COM boolean_t ret = B_FALSE; 368*7348SJose.Borrego@Sun.COM 369*7348SJose.Borrego@Sun.COM switch (prmpt_type) { 370*7348SJose.Borrego@Sun.COM 371*7348SJose.Borrego@Sun.COM case SMBADM_CHANGE_SECMODE: 372*7348SJose.Borrego@Sun.COM (void) printf(gettext("This operation requires that " 373*7348SJose.Borrego@Sun.COM "the service be restarted.\n")); 374*7348SJose.Borrego@Sun.COM ret = smbadm_confirm( 375*7348SJose.Borrego@Sun.COM "Would you like to continue ?", "no"); 376*7348SJose.Borrego@Sun.COM break; 377*7348SJose.Borrego@Sun.COM 378*7348SJose.Borrego@Sun.COM case SMBADM_CHANGE_DOMAIN: 379*7348SJose.Borrego@Sun.COM (void) printf(gettext("This system has already " 380*7348SJose.Borrego@Sun.COM "joined to '%s' domain.\n"), curdom); 381*7348SJose.Borrego@Sun.COM ret = smbadm_confirm( 382*7348SJose.Borrego@Sun.COM "Would you like to join the new domain ?", "no"); 383*7348SJose.Borrego@Sun.COM break; 384*7348SJose.Borrego@Sun.COM 385*7348SJose.Borrego@Sun.COM default: 386*7348SJose.Borrego@Sun.COM break; 387*7348SJose.Borrego@Sun.COM } 388*7348SJose.Borrego@Sun.COM 389*7348SJose.Borrego@Sun.COM return (ret); 390*7348SJose.Borrego@Sun.COM } 391*7348SJose.Borrego@Sun.COM 392*7348SJose.Borrego@Sun.COM /* 3935331Samw * smbadm_join 3945331Samw * 3955331Samw * Join the given domain/workgroup 3965331Samw */ 3975331Samw static int 3985331Samw smbadm_join(int argc, char **argv) 3995331Samw { 4005331Samw char option; 4015331Samw smb_joininfo_t jdi; 4025331Samw boolean_t join_w = B_FALSE; 4035331Samw boolean_t join_d = B_FALSE; 404*7348SJose.Borrego@Sun.COM boolean_t mode_change = B_FALSE; 4055331Samw uint32_t status; 4066600Sas200622 char curdom[MAXHOSTNAMELEN]; 4075331Samw 4085331Samw bzero(&jdi, sizeof (jdi)); 4095331Samw 4105331Samw while ((option = getopt(argc, argv, "u:w:")) != -1) { 4115331Samw switch (option) { 4125331Samw case 'w': 4135331Samw (void) strlcpy(jdi.domain_name, optarg, 4145331Samw sizeof (jdi.domain_name)); 4155331Samw jdi.mode = SMB_SECMODE_WORKGRP; 4165331Samw join_w = B_TRUE; 4175331Samw break; 4185331Samw 4195331Samw case 'u': 4205331Samw /* admin username */ 4215331Samw (void) strlcpy(jdi.domain_username, optarg, 4225331Samw sizeof (jdi.domain_username)); 4235331Samw jdi.mode = SMB_SECMODE_DOMAIN; 4245331Samw join_d = B_TRUE; 4255331Samw break; 4265331Samw 4275331Samw default: 4285331Samw smbadm_usage(B_FALSE); 4295331Samw } 4305331Samw } 4315331Samw 4325331Samw if (join_w && join_d) { 4335331Samw (void) fprintf(stderr, 4345331Samw gettext("domain and workgroup " 4355331Samw "can not be specified together\n")); 4365331Samw smbadm_usage(B_FALSE); 4375331Samw } 4385331Samw 4395331Samw if (join_d && (argv[optind] != NULL)) { 4405331Samw (void) strlcpy(jdi.domain_name, argv[optind], 4415331Samw sizeof (jdi.domain_name)); 4425331Samw } 4435331Samw 4445331Samw if (*jdi.domain_name == '\0') { 4455331Samw (void) fprintf(stderr, gettext("missing %s name\n"), 4465331Samw (join_d) ? "domain" : "workgroup"); 4475331Samw smbadm_usage(B_FALSE); 4485331Samw } 4495331Samw 4505331Samw if (join_d && *jdi.domain_username == '\0') { 4515331Samw (void) fprintf(stderr, gettext("missing username\n")); 4525331Samw smbadm_usage(B_FALSE); 4535331Samw } 4545331Samw 455*7348SJose.Borrego@Sun.COM if (smb_config_get_secmode() != jdi.mode) 456*7348SJose.Borrego@Sun.COM mode_change = B_TRUE; 457*7348SJose.Borrego@Sun.COM 4585331Samw if (join_w) { 459*7348SJose.Borrego@Sun.COM 460*7348SJose.Borrego@Sun.COM if (mode_change) 461*7348SJose.Borrego@Sun.COM if (!smbadm_join_prompt(NULL, SMBADM_CHANGE_SECMODE)) 462*7348SJose.Borrego@Sun.COM return (0); 463*7348SJose.Borrego@Sun.COM 4645331Samw status = smb_join(&jdi); 4655331Samw if (status == NT_STATUS_SUCCESS) { 466*7348SJose.Borrego@Sun.COM 467*7348SJose.Borrego@Sun.COM if (mode_change) 468*7348SJose.Borrego@Sun.COM if (smb_smf_restart_service() != 0) 469*7348SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext( 470*7348SJose.Borrego@Sun.COM "Unable to restart smb service. " 471*7348SJose.Borrego@Sun.COM "Run 'svcs -xv smb/server' for " 472*7348SJose.Borrego@Sun.COM "more information.")); 473*7348SJose.Borrego@Sun.COM 4745331Samw (void) printf( 4755331Samw gettext("Successfully joined workgroup '%s'\n"), 4765331Samw jdi.domain_name); 4775331Samw return (0); 4785331Samw } 4795331Samw 4805331Samw (void) fprintf(stderr, 4815331Samw gettext("failed to join workgroup '%s' (%s)\n"), 4825331Samw jdi.domain_name, xlate_nt_status(status)); 4835331Samw 4845331Samw return (1); 4855331Samw } 4865331Samw 4876600Sas200622 if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { 4886600Sas200622 (void) smb_getdomainname(curdom, MAXHOSTNAMELEN); 4896600Sas200622 if (*curdom != 0 && strncasecmp(curdom, jdi.domain_name, 4906600Sas200622 strlen(curdom))) { 491*7348SJose.Borrego@Sun.COM if (!smbadm_join_prompt(curdom, SMBADM_CHANGE_DOMAIN)) 4926139Sjb150015 return (0); 4936139Sjb150015 } 4946139Sjb150015 } 4956139Sjb150015 496*7348SJose.Borrego@Sun.COM if (mode_change) 497*7348SJose.Borrego@Sun.COM if (!smbadm_join_prompt(NULL, SMBADM_CHANGE_SECMODE)) 498*7348SJose.Borrego@Sun.COM return (0); 499*7348SJose.Borrego@Sun.COM 5005331Samw /* Join the domain */ 5015331Samw if (*jdi.domain_passwd == '\0') { 5025331Samw char *p = NULL; 5035331Samw char *prompt = gettext("Enter domain password: "); 5045331Samw p = getpassphrase(prompt); 5055331Samw if (!p) { 5065331Samw (void) fprintf(stderr, gettext("missing password\n")); 5075331Samw smbadm_usage(B_FALSE); 5085331Samw } 5095331Samw 5105331Samw (void) strlcpy(jdi.domain_passwd, p, 5115331Samw sizeof (jdi.domain_passwd)); 5125331Samw } 5135331Samw 5145331Samw (void) printf(gettext("Joining '%s' ... this may take a minute ...\n"), 5155331Samw jdi.domain_name); 5165331Samw 5175331Samw status = smb_join(&jdi); 5185331Samw 5195331Samw switch (status) { 5205331Samw case NT_STATUS_SUCCESS: 521*7348SJose.Borrego@Sun.COM 522*7348SJose.Borrego@Sun.COM if (mode_change) 523*7348SJose.Borrego@Sun.COM if (smb_smf_restart_service() != 0) 524*7348SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext( 525*7348SJose.Borrego@Sun.COM "Unable to restart smb service. " 526*7348SJose.Borrego@Sun.COM "Run 'svcs -xv smb/server' for " 527*7348SJose.Borrego@Sun.COM "more information.")); 528*7348SJose.Borrego@Sun.COM 5295331Samw (void) printf(gettext("Successfully joined domain '%s'\n"), 5305331Samw jdi.domain_name); 5316432Sas200622 5325331Samw return (0); 5335331Samw 5345331Samw case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND: 5355331Samw (void) fprintf(stderr, gettext("failed to find " 5365331Samw "any domain controllers for '%s'\n"), 5375331Samw jdi.domain_name); 5385331Samw break; 5395331Samw 5405331Samw default: 5415331Samw (void) fprintf(stderr, 5425331Samw gettext("failed to join domain '%s' (%s)\n"), 5435331Samw jdi.domain_name, xlate_nt_status(status)); 5445331Samw } 5455331Samw 5465331Samw return (1); 5475331Samw } 5485331Samw 5495331Samw /* 5505331Samw * smbadm_list 5515331Samw * 5525331Samw * Displays current security mode and domain/workgroup name. 5535331Samw */ 5545331Samw /*ARGSUSED*/ 5555331Samw static int 5565331Samw smbadm_list(int argc, char **argv) 5575331Samw { 5586139Sjb150015 char domain[MAXHOSTNAMELEN]; 5596139Sjb150015 char modename[16]; 5606139Sjb150015 int rc; 561*7348SJose.Borrego@Sun.COM char ipstr[INET6_ADDRSTRLEN]; 562*7348SJose.Borrego@Sun.COM smb_ntdomain_t domain_info; 5635331Samw 5646139Sjb150015 rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename)); 5656139Sjb150015 if (rc != SMBD_SMF_OK) { 5665331Samw (void) fprintf(stderr, 567*7348SJose.Borrego@Sun.COM gettext("failed to get the connected mode\n")); 5685331Samw return (1); 5695331Samw } 5705331Samw 5716139Sjb150015 if (smb_getdomainname(domain, sizeof (domain)) != 0) { 5726139Sjb150015 (void) fprintf(stderr, gettext("failed to get the %s name\n"), 5736139Sjb150015 modename); 5745331Samw return (1); 5755331Samw } 576*7348SJose.Borrego@Sun.COM if (strcmp(modename, "workgroup") == 0) { 577*7348SJose.Borrego@Sun.COM (void) printf(gettext("Workgroup: %s\n"), domain); 578*7348SJose.Borrego@Sun.COM return (0); 579*7348SJose.Borrego@Sun.COM } 580*7348SJose.Borrego@Sun.COM (void) printf(gettext("Domain: %s\n"), domain); 5815331Samw 582*7348SJose.Borrego@Sun.COM bzero(&domain_info, sizeof (smb_ntdomain_t)); 583*7348SJose.Borrego@Sun.COM if ((smb_get_dcinfo(&domain_info) == NT_STATUS_SUCCESS) && 584*7348SJose.Borrego@Sun.COM (*domain_info.domain != '\0') && (domain_info.ipaddr != 0)) { 585*7348SJose.Borrego@Sun.COM (void) inet_ntop(AF_INET, (const void *)&domain_info.ipaddr, 586*7348SJose.Borrego@Sun.COM ipstr, sizeof (ipstr)); 587*7348SJose.Borrego@Sun.COM (void) printf(gettext("Selected Domain Controller: %s (%s)\n"), 588*7348SJose.Borrego@Sun.COM domain_info.server, ipstr); 589*7348SJose.Borrego@Sun.COM } 590*7348SJose.Borrego@Sun.COM 5915331Samw return (0); 5925331Samw } 5935331Samw 5945331Samw /* 5955331Samw * smbadm_group_create 5965331Samw * 5975331Samw * Creates a local SMB group 5985331Samw */ 5995331Samw static int 6005331Samw smbadm_group_create(int argc, char **argv) 6015331Samw { 6025331Samw char *gname = NULL; 6035331Samw char *desc = NULL; 6045331Samw char option; 6055772Sas200622 int status; 6065331Samw 6075331Samw while ((option = getopt(argc, argv, "d:")) != -1) { 6085331Samw switch (option) { 6095331Samw case 'd': 6105331Samw desc = optarg; 6115331Samw break; 6125331Samw 6135331Samw default: 6145331Samw smbadm_usage(B_FALSE); 6155331Samw } 6165331Samw } 6175331Samw 6185331Samw gname = argv[optind]; 6195331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 6205331Samw (void) fprintf(stderr, gettext("missing group name\n")); 6215331Samw smbadm_usage(B_FALSE); 6225331Samw } 6235331Samw 6245331Samw if (getgrnam(gname) == NULL) { 6255331Samw (void) fprintf(stderr, 6265772Sas200622 gettext("failed to get the Solaris group '%s'\n"), gname); 6275331Samw (void) fprintf(stderr, 6285772Sas200622 gettext("use 'groupadd' to add '%s'\n"), gname); 6295331Samw return (1); 6305331Samw } 6315331Samw 6325772Sas200622 status = smb_lgrp_add(gname, desc); 6335772Sas200622 if (status != SMB_LGRP_SUCCESS) { 6345331Samw (void) fprintf(stderr, 6355331Samw gettext("failed to create the group (%s)\n"), 6365772Sas200622 smb_lgrp_strerror(status)); 6375331Samw } else { 6385772Sas200622 (void) printf(gettext("'%s' created.\n"), 6395331Samw gname); 6405331Samw } 6415331Samw 6425331Samw return (status); 6435331Samw } 6445331Samw 6455331Samw /* 6465331Samw * smbadm_group_dump_members 6475331Samw * 6485331Samw * Dump group members details. 6495331Samw */ 6505331Samw static void 6515772Sas200622 smbadm_group_dump_members(smb_gsid_t *members, int num) 6525331Samw { 6536432Sas200622 char sidstr[SMB_SID_STRSZ]; 6545331Samw int i; 6555331Samw 6565772Sas200622 if (num == 0) { 6575331Samw (void) printf(gettext("\tNo members\n")); 6585331Samw return; 6595331Samw } 6605331Samw 6615331Samw (void) printf(gettext("\tMembers:\n")); 6625772Sas200622 for (i = 0; i < num; i++) { 6636600Sas200622 *sidstr = '\0'; 6646600Sas200622 if (smb_lookup_sid(members[i].gs_sid, sidstr, 6656600Sas200622 sizeof (sidstr)) == NT_STATUS_SUCCESS) 6666600Sas200622 (void) printf(gettext("\t\t%s\n"), sidstr); 6676600Sas200622 else 6686600Sas200622 (void) printf(gettext("\t\tERROR! Invalid SID\n")); 6695331Samw } 6705331Samw } 6715331Samw 6725331Samw /* 6735331Samw * smbadm_group_dump_privs 6745331Samw * 6755331Samw * Dump group privilege details. 6765331Samw */ 6775331Samw static void 6785772Sas200622 smbadm_group_dump_privs(smb_privset_t *privs) 6795331Samw { 6805772Sas200622 smb_privinfo_t *pinfo; 6815772Sas200622 char *pstatus; 6825331Samw int i; 6835331Samw 6845331Samw (void) printf(gettext("\tPrivileges: \n")); 6855331Samw 6865772Sas200622 for (i = 0; i < privs->priv_cnt; i++) { 6875772Sas200622 pinfo = smb_priv_getbyvalue(privs->priv[i].luid.lo_part); 6885772Sas200622 if ((pinfo == NULL) || (pinfo->flags & PF_PRESENTABLE) == 0) 6895331Samw continue; 6905331Samw 6915772Sas200622 switch (privs->priv[i].attrs) { 6925772Sas200622 case SE_PRIVILEGE_ENABLED: 6935772Sas200622 pstatus = "On"; 6945772Sas200622 break; 6955772Sas200622 case SE_PRIVILEGE_DISABLED: 6965772Sas200622 pstatus = "Off"; 6975772Sas200622 break; 6985772Sas200622 default: 6995772Sas200622 pstatus = "Unknown"; 7005772Sas200622 break; 7015331Samw } 7025772Sas200622 (void) printf(gettext("\t\t%s: %s\n"), pinfo->name, pstatus); 7035331Samw } 7045331Samw 7055772Sas200622 if (privs->priv_cnt == 0) 7065331Samw (void) printf(gettext("\t\tNo privileges\n")); 7075331Samw } 7085331Samw 7095331Samw /* 7105331Samw * smbadm_group_dump 7115331Samw * 7125331Samw * Dump group details. 7135331Samw */ 7145772Sas200622 static void 7155772Sas200622 smbadm_group_dump(smb_group_t *grp, boolean_t show_mem, boolean_t show_privs) 7165331Samw { 7176432Sas200622 char sidstr[SMB_SID_STRSZ]; 7185331Samw 7195772Sas200622 (void) printf(gettext("%s (%s)\n"), grp->sg_name, grp->sg_cmnt); 7205331Samw 7216432Sas200622 smb_sid_tostr(grp->sg_id.gs_sid, sidstr); 7225772Sas200622 (void) printf(gettext("\tSID: %s\n"), sidstr); 7235331Samw 7245772Sas200622 if (show_privs) 7255772Sas200622 smbadm_group_dump_privs(grp->sg_privs); 7265331Samw 7275772Sas200622 if (show_mem) 7285772Sas200622 smbadm_group_dump_members(grp->sg_members, grp->sg_nmembers); 7295331Samw } 7305331Samw 7315331Samw /* 7325331Samw * smbadm_group_show 7335331Samw * 7345331Samw */ 7355331Samw static int 7365331Samw smbadm_group_show(int argc, char **argv) 7375331Samw { 7385331Samw char *gname = NULL; 7395331Samw boolean_t show_privs; 7405331Samw boolean_t show_members; 7415331Samw char option; 7425772Sas200622 int status; 7435772Sas200622 smb_group_t grp; 7445772Sas200622 smb_giter_t gi; 7455331Samw 7465331Samw show_privs = show_members = B_FALSE; 7475331Samw 7485331Samw while ((option = getopt(argc, argv, "mp")) != -1) { 7495331Samw switch (option) { 7505331Samw case 'm': 7515331Samw show_members = B_TRUE; 7525331Samw break; 7535331Samw case 'p': 7545331Samw show_privs = B_TRUE; 7555331Samw break; 7565331Samw 7575331Samw default: 7585331Samw smbadm_usage(B_FALSE); 7595331Samw } 7605331Samw } 7615331Samw 7625331Samw gname = argv[optind]; 7635331Samw if (optind >= argc || gname == NULL || *gname == '\0') 7645331Samw gname = "*"; 7655331Samw 7665772Sas200622 if (strcmp(gname, "*")) { 7675772Sas200622 status = smb_lgrp_getbyname(gname, &grp); 7685772Sas200622 if (status == SMB_LGRP_SUCCESS) { 7695772Sas200622 smbadm_group_dump(&grp, show_members, show_privs); 7705772Sas200622 smb_lgrp_free(&grp); 7715772Sas200622 } else { 7725772Sas200622 (void) fprintf(stderr, 7735772Sas200622 gettext("failed to find '%s' (%s)\n"), 7745772Sas200622 gname, smb_lgrp_strerror(status)); 7755772Sas200622 } 7765772Sas200622 return (status); 7775331Samw } 7785331Samw 7796432Sas200622 if ((status = smb_lgrp_iteropen(&gi)) != SMB_LGRP_SUCCESS) { 7805772Sas200622 (void) fprintf(stderr, 7815772Sas200622 gettext("failed to list groups (%s)\n"), 7825772Sas200622 smb_lgrp_strerror(status)); 7835772Sas200622 return (status); 7845331Samw } 7855331Samw 7866432Sas200622 while ((status = smb_lgrp_iterate(&gi, &grp)) == SMB_LGRP_SUCCESS) { 7875772Sas200622 smbadm_group_dump(&grp, show_members, show_privs); 7885772Sas200622 smb_lgrp_free(&grp); 7895772Sas200622 } 7906432Sas200622 7915772Sas200622 smb_lgrp_iterclose(&gi); 7925772Sas200622 7936432Sas200622 if (status != SMB_LGRP_NO_MORE) { 7946432Sas200622 (void) fprintf(stderr, 7956432Sas200622 gettext("failed to get all the groups (%s)\n"), 7966432Sas200622 smb_lgrp_strerror(status)); 7976432Sas200622 return (status); 7986432Sas200622 } 7996432Sas200622 8005772Sas200622 return (0); 8015331Samw } 8025331Samw 8035331Samw /* 8045331Samw * smbadm_group_delete 8055331Samw */ 8065331Samw static int 8075331Samw smbadm_group_delete(int argc, char **argv) 8085331Samw { 8095331Samw char *gname = NULL; 8105772Sas200622 int status; 8115331Samw 8125331Samw gname = argv[optind]; 8135331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 8145331Samw (void) fprintf(stderr, gettext("missing group name\n")); 8155331Samw smbadm_usage(B_FALSE); 8165331Samw } 8175331Samw 8185772Sas200622 status = smb_lgrp_delete(gname); 8195772Sas200622 if (status != SMB_LGRP_SUCCESS) { 8205331Samw (void) fprintf(stderr, 8215331Samw gettext("failed to delete the group (%s)\n"), 8225772Sas200622 smb_lgrp_strerror(status)); 8235331Samw } else { 8245772Sas200622 (void) printf(gettext("'%s' deleted.\n"), 8255331Samw gname); 8265331Samw } 8275331Samw 8285331Samw return (status); 8295331Samw } 8305331Samw 8315331Samw /* 8325331Samw * smbadm_group_rename 8335331Samw */ 8345331Samw static int 8355331Samw smbadm_group_rename(int argc, char **argv) 8365331Samw { 8375331Samw char *gname = NULL; 8385331Samw char *ngname = NULL; 8395772Sas200622 int status; 8405331Samw 8415331Samw gname = argv[optind]; 8425331Samw if (optind++ >= argc || gname == NULL || *gname == '\0') { 8435331Samw (void) fprintf(stderr, gettext("missing group name\n")); 8445331Samw smbadm_usage(B_FALSE); 8455331Samw } 8465331Samw 8475331Samw ngname = argv[optind]; 8485331Samw if (optind >= argc || ngname == NULL || *ngname == '\0') { 8495331Samw (void) fprintf(stderr, gettext("missing new group name\n")); 8505331Samw smbadm_usage(B_FALSE); 8515331Samw } 8525331Samw 8535772Sas200622 if (getgrnam(ngname) == NULL) { 8545331Samw (void) fprintf(stderr, 8555772Sas200622 gettext("failed to get the Solaris group '%s'\n"), ngname); 8565331Samw (void) fprintf(stderr, 8575772Sas200622 gettext("use 'groupadd' to add '%s'\n"), ngname); 8585331Samw return (1); 8595331Samw } 8605331Samw 8615772Sas200622 status = smb_lgrp_rename(gname, ngname); 8625772Sas200622 if (status != SMB_LGRP_SUCCESS) { 8635772Sas200622 if (status == SMB_LGRP_EXISTS) 8645772Sas200622 (void) fprintf(stderr, 8655772Sas200622 gettext("failed to rename '%s' (%s already " 8665772Sas200622 "exists)\n"), gname, ngname); 8675772Sas200622 else 8685772Sas200622 (void) fprintf(stderr, 8695772Sas200622 gettext("failed to rename '%s' (%s)\n"), gname, 8705772Sas200622 smb_lgrp_strerror(status)); 8715331Samw } else { 8725772Sas200622 (void) printf(gettext("'%s' renamed to '%s'\n"), gname, ngname); 8735331Samw } 8745331Samw 8755331Samw return (status); 8765331Samw } 8775331Samw 8785331Samw /* 8795331Samw * smbadm_group_setprop 8805331Samw * 8815331Samw * Set the group properties. 8825331Samw */ 8835331Samw static int 8845331Samw smbadm_group_setprop(int argc, char **argv) 8855331Samw { 8865331Samw char *gname = NULL; 8875331Samw smbadm_prop_t props[SMBADM_NPROP]; 8885331Samw smbadm_prop_handle_t *phandle; 8895331Samw char option; 8905331Samw int pcnt = 0; 8915331Samw int ret; 8925331Samw int p; 8935331Samw 8945331Samw bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 8955331Samw 8965331Samw while ((option = getopt(argc, argv, "p:")) != -1) { 8975331Samw switch (option) { 8985331Samw case 'p': 8995331Samw if (pcnt >= SMBADM_NPROP) { 9005331Samw (void) fprintf(stderr, 9015331Samw gettext("exceeded number of supported" 9025331Samw " properties\n")); 9035331Samw smbadm_usage(B_FALSE); 9045331Samw } 9055331Samw 9065772Sas200622 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 9075772Sas200622 smbadm_usage(B_FALSE); 9085331Samw break; 9095331Samw 9105331Samw default: 9115331Samw smbadm_usage(B_FALSE); 9125331Samw } 9135331Samw } 9145331Samw 9155331Samw if (pcnt == 0) { 9165331Samw (void) fprintf(stderr, 9175331Samw gettext("missing property=value argument\n")); 9185331Samw smbadm_usage(B_FALSE); 9195331Samw } 9205331Samw 9215331Samw gname = argv[optind]; 9225331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 9235331Samw (void) fprintf(stderr, gettext("missing group name\n")); 9245331Samw smbadm_usage(B_FALSE); 9255331Samw } 9265331Samw 9275331Samw for (p = 0; p < pcnt; p++) { 9285331Samw phandle = smbadm_prop_gethandle(props[p].p_name); 9295331Samw if (phandle) { 9305331Samw if (phandle->p_setfn(gname, &props[p]) != 0) 9315331Samw ret = 1; 9325331Samw } 9335331Samw } 9345331Samw 9355331Samw return (ret); 9365331Samw } 9375331Samw 9385331Samw /* 9395331Samw * smbadm_group_getprop 9405331Samw * 9415331Samw * Get the group properties. 9425331Samw */ 9435331Samw static int 9445331Samw smbadm_group_getprop(int argc, char **argv) 9455331Samw { 9465331Samw char *gname = NULL; 9475331Samw smbadm_prop_t props[SMBADM_NPROP]; 9485331Samw smbadm_prop_handle_t *phandle; 9495331Samw char option; 9505331Samw int pcnt = 0; 9515331Samw int ret; 9525331Samw int p; 9535331Samw 9545331Samw bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 9555331Samw 9565331Samw while ((option = getopt(argc, argv, "p:")) != -1) { 9575331Samw switch (option) { 9585331Samw case 'p': 9595331Samw if (pcnt >= SMBADM_NPROP) { 9605331Samw (void) fprintf(stderr, 9615331Samw gettext("exceeded number of supported" 9625331Samw " properties\n")); 9635331Samw smbadm_usage(B_FALSE); 9645331Samw } 9655331Samw 9665772Sas200622 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 9675772Sas200622 smbadm_usage(B_FALSE); 9685331Samw break; 9695331Samw 9705331Samw default: 9715331Samw smbadm_usage(B_FALSE); 9725331Samw } 9735331Samw } 9745331Samw 9755331Samw gname = argv[optind]; 9765331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 9775331Samw (void) fprintf(stderr, gettext("missing group name\n")); 9785331Samw smbadm_usage(B_FALSE); 9795331Samw } 9805331Samw 9815331Samw if (pcnt == 0) { 9825331Samw /* 9835331Samw * If no property has be specified then get 9845331Samw * all the properties. 9855331Samw */ 9865331Samw pcnt = SMBADM_NPROP; 9875331Samw for (p = 0; p < pcnt; p++) 9885331Samw props[p].p_name = smbadm_ptable[p].p_name; 9895331Samw } 9905331Samw 9915331Samw for (p = 0; p < pcnt; p++) { 9925331Samw phandle = smbadm_prop_gethandle(props[p].p_name); 9935331Samw if (phandle) { 9945331Samw if (phandle->p_getfn(gname, &props[p]) != 0) 9955331Samw ret = 1; 9965331Samw } 9975331Samw } 9985331Samw 9995331Samw return (ret); 10005331Samw } 10015331Samw 10025331Samw /* 10035331Samw * smbadm_group_addmember 10045331Samw * 10055331Samw */ 10065331Samw static int 10075331Samw smbadm_group_addmember(int argc, char **argv) 10085331Samw { 10095331Samw char *gname = NULL; 10105331Samw char **mname; 10115331Samw char option; 10125772Sas200622 smb_gsid_t msid; 10135772Sas200622 int status; 10145331Samw int mcnt = 0; 10155331Samw int ret = 0; 10165331Samw int i; 10175331Samw 10185331Samw 10195331Samw mname = (char **)malloc(argc * sizeof (char *)); 10205331Samw if (mname == NULL) { 10215331Samw (void) fprintf(stderr, gettext("out of memory\n")); 10225331Samw return (1); 10235331Samw } 10245331Samw bzero(mname, argc * sizeof (char *)); 10255331Samw 10265331Samw while ((option = getopt(argc, argv, "m:")) != -1) { 10275331Samw switch (option) { 10285331Samw case 'm': 10295331Samw mname[mcnt++] = optarg; 10305331Samw break; 10315331Samw 10325331Samw default: 10335331Samw free(mname); 10345331Samw smbadm_usage(B_FALSE); 10355331Samw } 10365331Samw } 10375331Samw 10385331Samw if (mcnt == 0) { 10395331Samw (void) fprintf(stderr, gettext("missing member name\n")); 10405331Samw free(mname); 10415331Samw smbadm_usage(B_FALSE); 10425331Samw } 10435331Samw 10445331Samw gname = argv[optind]; 10455331Samw if (optind >= argc || gname == NULL || *gname == 0) { 10465331Samw (void) fprintf(stderr, gettext("missing group name\n")); 10475331Samw free(mname); 10485331Samw smbadm_usage(B_FALSE); 10495331Samw } 10505331Samw 10515331Samw 10525331Samw for (i = 0; i < mcnt; i++) { 10535331Samw if (mname[i] == NULL) 10545331Samw continue; 10555331Samw 10565772Sas200622 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 10575772Sas200622 (void) fprintf(stderr, 10585772Sas200622 gettext("failed to add %s " 10595772Sas200622 "(could not obtain the SID)\n"), 10605772Sas200622 mname[i]); 10615772Sas200622 continue; 10625772Sas200622 } 10635772Sas200622 10645772Sas200622 status = smb_lgrp_add_member(gname, msid.gs_sid, msid.gs_type); 10655772Sas200622 free(msid.gs_sid); 10665772Sas200622 if (status != SMB_LGRP_SUCCESS) { 10675331Samw (void) fprintf(stderr, 10685331Samw gettext("failed to add %s (%s)\n"), 10695772Sas200622 mname[i], smb_lgrp_strerror(status)); 10705331Samw ret = 1; 10715772Sas200622 } else { 10725772Sas200622 (void) printf(gettext("'%s' is now a member of '%s'\n"), 10735772Sas200622 mname[i], gname); 10745331Samw } 10755331Samw } 10765331Samw 10775331Samw free(mname); 10785331Samw return (ret); 10795331Samw } 10805331Samw 10815331Samw /* 10825331Samw * smbadm_group_delmember 10835331Samw */ 10845331Samw static int 10855331Samw smbadm_group_delmember(int argc, char **argv) 10865331Samw { 10875331Samw char *gname = NULL; 10885331Samw char **mname; 10895331Samw char option; 10905772Sas200622 smb_gsid_t msid; 10915772Sas200622 int status; 10925331Samw int mcnt = 0; 10935331Samw int ret = 0; 10945331Samw int i; 10955331Samw 10965331Samw mname = (char **)malloc(argc * sizeof (char *)); 10975331Samw if (mname == NULL) { 10985331Samw (void) fprintf(stderr, gettext("out of memory\n")); 10995331Samw return (1); 11005331Samw } 11015331Samw bzero(mname, argc * sizeof (char *)); 11025331Samw 11035331Samw while ((option = getopt(argc, argv, "m:")) != -1) { 11045331Samw switch (option) { 11055331Samw case 'm': 11065331Samw mname[mcnt++] = optarg; 11075331Samw break; 11085331Samw 11095331Samw default: 11105331Samw free(mname); 11115331Samw smbadm_usage(B_FALSE); 11125331Samw } 11135331Samw } 11145331Samw 11155331Samw if (mcnt == 0) { 11165331Samw (void) fprintf(stderr, gettext("missing member name\n")); 11175331Samw free(mname); 11185331Samw smbadm_usage(B_FALSE); 11195331Samw } 11205331Samw 11215331Samw gname = argv[optind]; 11225331Samw if (optind >= argc || gname == NULL || *gname == 0) { 11235331Samw (void) fprintf(stderr, gettext("missing group name\n")); 11245331Samw free(mname); 11255331Samw smbadm_usage(B_FALSE); 11265331Samw } 11275331Samw 11285331Samw 11295331Samw for (i = 0; i < mcnt; i++) { 11305331Samw if (mname[i] == NULL) 11315331Samw continue; 11325331Samw 11335772Sas200622 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 11345772Sas200622 (void) fprintf(stderr, 11355772Sas200622 gettext("failed to remove %s " 11365772Sas200622 "(could not obtain the SID)\n"), 11375772Sas200622 mname[i]); 11385772Sas200622 continue; 11395772Sas200622 } 11405772Sas200622 11415772Sas200622 status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type); 11425772Sas200622 free(msid.gs_sid); 11435772Sas200622 if (status != SMB_LGRP_SUCCESS) { 11445331Samw (void) fprintf(stderr, 11455331Samw gettext("failed to remove %s (%s)\n"), 11465772Sas200622 mname[i], smb_lgrp_strerror(status)); 11475331Samw ret = 1; 11485331Samw } else { 11495331Samw (void) printf( 11505772Sas200622 gettext("'%s' has been removed from %s\n"), 11515331Samw mname[i], gname); 11525331Samw } 11535331Samw } 11545331Samw 11555331Samw return (ret); 11565331Samw } 11575331Samw 11585331Samw static int 11595331Samw smbadm_user_disable(int argc, char **argv) 11605331Samw { 11615331Samw int error; 11625331Samw char *user = NULL; 11635331Samw 11645331Samw user = argv[optind]; 11655331Samw if (optind >= argc || user == NULL || *user == '\0') { 11665331Samw (void) fprintf(stderr, gettext("missing user name\n")); 11675331Samw smbadm_usage(B_FALSE); 11685331Samw } 11695331Samw 11705331Samw error = smb_pwd_setcntl(user, SMB_PWC_DISABLE); 11715331Samw if (error == SMB_PWE_SUCCESS) 11725331Samw (void) printf(gettext("%s is disabled.\n"), user); 11735331Samw else 11745331Samw (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 11755331Samw 11765331Samw return (error); 11775331Samw } 11785331Samw 11795331Samw static int 11805331Samw smbadm_user_enable(int argc, char **argv) 11815331Samw { 11825331Samw int error; 11835331Samw char *user = NULL; 11845331Samw 11855331Samw user = argv[optind]; 11865331Samw if (optind >= argc || user == NULL || *user == '\0') { 11875331Samw (void) fprintf(stderr, gettext("missing user name\n")); 11885331Samw smbadm_usage(B_FALSE); 11895331Samw } 11905331Samw 11915331Samw error = smb_pwd_setcntl(user, SMB_PWC_ENABLE); 11925331Samw if (error == SMB_PWE_SUCCESS) 11935331Samw (void) printf(gettext("%s is enabled.\n"), user); 11945331Samw else 11955331Samw (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 11965331Samw 11975331Samw return (error); 11985331Samw } 11995331Samw 12005331Samw 12015331Samw int 12025331Samw main(int argc, char **argv) 12035331Samw { 12045772Sas200622 int ret; 12055331Samw int i; 12065331Samw 12075331Samw (void) malloc(0); /* satisfy libumem dependency */ 12085331Samw 12095331Samw progname = basename(argv[0]); 12105331Samw 12115331Samw if (getzoneid() != GLOBAL_ZONEID) { 12125331Samw (void) fprintf(stderr, 12135331Samw gettext("cannot execute in non-global zone\n")); 12145331Samw return (0); 12155331Samw } 12165331Samw 12175331Samw if (is_system_labeled()) { 12185331Samw (void) fprintf(stderr, 12195331Samw gettext("Trusted Extensions not supported\n")); 12205331Samw return (0); 12215331Samw } 12225331Samw 12235331Samw if (argc < 2) { 12245331Samw (void) fprintf(stderr, gettext("missing command\n")); 12255331Samw smbadm_usage(B_FALSE); 12265331Samw } 12275331Samw 12285331Samw /* 12295331Samw * Special case "cmd --help/-?" 12305331Samw */ 12315331Samw if (strcmp(argv[1], "-?") == 0 || 12325331Samw strcmp(argv[1], "--help") == 0 || 12335331Samw strcmp(argv[1], "-h") == 0) 12345331Samw smbadm_usage(B_TRUE); 12355331Samw 12365331Samw for (i = 0; i < SMBADM_NCMD; ++i) { 12375331Samw curcmd = &smbadm_cmdtable[i]; 12385331Samw if (strcasecmp(argv[1], curcmd->name) == 0) { 12395331Samw if (argc > 2) { 12405331Samw /* cmd subcmd --help/-? */ 12415331Samw if (strcmp(argv[2], "-?") == 0 || 12425331Samw strcmp(argv[2], "--help") == 0 || 12435331Samw strcmp(argv[2], "-h") == 0) 12445331Samw smbadm_usage(B_TRUE); 12455331Samw } 12465331Samw 12477052Samw if ((ret = smbadm_init()) != 0) 12486139Sjb150015 return (ret); 12495772Sas200622 12505772Sas200622 ret = curcmd->func(argc - 1, &argv[1]); 12516139Sjb150015 12527052Samw smbadm_fini(); 12535772Sas200622 return (ret); 12545331Samw } 12555331Samw } 12565331Samw 12575331Samw curcmd = NULL; 12585331Samw (void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]); 12595331Samw smbadm_usage(B_FALSE); 12605331Samw return (2); 12615331Samw } 12625331Samw 12636139Sjb150015 static int 12647052Samw smbadm_init(void) 12656139Sjb150015 { 12666139Sjb150015 int rc; 12676139Sjb150015 12687052Samw switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 12697052Samw case SMBADM_CMDF_GROUP: 12706139Sjb150015 if (smb_idmap_start() != 0) { 12716139Sjb150015 (void) fprintf(stderr, 12726139Sjb150015 gettext("failed to contact idmap service\n")); 12736139Sjb150015 return (1); 12746139Sjb150015 } 12756139Sjb150015 12766139Sjb150015 if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { 12776139Sjb150015 (void) fprintf(stderr, 12786139Sjb150015 gettext("failed to initialize (%s)\n"), 12796139Sjb150015 smb_lgrp_strerror(rc)); 12806139Sjb150015 smb_idmap_stop(); 12816139Sjb150015 return (1); 12826139Sjb150015 } 12837052Samw break; 12847052Samw 12857052Samw case SMBADM_CMDF_USER: 12867052Samw smb_pwd_init(B_FALSE); 12877052Samw break; 12887052Samw 12897052Samw default: 12907052Samw break; 12916139Sjb150015 } 12926139Sjb150015 12936139Sjb150015 return (0); 12946139Sjb150015 } 12956139Sjb150015 12966139Sjb150015 static void 12977052Samw smbadm_fini(void) 12986139Sjb150015 { 12997052Samw switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 13007052Samw case SMBADM_CMDF_GROUP: 13016139Sjb150015 smb_lgrp_stop(); 13026139Sjb150015 smb_idmap_stop(); 13037052Samw break; 13047052Samw 13057052Samw case SMBADM_CMDF_USER: 13067052Samw smb_pwd_fini(); 13077052Samw break; 13087052Samw 13097052Samw default: 13107052Samw break; 13116139Sjb150015 } 13126139Sjb150015 } 13136139Sjb150015 13145331Samw static boolean_t 13155331Samw smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 13165331Samw { 13175331Samw smbadm_prop_handle_t *pinfo; 13185331Samw int i; 13195331Samw 13205331Samw for (i = 0; i < SMBADM_NPROP; i++) { 13215331Samw pinfo = &smbadm_ptable[i]; 13225331Samw if (strcmp(pinfo->p_name, prop->p_name) == 0) { 13235331Samw if (pinfo->p_chkfn && chkval) 13245331Samw return (pinfo->p_chkfn(prop)); 13255331Samw 13265331Samw return (B_TRUE); 13275331Samw } 13285331Samw } 13295331Samw 13305331Samw (void) fprintf(stderr, 13315331Samw gettext("unrecognized property '%s'\n"), prop->p_name); 13325331Samw 13335331Samw return (B_FALSE); 13345331Samw } 13355331Samw 13365331Samw static int 13375331Samw smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 13385331Samw { 13395331Samw boolean_t parse_value; 13405331Samw char *equal; 13415331Samw 13425331Samw if (arg == NULL) 13435331Samw return (2); 13445331Samw 13455331Samw prop->p_name = prop->p_value = NULL; 13465331Samw 13475331Samw if (strcmp(curcmd->name, "set") == 0) 13485331Samw parse_value = B_TRUE; 13495331Samw else 13505331Samw parse_value = B_FALSE; 13515331Samw 13525331Samw prop->p_name = arg; 13535331Samw 13545331Samw if (parse_value) { 13555331Samw equal = strchr(arg, '='); 13565331Samw if (equal == NULL) 13575331Samw return (2); 13585331Samw 13595331Samw *equal++ = '\0'; 13605331Samw prop->p_value = equal; 13615331Samw } 13625331Samw 13635331Samw if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 13645331Samw return (2); 13655331Samw 13665331Samw return (0); 13675331Samw } 13685331Samw 13695331Samw static smbadm_prop_handle_t * 13705331Samw smbadm_prop_gethandle(char *pname) 13715331Samw { 13725331Samw int i; 13735331Samw 13745331Samw for (i = 0; i < SMBADM_NPROP; i++) 13755331Samw if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 13765331Samw return (&smbadm_ptable[i]); 13775331Samw 13785331Samw return (NULL); 13795331Samw } 13805331Samw 13815331Samw static int 13825331Samw smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 13835331Samw { 13845772Sas200622 int status; 13855331Samw 13865772Sas200622 status = smb_lgrp_setcmnt(gname, prop->p_value); 13875772Sas200622 if (status != SMB_LGRP_SUCCESS) { 13885331Samw (void) fprintf(stderr, 13895331Samw gettext("failed to modify the group description (%s)\n"), 13905772Sas200622 smb_lgrp_strerror(status)); 13915331Samw return (1); 13925331Samw } 13935331Samw 13945331Samw (void) printf(gettext("Successfully modified " 13955331Samw "'%s' description\n"), gname); 13965331Samw 13975331Samw return (0); 13985331Samw } 13995331Samw 14005331Samw static int 14015331Samw smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 14025331Samw { 14035772Sas200622 char *cmnt = NULL; 14045772Sas200622 int status; 14055331Samw 14065772Sas200622 status = smb_lgrp_getcmnt(gname, &cmnt); 14075772Sas200622 if (status != SMB_LGRP_SUCCESS) { 14085331Samw (void) fprintf(stderr, 14095772Sas200622 gettext("failed to get the group description (%s)\n"), 14105772Sas200622 smb_lgrp_strerror(status)); 14115331Samw return (1); 14125331Samw } 14135331Samw 14145772Sas200622 (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); 14155772Sas200622 free(cmnt); 14165331Samw return (0); 14175331Samw } 14185331Samw 14195331Samw static int 14205772Sas200622 smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 14215331Samw { 14225772Sas200622 boolean_t enable; 14235772Sas200622 int status; 14245331Samw int ret; 14255331Samw 14265331Samw if (strcasecmp(prop->p_value, "on") == 0) { 14275331Samw (void) printf(gettext("Enabling %s privilege "), prop->p_name); 14285772Sas200622 enable = B_TRUE; 14295331Samw } else { 14305331Samw (void) printf(gettext("Disabling %s privilege "), prop->p_name); 14315772Sas200622 enable = B_FALSE; 14325331Samw } 14335331Samw 14345772Sas200622 status = smb_lgrp_setpriv(gname, priv_id, enable); 14355772Sas200622 if (status == SMB_LGRP_SUCCESS) { 14365331Samw (void) printf(gettext("succeeded\n")); 14375331Samw ret = 0; 14385331Samw } else { 14395772Sas200622 (void) printf(gettext("failed: %s\n"), 14405772Sas200622 smb_lgrp_strerror(status)); 14415331Samw ret = 1; 14425331Samw } 14435331Samw 14445331Samw return (ret); 14455331Samw } 14465331Samw 14475331Samw static int 14485772Sas200622 smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 14495331Samw { 14505772Sas200622 boolean_t enable; 14515772Sas200622 int status; 14525331Samw 14535772Sas200622 status = smb_lgrp_getpriv(gname, priv_id, &enable); 14545772Sas200622 if (status != SMB_LGRP_SUCCESS) { 14555331Samw (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 14565772Sas200622 prop->p_name, smb_lgrp_strerror(status)); 14575331Samw return (1); 14585331Samw } 14595331Samw 14605772Sas200622 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 14615772Sas200622 (enable) ? "On" : "Off"); 14625331Samw 14635331Samw return (0); 14645331Samw } 14655331Samw 14665331Samw static int 14675331Samw smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 14685331Samw { 14695331Samw return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 14705331Samw } 14715331Samw 14725331Samw static int 14735331Samw smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 14745331Samw { 14755331Samw return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 14765331Samw } 14775331Samw 14785331Samw static int 14795331Samw smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 14805331Samw { 14815331Samw return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 14825331Samw } 14835331Samw 14845331Samw static int 14855331Samw smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 14865331Samw { 14875331Samw return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 14885331Samw } 14895331Samw 14905331Samw static int 14915331Samw smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 14925331Samw { 14935331Samw return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 14945331Samw } 14955331Samw 14965331Samw static int 14975331Samw smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 14985331Samw { 14995331Samw return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 15005331Samw } 15015331Samw 15025331Samw static boolean_t 15035331Samw smbadm_chkprop_priv(smbadm_prop_t *prop) 15045331Samw { 15055331Samw if (prop->p_value == NULL || *prop->p_value == '\0') { 15065331Samw (void) fprintf(stderr, 15075331Samw gettext("missing value for '%s'\n"), prop->p_name); 15085331Samw return (B_FALSE); 15095331Samw } 15105331Samw 15115331Samw if (strcasecmp(prop->p_value, "on") == 0) 15125331Samw return (B_TRUE); 15135331Samw 15145331Samw if (strcasecmp(prop->p_value, "off") == 0) 15155331Samw return (B_TRUE); 15165331Samw 15175331Samw (void) fprintf(stderr, 15185331Samw gettext("%s: unrecognized value for '%s' property\n"), 15195331Samw prop->p_value, prop->p_name); 15205331Samw 15215331Samw return (B_FALSE); 15225331Samw } 15235331Samw 15245331Samw static const char * 15255331Samw smbadm_pwd_strerror(int error) 15265331Samw { 15275331Samw switch (error) { 15285331Samw case SMB_PWE_SUCCESS: 15295331Samw return (gettext("Success.")); 15305331Samw 15315331Samw case SMB_PWE_USER_UNKNOWN: 15325331Samw return (gettext("User does not exist.")); 15335331Samw 15345331Samw case SMB_PWE_USER_DISABLE: 15355331Samw return (gettext("User is disable.")); 15365331Samw 15375331Samw case SMB_PWE_CLOSE_FAILED: 15385331Samw case SMB_PWE_OPEN_FAILED: 15395331Samw case SMB_PWE_WRITE_FAILED: 15405331Samw case SMB_PWE_UPDATE_FAILED: 15415331Samw return (gettext("Unexpected failure. " 15425331Samw "SMB password database unchanged.")); 15435331Samw 15445331Samw case SMB_PWE_STAT_FAILED: 15455331Samw return (gettext("stat of SMB password file failed.")); 15465331Samw 15475331Samw case SMB_PWE_BUSY: 15485331Samw return (gettext("SMB password database busy. " 15495331Samw "Try again later.")); 15505331Samw 15515331Samw case SMB_PWE_DENIED: 15525331Samw return (gettext("Operation not permitted.")); 15535331Samw 15545331Samw case SMB_PWE_SYSTEM_ERROR: 15555331Samw return (gettext("System error.")); 15567052Samw 15577052Samw default: 15587052Samw break; 15595331Samw } 15605331Samw 15615331Samw return (gettext("Unknown error code.")); 15625331Samw } 15635331Samw 15645331Samw /* 15655331Samw * Enable libumem debugging by default on DEBUG builds. 15665331Samw */ 15675331Samw #ifdef DEBUG 15685331Samw const char * 15695331Samw _umem_debug_init(void) 15705331Samw { 15715331Samw return ("default,verbose"); /* $UMEM_DEBUG setting */ 15725331Samw } 15735331Samw 15745331Samw const char * 15755331Samw _umem_logging_init(void) 15765331Samw { 15775331Samw return ("fail,contents"); /* $UMEM_LOGGING setting */ 15785331Samw } 15795331Samw #endif 1580