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 /* 228474SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw /* 275331Samw * This module contains smbadm CLI which offers smb configuration 285331Samw * functionalities. 295331Samw */ 308334SJose.Borrego@Sun.COM #include <errno.h> 318334SJose.Borrego@Sun.COM #include <err.h> 328334SJose.Borrego@Sun.COM #include <ctype.h> 335331Samw #include <stdlib.h> 345331Samw #include <stdio.h> 355331Samw #include <syslog.h> 365331Samw #include <strings.h> 375331Samw #include <limits.h> 385331Samw #include <getopt.h> 395331Samw #include <libintl.h> 405331Samw #include <zone.h> 415331Samw #include <grp.h> 425331Samw #include <libgen.h> 437348SJose.Borrego@Sun.COM #include <netinet/in.h> 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 657348SJose.Borrego@Sun.COM #define SMBADM_ANSBUFSIZ 64 667348SJose.Borrego@Sun.COM 675331Samw typedef struct smbadm_cmdinfo { 685331Samw char *name; 695331Samw int (*func)(int, char **); 705331Samw smbadm_help_t usage; 716139Sjb150015 uint32_t flags; 725331Samw } smbadm_cmdinfo_t; 735331Samw 745331Samw smbadm_cmdinfo_t *curcmd; 755331Samw static char *progname; 765331Samw 778334SJose.Borrego@Sun.COM static void smbadm_usage(boolean_t); 788334SJose.Borrego@Sun.COM static int smbadm_join_workgroup(const char *); 798334SJose.Borrego@Sun.COM static int smbadm_join_domain(const char *, const char *); 808334SJose.Borrego@Sun.COM static boolean_t smbadm_valid_domainname(const char *); 818334SJose.Borrego@Sun.COM static boolean_t smbadm_valid_username(const char *); 828334SJose.Borrego@Sun.COM static boolean_t smbadm_valid_workgroup(const char *); 838334SJose.Borrego@Sun.COM static void smbadm_extract_domain(char *, char **, char **); 848334SJose.Borrego@Sun.COM 855331Samw static int smbadm_join(int, char **); 865331Samw static int smbadm_list(int, char **); 875331Samw static int smbadm_group_create(int, char **); 885331Samw static int smbadm_group_delete(int, char **); 895331Samw static int smbadm_group_rename(int, char **); 905331Samw static int smbadm_group_show(int, char **); 915331Samw static int smbadm_group_getprop(int, char **); 925331Samw static int smbadm_group_setprop(int, char **); 935331Samw static int smbadm_group_addmember(int, char **); 945331Samw static int smbadm_group_delmember(int, char **); 955331Samw static int smbadm_user_disable(int, char **); 965331Samw static int smbadm_user_enable(int, char **); 975331Samw 985331Samw static smbadm_cmdinfo_t smbadm_cmdtable[] = 995331Samw { 1006139Sjb150015 { "add-member", smbadm_group_addmember, HELP_ADD_MEMBER, 1016139Sjb150015 SMBADM_CMDF_GROUP }, 1026139Sjb150015 { "create", smbadm_group_create, HELP_CREATE, 1036139Sjb150015 SMBADM_CMDF_GROUP }, 1046139Sjb150015 { "delete", smbadm_group_delete, HELP_DELETE, 1056139Sjb150015 SMBADM_CMDF_GROUP }, 1067052Samw { "disable-user", smbadm_user_disable, HELP_USER_DISABLE, 1077052Samw SMBADM_CMDF_USER }, 1087052Samw { "enable-user", smbadm_user_enable, HELP_USER_ENABLE, 1097052Samw SMBADM_CMDF_USER }, 1106139Sjb150015 { "get", smbadm_group_getprop, HELP_GET, 1116139Sjb150015 SMBADM_CMDF_GROUP }, 1126139Sjb150015 { "join", smbadm_join, HELP_JOIN, 0 }, 1136139Sjb150015 { "list", smbadm_list, HELP_LIST, 0 }, 1146139Sjb150015 { "remove-member", smbadm_group_delmember, HELP_DEL_MEMBER, 1156139Sjb150015 SMBADM_CMDF_GROUP }, 1166139Sjb150015 { "rename", smbadm_group_rename, HELP_RENAME, 1176139Sjb150015 SMBADM_CMDF_GROUP }, 1186139Sjb150015 { "set", smbadm_group_setprop, HELP_SET, 1196139Sjb150015 SMBADM_CMDF_GROUP }, 1206139Sjb150015 { "show", smbadm_group_show, HELP_SHOW, 1216139Sjb150015 SMBADM_CMDF_GROUP }, 1225331Samw }; 1235331Samw 1245331Samw #define SMBADM_NCMD (sizeof (smbadm_cmdtable) / sizeof (smbadm_cmdtable[0])) 1255331Samw 1265331Samw typedef struct smbadm_prop { 1275331Samw char *p_name; 1285331Samw char *p_value; 1295331Samw } smbadm_prop_t; 1305331Samw 1315331Samw typedef struct smbadm_prop_handle { 1325331Samw char *p_name; 1335331Samw char *p_dispvalue; 1345331Samw int (*p_setfn)(char *, smbadm_prop_t *); 1355331Samw int (*p_getfn)(char *, smbadm_prop_t *); 1365331Samw boolean_t (*p_chkfn)(smbadm_prop_t *); 1375331Samw } smbadm_prop_handle_t; 1385331Samw 1395331Samw static boolean_t smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval); 1405331Samw static int smbadm_prop_parse(char *arg, smbadm_prop_t *prop); 1415331Samw static smbadm_prop_handle_t *smbadm_prop_gethandle(char *pname); 1425331Samw 1435331Samw static boolean_t smbadm_chkprop_priv(smbadm_prop_t *prop); 1445331Samw static int smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop); 1455331Samw static int smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop); 1465331Samw static int smbadm_setprop_backup(char *gname, smbadm_prop_t *prop); 1475331Samw static int smbadm_getprop_backup(char *gname, smbadm_prop_t *prop); 1485331Samw static int smbadm_setprop_restore(char *gname, smbadm_prop_t *prop); 1495331Samw static int smbadm_getprop_restore(char *gname, smbadm_prop_t *prop); 1505331Samw static int smbadm_setprop_desc(char *gname, smbadm_prop_t *prop); 1515331Samw static int smbadm_getprop_desc(char *gname, smbadm_prop_t *prop); 1525331Samw 1535331Samw static smbadm_prop_handle_t smbadm_ptable[] = { 1545331Samw {"backup", "on | off", smbadm_setprop_backup, 1555331Samw smbadm_getprop_backup, smbadm_chkprop_priv }, 1565331Samw {"restore", "on | off", smbadm_setprop_restore, 1575331Samw smbadm_getprop_restore, smbadm_chkprop_priv }, 1585331Samw {"take-ownership", "on | off", smbadm_setprop_tkowner, 1595331Samw smbadm_getprop_tkowner, smbadm_chkprop_priv }, 1605331Samw {"description", "<string>", smbadm_setprop_desc, 1615331Samw smbadm_getprop_desc, NULL }, 1625331Samw }; 1635331Samw 1647052Samw static int smbadm_init(void); 1657052Samw static void smbadm_fini(void); 1665331Samw static const char *smbadm_pwd_strerror(int error); 1675331Samw 1685331Samw /* 1695331Samw * Number of supported properties 1705331Samw */ 1715331Samw #define SMBADM_NPROP (sizeof (smbadm_ptable) / sizeof (smbadm_ptable[0])) 1725331Samw 1735331Samw static void 1745331Samw smbadm_cmdusage(FILE *fp, smbadm_cmdinfo_t *cmd) 1755331Samw { 1765331Samw switch (cmd->usage) { 1775331Samw case HELP_ADD_MEMBER: 1785331Samw (void) fprintf(fp, 1795331Samw gettext("\t%s -m member [[-m member] ...] group\n"), 1805331Samw cmd->name); 1815331Samw return; 1825331Samw 1835331Samw case HELP_CREATE: 1845331Samw (void) fprintf(fp, gettext("\t%s [-d description] group\n"), 1855331Samw cmd->name); 1865331Samw return; 1875331Samw 1885331Samw case HELP_DELETE: 1895331Samw (void) fprintf(fp, gettext("\t%s group\n"), cmd->name); 1905331Samw return; 1915331Samw 1927052Samw case HELP_USER_DISABLE: 1937052Samw case HELP_USER_ENABLE: 1945331Samw (void) fprintf(fp, gettext("\t%s user\n"), cmd->name); 1955331Samw return; 1965331Samw 1975331Samw case HELP_GET: 1985331Samw (void) fprintf(fp, gettext("\t%s [[-p property] ...] group\n"), 1995331Samw cmd->name); 2005331Samw return; 2015331Samw 2025331Samw case HELP_JOIN: 2035331Samw (void) fprintf(fp, gettext("\t%s -u username domain\n" 2045331Samw "\t%s -w workgroup\n"), cmd->name, cmd->name); 2055331Samw return; 2065331Samw 2075331Samw case HELP_LIST: 2085331Samw (void) fprintf(fp, gettext("\t%s\n"), cmd->name); 2098474SJose.Borrego@Sun.COM (void) fprintf(fp, 2108474SJose.Borrego@Sun.COM gettext("\t\t[*] primary domain\n")); 2118474SJose.Borrego@Sun.COM (void) fprintf(fp, gettext("\t\t[.] local domain\n")); 2128474SJose.Borrego@Sun.COM (void) fprintf(fp, gettext("\t\t[-] other domains\n")); 2138474SJose.Borrego@Sun.COM (void) fprintf(fp, 2148474SJose.Borrego@Sun.COM gettext("\t\t[+] selected domain controller\n")); 2155331Samw return; 2165331Samw 2175331Samw case HELP_DEL_MEMBER: 2185331Samw (void) fprintf(fp, 2195331Samw gettext("\t%s -m member [[-m member] ...] group\n"), 2205331Samw cmd->name); 2215331Samw return; 2225331Samw 2235331Samw case HELP_RENAME: 2245331Samw (void) fprintf(fp, gettext("\t%s group new-group\n"), 2255331Samw cmd->name); 2265331Samw return; 2275331Samw 2285331Samw case HELP_SET: 2295331Samw (void) fprintf(fp, gettext("\t%s -p property=value " 2305331Samw "[[-p property=value] ...] group\n"), cmd->name); 2315331Samw return; 2325331Samw 2335331Samw case HELP_SHOW: 2345331Samw (void) fprintf(fp, gettext("\t%s [-m] [-p] [group]\n"), 2355331Samw cmd->name); 2365331Samw return; 2375331Samw 2387052Samw default: 2397052Samw break; 2405331Samw } 2415331Samw 2425331Samw abort(); 2435331Samw /* NOTREACHED */ 2445331Samw } 2455331Samw 2465331Samw static void 2475331Samw smbadm_usage(boolean_t requested) 2485331Samw { 2495331Samw FILE *fp = requested ? stdout : stderr; 2505331Samw boolean_t show_props = B_FALSE; 2515331Samw int i; 2525331Samw 2535331Samw if (curcmd == NULL) { 2545331Samw (void) fprintf(fp, 2555331Samw gettext("usage: %s [-h | <command> [options]]\n"), 2565331Samw progname); 2575331Samw (void) fprintf(fp, 2585331Samw gettext("where 'command' is one of the following:\n\n")); 2595331Samw 2605331Samw for (i = 0; i < SMBADM_NCMD; i++) 2615331Samw smbadm_cmdusage(fp, &smbadm_cmdtable[i]); 2625331Samw 2635331Samw (void) fprintf(fp, 2645331Samw gettext("\nFor property list, run %s %s|%s\n"), 2655331Samw progname, "get", "set"); 2665331Samw 2675331Samw exit(requested ? 0 : 2); 2685331Samw } 2695331Samw 2705331Samw (void) fprintf(fp, gettext("usage:\n")); 2715331Samw smbadm_cmdusage(fp, curcmd); 2725331Samw 2735331Samw if (strcmp(curcmd->name, "get") == 0 || 2745331Samw strcmp(curcmd->name, "set") == 0) 2755331Samw show_props = B_TRUE; 2765331Samw 2775331Samw if (show_props) { 2785331Samw (void) fprintf(fp, 2795331Samw gettext("\nThe following properties are supported:\n")); 2805331Samw 2815331Samw (void) fprintf(fp, "\n\t%-16s %s\n\n", 2825331Samw "PROPERTY", "VALUES"); 2835331Samw 2845331Samw for (i = 0; i < SMBADM_NPROP; i++) { 2855331Samw (void) fprintf(fp, "\t%-16s %s\n", 2865331Samw smbadm_ptable[i].p_name, 2875331Samw smbadm_ptable[i].p_dispvalue); 2885331Samw } 2895331Samw } 2905331Samw 2915331Samw exit(requested ? 0 : 2); 2925331Samw } 2935331Samw 2945331Samw /* 2957348SJose.Borrego@Sun.COM * smbadm_strcasecmplist 2967348SJose.Borrego@Sun.COM * 2977348SJose.Borrego@Sun.COM * Find a string 's' within a list of strings. 2987348SJose.Borrego@Sun.COM * 2997348SJose.Borrego@Sun.COM * Returns the index of the matching string or -1 if there is no match. 3007348SJose.Borrego@Sun.COM */ 3017348SJose.Borrego@Sun.COM static int 3027348SJose.Borrego@Sun.COM smbadm_strcasecmplist(const char *s, ...) 3037348SJose.Borrego@Sun.COM { 3047348SJose.Borrego@Sun.COM va_list ap; 3057348SJose.Borrego@Sun.COM char *p; 3067348SJose.Borrego@Sun.COM int ndx; 3077348SJose.Borrego@Sun.COM 3087348SJose.Borrego@Sun.COM va_start(ap, s); 3097348SJose.Borrego@Sun.COM 3107348SJose.Borrego@Sun.COM for (ndx = 0; ((p = va_arg(ap, char *)) != NULL); ++ndx) { 3117348SJose.Borrego@Sun.COM if (strcasecmp(s, p) == 0) { 3127348SJose.Borrego@Sun.COM va_end(ap); 3137348SJose.Borrego@Sun.COM return (ndx); 3147348SJose.Borrego@Sun.COM } 3157348SJose.Borrego@Sun.COM } 3167348SJose.Borrego@Sun.COM 3177348SJose.Borrego@Sun.COM va_end(ap); 3187348SJose.Borrego@Sun.COM return (-1); 3197348SJose.Borrego@Sun.COM } 3207348SJose.Borrego@Sun.COM 3217348SJose.Borrego@Sun.COM /* 3227348SJose.Borrego@Sun.COM * smbadm_answer_prompt 3237348SJose.Borrego@Sun.COM * 3247348SJose.Borrego@Sun.COM * Prompt for the answer to a question. A default response must be 3257348SJose.Borrego@Sun.COM * specified, which will be used if the user presses <enter> without 3267348SJose.Borrego@Sun.COM * answering the question. 3277348SJose.Borrego@Sun.COM */ 3287348SJose.Borrego@Sun.COM static int 3297348SJose.Borrego@Sun.COM smbadm_answer_prompt(const char *prompt, char *answer, const char *dflt) 3307348SJose.Borrego@Sun.COM { 3317348SJose.Borrego@Sun.COM char buf[SMBADM_ANSBUFSIZ]; 3327348SJose.Borrego@Sun.COM char *p; 3337348SJose.Borrego@Sun.COM 3347348SJose.Borrego@Sun.COM (void) printf(gettext("%s [%s]: "), prompt, dflt); 3357348SJose.Borrego@Sun.COM 3367348SJose.Borrego@Sun.COM if (fgets(buf, SMBADM_ANSBUFSIZ, stdin) == NULL) 3377348SJose.Borrego@Sun.COM return (-1); 3387348SJose.Borrego@Sun.COM 3397348SJose.Borrego@Sun.COM if ((p = strchr(buf, '\n')) != NULL) 3407348SJose.Borrego@Sun.COM *p = '\0'; 3417348SJose.Borrego@Sun.COM 3427348SJose.Borrego@Sun.COM if (*buf == '\0') 3437348SJose.Borrego@Sun.COM (void) strlcpy(answer, dflt, SMBADM_ANSBUFSIZ); 3447348SJose.Borrego@Sun.COM else 3457348SJose.Borrego@Sun.COM (void) strlcpy(answer, buf, SMBADM_ANSBUFSIZ); 3467348SJose.Borrego@Sun.COM 3477348SJose.Borrego@Sun.COM return (0); 3487348SJose.Borrego@Sun.COM } 3497348SJose.Borrego@Sun.COM 3507348SJose.Borrego@Sun.COM /* 3517348SJose.Borrego@Sun.COM * smbadm_confirm 3527348SJose.Borrego@Sun.COM * 3537348SJose.Borrego@Sun.COM * Ask a question that requires a yes/no answer. 3547348SJose.Borrego@Sun.COM * A default response must be specified. 3557348SJose.Borrego@Sun.COM */ 3567348SJose.Borrego@Sun.COM static boolean_t 3577348SJose.Borrego@Sun.COM smbadm_confirm(const char *prompt, const char *dflt) 3587348SJose.Borrego@Sun.COM { 3597348SJose.Borrego@Sun.COM char buf[SMBADM_ANSBUFSIZ]; 3607348SJose.Borrego@Sun.COM 3617348SJose.Borrego@Sun.COM for (;;) { 3627348SJose.Borrego@Sun.COM if (smbadm_answer_prompt(prompt, buf, dflt) < 0) 3637348SJose.Borrego@Sun.COM return (B_FALSE); 3647348SJose.Borrego@Sun.COM 3657348SJose.Borrego@Sun.COM if (smbadm_strcasecmplist(buf, "n", "no", 0) >= 0) 3667348SJose.Borrego@Sun.COM return (B_FALSE); 3677348SJose.Borrego@Sun.COM 3687348SJose.Borrego@Sun.COM if (smbadm_strcasecmplist(buf, "y", "yes", 0) >= 0) 3697348SJose.Borrego@Sun.COM return (B_TRUE); 3707348SJose.Borrego@Sun.COM 3717348SJose.Borrego@Sun.COM (void) printf(gettext("Please answer yes or no.\n")); 3727348SJose.Borrego@Sun.COM } 3737348SJose.Borrego@Sun.COM } 3747348SJose.Borrego@Sun.COM 3757348SJose.Borrego@Sun.COM static boolean_t 3768334SJose.Borrego@Sun.COM smbadm_join_prompt(const char *domain) 3777348SJose.Borrego@Sun.COM { 3788334SJose.Borrego@Sun.COM (void) printf(gettext("After joining %s the smb service will be " 3798334SJose.Borrego@Sun.COM "restarted automatically.\n"), domain); 3807348SJose.Borrego@Sun.COM 3818334SJose.Borrego@Sun.COM return (smbadm_confirm("Would you like to continue?", "no")); 3828334SJose.Borrego@Sun.COM } 3837348SJose.Borrego@Sun.COM 3848334SJose.Borrego@Sun.COM static void 3858334SJose.Borrego@Sun.COM smbadm_restart_service(void) 3868334SJose.Borrego@Sun.COM { 3878334SJose.Borrego@Sun.COM if (smb_smf_restart_service() != 0) { 3888334SJose.Borrego@Sun.COM (void) fprintf(stderr, 3898334SJose.Borrego@Sun.COM gettext("Unable to restart smb service. " 3908334SJose.Borrego@Sun.COM "Run 'svcs -xv smb/server' for more information.")); 3917348SJose.Borrego@Sun.COM } 3927348SJose.Borrego@Sun.COM } 3937348SJose.Borrego@Sun.COM 3947348SJose.Borrego@Sun.COM /* 3955331Samw * smbadm_join 3965331Samw * 3978334SJose.Borrego@Sun.COM * Join a domain or workgroup. 3988334SJose.Borrego@Sun.COM * 3998334SJose.Borrego@Sun.COM * When joining a domain, we may receive the username, password and 4008334SJose.Borrego@Sun.COM * domain name in any of the following combinations. Note that the 4018334SJose.Borrego@Sun.COM * password is optional on the command line: if it is not provided, 4028334SJose.Borrego@Sun.COM * we will prompt for it later. 4038334SJose.Borrego@Sun.COM * 4048334SJose.Borrego@Sun.COM * username+password domain 4058334SJose.Borrego@Sun.COM * domain\username+password 4068334SJose.Borrego@Sun.COM * domain/username+password 4078334SJose.Borrego@Sun.COM * username@domain 4088334SJose.Borrego@Sun.COM * 4098334SJose.Borrego@Sun.COM * We allow domain\name+password or domain/name+password but not 4108334SJose.Borrego@Sun.COM * name+password@domain because @ is a valid password character. 4118334SJose.Borrego@Sun.COM * 4128334SJose.Borrego@Sun.COM * If the username and domain name are passed as separate command 4138334SJose.Borrego@Sun.COM * line arguments, we process them directly. Otherwise we separate 4148334SJose.Borrego@Sun.COM * them and continue as if they were separate command line arguments. 4155331Samw */ 4165331Samw static int 4175331Samw smbadm_join(int argc, char **argv) 4185331Samw { 4198334SJose.Borrego@Sun.COM char buf[MAXHOSTNAMELEN * 2]; 4208334SJose.Borrego@Sun.COM char *domain = NULL; 4218334SJose.Borrego@Sun.COM char *username = NULL; 4228334SJose.Borrego@Sun.COM uint32_t mode = 0; 4235331Samw char option; 4245331Samw 4255331Samw while ((option = getopt(argc, argv, "u:w:")) != -1) { 4265331Samw switch (option) { 4275331Samw case 'w': 4288334SJose.Borrego@Sun.COM if (mode != 0) { 4298334SJose.Borrego@Sun.COM (void) fprintf(stderr, 4308334SJose.Borrego@Sun.COM gettext("-u and -w must only appear " 4318334SJose.Borrego@Sun.COM "once and are mutually exclusive\n")); 4328334SJose.Borrego@Sun.COM smbadm_usage(B_FALSE); 4338334SJose.Borrego@Sun.COM } 4348334SJose.Borrego@Sun.COM 4358334SJose.Borrego@Sun.COM mode = SMB_SECMODE_WORKGRP; 4368334SJose.Borrego@Sun.COM domain = optarg; 4375331Samw break; 4385331Samw 4395331Samw case 'u': 4408334SJose.Borrego@Sun.COM if (mode != 0) { 4418334SJose.Borrego@Sun.COM (void) fprintf(stderr, 4428334SJose.Borrego@Sun.COM gettext("-u and -w must only appear " 4438334SJose.Borrego@Sun.COM "once and are mutually exclusive\n")); 4448334SJose.Borrego@Sun.COM smbadm_usage(B_FALSE); 4458334SJose.Borrego@Sun.COM } 4468334SJose.Borrego@Sun.COM 4478334SJose.Borrego@Sun.COM mode = SMB_SECMODE_DOMAIN; 4488334SJose.Borrego@Sun.COM username = optarg; 4498334SJose.Borrego@Sun.COM 4508334SJose.Borrego@Sun.COM if ((domain = argv[optind]) == NULL) { 4518334SJose.Borrego@Sun.COM /* 4528334SJose.Borrego@Sun.COM * The domain was not specified as a separate 4538334SJose.Borrego@Sun.COM * argument, check for the combination forms. 4548334SJose.Borrego@Sun.COM */ 4558334SJose.Borrego@Sun.COM (void) strlcpy(buf, username, sizeof (buf)); 4568334SJose.Borrego@Sun.COM smbadm_extract_domain(buf, &username, &domain); 4578334SJose.Borrego@Sun.COM } 4588334SJose.Borrego@Sun.COM 4598334SJose.Borrego@Sun.COM if ((username == NULL) || (*username == '\0')) { 4608334SJose.Borrego@Sun.COM (void) fprintf(stderr, 4618334SJose.Borrego@Sun.COM gettext("missing username\n")); 4628334SJose.Borrego@Sun.COM smbadm_usage(B_FALSE); 4638334SJose.Borrego@Sun.COM } 4645331Samw break; 4655331Samw 4665331Samw default: 4675331Samw smbadm_usage(B_FALSE); 4688334SJose.Borrego@Sun.COM break; 4695331Samw } 4705331Samw } 4715331Samw 4728334SJose.Borrego@Sun.COM if ((domain == NULL) || (*domain == '\0')) { 4738334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("missing %s name\n"), 4748334SJose.Borrego@Sun.COM (mode == SMB_SECMODE_WORKGRP) ? "workgroup" : "domain"); 4755331Samw smbadm_usage(B_FALSE); 4765331Samw } 4775331Samw 4788334SJose.Borrego@Sun.COM if (mode == SMB_SECMODE_WORKGRP) 4798334SJose.Borrego@Sun.COM return (smbadm_join_workgroup(domain)); 4808334SJose.Borrego@Sun.COM else 4818334SJose.Borrego@Sun.COM return (smbadm_join_domain(domain, username)); 4828334SJose.Borrego@Sun.COM } 4835331Samw 4848334SJose.Borrego@Sun.COM /* 4858334SJose.Borrego@Sun.COM * Workgroups comprise a collection of standalone, independently administered 4868334SJose.Borrego@Sun.COM * computers that use a common workgroup name. This is a peer-to-peer model 4878334SJose.Borrego@Sun.COM * with no formal membership mechanism. 4888334SJose.Borrego@Sun.COM */ 4898334SJose.Borrego@Sun.COM static int 4908334SJose.Borrego@Sun.COM smbadm_join_workgroup(const char *workgroup) 4918334SJose.Borrego@Sun.COM { 4928334SJose.Borrego@Sun.COM smb_joininfo_t jdi; 4938334SJose.Borrego@Sun.COM uint32_t status; 4945331Samw 4958334SJose.Borrego@Sun.COM bzero(&jdi, sizeof (jdi)); 4968334SJose.Borrego@Sun.COM jdi.mode = SMB_SECMODE_WORKGRP; 4978334SJose.Borrego@Sun.COM (void) strlcpy(jdi.domain_name, workgroup, sizeof (jdi.domain_name)); 4988334SJose.Borrego@Sun.COM (void) strtrim(jdi.domain_name, " \t\n"); 4998334SJose.Borrego@Sun.COM 5008334SJose.Borrego@Sun.COM if (!smbadm_valid_workgroup(jdi.domain_name)) { 5018334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("workgroup name is invalid\n")); 5025331Samw smbadm_usage(B_FALSE); 5035331Samw } 5045331Samw 5058334SJose.Borrego@Sun.COM if (!smbadm_join_prompt(jdi.domain_name)) 5068334SJose.Borrego@Sun.COM return (0); 5077348SJose.Borrego@Sun.COM 5088334SJose.Borrego@Sun.COM if ((status = smb_join(&jdi)) != NT_STATUS_SUCCESS) { 5098334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("failed to join %s: %s\n"), 5105331Samw jdi.domain_name, xlate_nt_status(status)); 5115331Samw return (1); 5125331Samw } 5135331Samw 5148334SJose.Borrego@Sun.COM (void) printf(gettext("Successfully joined %s\n"), jdi.domain_name); 5158334SJose.Borrego@Sun.COM smbadm_restart_service(); 5168334SJose.Borrego@Sun.COM return (0); 5178334SJose.Borrego@Sun.COM } 5188334SJose.Borrego@Sun.COM 5198334SJose.Borrego@Sun.COM /* 5208334SJose.Borrego@Sun.COM * Domains comprise a centrally administered group of computers and accounts 5218334SJose.Borrego@Sun.COM * that share a common security and administration policy and database. 5228334SJose.Borrego@Sun.COM * Computers must join a domain and become domain members, which requires 5238334SJose.Borrego@Sun.COM * an administrator level account name. 5248334SJose.Borrego@Sun.COM * 5258334SJose.Borrego@Sun.COM * The '+' character is invalid within a username. We allow the password 5268334SJose.Borrego@Sun.COM * to be appended to the username using '+' as a scripting convenience. 5278334SJose.Borrego@Sun.COM */ 5288334SJose.Borrego@Sun.COM static int 5298334SJose.Borrego@Sun.COM smbadm_join_domain(const char *domain, const char *username) 5308334SJose.Borrego@Sun.COM { 5318334SJose.Borrego@Sun.COM smb_joininfo_t jdi; 5328334SJose.Borrego@Sun.COM uint32_t status; 5338334SJose.Borrego@Sun.COM char *prompt; 5348334SJose.Borrego@Sun.COM char *p; 5358334SJose.Borrego@Sun.COM int len; 5368334SJose.Borrego@Sun.COM 5378334SJose.Borrego@Sun.COM bzero(&jdi, sizeof (jdi)); 5388334SJose.Borrego@Sun.COM jdi.mode = SMB_SECMODE_DOMAIN; 5398334SJose.Borrego@Sun.COM (void) strlcpy(jdi.domain_name, domain, sizeof (jdi.domain_name)); 5408334SJose.Borrego@Sun.COM (void) strtrim(jdi.domain_name, " \t\n"); 5418334SJose.Borrego@Sun.COM 5428334SJose.Borrego@Sun.COM if (!smbadm_valid_domainname(jdi.domain_name)) { 5438334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("domain name is invalid\n")); 5448334SJose.Borrego@Sun.COM smbadm_usage(B_FALSE); 5456139Sjb150015 } 5466139Sjb150015 5478334SJose.Borrego@Sun.COM if (!smbadm_join_prompt(jdi.domain_name)) 5488334SJose.Borrego@Sun.COM return (0); 5498334SJose.Borrego@Sun.COM 5508334SJose.Borrego@Sun.COM if ((p = strchr(username, '+')) != NULL) { 5518334SJose.Borrego@Sun.COM ++p; 5528334SJose.Borrego@Sun.COM 5538334SJose.Borrego@Sun.COM len = (int)(p - username); 5548334SJose.Borrego@Sun.COM if (len > sizeof (jdi.domain_name)) 5558334SJose.Borrego@Sun.COM len = sizeof (jdi.domain_name); 5567348SJose.Borrego@Sun.COM 5578334SJose.Borrego@Sun.COM (void) strlcpy(jdi.domain_username, username, len); 5588334SJose.Borrego@Sun.COM (void) strlcpy(jdi.domain_passwd, p, 5598334SJose.Borrego@Sun.COM sizeof (jdi.domain_passwd)); 5608334SJose.Borrego@Sun.COM } else { 5618334SJose.Borrego@Sun.COM (void) strlcpy(jdi.domain_username, username, 5628334SJose.Borrego@Sun.COM sizeof (jdi.domain_username)); 5638334SJose.Borrego@Sun.COM } 5648334SJose.Borrego@Sun.COM 5658334SJose.Borrego@Sun.COM if (!smbadm_valid_username(jdi.domain_username)) { 5668334SJose.Borrego@Sun.COM (void) fprintf(stderr, 5678334SJose.Borrego@Sun.COM gettext("username contains invalid characters\n")); 5688334SJose.Borrego@Sun.COM smbadm_usage(B_FALSE); 5698334SJose.Borrego@Sun.COM } 5708334SJose.Borrego@Sun.COM 5715331Samw if (*jdi.domain_passwd == '\0') { 5728334SJose.Borrego@Sun.COM prompt = gettext("Enter domain password: "); 5738334SJose.Borrego@Sun.COM 5748334SJose.Borrego@Sun.COM if ((p = getpassphrase(prompt)) == NULL) { 5755331Samw (void) fprintf(stderr, gettext("missing password\n")); 5765331Samw smbadm_usage(B_FALSE); 5775331Samw } 5785331Samw 5795331Samw (void) strlcpy(jdi.domain_passwd, p, 5805331Samw sizeof (jdi.domain_passwd)); 5815331Samw } 5825331Samw 5838334SJose.Borrego@Sun.COM (void) printf(gettext("Joining %s ... this may take a minute ...\n"), 5845331Samw jdi.domain_name); 5855331Samw 5865331Samw status = smb_join(&jdi); 5875331Samw 5885331Samw switch (status) { 5895331Samw case NT_STATUS_SUCCESS: 5908334SJose.Borrego@Sun.COM (void) printf(gettext("Successfully joined %s\n"), 5915331Samw jdi.domain_name); 5928334SJose.Borrego@Sun.COM bzero(&jdi, sizeof (jdi)); 5938334SJose.Borrego@Sun.COM smbadm_restart_service(); 5945331Samw return (0); 5955331Samw 5965331Samw case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND: 5978334SJose.Borrego@Sun.COM (void) fprintf(stderr, 5988334SJose.Borrego@Sun.COM gettext("failed to find any domain controllers for %s\n"), 5995331Samw jdi.domain_name); 6008334SJose.Borrego@Sun.COM bzero(&jdi, sizeof (jdi)); 6018334SJose.Borrego@Sun.COM return (1); 6025331Samw 6035331Samw default: 6048334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("failed to join %s: %s\n"), 6055331Samw jdi.domain_name, xlate_nt_status(status)); 6068334SJose.Borrego@Sun.COM bzero(&jdi, sizeof (jdi)); 6078334SJose.Borrego@Sun.COM return (1); 6088334SJose.Borrego@Sun.COM } 6098334SJose.Borrego@Sun.COM } 6108334SJose.Borrego@Sun.COM 6118334SJose.Borrego@Sun.COM /* 6128334SJose.Borrego@Sun.COM * We want to process the user and domain names as separate strings. 6138334SJose.Borrego@Sun.COM * Check for names of the forms below and separate the components as 6148334SJose.Borrego@Sun.COM * required. 6158334SJose.Borrego@Sun.COM * 6168334SJose.Borrego@Sun.COM * name@domain 6178334SJose.Borrego@Sun.COM * domain\name 6188334SJose.Borrego@Sun.COM * domain/name 6198334SJose.Borrego@Sun.COM * 6208334SJose.Borrego@Sun.COM * If we encounter any of the forms above in arg, the @, / or \ 6218334SJose.Borrego@Sun.COM * separator is replaced by \0 and the username and domain pointers 6228334SJose.Borrego@Sun.COM * are changed to point to the appropriate components (in arg). 6238334SJose.Borrego@Sun.COM * 6248334SJose.Borrego@Sun.COM * If none of the separators are encountered, the username and domain 6258334SJose.Borrego@Sun.COM * pointers remain unchanged. 6268334SJose.Borrego@Sun.COM */ 6278334SJose.Borrego@Sun.COM static void 6288334SJose.Borrego@Sun.COM smbadm_extract_domain(char *arg, char **username, char **domain) 6298334SJose.Borrego@Sun.COM { 6308334SJose.Borrego@Sun.COM char *p; 6318334SJose.Borrego@Sun.COM 6328334SJose.Borrego@Sun.COM if ((p = strpbrk(arg, "/\\@")) != NULL) { 6338334SJose.Borrego@Sun.COM if (*p == '@') { 6348334SJose.Borrego@Sun.COM *p = '\0'; 6358334SJose.Borrego@Sun.COM ++p; 6368334SJose.Borrego@Sun.COM 6378334SJose.Borrego@Sun.COM if (strchr(arg, '+') != NULL) 6388334SJose.Borrego@Sun.COM return; 6398334SJose.Borrego@Sun.COM 6408334SJose.Borrego@Sun.COM *domain = p; 6418334SJose.Borrego@Sun.COM *username = arg; 6428334SJose.Borrego@Sun.COM } else { 6438334SJose.Borrego@Sun.COM *p = '\0'; 6448334SJose.Borrego@Sun.COM ++p; 6458334SJose.Borrego@Sun.COM *username = p; 6468334SJose.Borrego@Sun.COM *domain = arg; 6478334SJose.Borrego@Sun.COM } 6488334SJose.Borrego@Sun.COM } 6498334SJose.Borrego@Sun.COM } 6508334SJose.Borrego@Sun.COM 6518334SJose.Borrego@Sun.COM /* 6528334SJose.Borrego@Sun.COM * Check a domain name for RFC 1035 and 1123 compliance. Domain names may 6538334SJose.Borrego@Sun.COM * contain alphanumeric characters, hyphens and dots. The first and last 6548334SJose.Borrego@Sun.COM * character of a label must be alphanumeric. Interior characters may be 6558334SJose.Borrego@Sun.COM * alphanumeric or hypens. 6568334SJose.Borrego@Sun.COM * 6578334SJose.Borrego@Sun.COM * Domain names should not contain underscores but we allow them because 6588334SJose.Borrego@Sun.COM * Windows names are often in non-compliance with this rule. 6598334SJose.Borrego@Sun.COM */ 6608334SJose.Borrego@Sun.COM static boolean_t 6618334SJose.Borrego@Sun.COM smbadm_valid_domainname(const char *domain) 6628334SJose.Borrego@Sun.COM { 6638334SJose.Borrego@Sun.COM boolean_t new_label = B_TRUE; 6648334SJose.Borrego@Sun.COM const char *p; 6658334SJose.Borrego@Sun.COM char label_terminator; 6668334SJose.Borrego@Sun.COM 6678334SJose.Borrego@Sun.COM if (domain == NULL || *domain == '\0') 6688334SJose.Borrego@Sun.COM return (B_FALSE); 6698334SJose.Borrego@Sun.COM 6708334SJose.Borrego@Sun.COM label_terminator = *domain; 6718334SJose.Borrego@Sun.COM 6728334SJose.Borrego@Sun.COM for (p = domain; *p != '\0'; ++p) { 6738334SJose.Borrego@Sun.COM if (new_label) { 6748334SJose.Borrego@Sun.COM if (!isalnum(*p)) 6758334SJose.Borrego@Sun.COM return (B_FALSE); 6768334SJose.Borrego@Sun.COM new_label = B_FALSE; 6778334SJose.Borrego@Sun.COM label_terminator = *p; 6788334SJose.Borrego@Sun.COM continue; 6798334SJose.Borrego@Sun.COM } 6808334SJose.Borrego@Sun.COM 6818334SJose.Borrego@Sun.COM if (*p == '.') { 6828334SJose.Borrego@Sun.COM if (!isalnum(label_terminator)) 6838334SJose.Borrego@Sun.COM return (B_FALSE); 6848334SJose.Borrego@Sun.COM new_label = B_TRUE; 6858334SJose.Borrego@Sun.COM label_terminator = *p; 6868334SJose.Borrego@Sun.COM continue; 6878334SJose.Borrego@Sun.COM } 6888334SJose.Borrego@Sun.COM 6898334SJose.Borrego@Sun.COM label_terminator = *p; 6908334SJose.Borrego@Sun.COM 6918334SJose.Borrego@Sun.COM if (isalnum(*p) || *p == '-' || *p == '_') 6928334SJose.Borrego@Sun.COM continue; 6938334SJose.Borrego@Sun.COM 6948334SJose.Borrego@Sun.COM return (B_FALSE); 6955331Samw } 6965331Samw 6978334SJose.Borrego@Sun.COM if (!isalnum(label_terminator)) 6988334SJose.Borrego@Sun.COM return (B_FALSE); 6998334SJose.Borrego@Sun.COM return (B_TRUE); 7008334SJose.Borrego@Sun.COM } 7018334SJose.Borrego@Sun.COM 7028334SJose.Borrego@Sun.COM /* 7038334SJose.Borrego@Sun.COM * Windows user names cannot contain the following characters 7048334SJose.Borrego@Sun.COM * or control characters. 7058334SJose.Borrego@Sun.COM * 7068334SJose.Borrego@Sun.COM * " / \ [ ] < > + ; , ? * = @ 7078334SJose.Borrego@Sun.COM */ 7088334SJose.Borrego@Sun.COM static boolean_t 7098334SJose.Borrego@Sun.COM smbadm_valid_username(const char *username) 7108334SJose.Borrego@Sun.COM { 7118334SJose.Borrego@Sun.COM const char *invalid = "\"/\\[]<>+;,?*=@"; 7128334SJose.Borrego@Sun.COM const char *p; 7138334SJose.Borrego@Sun.COM 7148334SJose.Borrego@Sun.COM if (username == NULL) 7158334SJose.Borrego@Sun.COM return (B_FALSE); 7168334SJose.Borrego@Sun.COM 7178334SJose.Borrego@Sun.COM if (strpbrk(username, invalid)) 7188334SJose.Borrego@Sun.COM return (B_FALSE); 7198334SJose.Borrego@Sun.COM 7208334SJose.Borrego@Sun.COM for (p = username; *p != '\0'; p++) { 7218334SJose.Borrego@Sun.COM if (iscntrl(*p)) 7228334SJose.Borrego@Sun.COM return (B_FALSE); 7238334SJose.Borrego@Sun.COM } 7248334SJose.Borrego@Sun.COM 7258334SJose.Borrego@Sun.COM return (B_TRUE); 7268334SJose.Borrego@Sun.COM } 7278334SJose.Borrego@Sun.COM 7288334SJose.Borrego@Sun.COM /* 7298334SJose.Borrego@Sun.COM * A workgroup name can contain 1 to 15 characters but cannot be the same 7308334SJose.Borrego@Sun.COM * as the NetBIOS name. The name must begin with a letter or number. 7318334SJose.Borrego@Sun.COM * 7328334SJose.Borrego@Sun.COM * The name cannot consist entirely of spaces or dots, which is covered 7338334SJose.Borrego@Sun.COM * by the requirement that the name must begin with an alphanumeric 7348334SJose.Borrego@Sun.COM * character. 7358334SJose.Borrego@Sun.COM * 7368334SJose.Borrego@Sun.COM * The name must not contain any of the following characters or control 7378334SJose.Borrego@Sun.COM * characters. 7388334SJose.Borrego@Sun.COM * 7398334SJose.Borrego@Sun.COM * " / \ [ ] : | < > + = ; , ? 7408334SJose.Borrego@Sun.COM */ 7418334SJose.Borrego@Sun.COM static boolean_t 7428334SJose.Borrego@Sun.COM smbadm_valid_workgroup(const char *workgroup) 7438334SJose.Borrego@Sun.COM { 7448334SJose.Borrego@Sun.COM char netbiosname[NETBIOS_NAME_SZ]; 7458334SJose.Borrego@Sun.COM const char *invalid = "\"/\\[]:|<>+=;,?"; 7468334SJose.Borrego@Sun.COM const char *p; 7478334SJose.Borrego@Sun.COM 7488334SJose.Borrego@Sun.COM if (workgroup == NULL || *workgroup == '\0' || (!isalnum(*workgroup))) 7498334SJose.Borrego@Sun.COM return (B_FALSE); 7508334SJose.Borrego@Sun.COM 7518334SJose.Borrego@Sun.COM if (strlen(workgroup) >= NETBIOS_NAME_SZ) 7528334SJose.Borrego@Sun.COM return (B_FALSE); 7538334SJose.Borrego@Sun.COM 7548334SJose.Borrego@Sun.COM if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) { 7558334SJose.Borrego@Sun.COM if (utf8_strcasecmp(workgroup, netbiosname) == 0) 7568334SJose.Borrego@Sun.COM return (B_FALSE); 7578334SJose.Borrego@Sun.COM } 7588334SJose.Borrego@Sun.COM 7598334SJose.Borrego@Sun.COM if (strpbrk(workgroup, invalid)) 7608334SJose.Borrego@Sun.COM return (B_FALSE); 7618334SJose.Borrego@Sun.COM 7628334SJose.Borrego@Sun.COM for (p = workgroup; *p != '\0'; p++) { 7638334SJose.Borrego@Sun.COM if (iscntrl(*p)) 7648334SJose.Borrego@Sun.COM return (B_FALSE); 7658334SJose.Borrego@Sun.COM } 7668334SJose.Borrego@Sun.COM 7678334SJose.Borrego@Sun.COM return (B_TRUE); 7685331Samw } 7695331Samw 7705331Samw /* 7715331Samw * smbadm_list 7725331Samw * 7735331Samw * Displays current security mode and domain/workgroup name. 7745331Samw */ 7755331Samw /*ARGSUSED*/ 7765331Samw static int 7775331Samw smbadm_list(int argc, char **argv) 7785331Samw { 7796139Sjb150015 char domain[MAXHOSTNAMELEN]; 7808334SJose.Borrego@Sun.COM char fqdn[MAXHOSTNAMELEN]; 7818334SJose.Borrego@Sun.COM char srvname[MAXHOSTNAMELEN]; 7826139Sjb150015 char modename[16]; 7836139Sjb150015 int rc; 784*8670SJose.Borrego@Sun.COM smb_inaddr_t srvipaddr; 7857348SJose.Borrego@Sun.COM char ipstr[INET6_ADDRSTRLEN]; 7865331Samw 7876139Sjb150015 rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename)); 7886139Sjb150015 if (rc != SMBD_SMF_OK) { 7895331Samw (void) fprintf(stderr, 7908474SJose.Borrego@Sun.COM gettext("cannot determine the operational mode\n")); 7915331Samw return (1); 7925331Samw } 7935331Samw 7946139Sjb150015 if (smb_getdomainname(domain, sizeof (domain)) != 0) { 7956139Sjb150015 (void) fprintf(stderr, gettext("failed to get the %s name\n"), 7966139Sjb150015 modename); 7975331Samw return (1); 7985331Samw } 7998474SJose.Borrego@Sun.COM 8007348SJose.Borrego@Sun.COM if (strcmp(modename, "workgroup") == 0) { 8018474SJose.Borrego@Sun.COM (void) printf(gettext("[*] [%s]\n"), domain); 8027348SJose.Borrego@Sun.COM return (0); 8037348SJose.Borrego@Sun.COM } 8048474SJose.Borrego@Sun.COM 8058474SJose.Borrego@Sun.COM (void) printf(gettext("[*] [%s]\n"), domain); 8068334SJose.Borrego@Sun.COM if ((smb_getfqdomainname(fqdn, sizeof (fqdn)) == 0) && (*fqdn != '\0')) 8078474SJose.Borrego@Sun.COM (void) printf(gettext("[*] [%s]\n"), fqdn); 8085331Samw 8098334SJose.Borrego@Sun.COM if ((smb_get_dcinfo(srvname, MAXHOSTNAMELEN, &srvipaddr) 8108334SJose.Borrego@Sun.COM == NT_STATUS_SUCCESS) && (*srvname != '\0') && 811*8670SJose.Borrego@Sun.COM (!smb_inet_iszero(&srvipaddr))) { 812*8670SJose.Borrego@Sun.COM (void) smb_inet_ntop(&srvipaddr, ipstr, 813*8670SJose.Borrego@Sun.COM SMB_IPSTRLEN(srvipaddr.a_family)); 8148474SJose.Borrego@Sun.COM (void) printf(gettext("\t[+%s.%s] [%s]\n"), 8158474SJose.Borrego@Sun.COM srvname, fqdn, ipstr); 8167348SJose.Borrego@Sun.COM } 8178474SJose.Borrego@Sun.COM 8188474SJose.Borrego@Sun.COM nt_domain_show(); 8195331Samw return (0); 8205331Samw } 8215331Samw 8225331Samw /* 8235331Samw * smbadm_group_create 8245331Samw * 8255331Samw * Creates a local SMB group 8265331Samw */ 8275331Samw static int 8285331Samw smbadm_group_create(int argc, char **argv) 8295331Samw { 8305331Samw char *gname = NULL; 8315331Samw char *desc = NULL; 8325331Samw char option; 8335772Sas200622 int status; 8345331Samw 8355331Samw while ((option = getopt(argc, argv, "d:")) != -1) { 8365331Samw switch (option) { 8375331Samw case 'd': 8385331Samw desc = optarg; 8395331Samw break; 8405331Samw 8415331Samw default: 8425331Samw smbadm_usage(B_FALSE); 8435331Samw } 8445331Samw } 8455331Samw 8465331Samw gname = argv[optind]; 8475331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 8485331Samw (void) fprintf(stderr, gettext("missing group name\n")); 8495331Samw smbadm_usage(B_FALSE); 8505331Samw } 8515331Samw 8525331Samw if (getgrnam(gname) == NULL) { 8535331Samw (void) fprintf(stderr, 8545772Sas200622 gettext("failed to get the Solaris group '%s'\n"), gname); 8555331Samw (void) fprintf(stderr, 8565772Sas200622 gettext("use 'groupadd' to add '%s'\n"), gname); 8575331Samw return (1); 8585331Samw } 8595331Samw 8605772Sas200622 status = smb_lgrp_add(gname, desc); 8615772Sas200622 if (status != SMB_LGRP_SUCCESS) { 8625331Samw (void) fprintf(stderr, 8635331Samw gettext("failed to create the group (%s)\n"), 8645772Sas200622 smb_lgrp_strerror(status)); 8655331Samw } else { 8665772Sas200622 (void) printf(gettext("'%s' created.\n"), 8675331Samw gname); 8685331Samw } 8695331Samw 8705331Samw return (status); 8715331Samw } 8725331Samw 8735331Samw /* 8745331Samw * smbadm_group_dump_members 8755331Samw * 8765331Samw * Dump group members details. 8775331Samw */ 8785331Samw static void 8795772Sas200622 smbadm_group_dump_members(smb_gsid_t *members, int num) 8805331Samw { 8816432Sas200622 char sidstr[SMB_SID_STRSZ]; 8825331Samw int i; 8835331Samw 8845772Sas200622 if (num == 0) { 8855331Samw (void) printf(gettext("\tNo members\n")); 8865331Samw return; 8875331Samw } 8885331Samw 8895331Samw (void) printf(gettext("\tMembers:\n")); 8905772Sas200622 for (i = 0; i < num; i++) { 8916600Sas200622 *sidstr = '\0'; 8926600Sas200622 if (smb_lookup_sid(members[i].gs_sid, sidstr, 8936600Sas200622 sizeof (sidstr)) == NT_STATUS_SUCCESS) 8946600Sas200622 (void) printf(gettext("\t\t%s\n"), sidstr); 8956600Sas200622 else 8968334SJose.Borrego@Sun.COM (void) printf(gettext("\t\tinvalid SID\n")); 8975331Samw } 8985331Samw } 8995331Samw 9005331Samw /* 9015331Samw * smbadm_group_dump_privs 9025331Samw * 9035331Samw * Dump group privilege details. 9045331Samw */ 9055331Samw static void 9065772Sas200622 smbadm_group_dump_privs(smb_privset_t *privs) 9075331Samw { 9085772Sas200622 smb_privinfo_t *pinfo; 9095772Sas200622 char *pstatus; 9105331Samw int i; 9115331Samw 9125331Samw (void) printf(gettext("\tPrivileges: \n")); 9135331Samw 9145772Sas200622 for (i = 0; i < privs->priv_cnt; i++) { 9155772Sas200622 pinfo = smb_priv_getbyvalue(privs->priv[i].luid.lo_part); 9165772Sas200622 if ((pinfo == NULL) || (pinfo->flags & PF_PRESENTABLE) == 0) 9175331Samw continue; 9185331Samw 9195772Sas200622 switch (privs->priv[i].attrs) { 9205772Sas200622 case SE_PRIVILEGE_ENABLED: 9215772Sas200622 pstatus = "On"; 9225772Sas200622 break; 9235772Sas200622 case SE_PRIVILEGE_DISABLED: 9245772Sas200622 pstatus = "Off"; 9255772Sas200622 break; 9265772Sas200622 default: 9275772Sas200622 pstatus = "Unknown"; 9285772Sas200622 break; 9295331Samw } 9305772Sas200622 (void) printf(gettext("\t\t%s: %s\n"), pinfo->name, pstatus); 9315331Samw } 9325331Samw 9335772Sas200622 if (privs->priv_cnt == 0) 9345331Samw (void) printf(gettext("\t\tNo privileges\n")); 9355331Samw } 9365331Samw 9375331Samw /* 9385331Samw * smbadm_group_dump 9395331Samw * 9405331Samw * Dump group details. 9415331Samw */ 9425772Sas200622 static void 9435772Sas200622 smbadm_group_dump(smb_group_t *grp, boolean_t show_mem, boolean_t show_privs) 9445331Samw { 9456432Sas200622 char sidstr[SMB_SID_STRSZ]; 9465331Samw 9475772Sas200622 (void) printf(gettext("%s (%s)\n"), grp->sg_name, grp->sg_cmnt); 9485331Samw 9496432Sas200622 smb_sid_tostr(grp->sg_id.gs_sid, sidstr); 9505772Sas200622 (void) printf(gettext("\tSID: %s\n"), sidstr); 9515331Samw 9525772Sas200622 if (show_privs) 9535772Sas200622 smbadm_group_dump_privs(grp->sg_privs); 9545331Samw 9555772Sas200622 if (show_mem) 9565772Sas200622 smbadm_group_dump_members(grp->sg_members, grp->sg_nmembers); 9575331Samw } 9585331Samw 9595331Samw /* 9605331Samw * smbadm_group_show 9615331Samw * 9625331Samw */ 9635331Samw static int 9645331Samw smbadm_group_show(int argc, char **argv) 9655331Samw { 9665331Samw char *gname = NULL; 9675331Samw boolean_t show_privs; 9685331Samw boolean_t show_members; 9695331Samw char option; 9705772Sas200622 int status; 9715772Sas200622 smb_group_t grp; 9725772Sas200622 smb_giter_t gi; 9735331Samw 9745331Samw show_privs = show_members = B_FALSE; 9755331Samw 9765331Samw while ((option = getopt(argc, argv, "mp")) != -1) { 9775331Samw switch (option) { 9785331Samw case 'm': 9795331Samw show_members = B_TRUE; 9805331Samw break; 9815331Samw case 'p': 9825331Samw show_privs = B_TRUE; 9835331Samw break; 9845331Samw 9855331Samw default: 9865331Samw smbadm_usage(B_FALSE); 9875331Samw } 9885331Samw } 9895331Samw 9905331Samw gname = argv[optind]; 9915331Samw if (optind >= argc || gname == NULL || *gname == '\0') 9925331Samw gname = "*"; 9935331Samw 9945772Sas200622 if (strcmp(gname, "*")) { 9955772Sas200622 status = smb_lgrp_getbyname(gname, &grp); 9965772Sas200622 if (status == SMB_LGRP_SUCCESS) { 9975772Sas200622 smbadm_group_dump(&grp, show_members, show_privs); 9985772Sas200622 smb_lgrp_free(&grp); 9995772Sas200622 } else { 10005772Sas200622 (void) fprintf(stderr, 10018334SJose.Borrego@Sun.COM gettext("failed to find %s (%s)\n"), 10025772Sas200622 gname, smb_lgrp_strerror(status)); 10035772Sas200622 } 10045772Sas200622 return (status); 10055331Samw } 10065331Samw 10076432Sas200622 if ((status = smb_lgrp_iteropen(&gi)) != SMB_LGRP_SUCCESS) { 10088334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("failed to list groups (%s)\n"), 10095772Sas200622 smb_lgrp_strerror(status)); 10105772Sas200622 return (status); 10115331Samw } 10125331Samw 10136432Sas200622 while ((status = smb_lgrp_iterate(&gi, &grp)) == SMB_LGRP_SUCCESS) { 10145772Sas200622 smbadm_group_dump(&grp, show_members, show_privs); 10155772Sas200622 smb_lgrp_free(&grp); 10165772Sas200622 } 10176432Sas200622 10185772Sas200622 smb_lgrp_iterclose(&gi); 10195772Sas200622 10206432Sas200622 if (status != SMB_LGRP_NO_MORE) { 10216432Sas200622 (void) fprintf(stderr, 10226432Sas200622 gettext("failed to get all the groups (%s)\n"), 10236432Sas200622 smb_lgrp_strerror(status)); 10246432Sas200622 return (status); 10256432Sas200622 } 10266432Sas200622 10275772Sas200622 return (0); 10285331Samw } 10295331Samw 10305331Samw /* 10315331Samw * smbadm_group_delete 10325331Samw */ 10335331Samw static int 10345331Samw smbadm_group_delete(int argc, char **argv) 10355331Samw { 10365331Samw char *gname = NULL; 10375772Sas200622 int status; 10385331Samw 10395331Samw gname = argv[optind]; 10405331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 10415331Samw (void) fprintf(stderr, gettext("missing group name\n")); 10425331Samw smbadm_usage(B_FALSE); 10435331Samw } 10445331Samw 10455772Sas200622 status = smb_lgrp_delete(gname); 10465772Sas200622 if (status != SMB_LGRP_SUCCESS) { 10475331Samw (void) fprintf(stderr, 10488334SJose.Borrego@Sun.COM gettext("failed to delete %s (%s)\n"), gname, 10495772Sas200622 smb_lgrp_strerror(status)); 10505331Samw } else { 10518334SJose.Borrego@Sun.COM (void) printf(gettext("%s deleted.\n"), gname); 10525331Samw } 10535331Samw 10545331Samw return (status); 10555331Samw } 10565331Samw 10575331Samw /* 10585331Samw * smbadm_group_rename 10595331Samw */ 10605331Samw static int 10615331Samw smbadm_group_rename(int argc, char **argv) 10625331Samw { 10635331Samw char *gname = NULL; 10645331Samw char *ngname = NULL; 10655772Sas200622 int status; 10665331Samw 10675331Samw gname = argv[optind]; 10685331Samw if (optind++ >= argc || gname == NULL || *gname == '\0') { 10695331Samw (void) fprintf(stderr, gettext("missing group name\n")); 10705331Samw smbadm_usage(B_FALSE); 10715331Samw } 10725331Samw 10735331Samw ngname = argv[optind]; 10745331Samw if (optind >= argc || ngname == NULL || *ngname == '\0') { 10755331Samw (void) fprintf(stderr, gettext("missing new group name\n")); 10765331Samw smbadm_usage(B_FALSE); 10775331Samw } 10785331Samw 10795772Sas200622 if (getgrnam(ngname) == NULL) { 10805331Samw (void) fprintf(stderr, 10815772Sas200622 gettext("failed to get the Solaris group '%s'\n"), ngname); 10825331Samw (void) fprintf(stderr, 10835772Sas200622 gettext("use 'groupadd' to add '%s'\n"), ngname); 10845331Samw return (1); 10855331Samw } 10865331Samw 10875772Sas200622 status = smb_lgrp_rename(gname, ngname); 10885772Sas200622 if (status != SMB_LGRP_SUCCESS) { 10895772Sas200622 if (status == SMB_LGRP_EXISTS) 10905772Sas200622 (void) fprintf(stderr, 10915772Sas200622 gettext("failed to rename '%s' (%s already " 10925772Sas200622 "exists)\n"), gname, ngname); 10935772Sas200622 else 10945772Sas200622 (void) fprintf(stderr, 10955772Sas200622 gettext("failed to rename '%s' (%s)\n"), gname, 10965772Sas200622 smb_lgrp_strerror(status)); 10975331Samw } else { 10985772Sas200622 (void) printf(gettext("'%s' renamed to '%s'\n"), gname, ngname); 10995331Samw } 11005331Samw 11015331Samw return (status); 11025331Samw } 11035331Samw 11045331Samw /* 11055331Samw * smbadm_group_setprop 11065331Samw * 11075331Samw * Set the group properties. 11085331Samw */ 11095331Samw static int 11105331Samw smbadm_group_setprop(int argc, char **argv) 11115331Samw { 11125331Samw char *gname = NULL; 11135331Samw smbadm_prop_t props[SMBADM_NPROP]; 11145331Samw smbadm_prop_handle_t *phandle; 11155331Samw char option; 11165331Samw int pcnt = 0; 11175331Samw int ret; 11185331Samw int p; 11195331Samw 11205331Samw bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 11215331Samw 11225331Samw while ((option = getopt(argc, argv, "p:")) != -1) { 11235331Samw switch (option) { 11245331Samw case 'p': 11255331Samw if (pcnt >= SMBADM_NPROP) { 11265331Samw (void) fprintf(stderr, 11275331Samw gettext("exceeded number of supported" 11285331Samw " properties\n")); 11295331Samw smbadm_usage(B_FALSE); 11305331Samw } 11315331Samw 11325772Sas200622 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 11335772Sas200622 smbadm_usage(B_FALSE); 11345331Samw break; 11355331Samw 11365331Samw default: 11375331Samw smbadm_usage(B_FALSE); 11385331Samw } 11395331Samw } 11405331Samw 11415331Samw if (pcnt == 0) { 11425331Samw (void) fprintf(stderr, 11435331Samw gettext("missing property=value argument\n")); 11445331Samw smbadm_usage(B_FALSE); 11455331Samw } 11465331Samw 11475331Samw gname = argv[optind]; 11485331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 11495331Samw (void) fprintf(stderr, gettext("missing group name\n")); 11505331Samw smbadm_usage(B_FALSE); 11515331Samw } 11525331Samw 11535331Samw for (p = 0; p < pcnt; p++) { 11545331Samw phandle = smbadm_prop_gethandle(props[p].p_name); 11555331Samw if (phandle) { 11565331Samw if (phandle->p_setfn(gname, &props[p]) != 0) 11575331Samw ret = 1; 11585331Samw } 11595331Samw } 11605331Samw 11615331Samw return (ret); 11625331Samw } 11635331Samw 11645331Samw /* 11655331Samw * smbadm_group_getprop 11665331Samw * 11675331Samw * Get the group properties. 11685331Samw */ 11695331Samw static int 11705331Samw smbadm_group_getprop(int argc, char **argv) 11715331Samw { 11725331Samw char *gname = NULL; 11735331Samw smbadm_prop_t props[SMBADM_NPROP]; 11745331Samw smbadm_prop_handle_t *phandle; 11755331Samw char option; 11765331Samw int pcnt = 0; 11775331Samw int ret; 11785331Samw int p; 11795331Samw 11805331Samw bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 11815331Samw 11825331Samw while ((option = getopt(argc, argv, "p:")) != -1) { 11835331Samw switch (option) { 11845331Samw case 'p': 11855331Samw if (pcnt >= SMBADM_NPROP) { 11865331Samw (void) fprintf(stderr, 11875331Samw gettext("exceeded number of supported" 11885331Samw " properties\n")); 11895331Samw smbadm_usage(B_FALSE); 11905331Samw } 11915331Samw 11925772Sas200622 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 11935772Sas200622 smbadm_usage(B_FALSE); 11945331Samw break; 11955331Samw 11965331Samw default: 11975331Samw smbadm_usage(B_FALSE); 11985331Samw } 11995331Samw } 12005331Samw 12015331Samw gname = argv[optind]; 12025331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 12035331Samw (void) fprintf(stderr, gettext("missing group name\n")); 12045331Samw smbadm_usage(B_FALSE); 12055331Samw } 12065331Samw 12075331Samw if (pcnt == 0) { 12085331Samw /* 12095331Samw * If no property has be specified then get 12105331Samw * all the properties. 12115331Samw */ 12125331Samw pcnt = SMBADM_NPROP; 12135331Samw for (p = 0; p < pcnt; p++) 12145331Samw props[p].p_name = smbadm_ptable[p].p_name; 12155331Samw } 12165331Samw 12175331Samw for (p = 0; p < pcnt; p++) { 12185331Samw phandle = smbadm_prop_gethandle(props[p].p_name); 12195331Samw if (phandle) { 12205331Samw if (phandle->p_getfn(gname, &props[p]) != 0) 12215331Samw ret = 1; 12225331Samw } 12235331Samw } 12245331Samw 12255331Samw return (ret); 12265331Samw } 12275331Samw 12285331Samw /* 12295331Samw * smbadm_group_addmember 12305331Samw * 12315331Samw */ 12325331Samw static int 12335331Samw smbadm_group_addmember(int argc, char **argv) 12345331Samw { 12355331Samw char *gname = NULL; 12365331Samw char **mname; 12375331Samw char option; 12385772Sas200622 smb_gsid_t msid; 12395772Sas200622 int status; 12405331Samw int mcnt = 0; 12415331Samw int ret = 0; 12425331Samw int i; 12435331Samw 12445331Samw 12455331Samw mname = (char **)malloc(argc * sizeof (char *)); 12465331Samw if (mname == NULL) { 12478334SJose.Borrego@Sun.COM warn(gettext("failed to add group member")); 12485331Samw return (1); 12495331Samw } 12505331Samw bzero(mname, argc * sizeof (char *)); 12515331Samw 12525331Samw while ((option = getopt(argc, argv, "m:")) != -1) { 12535331Samw switch (option) { 12545331Samw case 'm': 12555331Samw mname[mcnt++] = optarg; 12565331Samw break; 12575331Samw 12585331Samw default: 12595331Samw free(mname); 12605331Samw smbadm_usage(B_FALSE); 12615331Samw } 12625331Samw } 12635331Samw 12645331Samw if (mcnt == 0) { 12655331Samw (void) fprintf(stderr, gettext("missing member name\n")); 12665331Samw free(mname); 12675331Samw smbadm_usage(B_FALSE); 12685331Samw } 12695331Samw 12705331Samw gname = argv[optind]; 12715331Samw if (optind >= argc || gname == NULL || *gname == 0) { 12725331Samw (void) fprintf(stderr, gettext("missing group name\n")); 12735331Samw free(mname); 12745331Samw smbadm_usage(B_FALSE); 12755331Samw } 12765331Samw 12775331Samw 12785331Samw for (i = 0; i < mcnt; i++) { 12795331Samw if (mname[i] == NULL) 12805331Samw continue; 12815331Samw 12825772Sas200622 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 12835772Sas200622 (void) fprintf(stderr, 12848334SJose.Borrego@Sun.COM gettext("failed to add %s: unable to obtain SID\n"), 12855772Sas200622 mname[i]); 12865772Sas200622 continue; 12875772Sas200622 } 12885772Sas200622 12895772Sas200622 status = smb_lgrp_add_member(gname, msid.gs_sid, msid.gs_type); 12905772Sas200622 free(msid.gs_sid); 12915772Sas200622 if (status != SMB_LGRP_SUCCESS) { 12925331Samw (void) fprintf(stderr, 12935331Samw gettext("failed to add %s (%s)\n"), 12945772Sas200622 mname[i], smb_lgrp_strerror(status)); 12955331Samw ret = 1; 12965772Sas200622 } else { 12975772Sas200622 (void) printf(gettext("'%s' is now a member of '%s'\n"), 12985772Sas200622 mname[i], gname); 12995331Samw } 13005331Samw } 13015331Samw 13025331Samw free(mname); 13035331Samw return (ret); 13045331Samw } 13055331Samw 13065331Samw /* 13075331Samw * smbadm_group_delmember 13085331Samw */ 13095331Samw static int 13105331Samw smbadm_group_delmember(int argc, char **argv) 13115331Samw { 13125331Samw char *gname = NULL; 13135331Samw char **mname; 13145331Samw char option; 13155772Sas200622 smb_gsid_t msid; 13165772Sas200622 int status; 13175331Samw int mcnt = 0; 13185331Samw int ret = 0; 13195331Samw int i; 13205331Samw 13215331Samw mname = (char **)malloc(argc * sizeof (char *)); 13225331Samw if (mname == NULL) { 13238334SJose.Borrego@Sun.COM warn(gettext("failed to delete group member")); 13245331Samw return (1); 13255331Samw } 13265331Samw bzero(mname, argc * sizeof (char *)); 13275331Samw 13285331Samw while ((option = getopt(argc, argv, "m:")) != -1) { 13295331Samw switch (option) { 13305331Samw case 'm': 13315331Samw mname[mcnt++] = optarg; 13325331Samw break; 13335331Samw 13345331Samw default: 13355331Samw free(mname); 13365331Samw smbadm_usage(B_FALSE); 13375331Samw } 13385331Samw } 13395331Samw 13405331Samw if (mcnt == 0) { 13415331Samw (void) fprintf(stderr, gettext("missing member name\n")); 13425331Samw free(mname); 13435331Samw smbadm_usage(B_FALSE); 13445331Samw } 13455331Samw 13465331Samw gname = argv[optind]; 13475331Samw if (optind >= argc || gname == NULL || *gname == 0) { 13485331Samw (void) fprintf(stderr, gettext("missing group name\n")); 13495331Samw free(mname); 13505331Samw smbadm_usage(B_FALSE); 13515331Samw } 13525331Samw 13535331Samw 13545331Samw for (i = 0; i < mcnt; i++) { 13555331Samw if (mname[i] == NULL) 13565331Samw continue; 13575331Samw 13585772Sas200622 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 13595772Sas200622 (void) fprintf(stderr, 13608334SJose.Borrego@Sun.COM gettext("failed to remove %s: " 13618334SJose.Borrego@Sun.COM "unable to obtain SID\n"), 13625772Sas200622 mname[i]); 13635772Sas200622 continue; 13645772Sas200622 } 13655772Sas200622 13665772Sas200622 status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type); 13675772Sas200622 free(msid.gs_sid); 13685772Sas200622 if (status != SMB_LGRP_SUCCESS) { 13695331Samw (void) fprintf(stderr, 13705331Samw gettext("failed to remove %s (%s)\n"), 13715772Sas200622 mname[i], smb_lgrp_strerror(status)); 13725331Samw ret = 1; 13735331Samw } else { 13745331Samw (void) printf( 13755772Sas200622 gettext("'%s' has been removed from %s\n"), 13765331Samw mname[i], gname); 13775331Samw } 13785331Samw } 13795331Samw 13805331Samw return (ret); 13815331Samw } 13825331Samw 13835331Samw static int 13845331Samw smbadm_user_disable(int argc, char **argv) 13855331Samw { 13865331Samw int error; 13875331Samw char *user = NULL; 13885331Samw 13895331Samw user = argv[optind]; 13905331Samw if (optind >= argc || user == NULL || *user == '\0') { 13915331Samw (void) fprintf(stderr, gettext("missing user name\n")); 13925331Samw smbadm_usage(B_FALSE); 13935331Samw } 13945331Samw 13955331Samw error = smb_pwd_setcntl(user, SMB_PWC_DISABLE); 13965331Samw if (error == SMB_PWE_SUCCESS) 13975331Samw (void) printf(gettext("%s is disabled.\n"), user); 13985331Samw else 13995331Samw (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 14005331Samw 14015331Samw return (error); 14025331Samw } 14035331Samw 14045331Samw static int 14055331Samw smbadm_user_enable(int argc, char **argv) 14065331Samw { 14075331Samw int error; 14085331Samw char *user = NULL; 14095331Samw 14105331Samw user = argv[optind]; 14115331Samw if (optind >= argc || user == NULL || *user == '\0') { 14125331Samw (void) fprintf(stderr, gettext("missing user name\n")); 14135331Samw smbadm_usage(B_FALSE); 14145331Samw } 14155331Samw 14165331Samw error = smb_pwd_setcntl(user, SMB_PWC_ENABLE); 14175331Samw if (error == SMB_PWE_SUCCESS) 14185331Samw (void) printf(gettext("%s is enabled.\n"), user); 14195331Samw else 14205331Samw (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 14215331Samw 14225331Samw return (error); 14235331Samw } 14245331Samw 14255331Samw 14265331Samw int 14275331Samw main(int argc, char **argv) 14285331Samw { 14295772Sas200622 int ret; 14305331Samw int i; 14315331Samw 14325331Samw (void) malloc(0); /* satisfy libumem dependency */ 14335331Samw 14345331Samw progname = basename(argv[0]); 14355331Samw 14365331Samw if (getzoneid() != GLOBAL_ZONEID) { 14375331Samw (void) fprintf(stderr, 14385331Samw gettext("cannot execute in non-global zone\n")); 14395331Samw return (0); 14405331Samw } 14415331Samw 14425331Samw if (is_system_labeled()) { 14435331Samw (void) fprintf(stderr, 14445331Samw gettext("Trusted Extensions not supported\n")); 14455331Samw return (0); 14465331Samw } 14475331Samw 14485331Samw if (argc < 2) { 14495331Samw (void) fprintf(stderr, gettext("missing command\n")); 14505331Samw smbadm_usage(B_FALSE); 14515331Samw } 14525331Samw 14535331Samw /* 14545331Samw * Special case "cmd --help/-?" 14555331Samw */ 14565331Samw if (strcmp(argv[1], "-?") == 0 || 14575331Samw strcmp(argv[1], "--help") == 0 || 14585331Samw strcmp(argv[1], "-h") == 0) 14595331Samw smbadm_usage(B_TRUE); 14605331Samw 14615331Samw for (i = 0; i < SMBADM_NCMD; ++i) { 14625331Samw curcmd = &smbadm_cmdtable[i]; 14635331Samw if (strcasecmp(argv[1], curcmd->name) == 0) { 14645331Samw if (argc > 2) { 14655331Samw /* cmd subcmd --help/-? */ 14665331Samw if (strcmp(argv[2], "-?") == 0 || 14675331Samw strcmp(argv[2], "--help") == 0 || 14685331Samw strcmp(argv[2], "-h") == 0) 14695331Samw smbadm_usage(B_TRUE); 14705331Samw } 14715331Samw 14727052Samw if ((ret = smbadm_init()) != 0) 14736139Sjb150015 return (ret); 14745772Sas200622 14755772Sas200622 ret = curcmd->func(argc - 1, &argv[1]); 14766139Sjb150015 14777052Samw smbadm_fini(); 14785772Sas200622 return (ret); 14795331Samw } 14805331Samw } 14815331Samw 14825331Samw curcmd = NULL; 14835331Samw (void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]); 14845331Samw smbadm_usage(B_FALSE); 14855331Samw return (2); 14865331Samw } 14875331Samw 14886139Sjb150015 static int 14897052Samw smbadm_init(void) 14906139Sjb150015 { 14916139Sjb150015 int rc; 14926139Sjb150015 14937052Samw switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 14947052Samw case SMBADM_CMDF_GROUP: 14956139Sjb150015 if (smb_idmap_start() != 0) { 14966139Sjb150015 (void) fprintf(stderr, 14976139Sjb150015 gettext("failed to contact idmap service\n")); 14986139Sjb150015 return (1); 14996139Sjb150015 } 15006139Sjb150015 15016139Sjb150015 if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { 15026139Sjb150015 (void) fprintf(stderr, 15036139Sjb150015 gettext("failed to initialize (%s)\n"), 15046139Sjb150015 smb_lgrp_strerror(rc)); 15056139Sjb150015 smb_idmap_stop(); 15066139Sjb150015 return (1); 15076139Sjb150015 } 15087052Samw break; 15097052Samw 15107052Samw case SMBADM_CMDF_USER: 15117052Samw smb_pwd_init(B_FALSE); 15127052Samw break; 15137052Samw 15147052Samw default: 15157052Samw break; 15166139Sjb150015 } 15176139Sjb150015 15186139Sjb150015 return (0); 15196139Sjb150015 } 15206139Sjb150015 15216139Sjb150015 static void 15227052Samw smbadm_fini(void) 15236139Sjb150015 { 15247052Samw switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 15257052Samw case SMBADM_CMDF_GROUP: 15266139Sjb150015 smb_lgrp_stop(); 15276139Sjb150015 smb_idmap_stop(); 15287052Samw break; 15297052Samw 15307052Samw case SMBADM_CMDF_USER: 15317052Samw smb_pwd_fini(); 15327052Samw break; 15337052Samw 15347052Samw default: 15357052Samw break; 15366139Sjb150015 } 15376139Sjb150015 } 15386139Sjb150015 15395331Samw static boolean_t 15405331Samw smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 15415331Samw { 15425331Samw smbadm_prop_handle_t *pinfo; 15435331Samw int i; 15445331Samw 15455331Samw for (i = 0; i < SMBADM_NPROP; i++) { 15465331Samw pinfo = &smbadm_ptable[i]; 15475331Samw if (strcmp(pinfo->p_name, prop->p_name) == 0) { 15485331Samw if (pinfo->p_chkfn && chkval) 15495331Samw return (pinfo->p_chkfn(prop)); 15505331Samw 15515331Samw return (B_TRUE); 15525331Samw } 15535331Samw } 15545331Samw 15558334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("unrecognized property '%s'\n"), 15568334SJose.Borrego@Sun.COM prop->p_name); 15575331Samw 15585331Samw return (B_FALSE); 15595331Samw } 15605331Samw 15615331Samw static int 15625331Samw smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 15635331Samw { 15645331Samw boolean_t parse_value; 15655331Samw char *equal; 15665331Samw 15675331Samw if (arg == NULL) 15685331Samw return (2); 15695331Samw 15705331Samw prop->p_name = prop->p_value = NULL; 15715331Samw 15725331Samw if (strcmp(curcmd->name, "set") == 0) 15735331Samw parse_value = B_TRUE; 15745331Samw else 15755331Samw parse_value = B_FALSE; 15765331Samw 15775331Samw prop->p_name = arg; 15785331Samw 15795331Samw if (parse_value) { 15805331Samw equal = strchr(arg, '='); 15815331Samw if (equal == NULL) 15825331Samw return (2); 15835331Samw 15845331Samw *equal++ = '\0'; 15855331Samw prop->p_value = equal; 15865331Samw } 15875331Samw 15885331Samw if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 15895331Samw return (2); 15905331Samw 15915331Samw return (0); 15925331Samw } 15935331Samw 15945331Samw static smbadm_prop_handle_t * 15955331Samw smbadm_prop_gethandle(char *pname) 15965331Samw { 15975331Samw int i; 15985331Samw 15995331Samw for (i = 0; i < SMBADM_NPROP; i++) 16005331Samw if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 16015331Samw return (&smbadm_ptable[i]); 16025331Samw 16035331Samw return (NULL); 16045331Samw } 16055331Samw 16065331Samw static int 16075331Samw smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 16085331Samw { 16095772Sas200622 int status; 16105331Samw 16115772Sas200622 status = smb_lgrp_setcmnt(gname, prop->p_value); 16125772Sas200622 if (status != SMB_LGRP_SUCCESS) { 16135331Samw (void) fprintf(stderr, 16145331Samw gettext("failed to modify the group description (%s)\n"), 16155772Sas200622 smb_lgrp_strerror(status)); 16165331Samw return (1); 16175331Samw } 16185331Samw 16198334SJose.Borrego@Sun.COM (void) printf(gettext("%s: description modified\n"), gname); 16205331Samw return (0); 16215331Samw } 16225331Samw 16235331Samw static int 16245331Samw smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 16255331Samw { 16265772Sas200622 char *cmnt = NULL; 16275772Sas200622 int status; 16285331Samw 16295772Sas200622 status = smb_lgrp_getcmnt(gname, &cmnt); 16305772Sas200622 if (status != SMB_LGRP_SUCCESS) { 16315331Samw (void) fprintf(stderr, 16325772Sas200622 gettext("failed to get the group description (%s)\n"), 16335772Sas200622 smb_lgrp_strerror(status)); 16345331Samw return (1); 16355331Samw } 16365331Samw 16375772Sas200622 (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); 16385772Sas200622 free(cmnt); 16395331Samw return (0); 16405331Samw } 16415331Samw 16425331Samw static int 16435772Sas200622 smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 16445331Samw { 16455772Sas200622 boolean_t enable; 16465772Sas200622 int status; 16475331Samw int ret; 16485331Samw 16495331Samw if (strcasecmp(prop->p_value, "on") == 0) { 16505331Samw (void) printf(gettext("Enabling %s privilege "), prop->p_name); 16515772Sas200622 enable = B_TRUE; 16525331Samw } else { 16535331Samw (void) printf(gettext("Disabling %s privilege "), prop->p_name); 16545772Sas200622 enable = B_FALSE; 16555331Samw } 16565331Samw 16575772Sas200622 status = smb_lgrp_setpriv(gname, priv_id, enable); 16585772Sas200622 if (status == SMB_LGRP_SUCCESS) { 16595331Samw (void) printf(gettext("succeeded\n")); 16605331Samw ret = 0; 16615331Samw } else { 16625772Sas200622 (void) printf(gettext("failed: %s\n"), 16635772Sas200622 smb_lgrp_strerror(status)); 16645331Samw ret = 1; 16655331Samw } 16665331Samw 16675331Samw return (ret); 16685331Samw } 16695331Samw 16705331Samw static int 16715772Sas200622 smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 16725331Samw { 16735772Sas200622 boolean_t enable; 16745772Sas200622 int status; 16755331Samw 16765772Sas200622 status = smb_lgrp_getpriv(gname, priv_id, &enable); 16775772Sas200622 if (status != SMB_LGRP_SUCCESS) { 16785331Samw (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 16795772Sas200622 prop->p_name, smb_lgrp_strerror(status)); 16805331Samw return (1); 16815331Samw } 16825331Samw 16835772Sas200622 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 16845772Sas200622 (enable) ? "On" : "Off"); 16855331Samw 16865331Samw return (0); 16875331Samw } 16885331Samw 16895331Samw static int 16905331Samw smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 16915331Samw { 16925331Samw return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 16935331Samw } 16945331Samw 16955331Samw static int 16965331Samw smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 16975331Samw { 16985331Samw return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 16995331Samw } 17005331Samw 17015331Samw static int 17025331Samw smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 17035331Samw { 17045331Samw return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 17055331Samw } 17065331Samw 17075331Samw static int 17085331Samw smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 17095331Samw { 17105331Samw return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 17115331Samw } 17125331Samw 17135331Samw static int 17145331Samw smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 17155331Samw { 17165331Samw return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 17175331Samw } 17185331Samw 17195331Samw static int 17205331Samw smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 17215331Samw { 17225331Samw return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 17235331Samw } 17245331Samw 17255331Samw static boolean_t 17265331Samw smbadm_chkprop_priv(smbadm_prop_t *prop) 17275331Samw { 17285331Samw if (prop->p_value == NULL || *prop->p_value == '\0') { 17295331Samw (void) fprintf(stderr, 17305331Samw gettext("missing value for '%s'\n"), prop->p_name); 17315331Samw return (B_FALSE); 17325331Samw } 17335331Samw 17345331Samw if (strcasecmp(prop->p_value, "on") == 0) 17355331Samw return (B_TRUE); 17365331Samw 17375331Samw if (strcasecmp(prop->p_value, "off") == 0) 17385331Samw return (B_TRUE); 17395331Samw 17405331Samw (void) fprintf(stderr, 17415331Samw gettext("%s: unrecognized value for '%s' property\n"), 17425331Samw prop->p_value, prop->p_name); 17435331Samw 17445331Samw return (B_FALSE); 17455331Samw } 17465331Samw 17475331Samw static const char * 17485331Samw smbadm_pwd_strerror(int error) 17495331Samw { 17505331Samw switch (error) { 17515331Samw case SMB_PWE_SUCCESS: 17525331Samw return (gettext("Success.")); 17535331Samw 17545331Samw case SMB_PWE_USER_UNKNOWN: 17555331Samw return (gettext("User does not exist.")); 17565331Samw 17575331Samw case SMB_PWE_USER_DISABLE: 17588334SJose.Borrego@Sun.COM return (gettext("User is disabled.")); 17595331Samw 17605331Samw case SMB_PWE_CLOSE_FAILED: 17615331Samw case SMB_PWE_OPEN_FAILED: 17625331Samw case SMB_PWE_WRITE_FAILED: 17635331Samw case SMB_PWE_UPDATE_FAILED: 17645331Samw return (gettext("Unexpected failure. " 17655331Samw "SMB password database unchanged.")); 17665331Samw 17675331Samw case SMB_PWE_STAT_FAILED: 17685331Samw return (gettext("stat of SMB password file failed.")); 17695331Samw 17705331Samw case SMB_PWE_BUSY: 17715331Samw return (gettext("SMB password database busy. " 17725331Samw "Try again later.")); 17735331Samw 17745331Samw case SMB_PWE_DENIED: 17755331Samw return (gettext("Operation not permitted.")); 17765331Samw 17775331Samw case SMB_PWE_SYSTEM_ERROR: 17785331Samw return (gettext("System error.")); 17797052Samw 17807052Samw default: 17817052Samw break; 17825331Samw } 17835331Samw 17845331Samw return (gettext("Unknown error code.")); 17855331Samw } 17865331Samw 17875331Samw /* 17885331Samw * Enable libumem debugging by default on DEBUG builds. 17895331Samw */ 17905331Samw #ifdef DEBUG 17915331Samw const char * 17925331Samw _umem_debug_init(void) 17935331Samw { 17945331Samw return ("default,verbose"); /* $UMEM_DEBUG setting */ 17955331Samw } 17965331Samw 17975331Samw const char * 17985331Samw _umem_logging_init(void) 17995331Samw { 18005331Samw return ("fail,contents"); /* $UMEM_LOGGING setting */ 18015331Samw } 18025331Samw #endif 1803