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)); 6069021Samw@Sun.COM (void) fprintf(stderr, gettext("Please refer to the system log" 6079021Samw@Sun.COM " for more information.\n")); 6088334SJose.Borrego@Sun.COM bzero(&jdi, sizeof (jdi)); 6098334SJose.Borrego@Sun.COM return (1); 6108334SJose.Borrego@Sun.COM } 6118334SJose.Borrego@Sun.COM } 6128334SJose.Borrego@Sun.COM 6138334SJose.Borrego@Sun.COM /* 6148334SJose.Borrego@Sun.COM * We want to process the user and domain names as separate strings. 6158334SJose.Borrego@Sun.COM * Check for names of the forms below and separate the components as 6168334SJose.Borrego@Sun.COM * required. 6178334SJose.Borrego@Sun.COM * 6188334SJose.Borrego@Sun.COM * name@domain 6198334SJose.Borrego@Sun.COM * domain\name 6208334SJose.Borrego@Sun.COM * domain/name 6218334SJose.Borrego@Sun.COM * 6228334SJose.Borrego@Sun.COM * If we encounter any of the forms above in arg, the @, / or \ 6238334SJose.Borrego@Sun.COM * separator is replaced by \0 and the username and domain pointers 6248334SJose.Borrego@Sun.COM * are changed to point to the appropriate components (in arg). 6258334SJose.Borrego@Sun.COM * 6268334SJose.Borrego@Sun.COM * If none of the separators are encountered, the username and domain 6278334SJose.Borrego@Sun.COM * pointers remain unchanged. 6288334SJose.Borrego@Sun.COM */ 6298334SJose.Borrego@Sun.COM static void 6308334SJose.Borrego@Sun.COM smbadm_extract_domain(char *arg, char **username, char **domain) 6318334SJose.Borrego@Sun.COM { 6328334SJose.Borrego@Sun.COM char *p; 6338334SJose.Borrego@Sun.COM 6348334SJose.Borrego@Sun.COM if ((p = strpbrk(arg, "/\\@")) != NULL) { 6358334SJose.Borrego@Sun.COM if (*p == '@') { 6368334SJose.Borrego@Sun.COM *p = '\0'; 6378334SJose.Borrego@Sun.COM ++p; 6388334SJose.Borrego@Sun.COM 6398334SJose.Borrego@Sun.COM if (strchr(arg, '+') != NULL) 6408334SJose.Borrego@Sun.COM return; 6418334SJose.Borrego@Sun.COM 6428334SJose.Borrego@Sun.COM *domain = p; 6438334SJose.Borrego@Sun.COM *username = arg; 6448334SJose.Borrego@Sun.COM } else { 6458334SJose.Borrego@Sun.COM *p = '\0'; 6468334SJose.Borrego@Sun.COM ++p; 6478334SJose.Borrego@Sun.COM *username = p; 6488334SJose.Borrego@Sun.COM *domain = arg; 6498334SJose.Borrego@Sun.COM } 6508334SJose.Borrego@Sun.COM } 6518334SJose.Borrego@Sun.COM } 6528334SJose.Borrego@Sun.COM 6538334SJose.Borrego@Sun.COM /* 6548334SJose.Borrego@Sun.COM * Check a domain name for RFC 1035 and 1123 compliance. Domain names may 6558334SJose.Borrego@Sun.COM * contain alphanumeric characters, hyphens and dots. The first and last 6568334SJose.Borrego@Sun.COM * character of a label must be alphanumeric. Interior characters may be 6578334SJose.Borrego@Sun.COM * alphanumeric or hypens. 6588334SJose.Borrego@Sun.COM * 6598334SJose.Borrego@Sun.COM * Domain names should not contain underscores but we allow them because 6608334SJose.Borrego@Sun.COM * Windows names are often in non-compliance with this rule. 6618334SJose.Borrego@Sun.COM */ 6628334SJose.Borrego@Sun.COM static boolean_t 6638334SJose.Borrego@Sun.COM smbadm_valid_domainname(const char *domain) 6648334SJose.Borrego@Sun.COM { 6658334SJose.Borrego@Sun.COM boolean_t new_label = B_TRUE; 6668334SJose.Borrego@Sun.COM const char *p; 6678334SJose.Borrego@Sun.COM char label_terminator; 6688334SJose.Borrego@Sun.COM 6698334SJose.Borrego@Sun.COM if (domain == NULL || *domain == '\0') 6708334SJose.Borrego@Sun.COM return (B_FALSE); 6718334SJose.Borrego@Sun.COM 6728334SJose.Borrego@Sun.COM label_terminator = *domain; 6738334SJose.Borrego@Sun.COM 6748334SJose.Borrego@Sun.COM for (p = domain; *p != '\0'; ++p) { 6758334SJose.Borrego@Sun.COM if (new_label) { 6768334SJose.Borrego@Sun.COM if (!isalnum(*p)) 6778334SJose.Borrego@Sun.COM return (B_FALSE); 6788334SJose.Borrego@Sun.COM new_label = B_FALSE; 6798334SJose.Borrego@Sun.COM label_terminator = *p; 6808334SJose.Borrego@Sun.COM continue; 6818334SJose.Borrego@Sun.COM } 6828334SJose.Borrego@Sun.COM 6838334SJose.Borrego@Sun.COM if (*p == '.') { 6848334SJose.Borrego@Sun.COM if (!isalnum(label_terminator)) 6858334SJose.Borrego@Sun.COM return (B_FALSE); 6868334SJose.Borrego@Sun.COM new_label = B_TRUE; 6878334SJose.Borrego@Sun.COM label_terminator = *p; 6888334SJose.Borrego@Sun.COM continue; 6898334SJose.Borrego@Sun.COM } 6908334SJose.Borrego@Sun.COM 6918334SJose.Borrego@Sun.COM label_terminator = *p; 6928334SJose.Borrego@Sun.COM 6938334SJose.Borrego@Sun.COM if (isalnum(*p) || *p == '-' || *p == '_') 6948334SJose.Borrego@Sun.COM continue; 6958334SJose.Borrego@Sun.COM 6968334SJose.Borrego@Sun.COM return (B_FALSE); 6975331Samw } 6985331Samw 6998334SJose.Borrego@Sun.COM if (!isalnum(label_terminator)) 7008334SJose.Borrego@Sun.COM return (B_FALSE); 7018334SJose.Borrego@Sun.COM return (B_TRUE); 7028334SJose.Borrego@Sun.COM } 7038334SJose.Borrego@Sun.COM 7048334SJose.Borrego@Sun.COM /* 7058334SJose.Borrego@Sun.COM * Windows user names cannot contain the following characters 7068334SJose.Borrego@Sun.COM * or control characters. 7078334SJose.Borrego@Sun.COM * 7088334SJose.Borrego@Sun.COM * " / \ [ ] < > + ; , ? * = @ 7098334SJose.Borrego@Sun.COM */ 7108334SJose.Borrego@Sun.COM static boolean_t 7118334SJose.Borrego@Sun.COM smbadm_valid_username(const char *username) 7128334SJose.Borrego@Sun.COM { 7138334SJose.Borrego@Sun.COM const char *invalid = "\"/\\[]<>+;,?*=@"; 7148334SJose.Borrego@Sun.COM const char *p; 7158334SJose.Borrego@Sun.COM 7168334SJose.Borrego@Sun.COM if (username == NULL) 7178334SJose.Borrego@Sun.COM return (B_FALSE); 7188334SJose.Borrego@Sun.COM 7198334SJose.Borrego@Sun.COM if (strpbrk(username, invalid)) 7208334SJose.Borrego@Sun.COM return (B_FALSE); 7218334SJose.Borrego@Sun.COM 7228334SJose.Borrego@Sun.COM for (p = username; *p != '\0'; p++) { 7238334SJose.Borrego@Sun.COM if (iscntrl(*p)) 7248334SJose.Borrego@Sun.COM return (B_FALSE); 7258334SJose.Borrego@Sun.COM } 7268334SJose.Borrego@Sun.COM 7278334SJose.Borrego@Sun.COM return (B_TRUE); 7288334SJose.Borrego@Sun.COM } 7298334SJose.Borrego@Sun.COM 7308334SJose.Borrego@Sun.COM /* 7318334SJose.Borrego@Sun.COM * A workgroup name can contain 1 to 15 characters but cannot be the same 7328334SJose.Borrego@Sun.COM * as the NetBIOS name. The name must begin with a letter or number. 7338334SJose.Borrego@Sun.COM * 7348334SJose.Borrego@Sun.COM * The name cannot consist entirely of spaces or dots, which is covered 7358334SJose.Borrego@Sun.COM * by the requirement that the name must begin with an alphanumeric 7368334SJose.Borrego@Sun.COM * character. 7378334SJose.Borrego@Sun.COM * 7388334SJose.Borrego@Sun.COM * The name must not contain any of the following characters or control 7398334SJose.Borrego@Sun.COM * characters. 7408334SJose.Borrego@Sun.COM * 7418334SJose.Borrego@Sun.COM * " / \ [ ] : | < > + = ; , ? 7428334SJose.Borrego@Sun.COM */ 7438334SJose.Borrego@Sun.COM static boolean_t 7448334SJose.Borrego@Sun.COM smbadm_valid_workgroup(const char *workgroup) 7458334SJose.Borrego@Sun.COM { 7468334SJose.Borrego@Sun.COM char netbiosname[NETBIOS_NAME_SZ]; 7478334SJose.Borrego@Sun.COM const char *invalid = "\"/\\[]:|<>+=;,?"; 7488334SJose.Borrego@Sun.COM const char *p; 7498334SJose.Borrego@Sun.COM 7508334SJose.Borrego@Sun.COM if (workgroup == NULL || *workgroup == '\0' || (!isalnum(*workgroup))) 7518334SJose.Borrego@Sun.COM return (B_FALSE); 7528334SJose.Borrego@Sun.COM 7538334SJose.Borrego@Sun.COM if (strlen(workgroup) >= NETBIOS_NAME_SZ) 7548334SJose.Borrego@Sun.COM return (B_FALSE); 7558334SJose.Borrego@Sun.COM 7568334SJose.Borrego@Sun.COM if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) == 0) { 7578334SJose.Borrego@Sun.COM if (utf8_strcasecmp(workgroup, netbiosname) == 0) 7588334SJose.Borrego@Sun.COM return (B_FALSE); 7598334SJose.Borrego@Sun.COM } 7608334SJose.Borrego@Sun.COM 7618334SJose.Borrego@Sun.COM if (strpbrk(workgroup, invalid)) 7628334SJose.Borrego@Sun.COM return (B_FALSE); 7638334SJose.Borrego@Sun.COM 7648334SJose.Borrego@Sun.COM for (p = workgroup; *p != '\0'; p++) { 7658334SJose.Borrego@Sun.COM if (iscntrl(*p)) 7668334SJose.Borrego@Sun.COM return (B_FALSE); 7678334SJose.Borrego@Sun.COM } 7688334SJose.Borrego@Sun.COM 7698334SJose.Borrego@Sun.COM return (B_TRUE); 7705331Samw } 7715331Samw 7725331Samw /* 7735331Samw * smbadm_list 7745331Samw * 7755331Samw * Displays current security mode and domain/workgroup name. 7765331Samw */ 7775331Samw /*ARGSUSED*/ 7785331Samw static int 7795331Samw smbadm_list(int argc, char **argv) 7805331Samw { 7816139Sjb150015 char domain[MAXHOSTNAMELEN]; 7828334SJose.Borrego@Sun.COM char fqdn[MAXHOSTNAMELEN]; 7838334SJose.Borrego@Sun.COM char srvname[MAXHOSTNAMELEN]; 7846139Sjb150015 char modename[16]; 7856139Sjb150015 int rc; 7868670SJose.Borrego@Sun.COM smb_inaddr_t srvipaddr; 7877348SJose.Borrego@Sun.COM char ipstr[INET6_ADDRSTRLEN]; 7885331Samw 7896139Sjb150015 rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename)); 7906139Sjb150015 if (rc != SMBD_SMF_OK) { 7915331Samw (void) fprintf(stderr, 7928474SJose.Borrego@Sun.COM gettext("cannot determine the operational mode\n")); 7935331Samw return (1); 7945331Samw } 7955331Samw 7966139Sjb150015 if (smb_getdomainname(domain, sizeof (domain)) != 0) { 7976139Sjb150015 (void) fprintf(stderr, gettext("failed to get the %s name\n"), 7986139Sjb150015 modename); 7995331Samw return (1); 8005331Samw } 8018474SJose.Borrego@Sun.COM 8027348SJose.Borrego@Sun.COM if (strcmp(modename, "workgroup") == 0) { 8038474SJose.Borrego@Sun.COM (void) printf(gettext("[*] [%s]\n"), domain); 8047348SJose.Borrego@Sun.COM return (0); 8057348SJose.Borrego@Sun.COM } 8068474SJose.Borrego@Sun.COM 8078474SJose.Borrego@Sun.COM (void) printf(gettext("[*] [%s]\n"), domain); 8088334SJose.Borrego@Sun.COM if ((smb_getfqdomainname(fqdn, sizeof (fqdn)) == 0) && (*fqdn != '\0')) 8098474SJose.Borrego@Sun.COM (void) printf(gettext("[*] [%s]\n"), fqdn); 8105331Samw 8118334SJose.Borrego@Sun.COM if ((smb_get_dcinfo(srvname, MAXHOSTNAMELEN, &srvipaddr) 8128334SJose.Borrego@Sun.COM == NT_STATUS_SUCCESS) && (*srvname != '\0') && 8138670SJose.Borrego@Sun.COM (!smb_inet_iszero(&srvipaddr))) { 8148670SJose.Borrego@Sun.COM (void) smb_inet_ntop(&srvipaddr, ipstr, 8158670SJose.Borrego@Sun.COM SMB_IPSTRLEN(srvipaddr.a_family)); 8168474SJose.Borrego@Sun.COM (void) printf(gettext("\t[+%s.%s] [%s]\n"), 8178474SJose.Borrego@Sun.COM srvname, fqdn, ipstr); 8187348SJose.Borrego@Sun.COM } 8198474SJose.Borrego@Sun.COM 820*10717Samw@Sun.COM smb_domain_show(); 8215331Samw return (0); 8225331Samw } 8235331Samw 8245331Samw /* 8255331Samw * smbadm_group_create 8265331Samw * 8275331Samw * Creates a local SMB group 8285331Samw */ 8295331Samw static int 8305331Samw smbadm_group_create(int argc, char **argv) 8315331Samw { 8325331Samw char *gname = NULL; 8335331Samw char *desc = NULL; 8345331Samw char option; 8355772Sas200622 int status; 8365331Samw 8375331Samw while ((option = getopt(argc, argv, "d:")) != -1) { 8385331Samw switch (option) { 8395331Samw case 'd': 8405331Samw desc = optarg; 8415331Samw break; 8425331Samw 8435331Samw default: 8445331Samw smbadm_usage(B_FALSE); 8455331Samw } 8465331Samw } 8475331Samw 8485331Samw gname = argv[optind]; 8495331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 8505331Samw (void) fprintf(stderr, gettext("missing group name\n")); 8515331Samw smbadm_usage(B_FALSE); 8525331Samw } 8535331Samw 8545331Samw if (getgrnam(gname) == NULL) { 8555331Samw (void) fprintf(stderr, 8565772Sas200622 gettext("failed to get the Solaris group '%s'\n"), gname); 8575331Samw (void) fprintf(stderr, 8585772Sas200622 gettext("use 'groupadd' to add '%s'\n"), gname); 8595331Samw return (1); 8605331Samw } 8615331Samw 8625772Sas200622 status = smb_lgrp_add(gname, desc); 8635772Sas200622 if (status != SMB_LGRP_SUCCESS) { 8645331Samw (void) fprintf(stderr, 8655331Samw gettext("failed to create the group (%s)\n"), 8665772Sas200622 smb_lgrp_strerror(status)); 8675331Samw } else { 8685772Sas200622 (void) printf(gettext("'%s' created.\n"), 8695331Samw gname); 8705331Samw } 8715331Samw 8725331Samw return (status); 8735331Samw } 8745331Samw 8755331Samw /* 8765331Samw * smbadm_group_dump_members 8775331Samw * 8785331Samw * Dump group members details. 8795331Samw */ 8805331Samw static void 8815772Sas200622 smbadm_group_dump_members(smb_gsid_t *members, int num) 8825331Samw { 8836432Sas200622 char sidstr[SMB_SID_STRSZ]; 8845331Samw int i; 8855331Samw 8865772Sas200622 if (num == 0) { 8875331Samw (void) printf(gettext("\tNo members\n")); 8885331Samw return; 8895331Samw } 8905331Samw 8915331Samw (void) printf(gettext("\tMembers:\n")); 8925772Sas200622 for (i = 0; i < num; i++) { 8936600Sas200622 *sidstr = '\0'; 8946600Sas200622 if (smb_lookup_sid(members[i].gs_sid, sidstr, 8956600Sas200622 sizeof (sidstr)) == NT_STATUS_SUCCESS) 8966600Sas200622 (void) printf(gettext("\t\t%s\n"), sidstr); 8976600Sas200622 else 8988334SJose.Borrego@Sun.COM (void) printf(gettext("\t\tinvalid SID\n")); 8995331Samw } 9005331Samw } 9015331Samw 9025331Samw /* 9035331Samw * smbadm_group_dump_privs 9045331Samw * 9055331Samw * Dump group privilege details. 9065331Samw */ 9075331Samw static void 9085772Sas200622 smbadm_group_dump_privs(smb_privset_t *privs) 9095331Samw { 9105772Sas200622 smb_privinfo_t *pinfo; 9115772Sas200622 char *pstatus; 9125331Samw int i; 9135331Samw 9145331Samw (void) printf(gettext("\tPrivileges: \n")); 9155331Samw 9165772Sas200622 for (i = 0; i < privs->priv_cnt; i++) { 9175772Sas200622 pinfo = smb_priv_getbyvalue(privs->priv[i].luid.lo_part); 9185772Sas200622 if ((pinfo == NULL) || (pinfo->flags & PF_PRESENTABLE) == 0) 9195331Samw continue; 9205331Samw 9215772Sas200622 switch (privs->priv[i].attrs) { 9225772Sas200622 case SE_PRIVILEGE_ENABLED: 9235772Sas200622 pstatus = "On"; 9245772Sas200622 break; 9255772Sas200622 case SE_PRIVILEGE_DISABLED: 9265772Sas200622 pstatus = "Off"; 9275772Sas200622 break; 9285772Sas200622 default: 9295772Sas200622 pstatus = "Unknown"; 9305772Sas200622 break; 9315331Samw } 9325772Sas200622 (void) printf(gettext("\t\t%s: %s\n"), pinfo->name, pstatus); 9335331Samw } 9345331Samw 9355772Sas200622 if (privs->priv_cnt == 0) 9365331Samw (void) printf(gettext("\t\tNo privileges\n")); 9375331Samw } 9385331Samw 9395331Samw /* 9405331Samw * smbadm_group_dump 9415331Samw * 9425331Samw * Dump group details. 9435331Samw */ 9445772Sas200622 static void 9455772Sas200622 smbadm_group_dump(smb_group_t *grp, boolean_t show_mem, boolean_t show_privs) 9465331Samw { 9476432Sas200622 char sidstr[SMB_SID_STRSZ]; 9485331Samw 9495772Sas200622 (void) printf(gettext("%s (%s)\n"), grp->sg_name, grp->sg_cmnt); 9505331Samw 9516432Sas200622 smb_sid_tostr(grp->sg_id.gs_sid, sidstr); 9525772Sas200622 (void) printf(gettext("\tSID: %s\n"), sidstr); 9535331Samw 9545772Sas200622 if (show_privs) 9555772Sas200622 smbadm_group_dump_privs(grp->sg_privs); 9565331Samw 9575772Sas200622 if (show_mem) 9585772Sas200622 smbadm_group_dump_members(grp->sg_members, grp->sg_nmembers); 9595331Samw } 9605331Samw 9615331Samw /* 9625331Samw * smbadm_group_show 9635331Samw * 9645331Samw */ 9655331Samw static int 9665331Samw smbadm_group_show(int argc, char **argv) 9675331Samw { 9685331Samw char *gname = NULL; 9695331Samw boolean_t show_privs; 9705331Samw boolean_t show_members; 9715331Samw char option; 9725772Sas200622 int status; 9735772Sas200622 smb_group_t grp; 9745772Sas200622 smb_giter_t gi; 9755331Samw 9765331Samw show_privs = show_members = B_FALSE; 9775331Samw 9785331Samw while ((option = getopt(argc, argv, "mp")) != -1) { 9795331Samw switch (option) { 9805331Samw case 'm': 9815331Samw show_members = B_TRUE; 9825331Samw break; 9835331Samw case 'p': 9845331Samw show_privs = B_TRUE; 9855331Samw break; 9865331Samw 9875331Samw default: 9885331Samw smbadm_usage(B_FALSE); 9895331Samw } 9905331Samw } 9915331Samw 9925331Samw gname = argv[optind]; 9935331Samw if (optind >= argc || gname == NULL || *gname == '\0') 9945331Samw gname = "*"; 9955331Samw 9965772Sas200622 if (strcmp(gname, "*")) { 9975772Sas200622 status = smb_lgrp_getbyname(gname, &grp); 9985772Sas200622 if (status == SMB_LGRP_SUCCESS) { 9995772Sas200622 smbadm_group_dump(&grp, show_members, show_privs); 10005772Sas200622 smb_lgrp_free(&grp); 10015772Sas200622 } else { 10025772Sas200622 (void) fprintf(stderr, 10038334SJose.Borrego@Sun.COM gettext("failed to find %s (%s)\n"), 10045772Sas200622 gname, smb_lgrp_strerror(status)); 10055772Sas200622 } 10065772Sas200622 return (status); 10075331Samw } 10085331Samw 10096432Sas200622 if ((status = smb_lgrp_iteropen(&gi)) != SMB_LGRP_SUCCESS) { 10108334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("failed to list groups (%s)\n"), 10115772Sas200622 smb_lgrp_strerror(status)); 10125772Sas200622 return (status); 10135331Samw } 10145331Samw 10156432Sas200622 while ((status = smb_lgrp_iterate(&gi, &grp)) == SMB_LGRP_SUCCESS) { 10165772Sas200622 smbadm_group_dump(&grp, show_members, show_privs); 10175772Sas200622 smb_lgrp_free(&grp); 10185772Sas200622 } 10196432Sas200622 10205772Sas200622 smb_lgrp_iterclose(&gi); 10215772Sas200622 10226432Sas200622 if (status != SMB_LGRP_NO_MORE) { 10236432Sas200622 (void) fprintf(stderr, 10246432Sas200622 gettext("failed to get all the groups (%s)\n"), 10256432Sas200622 smb_lgrp_strerror(status)); 10266432Sas200622 return (status); 10276432Sas200622 } 10286432Sas200622 10295772Sas200622 return (0); 10305331Samw } 10315331Samw 10325331Samw /* 10335331Samw * smbadm_group_delete 10345331Samw */ 10355331Samw static int 10365331Samw smbadm_group_delete(int argc, char **argv) 10375331Samw { 10385331Samw char *gname = NULL; 10395772Sas200622 int status; 10405331Samw 10415331Samw gname = argv[optind]; 10425331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 10435331Samw (void) fprintf(stderr, gettext("missing group name\n")); 10445331Samw smbadm_usage(B_FALSE); 10455331Samw } 10465331Samw 10475772Sas200622 status = smb_lgrp_delete(gname); 10485772Sas200622 if (status != SMB_LGRP_SUCCESS) { 10495331Samw (void) fprintf(stderr, 10508334SJose.Borrego@Sun.COM gettext("failed to delete %s (%s)\n"), gname, 10515772Sas200622 smb_lgrp_strerror(status)); 10525331Samw } else { 10538334SJose.Borrego@Sun.COM (void) printf(gettext("%s deleted.\n"), gname); 10545331Samw } 10555331Samw 10565331Samw return (status); 10575331Samw } 10585331Samw 10595331Samw /* 10605331Samw * smbadm_group_rename 10615331Samw */ 10625331Samw static int 10635331Samw smbadm_group_rename(int argc, char **argv) 10645331Samw { 10655331Samw char *gname = NULL; 10665331Samw char *ngname = NULL; 10675772Sas200622 int status; 10685331Samw 10695331Samw gname = argv[optind]; 10705331Samw if (optind++ >= argc || gname == NULL || *gname == '\0') { 10715331Samw (void) fprintf(stderr, gettext("missing group name\n")); 10725331Samw smbadm_usage(B_FALSE); 10735331Samw } 10745331Samw 10755331Samw ngname = argv[optind]; 10765331Samw if (optind >= argc || ngname == NULL || *ngname == '\0') { 10775331Samw (void) fprintf(stderr, gettext("missing new group name\n")); 10785331Samw smbadm_usage(B_FALSE); 10795331Samw } 10805331Samw 10815772Sas200622 if (getgrnam(ngname) == NULL) { 10825331Samw (void) fprintf(stderr, 10835772Sas200622 gettext("failed to get the Solaris group '%s'\n"), ngname); 10845331Samw (void) fprintf(stderr, 10855772Sas200622 gettext("use 'groupadd' to add '%s'\n"), ngname); 10865331Samw return (1); 10875331Samw } 10885331Samw 10895772Sas200622 status = smb_lgrp_rename(gname, ngname); 10905772Sas200622 if (status != SMB_LGRP_SUCCESS) { 10915772Sas200622 if (status == SMB_LGRP_EXISTS) 10925772Sas200622 (void) fprintf(stderr, 10935772Sas200622 gettext("failed to rename '%s' (%s already " 10945772Sas200622 "exists)\n"), gname, ngname); 10955772Sas200622 else 10965772Sas200622 (void) fprintf(stderr, 10975772Sas200622 gettext("failed to rename '%s' (%s)\n"), gname, 10985772Sas200622 smb_lgrp_strerror(status)); 10995331Samw } else { 11005772Sas200622 (void) printf(gettext("'%s' renamed to '%s'\n"), gname, ngname); 11015331Samw } 11025331Samw 11035331Samw return (status); 11045331Samw } 11055331Samw 11065331Samw /* 11075331Samw * smbadm_group_setprop 11085331Samw * 11095331Samw * Set the group properties. 11105331Samw */ 11115331Samw static int 11125331Samw smbadm_group_setprop(int argc, char **argv) 11135331Samw { 11145331Samw char *gname = NULL; 11155331Samw smbadm_prop_t props[SMBADM_NPROP]; 11165331Samw smbadm_prop_handle_t *phandle; 11175331Samw char option; 11185331Samw int pcnt = 0; 11195331Samw int ret; 11205331Samw int p; 11215331Samw 11225331Samw bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 11235331Samw 11245331Samw while ((option = getopt(argc, argv, "p:")) != -1) { 11255331Samw switch (option) { 11265331Samw case 'p': 11275331Samw if (pcnt >= SMBADM_NPROP) { 11285331Samw (void) fprintf(stderr, 11295331Samw gettext("exceeded number of supported" 11305331Samw " properties\n")); 11315331Samw smbadm_usage(B_FALSE); 11325331Samw } 11335331Samw 11345772Sas200622 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 11355772Sas200622 smbadm_usage(B_FALSE); 11365331Samw break; 11375331Samw 11385331Samw default: 11395331Samw smbadm_usage(B_FALSE); 11405331Samw } 11415331Samw } 11425331Samw 11435331Samw if (pcnt == 0) { 11445331Samw (void) fprintf(stderr, 11455331Samw gettext("missing property=value argument\n")); 11465331Samw smbadm_usage(B_FALSE); 11475331Samw } 11485331Samw 11495331Samw gname = argv[optind]; 11505331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 11515331Samw (void) fprintf(stderr, gettext("missing group name\n")); 11525331Samw smbadm_usage(B_FALSE); 11535331Samw } 11545331Samw 11555331Samw for (p = 0; p < pcnt; p++) { 11565331Samw phandle = smbadm_prop_gethandle(props[p].p_name); 11575331Samw if (phandle) { 11585331Samw if (phandle->p_setfn(gname, &props[p]) != 0) 11595331Samw ret = 1; 11605331Samw } 11615331Samw } 11625331Samw 11635331Samw return (ret); 11645331Samw } 11655331Samw 11665331Samw /* 11675331Samw * smbadm_group_getprop 11685331Samw * 11695331Samw * Get the group properties. 11705331Samw */ 11715331Samw static int 11725331Samw smbadm_group_getprop(int argc, char **argv) 11735331Samw { 11745331Samw char *gname = NULL; 11755331Samw smbadm_prop_t props[SMBADM_NPROP]; 11765331Samw smbadm_prop_handle_t *phandle; 11775331Samw char option; 11785331Samw int pcnt = 0; 11795331Samw int ret; 11805331Samw int p; 11815331Samw 11825331Samw bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t)); 11835331Samw 11845331Samw while ((option = getopt(argc, argv, "p:")) != -1) { 11855331Samw switch (option) { 11865331Samw case 'p': 11875331Samw if (pcnt >= SMBADM_NPROP) { 11885331Samw (void) fprintf(stderr, 11895331Samw gettext("exceeded number of supported" 11905331Samw " properties\n")); 11915331Samw smbadm_usage(B_FALSE); 11925331Samw } 11935331Samw 11945772Sas200622 if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) 11955772Sas200622 smbadm_usage(B_FALSE); 11965331Samw break; 11975331Samw 11985331Samw default: 11995331Samw smbadm_usage(B_FALSE); 12005331Samw } 12015331Samw } 12025331Samw 12035331Samw gname = argv[optind]; 12045331Samw if (optind >= argc || gname == NULL || *gname == '\0') { 12055331Samw (void) fprintf(stderr, gettext("missing group name\n")); 12065331Samw smbadm_usage(B_FALSE); 12075331Samw } 12085331Samw 12095331Samw if (pcnt == 0) { 12105331Samw /* 12115331Samw * If no property has be specified then get 12125331Samw * all the properties. 12135331Samw */ 12145331Samw pcnt = SMBADM_NPROP; 12155331Samw for (p = 0; p < pcnt; p++) 12165331Samw props[p].p_name = smbadm_ptable[p].p_name; 12175331Samw } 12185331Samw 12195331Samw for (p = 0; p < pcnt; p++) { 12205331Samw phandle = smbadm_prop_gethandle(props[p].p_name); 12215331Samw if (phandle) { 12225331Samw if (phandle->p_getfn(gname, &props[p]) != 0) 12235331Samw ret = 1; 12245331Samw } 12255331Samw } 12265331Samw 12275331Samw return (ret); 12285331Samw } 12295331Samw 12305331Samw /* 12315331Samw * smbadm_group_addmember 12325331Samw * 12335331Samw */ 12345331Samw static int 12355331Samw smbadm_group_addmember(int argc, char **argv) 12365331Samw { 12375331Samw char *gname = NULL; 12385331Samw char **mname; 12395331Samw char option; 12405772Sas200622 smb_gsid_t msid; 12415772Sas200622 int status; 12425331Samw int mcnt = 0; 12435331Samw int ret = 0; 12445331Samw int i; 12455331Samw 12465331Samw 12475331Samw mname = (char **)malloc(argc * sizeof (char *)); 12485331Samw if (mname == NULL) { 12498334SJose.Borrego@Sun.COM warn(gettext("failed to add group member")); 12505331Samw return (1); 12515331Samw } 12525331Samw bzero(mname, argc * sizeof (char *)); 12535331Samw 12545331Samw while ((option = getopt(argc, argv, "m:")) != -1) { 12555331Samw switch (option) { 12565331Samw case 'm': 12575331Samw mname[mcnt++] = optarg; 12585331Samw break; 12595331Samw 12605331Samw default: 12615331Samw free(mname); 12625331Samw smbadm_usage(B_FALSE); 12635331Samw } 12645331Samw } 12655331Samw 12665331Samw if (mcnt == 0) { 12675331Samw (void) fprintf(stderr, gettext("missing member name\n")); 12685331Samw free(mname); 12695331Samw smbadm_usage(B_FALSE); 12705331Samw } 12715331Samw 12725331Samw gname = argv[optind]; 12735331Samw if (optind >= argc || gname == NULL || *gname == 0) { 12745331Samw (void) fprintf(stderr, gettext("missing group name\n")); 12755331Samw free(mname); 12765331Samw smbadm_usage(B_FALSE); 12775331Samw } 12785331Samw 12795331Samw 12805331Samw for (i = 0; i < mcnt; i++) { 12815331Samw if (mname[i] == NULL) 12825331Samw continue; 12835331Samw 12845772Sas200622 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 12855772Sas200622 (void) fprintf(stderr, 12868334SJose.Borrego@Sun.COM gettext("failed to add %s: unable to obtain SID\n"), 12875772Sas200622 mname[i]); 12885772Sas200622 continue; 12895772Sas200622 } 12905772Sas200622 12915772Sas200622 status = smb_lgrp_add_member(gname, msid.gs_sid, msid.gs_type); 12925772Sas200622 free(msid.gs_sid); 12935772Sas200622 if (status != SMB_LGRP_SUCCESS) { 12945331Samw (void) fprintf(stderr, 12955331Samw gettext("failed to add %s (%s)\n"), 12965772Sas200622 mname[i], smb_lgrp_strerror(status)); 12975331Samw ret = 1; 12985772Sas200622 } else { 12995772Sas200622 (void) printf(gettext("'%s' is now a member of '%s'\n"), 13005772Sas200622 mname[i], gname); 13015331Samw } 13025331Samw } 13035331Samw 13045331Samw free(mname); 13055331Samw return (ret); 13065331Samw } 13075331Samw 13085331Samw /* 13095331Samw * smbadm_group_delmember 13105331Samw */ 13115331Samw static int 13125331Samw smbadm_group_delmember(int argc, char **argv) 13135331Samw { 13145331Samw char *gname = NULL; 13155331Samw char **mname; 13165331Samw char option; 13175772Sas200622 smb_gsid_t msid; 13185772Sas200622 int status; 13195331Samw int mcnt = 0; 13205331Samw int ret = 0; 13215331Samw int i; 13225331Samw 13235331Samw mname = (char **)malloc(argc * sizeof (char *)); 13245331Samw if (mname == NULL) { 13258334SJose.Borrego@Sun.COM warn(gettext("failed to delete group member")); 13265331Samw return (1); 13275331Samw } 13285331Samw bzero(mname, argc * sizeof (char *)); 13295331Samw 13305331Samw while ((option = getopt(argc, argv, "m:")) != -1) { 13315331Samw switch (option) { 13325331Samw case 'm': 13335331Samw mname[mcnt++] = optarg; 13345331Samw break; 13355331Samw 13365331Samw default: 13375331Samw free(mname); 13385331Samw smbadm_usage(B_FALSE); 13395331Samw } 13405331Samw } 13415331Samw 13425331Samw if (mcnt == 0) { 13435331Samw (void) fprintf(stderr, gettext("missing member name\n")); 13445331Samw free(mname); 13455331Samw smbadm_usage(B_FALSE); 13465331Samw } 13475331Samw 13485331Samw gname = argv[optind]; 13495331Samw if (optind >= argc || gname == NULL || *gname == 0) { 13505331Samw (void) fprintf(stderr, gettext("missing group name\n")); 13515331Samw free(mname); 13525331Samw smbadm_usage(B_FALSE); 13535331Samw } 13545331Samw 13555331Samw 13565331Samw for (i = 0; i < mcnt; i++) { 13575331Samw if (mname[i] == NULL) 13585331Samw continue; 13595331Samw 13605772Sas200622 if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { 13615772Sas200622 (void) fprintf(stderr, 13628334SJose.Borrego@Sun.COM gettext("failed to remove %s: " 13638334SJose.Borrego@Sun.COM "unable to obtain SID\n"), 13645772Sas200622 mname[i]); 13655772Sas200622 continue; 13665772Sas200622 } 13675772Sas200622 13685772Sas200622 status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type); 13695772Sas200622 free(msid.gs_sid); 13705772Sas200622 if (status != SMB_LGRP_SUCCESS) { 13715331Samw (void) fprintf(stderr, 13725331Samw gettext("failed to remove %s (%s)\n"), 13735772Sas200622 mname[i], smb_lgrp_strerror(status)); 13745331Samw ret = 1; 13755331Samw } else { 13765331Samw (void) printf( 13775772Sas200622 gettext("'%s' has been removed from %s\n"), 13785331Samw mname[i], gname); 13795331Samw } 13805331Samw } 13815331Samw 13825331Samw return (ret); 13835331Samw } 13845331Samw 13855331Samw static int 13865331Samw smbadm_user_disable(int argc, char **argv) 13875331Samw { 13885331Samw int error; 13895331Samw char *user = NULL; 13905331Samw 13915331Samw user = argv[optind]; 13925331Samw if (optind >= argc || user == NULL || *user == '\0') { 13935331Samw (void) fprintf(stderr, gettext("missing user name\n")); 13945331Samw smbadm_usage(B_FALSE); 13955331Samw } 13965331Samw 13975331Samw error = smb_pwd_setcntl(user, SMB_PWC_DISABLE); 13985331Samw if (error == SMB_PWE_SUCCESS) 13995331Samw (void) printf(gettext("%s is disabled.\n"), user); 14005331Samw else 14015331Samw (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 14025331Samw 14035331Samw return (error); 14045331Samw } 14055331Samw 14065331Samw static int 14075331Samw smbadm_user_enable(int argc, char **argv) 14085331Samw { 14095331Samw int error; 14105331Samw char *user = NULL; 14115331Samw 14125331Samw user = argv[optind]; 14135331Samw if (optind >= argc || user == NULL || *user == '\0') { 14145331Samw (void) fprintf(stderr, gettext("missing user name\n")); 14155331Samw smbadm_usage(B_FALSE); 14165331Samw } 14175331Samw 14185331Samw error = smb_pwd_setcntl(user, SMB_PWC_ENABLE); 14195331Samw if (error == SMB_PWE_SUCCESS) 14205331Samw (void) printf(gettext("%s is enabled.\n"), user); 14215331Samw else 14225331Samw (void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error)); 14235331Samw 14245331Samw return (error); 14255331Samw } 14265331Samw 14275331Samw 14285331Samw int 14295331Samw main(int argc, char **argv) 14305331Samw { 14315772Sas200622 int ret; 14325331Samw int i; 14335331Samw 14345331Samw (void) malloc(0); /* satisfy libumem dependency */ 14355331Samw 14365331Samw progname = basename(argv[0]); 14375331Samw 14385331Samw if (getzoneid() != GLOBAL_ZONEID) { 14395331Samw (void) fprintf(stderr, 14405331Samw gettext("cannot execute in non-global zone\n")); 14415331Samw return (0); 14425331Samw } 14435331Samw 14445331Samw if (is_system_labeled()) { 14455331Samw (void) fprintf(stderr, 14465331Samw gettext("Trusted Extensions not supported\n")); 14475331Samw return (0); 14485331Samw } 14495331Samw 14505331Samw if (argc < 2) { 14515331Samw (void) fprintf(stderr, gettext("missing command\n")); 14525331Samw smbadm_usage(B_FALSE); 14535331Samw } 14545331Samw 14555331Samw /* 14565331Samw * Special case "cmd --help/-?" 14575331Samw */ 14585331Samw if (strcmp(argv[1], "-?") == 0 || 14595331Samw strcmp(argv[1], "--help") == 0 || 14605331Samw strcmp(argv[1], "-h") == 0) 14615331Samw smbadm_usage(B_TRUE); 14625331Samw 14635331Samw for (i = 0; i < SMBADM_NCMD; ++i) { 14645331Samw curcmd = &smbadm_cmdtable[i]; 14655331Samw if (strcasecmp(argv[1], curcmd->name) == 0) { 14665331Samw if (argc > 2) { 14675331Samw /* cmd subcmd --help/-? */ 14685331Samw if (strcmp(argv[2], "-?") == 0 || 14695331Samw strcmp(argv[2], "--help") == 0 || 14705331Samw strcmp(argv[2], "-h") == 0) 14715331Samw smbadm_usage(B_TRUE); 14725331Samw } 14735331Samw 14747052Samw if ((ret = smbadm_init()) != 0) 14756139Sjb150015 return (ret); 14765772Sas200622 14775772Sas200622 ret = curcmd->func(argc - 1, &argv[1]); 14786139Sjb150015 14797052Samw smbadm_fini(); 14805772Sas200622 return (ret); 14815331Samw } 14825331Samw } 14835331Samw 14845331Samw curcmd = NULL; 14855331Samw (void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]); 14865331Samw smbadm_usage(B_FALSE); 14875331Samw return (2); 14885331Samw } 14895331Samw 14906139Sjb150015 static int 14917052Samw smbadm_init(void) 14926139Sjb150015 { 14936139Sjb150015 int rc; 14946139Sjb150015 14957052Samw switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 14967052Samw case SMBADM_CMDF_GROUP: 14976139Sjb150015 if (smb_idmap_start() != 0) { 14986139Sjb150015 (void) fprintf(stderr, 14996139Sjb150015 gettext("failed to contact idmap service\n")); 15006139Sjb150015 return (1); 15016139Sjb150015 } 15026139Sjb150015 15036139Sjb150015 if ((rc = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { 15046139Sjb150015 (void) fprintf(stderr, 15056139Sjb150015 gettext("failed to initialize (%s)\n"), 15066139Sjb150015 smb_lgrp_strerror(rc)); 15076139Sjb150015 smb_idmap_stop(); 15086139Sjb150015 return (1); 15096139Sjb150015 } 15107052Samw break; 15117052Samw 15127052Samw case SMBADM_CMDF_USER: 15137052Samw smb_pwd_init(B_FALSE); 15147052Samw break; 15157052Samw 15167052Samw default: 15177052Samw break; 15186139Sjb150015 } 15196139Sjb150015 15206139Sjb150015 return (0); 15216139Sjb150015 } 15226139Sjb150015 15236139Sjb150015 static void 15247052Samw smbadm_fini(void) 15256139Sjb150015 { 15267052Samw switch (curcmd->flags & SMBADM_CMDF_TYPEMASK) { 15277052Samw case SMBADM_CMDF_GROUP: 15286139Sjb150015 smb_lgrp_stop(); 15296139Sjb150015 smb_idmap_stop(); 15307052Samw break; 15317052Samw 15327052Samw case SMBADM_CMDF_USER: 15337052Samw smb_pwd_fini(); 15347052Samw break; 15357052Samw 15367052Samw default: 15377052Samw break; 15386139Sjb150015 } 15396139Sjb150015 } 15406139Sjb150015 15415331Samw static boolean_t 15425331Samw smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval) 15435331Samw { 15445331Samw smbadm_prop_handle_t *pinfo; 15455331Samw int i; 15465331Samw 15475331Samw for (i = 0; i < SMBADM_NPROP; i++) { 15485331Samw pinfo = &smbadm_ptable[i]; 15495331Samw if (strcmp(pinfo->p_name, prop->p_name) == 0) { 15505331Samw if (pinfo->p_chkfn && chkval) 15515331Samw return (pinfo->p_chkfn(prop)); 15525331Samw 15535331Samw return (B_TRUE); 15545331Samw } 15555331Samw } 15565331Samw 15578334SJose.Borrego@Sun.COM (void) fprintf(stderr, gettext("unrecognized property '%s'\n"), 15588334SJose.Borrego@Sun.COM prop->p_name); 15595331Samw 15605331Samw return (B_FALSE); 15615331Samw } 15625331Samw 15635331Samw static int 15645331Samw smbadm_prop_parse(char *arg, smbadm_prop_t *prop) 15655331Samw { 15665331Samw boolean_t parse_value; 15675331Samw char *equal; 15685331Samw 15695331Samw if (arg == NULL) 15705331Samw return (2); 15715331Samw 15725331Samw prop->p_name = prop->p_value = NULL; 15735331Samw 15745331Samw if (strcmp(curcmd->name, "set") == 0) 15755331Samw parse_value = B_TRUE; 15765331Samw else 15775331Samw parse_value = B_FALSE; 15785331Samw 15795331Samw prop->p_name = arg; 15805331Samw 15815331Samw if (parse_value) { 15825331Samw equal = strchr(arg, '='); 15835331Samw if (equal == NULL) 15845331Samw return (2); 15855331Samw 15865331Samw *equal++ = '\0'; 15875331Samw prop->p_value = equal; 15885331Samw } 15895331Samw 15905331Samw if (smbadm_prop_validate(prop, parse_value) == B_FALSE) 15915331Samw return (2); 15925331Samw 15935331Samw return (0); 15945331Samw } 15955331Samw 15965331Samw static smbadm_prop_handle_t * 15975331Samw smbadm_prop_gethandle(char *pname) 15985331Samw { 15995331Samw int i; 16005331Samw 16015331Samw for (i = 0; i < SMBADM_NPROP; i++) 16025331Samw if (strcmp(pname, smbadm_ptable[i].p_name) == 0) 16035331Samw return (&smbadm_ptable[i]); 16045331Samw 16055331Samw return (NULL); 16065331Samw } 16075331Samw 16085331Samw static int 16095331Samw smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) 16105331Samw { 16115772Sas200622 int status; 16125331Samw 16135772Sas200622 status = smb_lgrp_setcmnt(gname, prop->p_value); 16145772Sas200622 if (status != SMB_LGRP_SUCCESS) { 16155331Samw (void) fprintf(stderr, 16165331Samw gettext("failed to modify the group description (%s)\n"), 16175772Sas200622 smb_lgrp_strerror(status)); 16185331Samw return (1); 16195331Samw } 16205331Samw 16218334SJose.Borrego@Sun.COM (void) printf(gettext("%s: description modified\n"), gname); 16225331Samw return (0); 16235331Samw } 16245331Samw 16255331Samw static int 16265331Samw smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) 16275331Samw { 16285772Sas200622 char *cmnt = NULL; 16295772Sas200622 int status; 16305331Samw 16315772Sas200622 status = smb_lgrp_getcmnt(gname, &cmnt); 16325772Sas200622 if (status != SMB_LGRP_SUCCESS) { 16335331Samw (void) fprintf(stderr, 16345772Sas200622 gettext("failed to get the group description (%s)\n"), 16355772Sas200622 smb_lgrp_strerror(status)); 16365331Samw return (1); 16375331Samw } 16385331Samw 16395772Sas200622 (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); 16405772Sas200622 free(cmnt); 16415331Samw return (0); 16425331Samw } 16435331Samw 16445331Samw static int 16455772Sas200622 smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 16465331Samw { 16475772Sas200622 boolean_t enable; 16485772Sas200622 int status; 16495331Samw int ret; 16505331Samw 16515331Samw if (strcasecmp(prop->p_value, "on") == 0) { 16525331Samw (void) printf(gettext("Enabling %s privilege "), prop->p_name); 16535772Sas200622 enable = B_TRUE; 16545331Samw } else { 16555331Samw (void) printf(gettext("Disabling %s privilege "), prop->p_name); 16565772Sas200622 enable = B_FALSE; 16575331Samw } 16585331Samw 16595772Sas200622 status = smb_lgrp_setpriv(gname, priv_id, enable); 16605772Sas200622 if (status == SMB_LGRP_SUCCESS) { 16615331Samw (void) printf(gettext("succeeded\n")); 16625331Samw ret = 0; 16635331Samw } else { 16645772Sas200622 (void) printf(gettext("failed: %s\n"), 16655772Sas200622 smb_lgrp_strerror(status)); 16665331Samw ret = 1; 16675331Samw } 16685331Samw 16695331Samw return (ret); 16705331Samw } 16715331Samw 16725331Samw static int 16735772Sas200622 smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) 16745331Samw { 16755772Sas200622 boolean_t enable; 16765772Sas200622 int status; 16775331Samw 16785772Sas200622 status = smb_lgrp_getpriv(gname, priv_id, &enable); 16795772Sas200622 if (status != SMB_LGRP_SUCCESS) { 16805331Samw (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), 16815772Sas200622 prop->p_name, smb_lgrp_strerror(status)); 16825331Samw return (1); 16835331Samw } 16845331Samw 16855772Sas200622 (void) printf(gettext("\t%s: %s\n"), prop->p_name, 16865772Sas200622 (enable) ? "On" : "Off"); 16875331Samw 16885331Samw return (0); 16895331Samw } 16905331Samw 16915331Samw static int 16925331Samw smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop) 16935331Samw { 16945331Samw return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 16955331Samw } 16965331Samw 16975331Samw static int 16985331Samw smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop) 16995331Samw { 17005331Samw return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop)); 17015331Samw } 17025331Samw 17035331Samw static int 17045331Samw smbadm_setprop_backup(char *gname, smbadm_prop_t *prop) 17055331Samw { 17065331Samw return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop)); 17075331Samw } 17085331Samw 17095331Samw static int 17105331Samw smbadm_getprop_backup(char *gname, smbadm_prop_t *prop) 17115331Samw { 17125331Samw return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop)); 17135331Samw } 17145331Samw 17155331Samw static int 17165331Samw smbadm_setprop_restore(char *gname, smbadm_prop_t *prop) 17175331Samw { 17185331Samw return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop)); 17195331Samw } 17205331Samw 17215331Samw static int 17225331Samw smbadm_getprop_restore(char *gname, smbadm_prop_t *prop) 17235331Samw { 17245331Samw return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop)); 17255331Samw } 17265331Samw 17275331Samw static boolean_t 17285331Samw smbadm_chkprop_priv(smbadm_prop_t *prop) 17295331Samw { 17305331Samw if (prop->p_value == NULL || *prop->p_value == '\0') { 17315331Samw (void) fprintf(stderr, 17325331Samw gettext("missing value for '%s'\n"), prop->p_name); 17335331Samw return (B_FALSE); 17345331Samw } 17355331Samw 17365331Samw if (strcasecmp(prop->p_value, "on") == 0) 17375331Samw return (B_TRUE); 17385331Samw 17395331Samw if (strcasecmp(prop->p_value, "off") == 0) 17405331Samw return (B_TRUE); 17415331Samw 17425331Samw (void) fprintf(stderr, 17435331Samw gettext("%s: unrecognized value for '%s' property\n"), 17445331Samw prop->p_value, prop->p_name); 17455331Samw 17465331Samw return (B_FALSE); 17475331Samw } 17485331Samw 17495331Samw static const char * 17505331Samw smbadm_pwd_strerror(int error) 17515331Samw { 17525331Samw switch (error) { 17535331Samw case SMB_PWE_SUCCESS: 17545331Samw return (gettext("Success.")); 17555331Samw 17565331Samw case SMB_PWE_USER_UNKNOWN: 17575331Samw return (gettext("User does not exist.")); 17585331Samw 17595331Samw case SMB_PWE_USER_DISABLE: 17608334SJose.Borrego@Sun.COM return (gettext("User is disabled.")); 17615331Samw 17625331Samw case SMB_PWE_CLOSE_FAILED: 17635331Samw case SMB_PWE_OPEN_FAILED: 17645331Samw case SMB_PWE_WRITE_FAILED: 17655331Samw case SMB_PWE_UPDATE_FAILED: 17665331Samw return (gettext("Unexpected failure. " 17675331Samw "SMB password database unchanged.")); 17685331Samw 17695331Samw case SMB_PWE_STAT_FAILED: 17705331Samw return (gettext("stat of SMB password file failed.")); 17715331Samw 17725331Samw case SMB_PWE_BUSY: 17735331Samw return (gettext("SMB password database busy. " 17745331Samw "Try again later.")); 17755331Samw 17765331Samw case SMB_PWE_DENIED: 17775331Samw return (gettext("Operation not permitted.")); 17785331Samw 17795331Samw case SMB_PWE_SYSTEM_ERROR: 17805331Samw return (gettext("System error.")); 17817052Samw 17827052Samw default: 17837052Samw break; 17845331Samw } 17855331Samw 17865331Samw return (gettext("Unknown error code.")); 17875331Samw } 17885331Samw 17895331Samw /* 17905331Samw * Enable libumem debugging by default on DEBUG builds. 17915331Samw */ 17925331Samw #ifdef DEBUG 17935331Samw const char * 17945331Samw _umem_debug_init(void) 17955331Samw { 17965331Samw return ("default,verbose"); /* $UMEM_DEBUG setting */ 17975331Samw } 17985331Samw 17995331Samw const char * 18005331Samw _umem_logging_init(void) 18015331Samw { 18025331Samw return ("fail,contents"); /* $UMEM_LOGGING setting */ 18035331Samw } 18045331Samw #endif 1805