xref: /onnv-gate/usr/src/cmd/smbsrv/smbadm/smbadm.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw /*
29*5331Samw  * This module contains smbadm CLI which offers smb configuration
30*5331Samw  * functionalities.
31*5331Samw  */
32*5331Samw #include <stdlib.h>
33*5331Samw #include <stdio.h>
34*5331Samw #include <syslog.h>
35*5331Samw #include <strings.h>
36*5331Samw #include <limits.h>
37*5331Samw #include <getopt.h>
38*5331Samw #include <libintl.h>
39*5331Samw #include <zone.h>
40*5331Samw #include <grp.h>
41*5331Samw #include <libgen.h>
42*5331Samw 
43*5331Samw #include <smbsrv/libsmb.h>
44*5331Samw #include <smbsrv/libmlsvc.h>
45*5331Samw 
46*5331Samw typedef enum {
47*5331Samw 	HELP_ADD_MEMBER,
48*5331Samw 	HELP_CREATE,
49*5331Samw 	HELP_DELETE,
50*5331Samw 	HELP_DEL_MEMBER,
51*5331Samw 	HELP_GET,
52*5331Samw 	HELP_JOIN,
53*5331Samw 	HELP_LIST,
54*5331Samw 	HELP_RENAME,
55*5331Samw 	HELP_SET,
56*5331Samw 	HELP_SHOW,
57*5331Samw 	HELP_UDISABLE,
58*5331Samw 	HELP_UENABLE
59*5331Samw } smbadm_help_t;
60*5331Samw 
61*5331Samw typedef struct smbadm_cmdinfo {
62*5331Samw 	char *name;
63*5331Samw 	int (*func)(int, char **);
64*5331Samw 	smbadm_help_t usage;
65*5331Samw } smbadm_cmdinfo_t;
66*5331Samw 
67*5331Samw smbadm_cmdinfo_t *curcmd;
68*5331Samw static char *progname;
69*5331Samw 
70*5331Samw static int smbadm_join(int, char **);
71*5331Samw static int smbadm_list(int, char **);
72*5331Samw static int smbadm_group_create(int, char **);
73*5331Samw static int smbadm_group_delete(int, char **);
74*5331Samw static int smbadm_group_rename(int, char **);
75*5331Samw static int smbadm_group_show(int, char **);
76*5331Samw static int smbadm_group_getprop(int, char **);
77*5331Samw static int smbadm_group_setprop(int, char **);
78*5331Samw static int smbadm_group_addmember(int, char **);
79*5331Samw static int smbadm_group_delmember(int, char **);
80*5331Samw static int smbadm_user_disable(int, char **);
81*5331Samw static int smbadm_user_enable(int, char **);
82*5331Samw 
83*5331Samw static smbadm_cmdinfo_t smbadm_cmdtable[] =
84*5331Samw {
85*5331Samw 	{ "add-member",		smbadm_group_addmember,	HELP_ADD_MEMBER	},
86*5331Samw 	{ "create",		smbadm_group_create,	HELP_CREATE	},
87*5331Samw 	{ "delete",		smbadm_group_delete,	HELP_DELETE	},
88*5331Samw 	{ "disable-user",	smbadm_user_disable,	HELP_UDISABLE	},
89*5331Samw 	{ "enable-user",	smbadm_user_enable,	HELP_UENABLE	},
90*5331Samw 	{ "get",		smbadm_group_getprop,	HELP_GET	},
91*5331Samw 	{ "join",		smbadm_join,		HELP_JOIN	},
92*5331Samw 	{ "list",		smbadm_list,		HELP_LIST	},
93*5331Samw 	{ "remove-member",	smbadm_group_delmember,	HELP_DEL_MEMBER	},
94*5331Samw 	{ "rename",		smbadm_group_rename,	HELP_RENAME	},
95*5331Samw 	{ "set",		smbadm_group_setprop,	HELP_SET	},
96*5331Samw 	{ "show",		smbadm_group_show,	HELP_SHOW	},
97*5331Samw };
98*5331Samw 
99*5331Samw #define	SMBADM_NCMD	(sizeof (smbadm_cmdtable) / sizeof (smbadm_cmdtable[0]))
100*5331Samw 
101*5331Samw typedef struct smbadm_prop {
102*5331Samw 	char *p_name;
103*5331Samw 	char *p_value;
104*5331Samw } smbadm_prop_t;
105*5331Samw 
106*5331Samw typedef struct smbadm_prop_handle {
107*5331Samw 	char *p_name;
108*5331Samw 	char *p_dispvalue;
109*5331Samw 	int (*p_setfn)(char *, smbadm_prop_t *);
110*5331Samw 	int (*p_getfn)(char *, smbadm_prop_t *);
111*5331Samw 	boolean_t (*p_chkfn)(smbadm_prop_t *);
112*5331Samw } smbadm_prop_handle_t;
113*5331Samw 
114*5331Samw static boolean_t smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval);
115*5331Samw static int smbadm_prop_parse(char *arg, smbadm_prop_t *prop);
116*5331Samw static smbadm_prop_handle_t *smbadm_prop_gethandle(char *pname);
117*5331Samw 
118*5331Samw static boolean_t smbadm_chkprop_priv(smbadm_prop_t *prop);
119*5331Samw static int smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop);
120*5331Samw static int smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop);
121*5331Samw static int smbadm_setprop_backup(char *gname, smbadm_prop_t *prop);
122*5331Samw static int smbadm_getprop_backup(char *gname, smbadm_prop_t *prop);
123*5331Samw static int smbadm_setprop_restore(char *gname, smbadm_prop_t *prop);
124*5331Samw static int smbadm_getprop_restore(char *gname, smbadm_prop_t *prop);
125*5331Samw static int smbadm_setprop_desc(char *gname, smbadm_prop_t *prop);
126*5331Samw static int smbadm_getprop_desc(char *gname, smbadm_prop_t *prop);
127*5331Samw 
128*5331Samw static smbadm_prop_handle_t smbadm_ptable[] = {
129*5331Samw 	{"backup",	"on | off", 	smbadm_setprop_backup,
130*5331Samw 	smbadm_getprop_backup,	smbadm_chkprop_priv 	},
131*5331Samw 	{"restore",	"on | off",	smbadm_setprop_restore,
132*5331Samw 	smbadm_getprop_restore,	smbadm_chkprop_priv	},
133*5331Samw 	{"take-ownership", "on | off",	smbadm_setprop_tkowner,
134*5331Samw 	smbadm_getprop_tkowner,	smbadm_chkprop_priv	},
135*5331Samw 	{"description",	"<string>",	smbadm_setprop_desc,
136*5331Samw 	smbadm_getprop_desc,	NULL			},
137*5331Samw };
138*5331Samw 
139*5331Samw static const char *smbadm_pwd_strerror(int error);
140*5331Samw 
141*5331Samw /*
142*5331Samw  * Number of supported properties
143*5331Samw  */
144*5331Samw #define	SMBADM_NPROP	(sizeof (smbadm_ptable) / sizeof (smbadm_ptable[0]))
145*5331Samw 
146*5331Samw static void
147*5331Samw smbadm_cmdusage(FILE *fp, smbadm_cmdinfo_t *cmd)
148*5331Samw {
149*5331Samw 	switch (cmd->usage) {
150*5331Samw 	case HELP_ADD_MEMBER:
151*5331Samw 		(void) fprintf(fp,
152*5331Samw 		    gettext("\t%s -m member [[-m member] ...] group\n"),
153*5331Samw 		    cmd->name);
154*5331Samw 		return;
155*5331Samw 
156*5331Samw 	case HELP_CREATE:
157*5331Samw 		(void) fprintf(fp, gettext("\t%s [-d description] group\n"),
158*5331Samw 		    cmd->name);
159*5331Samw 		return;
160*5331Samw 
161*5331Samw 	case HELP_DELETE:
162*5331Samw 		(void) fprintf(fp, gettext("\t%s group\n"), cmd->name);
163*5331Samw 		return;
164*5331Samw 
165*5331Samw 	case HELP_UDISABLE:
166*5331Samw 	case HELP_UENABLE:
167*5331Samw 		(void) fprintf(fp, gettext("\t%s user\n"), cmd->name);
168*5331Samw 		return;
169*5331Samw 
170*5331Samw 	case HELP_GET:
171*5331Samw 		(void) fprintf(fp, gettext("\t%s [[-p property] ...] group\n"),
172*5331Samw 		    cmd->name);
173*5331Samw 		return;
174*5331Samw 
175*5331Samw 	case HELP_JOIN:
176*5331Samw 		(void) fprintf(fp, gettext("\t%s -u username domain\n"
177*5331Samw 		    "\t%s -w workgroup\n"), cmd->name, cmd->name);
178*5331Samw 		return;
179*5331Samw 
180*5331Samw 	case HELP_LIST:
181*5331Samw 		(void) fprintf(fp, gettext("\t%s\n"), cmd->name);
182*5331Samw 		return;
183*5331Samw 
184*5331Samw 	case HELP_DEL_MEMBER:
185*5331Samw 		(void) fprintf(fp,
186*5331Samw 		    gettext("\t%s -m member [[-m member] ...] group\n"),
187*5331Samw 		    cmd->name);
188*5331Samw 		return;
189*5331Samw 
190*5331Samw 	case HELP_RENAME:
191*5331Samw 		(void) fprintf(fp, gettext("\t%s group new-group\n"),
192*5331Samw 		    cmd->name);
193*5331Samw 		return;
194*5331Samw 
195*5331Samw 	case HELP_SET:
196*5331Samw 		(void) fprintf(fp, gettext("\t%s -p property=value "
197*5331Samw 		    "[[-p property=value] ...] group\n"), cmd->name);
198*5331Samw 		return;
199*5331Samw 
200*5331Samw 	case HELP_SHOW:
201*5331Samw 		(void) fprintf(fp, gettext("\t%s [-m] [-p] [group]\n"),
202*5331Samw 		    cmd->name);
203*5331Samw 		return;
204*5331Samw 
205*5331Samw 	}
206*5331Samw 
207*5331Samw 	abort();
208*5331Samw 	/* NOTREACHED */
209*5331Samw }
210*5331Samw 
211*5331Samw static void
212*5331Samw smbadm_usage(boolean_t requested)
213*5331Samw {
214*5331Samw 	FILE *fp = requested ? stdout : stderr;
215*5331Samw 	boolean_t show_props = B_FALSE;
216*5331Samw 	int i;
217*5331Samw 
218*5331Samw 	if (curcmd == NULL) {
219*5331Samw 		(void) fprintf(fp,
220*5331Samw 		    gettext("usage: %s [-h | <command> [options]]\n"),
221*5331Samw 		    progname);
222*5331Samw 		(void) fprintf(fp,
223*5331Samw 		    gettext("where 'command' is one of the following:\n\n"));
224*5331Samw 
225*5331Samw 		for (i = 0; i < SMBADM_NCMD; i++)
226*5331Samw 			smbadm_cmdusage(fp, &smbadm_cmdtable[i]);
227*5331Samw 
228*5331Samw 		(void) fprintf(fp,
229*5331Samw 		    gettext("\nFor property list, run %s %s|%s\n"),
230*5331Samw 		    progname, "get", "set");
231*5331Samw 
232*5331Samw 		exit(requested ? 0 : 2);
233*5331Samw 	}
234*5331Samw 
235*5331Samw 	(void) fprintf(fp, gettext("usage:\n"));
236*5331Samw 	smbadm_cmdusage(fp, curcmd);
237*5331Samw 
238*5331Samw 	if (strcmp(curcmd->name, "get") == 0 ||
239*5331Samw 	    strcmp(curcmd->name, "set") == 0)
240*5331Samw 		show_props = B_TRUE;
241*5331Samw 
242*5331Samw 	if (show_props) {
243*5331Samw 		(void) fprintf(fp,
244*5331Samw 		    gettext("\nThe following properties are supported:\n"));
245*5331Samw 
246*5331Samw 		(void) fprintf(fp, "\n\t%-16s   %s\n\n",
247*5331Samw 		    "PROPERTY", "VALUES");
248*5331Samw 
249*5331Samw 		for (i = 0; i < SMBADM_NPROP; i++) {
250*5331Samw 			(void) fprintf(fp, "\t%-16s   %s\n",
251*5331Samw 			    smbadm_ptable[i].p_name,
252*5331Samw 			    smbadm_ptable[i].p_dispvalue);
253*5331Samw 		}
254*5331Samw 	}
255*5331Samw 
256*5331Samw 	exit(requested ? 0 : 2);
257*5331Samw }
258*5331Samw 
259*5331Samw /*
260*5331Samw  * smbadm_join
261*5331Samw  *
262*5331Samw  * Join the given domain/workgroup
263*5331Samw  */
264*5331Samw static int
265*5331Samw smbadm_join(int argc, char **argv)
266*5331Samw {
267*5331Samw 	char option;
268*5331Samw 	smb_joininfo_t jdi;
269*5331Samw 	boolean_t join_w = B_FALSE;
270*5331Samw 	boolean_t join_d = B_FALSE;
271*5331Samw 	uint32_t status;
272*5331Samw 
273*5331Samw 	bzero(&jdi, sizeof (jdi));
274*5331Samw 
275*5331Samw 	while ((option = getopt(argc, argv, "u:w:")) != -1) {
276*5331Samw 		switch (option) {
277*5331Samw 		case 'w':
278*5331Samw 			(void) strlcpy(jdi.domain_name, optarg,
279*5331Samw 			    sizeof (jdi.domain_name));
280*5331Samw 			jdi.mode = SMB_SECMODE_WORKGRP;
281*5331Samw 			join_w = B_TRUE;
282*5331Samw 			break;
283*5331Samw 
284*5331Samw 		case 'u':
285*5331Samw 			/* admin username */
286*5331Samw 			(void) strlcpy(jdi.domain_username, optarg,
287*5331Samw 			    sizeof (jdi.domain_username));
288*5331Samw 			jdi.mode = SMB_SECMODE_DOMAIN;
289*5331Samw 			join_d = B_TRUE;
290*5331Samw 			break;
291*5331Samw 
292*5331Samw 		default:
293*5331Samw 			smbadm_usage(B_FALSE);
294*5331Samw 		}
295*5331Samw 	}
296*5331Samw 
297*5331Samw 	if (join_w && join_d) {
298*5331Samw 		(void) fprintf(stderr,
299*5331Samw 		    gettext("domain and workgroup "
300*5331Samw 		    "can not be specified together\n"));
301*5331Samw 		smbadm_usage(B_FALSE);
302*5331Samw 	}
303*5331Samw 
304*5331Samw 	if (join_d && (argv[optind] != NULL)) {
305*5331Samw 		(void) strlcpy(jdi.domain_name, argv[optind],
306*5331Samw 		    sizeof (jdi.domain_name));
307*5331Samw 	}
308*5331Samw 
309*5331Samw 	if (*jdi.domain_name == '\0') {
310*5331Samw 		(void) fprintf(stderr, gettext("missing %s name\n"),
311*5331Samw 		    (join_d) ? "domain" : "workgroup");
312*5331Samw 		smbadm_usage(B_FALSE);
313*5331Samw 	}
314*5331Samw 
315*5331Samw 	if (join_d && *jdi.domain_username == '\0') {
316*5331Samw 		(void) fprintf(stderr, gettext("missing username\n"));
317*5331Samw 		smbadm_usage(B_FALSE);
318*5331Samw 	}
319*5331Samw 
320*5331Samw 	if (join_w) {
321*5331Samw 		status = smb_join(&jdi);
322*5331Samw 		if (status == NT_STATUS_SUCCESS) {
323*5331Samw 			(void) printf(
324*5331Samw 			    gettext("Successfully joined workgroup '%s'\n"),
325*5331Samw 			    jdi.domain_name);
326*5331Samw 			return (0);
327*5331Samw 		}
328*5331Samw 
329*5331Samw 		(void) fprintf(stderr,
330*5331Samw 		    gettext("failed to join workgroup '%s' (%s)\n"),
331*5331Samw 		    jdi.domain_name, xlate_nt_status(status));
332*5331Samw 
333*5331Samw 		return (1);
334*5331Samw 	}
335*5331Samw 
336*5331Samw 	/* Join the domain */
337*5331Samw 	if (*jdi.domain_passwd == '\0') {
338*5331Samw 		char *p = NULL;
339*5331Samw 		char *prompt = gettext("Enter domain password: ");
340*5331Samw 		p = getpassphrase(prompt);
341*5331Samw 		if (!p) {
342*5331Samw 			(void) fprintf(stderr, gettext("missing password\n"));
343*5331Samw 			smbadm_usage(B_FALSE);
344*5331Samw 		}
345*5331Samw 
346*5331Samw 		(void) strlcpy(jdi.domain_passwd, p,
347*5331Samw 		    sizeof (jdi.domain_passwd));
348*5331Samw 	}
349*5331Samw 
350*5331Samw 	(void) printf(gettext("Joining '%s' ... this may take a minute ...\n"),
351*5331Samw 	    jdi.domain_name);
352*5331Samw 
353*5331Samw 	status = smb_join(&jdi);
354*5331Samw 
355*5331Samw 	switch (status) {
356*5331Samw 	case NT_STATUS_SUCCESS:
357*5331Samw 		(void) printf(gettext("Successfully joined domain '%s'\n"),
358*5331Samw 		    jdi.domain_name);
359*5331Samw 		return (0);
360*5331Samw 
361*5331Samw 	case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
362*5331Samw 		(void) fprintf(stderr, gettext("failed to find "
363*5331Samw 		    "any domain controllers for '%s'\n"),
364*5331Samw 		    jdi.domain_name);
365*5331Samw 		break;
366*5331Samw 
367*5331Samw 	default:
368*5331Samw 		(void) fprintf(stderr,
369*5331Samw 		    gettext("failed to join domain '%s' (%s)\n"),
370*5331Samw 		    jdi.domain_name, xlate_nt_status(status));
371*5331Samw 	}
372*5331Samw 
373*5331Samw 	return (1);
374*5331Samw }
375*5331Samw 
376*5331Samw /*
377*5331Samw  * smbadm_list
378*5331Samw  *
379*5331Samw  * Displays current security mode and domain/workgroup name.
380*5331Samw  */
381*5331Samw /*ARGSUSED*/
382*5331Samw static int
383*5331Samw smbadm_list(int argc, char **argv)
384*5331Samw {
385*5331Samw 	char resource_domain[SMB_PI_MAX_DOMAIN];
386*5331Samw 	int sec_mode;
387*5331Samw 	char *modename;
388*5331Samw 
389*5331Samw 	if (smbd_get_security_mode(&sec_mode)) {
390*5331Samw 		(void) fprintf(stderr,
391*5331Samw 		    gettext("failed to get the security mode\n"));
392*5331Samw 		return (1);
393*5331Samw 	}
394*5331Samw 
395*5331Samw 	modename = (sec_mode == SMB_SECMODE_DOMAIN) ? "domain" : "workgroup";
396*5331Samw 
397*5331Samw 	(void) printf(gettext("security mode: %s\n"),
398*5331Samw 	    smb_config_secmode_tostr(sec_mode));
399*5331Samw 
400*5331Samw 	if (smbd_get_param(SMB_CI_DOMAIN_NAME, resource_domain) != 0) {
401*5331Samw 		(void) fprintf(stderr,
402*5331Samw 		    gettext("failed to get the %s name\n"), modename);
403*5331Samw 		return (1);
404*5331Samw 	}
405*5331Samw 
406*5331Samw 	(void) printf(gettext("%s name: %s\n"),
407*5331Samw 	    modename, resource_domain);
408*5331Samw 
409*5331Samw 	return (0);
410*5331Samw }
411*5331Samw 
412*5331Samw /*
413*5331Samw  * smbadm_group_create
414*5331Samw  *
415*5331Samw  * Creates a local SMB group
416*5331Samw  */
417*5331Samw static int
418*5331Samw smbadm_group_create(int argc, char **argv)
419*5331Samw {
420*5331Samw 	char *gname = NULL;
421*5331Samw 	char *desc = NULL;
422*5331Samw 	char option;
423*5331Samw 	uint32_t status;
424*5331Samw 
425*5331Samw 	while ((option = getopt(argc, argv, "d:")) != -1) {
426*5331Samw 		switch (option) {
427*5331Samw 		case 'd':
428*5331Samw 			desc = optarg;
429*5331Samw 			break;
430*5331Samw 
431*5331Samw 		default:
432*5331Samw 			smbadm_usage(B_FALSE);
433*5331Samw 		}
434*5331Samw 	}
435*5331Samw 
436*5331Samw 	gname = argv[optind];
437*5331Samw 	if (optind >= argc || gname == NULL || *gname == '\0') {
438*5331Samw 		(void) fprintf(stderr, gettext("missing group name\n"));
439*5331Samw 		smbadm_usage(B_FALSE);
440*5331Samw 	}
441*5331Samw 
442*5331Samw 	if (getgrnam(gname) == NULL) {
443*5331Samw 		(void) fprintf(stderr,
444*5331Samw 		    gettext("failed to get the Solaris group\n"));
445*5331Samw 		(void) fprintf(stderr,
446*5331Samw 		    gettext("use 'groupadd' to add the Solaris group\n"));
447*5331Samw 		return (1);
448*5331Samw 	}
449*5331Samw 
450*5331Samw 	status = smb_group_add(gname, desc);
451*5331Samw 	if (status != NT_STATUS_SUCCESS) {
452*5331Samw 		(void) fprintf(stderr,
453*5331Samw 		    gettext("failed to create the group (%s)\n"),
454*5331Samw 		    xlate_nt_status(status));
455*5331Samw 	} else {
456*5331Samw 		(void) printf(gettext("Successfully created group '%s'\n"),
457*5331Samw 		    gname);
458*5331Samw 	}
459*5331Samw 
460*5331Samw 	return (status);
461*5331Samw }
462*5331Samw 
463*5331Samw /*
464*5331Samw  * smbadm_group_dump_members
465*5331Samw  *
466*5331Samw  * Dump group members details.
467*5331Samw  */
468*5331Samw static void
469*5331Samw smbadm_group_dump_members(char *gname)
470*5331Samw {
471*5331Samw 	ntgrp_member_list_t *members = NULL;
472*5331Samw 	int mem_cnt = 0;
473*5331Samw 	int offset = 0;
474*5331Samw 	uint32_t status;
475*5331Samw 	int i;
476*5331Samw 
477*5331Samw 	status = smb_group_member_count(gname, &mem_cnt);
478*5331Samw 	if (mem_cnt < 0) {
479*5331Samw 		(void) fprintf(stderr,
480*5331Samw 		    gettext("failed to get the group members (%s)\n"),
481*5331Samw 		    xlate_nt_status(status));
482*5331Samw 	}
483*5331Samw 
484*5331Samw 	if (mem_cnt == 0) {
485*5331Samw 		(void) printf(gettext("\tNo members\n"));
486*5331Samw 		return;
487*5331Samw 	}
488*5331Samw 
489*5331Samw 	(void) printf(gettext("\tMembers:\n"));
490*5331Samw 	while (smb_group_member_list(gname, offset, &members) == 0) {
491*5331Samw 		if (members == NULL)
492*5331Samw 			break;
493*5331Samw 
494*5331Samw 		for (i = 0; i < members->cnt; i++)
495*5331Samw 			(void) printf(gettext("\t\t%s\n"), members->members[i]);
496*5331Samw 
497*5331Samw 		offset += members->cnt;
498*5331Samw 		smb_group_free_memberlist(members, 0);
499*5331Samw 		if (offset >= mem_cnt)
500*5331Samw 			break;
501*5331Samw 	}
502*5331Samw }
503*5331Samw 
504*5331Samw /*
505*5331Samw  * smbadm_group_dump_privs
506*5331Samw  *
507*5331Samw  * Dump group privilege details.
508*5331Samw  */
509*5331Samw static void
510*5331Samw smbadm_group_dump_privs(char *gname, ntpriv_list_t *privs)
511*5331Samw {
512*5331Samw 	int privcnt = 0;
513*5331Samw 	uint32_t privval;
514*5331Samw 	char *name = NULL;
515*5331Samw 	int i;
516*5331Samw 
517*5331Samw 	(void) printf(gettext("\tPrivileges: \n"));
518*5331Samw 
519*5331Samw 	for (i = 0; i < privs->cnt; i++) {
520*5331Samw 		name = privs->privs[i]->name;
521*5331Samw 		if (name == NULL)
522*5331Samw 			continue;
523*5331Samw 
524*5331Samw 		if (smb_group_priv_get(gname, privs->privs[i]->id,
525*5331Samw 		    &privval) != 0) {
526*5331Samw 			continue;
527*5331Samw 		}
528*5331Samw 
529*5331Samw 		if (privval == SE_PRIVILEGE_ENABLED) {
530*5331Samw 			(void) printf(gettext("\t\t%s: On\n"), name);
531*5331Samw 		} else if (privval == SE_PRIVILEGE_DISABLED) {
532*5331Samw 			(void) printf(gettext("\t\t%s: Off\n"), name);
533*5331Samw 		} else {
534*5331Samw 			(void) printf(gettext("\t\t%s: %d\n"),
535*5331Samw 			    name, privval);
536*5331Samw 		}
537*5331Samw 
538*5331Samw 		name = NULL;
539*5331Samw 		privcnt++;
540*5331Samw 	}
541*5331Samw 
542*5331Samw 	if (privcnt == 0)
543*5331Samw 		(void) printf(gettext("\t\tNo privileges\n"));
544*5331Samw }
545*5331Samw 
546*5331Samw /*
547*5331Samw  * smbadm_group_dump
548*5331Samw  *
549*5331Samw  * Dump group details.
550*5331Samw  */
551*5331Samw static int
552*5331Samw smbadm_group_dump(ntgrp_list_t *list, boolean_t show_mem, boolean_t show_privs)
553*5331Samw {
554*5331Samw 	ntpriv_list_t *privs = NULL;
555*5331Samw 	char *gname;
556*5331Samw 	uint32_t status;
557*5331Samw 	int i;
558*5331Samw 
559*5331Samw 	if (show_privs) {
560*5331Samw 		if ((status = smb_group_priv_list(&privs)) != 0) {
561*5331Samw 			(void) fprintf(stderr,
562*5331Samw 			    gettext("failed to get privileges (%s)\n"),
563*5331Samw 			    xlate_nt_status(status));
564*5331Samw 			return (1);
565*5331Samw 		}
566*5331Samw 	}
567*5331Samw 
568*5331Samw 	for (i = 0; i < list->cnt; i++) {
569*5331Samw 		gname = list->groups[i].name;
570*5331Samw 
571*5331Samw 		(void) printf(gettext("%s (%s)\n"), gname,
572*5331Samw 		    list->groups[i].desc);
573*5331Samw 		(void) printf(gettext("\tType: %s, Attr: %X\n"),
574*5331Samw 		    list->groups[i].type, list->groups[i].attr);
575*5331Samw 		(void) printf(gettext("\tSID: %s\n"),
576*5331Samw 		    list->groups[i].sid);
577*5331Samw 
578*5331Samw 		if (show_privs)
579*5331Samw 			smbadm_group_dump_privs(gname, privs);
580*5331Samw 
581*5331Samw 		if (show_mem)
582*5331Samw 			smbadm_group_dump_members(list->groups[i].name);
583*5331Samw 	}
584*5331Samw 
585*5331Samw 	return (0);
586*5331Samw }
587*5331Samw 
588*5331Samw /*
589*5331Samw  * smbadm_group_show
590*5331Samw  *
591*5331Samw  */
592*5331Samw static int
593*5331Samw smbadm_group_show(int argc, char **argv)
594*5331Samw {
595*5331Samw 	char *gname = NULL;
596*5331Samw 	int cnt = 0;
597*5331Samw 	int offset = 0;
598*5331Samw 	boolean_t show_privs;
599*5331Samw 	boolean_t show_members;
600*5331Samw 	char option;
601*5331Samw 	uint32_t status;
602*5331Samw 	ntgrp_list_t *list = NULL;
603*5331Samw 	int ret = 0;
604*5331Samw 
605*5331Samw 	show_privs = show_members = B_FALSE;
606*5331Samw 
607*5331Samw 	while ((option = getopt(argc, argv, "mp")) != -1) {
608*5331Samw 		switch (option) {
609*5331Samw 		case 'm':
610*5331Samw 			show_members = B_TRUE;
611*5331Samw 			break;
612*5331Samw 		case 'p':
613*5331Samw 			show_privs = B_TRUE;
614*5331Samw 			break;
615*5331Samw 
616*5331Samw 		default:
617*5331Samw 			smbadm_usage(B_FALSE);
618*5331Samw 		}
619*5331Samw 	}
620*5331Samw 
621*5331Samw 	gname = argv[optind];
622*5331Samw 	if (optind >= argc || gname == NULL || *gname == '\0')
623*5331Samw 		gname = "*";
624*5331Samw 
625*5331Samw 	status = smb_group_count(&cnt);
626*5331Samw 	if ((status != NT_STATUS_SUCCESS) || (cnt < 0)) {
627*5331Samw 		(void) fprintf(stderr,
628*5331Samw 		    gettext("failed to get the number of group(s) (%s)\n"),
629*5331Samw 		    xlate_nt_status(status));
630*5331Samw 		return (1);
631*5331Samw 	}
632*5331Samw 
633*5331Samw 	while ((offset < cnt)) {
634*5331Samw 		status = smb_group_list(offset, &list, gname, 0);
635*5331Samw 		if (status != NT_STATUS_SUCCESS) {
636*5331Samw 			(void) fprintf(stderr,
637*5331Samw 			    gettext("failed to get the group(s) (%s)\n"),
638*5331Samw 			    xlate_nt_status(status));
639*5331Samw 			return (1);
640*5331Samw 		}
641*5331Samw 
642*5331Samw 		if ((list == NULL) || (list->cnt <= 0))
643*5331Samw 			break;
644*5331Samw 
645*5331Samw 		ret = smbadm_group_dump(list, show_members, show_privs);
646*5331Samw 		if (ret)
647*5331Samw 			break;
648*5331Samw 
649*5331Samw 		offset += list->cnt;
650*5331Samw 		smb_group_free_list(list, 0);
651*5331Samw 		list = NULL;
652*5331Samw 	}
653*5331Samw 
654*5331Samw 	return (ret);
655*5331Samw }
656*5331Samw 
657*5331Samw /*
658*5331Samw  * smbadm_group_delete
659*5331Samw  *
660*5331Samw  */
661*5331Samw static int
662*5331Samw smbadm_group_delete(int argc, char **argv)
663*5331Samw {
664*5331Samw 	uint32_t status;
665*5331Samw 	char *gname = NULL;
666*5331Samw 
667*5331Samw 	gname = argv[optind];
668*5331Samw 	if (optind >= argc || gname == NULL || *gname == '\0') {
669*5331Samw 		(void) fprintf(stderr, gettext("missing group name\n"));
670*5331Samw 		smbadm_usage(B_FALSE);
671*5331Samw 	}
672*5331Samw 
673*5331Samw 	status = smb_group_delete(gname);
674*5331Samw 	if (status != NT_STATUS_SUCCESS) {
675*5331Samw 		(void) fprintf(stderr,
676*5331Samw 		    gettext("failed to delete the group (%s)\n"),
677*5331Samw 		    xlate_nt_status(status));
678*5331Samw 	} else {
679*5331Samw 		(void) printf(gettext("Successfully deleted group '%s'\n"),
680*5331Samw 		    gname);
681*5331Samw 	}
682*5331Samw 
683*5331Samw 	return (status);
684*5331Samw }
685*5331Samw 
686*5331Samw /*
687*5331Samw  * smbadm_group_rename
688*5331Samw  *
689*5331Samw  */
690*5331Samw static int
691*5331Samw smbadm_group_rename(int argc, char **argv)
692*5331Samw {
693*5331Samw 	char *gname = NULL;
694*5331Samw 	char *ngname = NULL;
695*5331Samw 	uint32_t status;
696*5331Samw 
697*5331Samw 	gname = argv[optind];
698*5331Samw 	if (optind++ >= argc || gname == NULL || *gname == '\0') {
699*5331Samw 		(void) fprintf(stderr, gettext("missing group name\n"));
700*5331Samw 		smbadm_usage(B_FALSE);
701*5331Samw 	}
702*5331Samw 
703*5331Samw 	ngname = argv[optind];
704*5331Samw 	if (optind >= argc || ngname == NULL || *ngname == '\0') {
705*5331Samw 		(void) fprintf(stderr, gettext("missing new group name\n"));
706*5331Samw 		smbadm_usage(B_FALSE);
707*5331Samw 	}
708*5331Samw 
709*5331Samw 	if (getgrnam(gname) == NULL) {
710*5331Samw 		(void) fprintf(stderr,
711*5331Samw 		    gettext("failed to get the Solaris group\n"));
712*5331Samw 		(void) fprintf(stderr,
713*5331Samw 		    gettext("use 'groupadd' to add the Solaris group\n"));
714*5331Samw 		return (1);
715*5331Samw 	}
716*5331Samw 
717*5331Samw 	status = smb_group_modify(gname, ngname, NULL);
718*5331Samw 	if (status != NT_STATUS_SUCCESS) {
719*5331Samw 		(void) fprintf(stderr,
720*5331Samw 		    gettext("failed to modify the group (%s)\n"),
721*5331Samw 		    xlate_nt_status(status));
722*5331Samw 	} else {
723*5331Samw 		(void) printf(gettext("Successfully modified "
724*5331Samw 		    "group '%s'\n"), gname);
725*5331Samw 	}
726*5331Samw 
727*5331Samw 	return (status);
728*5331Samw }
729*5331Samw 
730*5331Samw /*
731*5331Samw  * smbadm_group_setprop
732*5331Samw  *
733*5331Samw  * Set the group properties.
734*5331Samw  */
735*5331Samw static int
736*5331Samw smbadm_group_setprop(int argc, char **argv)
737*5331Samw {
738*5331Samw 	char *gname = NULL;
739*5331Samw 	smbadm_prop_t props[SMBADM_NPROP];
740*5331Samw 	smbadm_prop_handle_t *phandle;
741*5331Samw 	char option;
742*5331Samw 	int pcnt = 0;
743*5331Samw 	int ret;
744*5331Samw 	int p;
745*5331Samw 
746*5331Samw 	bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t));
747*5331Samw 
748*5331Samw 	while ((option = getopt(argc, argv, "p:")) != -1) {
749*5331Samw 		switch (option) {
750*5331Samw 		case 'p':
751*5331Samw 			if (pcnt >= SMBADM_NPROP) {
752*5331Samw 				(void) fprintf(stderr,
753*5331Samw 				    gettext("exceeded number of supported"
754*5331Samw 				    " properties\n"));
755*5331Samw 				smbadm_usage(B_FALSE);
756*5331Samw 			}
757*5331Samw 
758*5331Samw 			ret = smbadm_prop_parse(optarg, &props[pcnt++]);
759*5331Samw 			if (ret) {
760*5331Samw 				if (ret == 1)
761*5331Samw 					exit(1);
762*5331Samw 
763*5331Samw 				if (ret == 2)
764*5331Samw 					smbadm_usage(B_FALSE);
765*5331Samw 			}
766*5331Samw 			break;
767*5331Samw 
768*5331Samw 		default:
769*5331Samw 			smbadm_usage(B_FALSE);
770*5331Samw 		}
771*5331Samw 	}
772*5331Samw 
773*5331Samw 	if (pcnt == 0) {
774*5331Samw 		(void) fprintf(stderr,
775*5331Samw 		    gettext("missing property=value argument\n"));
776*5331Samw 		smbadm_usage(B_FALSE);
777*5331Samw 	}
778*5331Samw 
779*5331Samw 	gname = argv[optind];
780*5331Samw 	if (optind >= argc || gname == NULL || *gname == '\0') {
781*5331Samw 		(void) fprintf(stderr, gettext("missing group name\n"));
782*5331Samw 		smbadm_usage(B_FALSE);
783*5331Samw 	}
784*5331Samw 
785*5331Samw 	for (p = 0; p < pcnt; p++) {
786*5331Samw 		phandle = smbadm_prop_gethandle(props[p].p_name);
787*5331Samw 		if (phandle) {
788*5331Samw 			if (phandle->p_setfn(gname, &props[p]) != 0)
789*5331Samw 				ret = 1;
790*5331Samw 		}
791*5331Samw 	}
792*5331Samw 
793*5331Samw 	return (ret);
794*5331Samw }
795*5331Samw 
796*5331Samw /*
797*5331Samw  * smbadm_group_getprop
798*5331Samw  *
799*5331Samw  * Get the group properties.
800*5331Samw  */
801*5331Samw static int
802*5331Samw smbadm_group_getprop(int argc, char **argv)
803*5331Samw {
804*5331Samw 	char *gname = NULL;
805*5331Samw 	smbadm_prop_t props[SMBADM_NPROP];
806*5331Samw 	smbadm_prop_handle_t *phandle;
807*5331Samw 	char option;
808*5331Samw 	int pcnt = 0;
809*5331Samw 	int ret;
810*5331Samw 	int p;
811*5331Samw 
812*5331Samw 	bzero(props, SMBADM_NPROP * sizeof (smbadm_prop_t));
813*5331Samw 
814*5331Samw 	while ((option = getopt(argc, argv, "p:")) != -1) {
815*5331Samw 		switch (option) {
816*5331Samw 		case 'p':
817*5331Samw 			if (pcnt >= SMBADM_NPROP) {
818*5331Samw 				(void) fprintf(stderr,
819*5331Samw 				    gettext("exceeded number of supported"
820*5331Samw 				    " properties\n"));
821*5331Samw 				smbadm_usage(B_FALSE);
822*5331Samw 			}
823*5331Samw 
824*5331Samw 			ret = smbadm_prop_parse(optarg, &props[pcnt++]);
825*5331Samw 			if (ret) {
826*5331Samw 				if (ret == 1)
827*5331Samw 					exit(1);
828*5331Samw 
829*5331Samw 				if (ret == 2)
830*5331Samw 					smbadm_usage(B_FALSE);
831*5331Samw 			}
832*5331Samw 			break;
833*5331Samw 
834*5331Samw 		default:
835*5331Samw 			smbadm_usage(B_FALSE);
836*5331Samw 		}
837*5331Samw 	}
838*5331Samw 
839*5331Samw 	gname = argv[optind];
840*5331Samw 	if (optind >= argc || gname == NULL || *gname == '\0') {
841*5331Samw 		(void) fprintf(stderr, gettext("missing group name\n"));
842*5331Samw 		smbadm_usage(B_FALSE);
843*5331Samw 	}
844*5331Samw 
845*5331Samw 	if (pcnt == 0) {
846*5331Samw 		/*
847*5331Samw 		 * If no property has be specified then get
848*5331Samw 		 * all the properties.
849*5331Samw 		 */
850*5331Samw 		pcnt = SMBADM_NPROP;
851*5331Samw 		for (p = 0; p < pcnt; p++)
852*5331Samw 			props[p].p_name = smbadm_ptable[p].p_name;
853*5331Samw 	}
854*5331Samw 
855*5331Samw 	for (p = 0; p < pcnt; p++) {
856*5331Samw 		phandle = smbadm_prop_gethandle(props[p].p_name);
857*5331Samw 		if (phandle) {
858*5331Samw 			if (phandle->p_getfn(gname, &props[p]) != 0)
859*5331Samw 				ret = 1;
860*5331Samw 		}
861*5331Samw 	}
862*5331Samw 
863*5331Samw 	return (ret);
864*5331Samw }
865*5331Samw 
866*5331Samw /*
867*5331Samw  * smbadm_group_addmember
868*5331Samw  *
869*5331Samw  */
870*5331Samw static int
871*5331Samw smbadm_group_addmember(int argc, char **argv)
872*5331Samw {
873*5331Samw 	char *gname = NULL;
874*5331Samw 	char **mname;
875*5331Samw 	char option;
876*5331Samw 	uint32_t status;
877*5331Samw 	int mcnt = 0;
878*5331Samw 	int ret = 0;
879*5331Samw 	int i;
880*5331Samw 
881*5331Samw 
882*5331Samw 	mname = (char **)malloc(argc * sizeof (char *));
883*5331Samw 	if (mname == NULL) {
884*5331Samw 		(void) fprintf(stderr, gettext("out of memory\n"));
885*5331Samw 		return (1);
886*5331Samw 	}
887*5331Samw 	bzero(mname, argc * sizeof (char *));
888*5331Samw 
889*5331Samw 	while ((option = getopt(argc, argv, "m:")) != -1) {
890*5331Samw 		switch (option) {
891*5331Samw 		case 'm':
892*5331Samw 			mname[mcnt++] = optarg;
893*5331Samw 			break;
894*5331Samw 
895*5331Samw 		default:
896*5331Samw 			free(mname);
897*5331Samw 			smbadm_usage(B_FALSE);
898*5331Samw 		}
899*5331Samw 	}
900*5331Samw 
901*5331Samw 	if (mcnt == 0) {
902*5331Samw 		(void) fprintf(stderr, gettext("missing member name\n"));
903*5331Samw 		free(mname);
904*5331Samw 		smbadm_usage(B_FALSE);
905*5331Samw 	}
906*5331Samw 
907*5331Samw 	gname = argv[optind];
908*5331Samw 	if (optind >= argc || gname == NULL || *gname == 0) {
909*5331Samw 		(void) fprintf(stderr, gettext("missing group name\n"));
910*5331Samw 		free(mname);
911*5331Samw 		smbadm_usage(B_FALSE);
912*5331Samw 	}
913*5331Samw 
914*5331Samw 
915*5331Samw 	for (i = 0; i < mcnt; i++) {
916*5331Samw 		if (mname[i] == NULL)
917*5331Samw 			continue;
918*5331Samw 
919*5331Samw 		status = smb_group_member_add(gname, mname[i]);
920*5331Samw 		if (status != NT_STATUS_SUCCESS) {
921*5331Samw 			(void) fprintf(stderr,
922*5331Samw 			    gettext("failed to add %s (%s)\n"),
923*5331Samw 			    mname[i], xlate_nt_status(status));
924*5331Samw 			ret = 1;
925*5331Samw 		}
926*5331Samw 		else
927*5331Samw 			(void) printf(gettext("Successfully added %s to %s\n"),
928*5331Samw 			    mname[i], gname);
929*5331Samw 	}
930*5331Samw 
931*5331Samw 	free(mname);
932*5331Samw 	return (ret);
933*5331Samw }
934*5331Samw 
935*5331Samw /*
936*5331Samw  * smbadm_group_delmember
937*5331Samw  */
938*5331Samw static int
939*5331Samw smbadm_group_delmember(int argc, char **argv)
940*5331Samw {
941*5331Samw 	char *gname = NULL;
942*5331Samw 	char **mname;
943*5331Samw 	char option;
944*5331Samw 	uint32_t status;
945*5331Samw 	int mcnt = 0;
946*5331Samw 	int ret = 0;
947*5331Samw 	int i;
948*5331Samw 
949*5331Samw 	mname = (char **)malloc(argc * sizeof (char *));
950*5331Samw 	if (mname == NULL) {
951*5331Samw 		(void) fprintf(stderr, gettext("out of memory\n"));
952*5331Samw 		return (1);
953*5331Samw 	}
954*5331Samw 	bzero(mname, argc * sizeof (char *));
955*5331Samw 
956*5331Samw 	while ((option = getopt(argc, argv, "m:")) != -1) {
957*5331Samw 		switch (option) {
958*5331Samw 		case 'm':
959*5331Samw 			mname[mcnt++] = optarg;
960*5331Samw 			break;
961*5331Samw 
962*5331Samw 		default:
963*5331Samw 			free(mname);
964*5331Samw 			smbadm_usage(B_FALSE);
965*5331Samw 		}
966*5331Samw 	}
967*5331Samw 
968*5331Samw 	if (mcnt == 0) {
969*5331Samw 		(void) fprintf(stderr, gettext("missing member name\n"));
970*5331Samw 		free(mname);
971*5331Samw 		smbadm_usage(B_FALSE);
972*5331Samw 	}
973*5331Samw 
974*5331Samw 	gname = argv[optind];
975*5331Samw 	if (optind >= argc || gname == NULL || *gname == 0) {
976*5331Samw 		(void) fprintf(stderr, gettext("missing group name\n"));
977*5331Samw 		free(mname);
978*5331Samw 		smbadm_usage(B_FALSE);
979*5331Samw 	}
980*5331Samw 
981*5331Samw 
982*5331Samw 	for (i = 0; i < mcnt; i++) {
983*5331Samw 		if (mname[i] == NULL)
984*5331Samw 			continue;
985*5331Samw 
986*5331Samw 		status = smb_group_member_remove(gname, mname[i]);
987*5331Samw 		if (status != NT_STATUS_SUCCESS) {
988*5331Samw 			(void) fprintf(stderr,
989*5331Samw 			    gettext("failed to remove %s (%s)\n"),
990*5331Samw 			    mname[i], xlate_nt_status(status));
991*5331Samw 			ret = 1;
992*5331Samw 		} else {
993*5331Samw 			(void) printf(
994*5331Samw 			    gettext("Successfully removed %s from %s\n"),
995*5331Samw 			    mname[i], gname);
996*5331Samw 		}
997*5331Samw 	}
998*5331Samw 
999*5331Samw 	return (ret);
1000*5331Samw }
1001*5331Samw 
1002*5331Samw static int
1003*5331Samw smbadm_user_disable(int argc, char **argv)
1004*5331Samw {
1005*5331Samw 	int error;
1006*5331Samw 	char *user = NULL;
1007*5331Samw 
1008*5331Samw 	user = argv[optind];
1009*5331Samw 	if (optind >= argc || user == NULL || *user == '\0') {
1010*5331Samw 		(void) fprintf(stderr, gettext("missing user name\n"));
1011*5331Samw 		smbadm_usage(B_FALSE);
1012*5331Samw 	}
1013*5331Samw 
1014*5331Samw 	error = smb_pwd_setcntl(user, SMB_PWC_DISABLE);
1015*5331Samw 	if (error == SMB_PWE_SUCCESS)
1016*5331Samw 		(void) printf(gettext("%s is disabled.\n"), user);
1017*5331Samw 	else
1018*5331Samw 		(void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error));
1019*5331Samw 
1020*5331Samw 	return (error);
1021*5331Samw }
1022*5331Samw 
1023*5331Samw static int
1024*5331Samw smbadm_user_enable(int argc, char **argv)
1025*5331Samw {
1026*5331Samw 	int error;
1027*5331Samw 	char *user = NULL;
1028*5331Samw 
1029*5331Samw 	user = argv[optind];
1030*5331Samw 	if (optind >= argc || user == NULL || *user == '\0') {
1031*5331Samw 		(void) fprintf(stderr, gettext("missing user name\n"));
1032*5331Samw 		smbadm_usage(B_FALSE);
1033*5331Samw 	}
1034*5331Samw 
1035*5331Samw 	error = smb_pwd_setcntl(user, SMB_PWC_ENABLE);
1036*5331Samw 	if (error == SMB_PWE_SUCCESS)
1037*5331Samw 		(void) printf(gettext("%s is enabled.\n"), user);
1038*5331Samw 	else
1039*5331Samw 		(void) fprintf(stderr, "%s\n", smbadm_pwd_strerror(error));
1040*5331Samw 
1041*5331Samw 	return (error);
1042*5331Samw }
1043*5331Samw 
1044*5331Samw 
1045*5331Samw int
1046*5331Samw main(int argc, char **argv)
1047*5331Samw {
1048*5331Samw 	int i;
1049*5331Samw 
1050*5331Samw 	(void) malloc(0);	/* satisfy libumem dependency */
1051*5331Samw 
1052*5331Samw 	progname = basename(argv[0]);
1053*5331Samw 
1054*5331Samw 	if (getzoneid() != GLOBAL_ZONEID) {
1055*5331Samw 		(void) fprintf(stderr,
1056*5331Samw 		    gettext("cannot execute in non-global zone\n"));
1057*5331Samw 		return (0);
1058*5331Samw 	}
1059*5331Samw 
1060*5331Samw 	if (is_system_labeled()) {
1061*5331Samw 		(void) fprintf(stderr,
1062*5331Samw 		    gettext("Trusted Extensions not supported\n"));
1063*5331Samw 		return (0);
1064*5331Samw 	}
1065*5331Samw 
1066*5331Samw 	if (argc < 2) {
1067*5331Samw 		(void) fprintf(stderr, gettext("missing command\n"));
1068*5331Samw 		smbadm_usage(B_FALSE);
1069*5331Samw 	}
1070*5331Samw 
1071*5331Samw 	/*
1072*5331Samw 	 * Special case "cmd --help/-?"
1073*5331Samw 	 */
1074*5331Samw 	if (strcmp(argv[1], "-?") == 0 ||
1075*5331Samw 	    strcmp(argv[1], "--help") == 0 ||
1076*5331Samw 	    strcmp(argv[1], "-h") == 0)
1077*5331Samw 		smbadm_usage(B_TRUE);
1078*5331Samw 
1079*5331Samw 	for (i = 0; i < SMBADM_NCMD; ++i) {
1080*5331Samw 		curcmd = &smbadm_cmdtable[i];
1081*5331Samw 		if (strcasecmp(argv[1], curcmd->name) == 0) {
1082*5331Samw 			if (argc > 2) {
1083*5331Samw 				/* cmd subcmd --help/-? */
1084*5331Samw 				if (strcmp(argv[2], "-?") == 0 ||
1085*5331Samw 				    strcmp(argv[2], "--help") == 0 ||
1086*5331Samw 				    strcmp(argv[2], "-h") == 0)
1087*5331Samw 					smbadm_usage(B_TRUE);
1088*5331Samw 			}
1089*5331Samw 
1090*5331Samw 			return (curcmd->func(argc - 1, &argv[1]));
1091*5331Samw 		}
1092*5331Samw 	}
1093*5331Samw 
1094*5331Samw 	curcmd = NULL;
1095*5331Samw 	(void) fprintf(stderr, gettext("unknown subcommand (%s)\n"), argv[1]);
1096*5331Samw 	smbadm_usage(B_FALSE);
1097*5331Samw 	return (2);
1098*5331Samw }
1099*5331Samw 
1100*5331Samw static boolean_t
1101*5331Samw smbadm_prop_validate(smbadm_prop_t *prop, boolean_t chkval)
1102*5331Samw {
1103*5331Samw 	smbadm_prop_handle_t *pinfo;
1104*5331Samw 	int i;
1105*5331Samw 
1106*5331Samw 	for (i = 0; i < SMBADM_NPROP; i++) {
1107*5331Samw 		pinfo = &smbadm_ptable[i];
1108*5331Samw 		if (strcmp(pinfo->p_name, prop->p_name) == 0) {
1109*5331Samw 			if (pinfo->p_chkfn && chkval)
1110*5331Samw 				return (pinfo->p_chkfn(prop));
1111*5331Samw 
1112*5331Samw 			return (B_TRUE);
1113*5331Samw 		}
1114*5331Samw 	}
1115*5331Samw 
1116*5331Samw 	(void) fprintf(stderr,
1117*5331Samw 	    gettext("unrecognized property '%s'\n"), prop->p_name);
1118*5331Samw 
1119*5331Samw 	return (B_FALSE);
1120*5331Samw }
1121*5331Samw 
1122*5331Samw static int
1123*5331Samw smbadm_prop_parse(char *arg, smbadm_prop_t *prop)
1124*5331Samw {
1125*5331Samw 	boolean_t parse_value;
1126*5331Samw 	char *equal;
1127*5331Samw 
1128*5331Samw 	if (arg == NULL)
1129*5331Samw 		return (2);
1130*5331Samw 
1131*5331Samw 	prop->p_name = prop->p_value = NULL;
1132*5331Samw 
1133*5331Samw 	if (strcmp(curcmd->name, "set") == 0)
1134*5331Samw 		parse_value = B_TRUE;
1135*5331Samw 	else
1136*5331Samw 		parse_value = B_FALSE;
1137*5331Samw 
1138*5331Samw 	prop->p_name = arg;
1139*5331Samw 
1140*5331Samw 	if (parse_value) {
1141*5331Samw 		equal = strchr(arg, '=');
1142*5331Samw 		if (equal == NULL)
1143*5331Samw 			return (2);
1144*5331Samw 
1145*5331Samw 		*equal++ = '\0';
1146*5331Samw 		prop->p_value = equal;
1147*5331Samw 	}
1148*5331Samw 
1149*5331Samw 	if (smbadm_prop_validate(prop, parse_value) == B_FALSE)
1150*5331Samw 		return (2);
1151*5331Samw 
1152*5331Samw 	return (0);
1153*5331Samw }
1154*5331Samw 
1155*5331Samw static smbadm_prop_handle_t *
1156*5331Samw smbadm_prop_gethandle(char *pname)
1157*5331Samw {
1158*5331Samw 	int i;
1159*5331Samw 
1160*5331Samw 	for (i = 0; i < SMBADM_NPROP; i++)
1161*5331Samw 		if (strcmp(pname, smbadm_ptable[i].p_name) == 0)
1162*5331Samw 			return (&smbadm_ptable[i]);
1163*5331Samw 
1164*5331Samw 	return (NULL);
1165*5331Samw }
1166*5331Samw 
1167*5331Samw static int
1168*5331Samw smbadm_setprop_desc(char *gname, smbadm_prop_t *prop)
1169*5331Samw {
1170*5331Samw 	uint32_t status;
1171*5331Samw 
1172*5331Samw 	status = smb_group_modify(gname, gname, prop->p_value);
1173*5331Samw 	if (status != NT_STATUS_SUCCESS) {
1174*5331Samw 		(void) fprintf(stderr,
1175*5331Samw 		    gettext("failed to modify the group description (%s)\n"),
1176*5331Samw 		    xlate_nt_status(status));
1177*5331Samw 		return (1);
1178*5331Samw 	}
1179*5331Samw 
1180*5331Samw 	(void) printf(gettext("Successfully modified "
1181*5331Samw 	    "'%s' description\n"), gname);
1182*5331Samw 
1183*5331Samw 	return (0);
1184*5331Samw }
1185*5331Samw 
1186*5331Samw static int
1187*5331Samw smbadm_getprop_desc(char *gname, smbadm_prop_t *prop)
1188*5331Samw {
1189*5331Samw 	uint32_t status;
1190*5331Samw 	ntgrp_list_t *list = NULL;
1191*5331Samw 
1192*5331Samw 	status = smb_group_list(0, &list, gname, 0);
1193*5331Samw 	if (status != NT_STATUS_SUCCESS) {
1194*5331Samw 		(void) fprintf(stderr,
1195*5331Samw 		    gettext("failed to get the %s (%s)\n"),
1196*5331Samw 		    prop->p_name, xlate_nt_status(status));
1197*5331Samw 		return (1);
1198*5331Samw 	}
1199*5331Samw 
1200*5331Samw 	if ((list == NULL) || (list->cnt <= 0)) {
1201*5331Samw 		(void) fprintf(stderr, gettext("%s: no such group\n"), gname);
1202*5331Samw 		return (1);
1203*5331Samw 	}
1204*5331Samw 
1205*5331Samw 	(void) printf(gettext("\t%s: %s\n"), prop->p_name,
1206*5331Samw 	    list->groups[0].desc);
1207*5331Samw 	smb_group_free_list(list, 0);
1208*5331Samw 	return (0);
1209*5331Samw }
1210*5331Samw 
1211*5331Samw static int
1212*5331Samw smbadm_group_setpriv(char *gname, uint32_t priv_id, smbadm_prop_t *prop)
1213*5331Samw {
1214*5331Samw 	uint32_t priv_attr;
1215*5331Samw 	uint32_t status;
1216*5331Samw 	int ret;
1217*5331Samw 
1218*5331Samw 	if (strcasecmp(prop->p_value, "on") == 0) {
1219*5331Samw 		(void) printf(gettext("Enabling %s privilege "), prop->p_name);
1220*5331Samw 		priv_attr = SE_PRIVILEGE_ENABLED;
1221*5331Samw 	} else {
1222*5331Samw 		(void) printf(gettext("Disabling %s privilege "), prop->p_name);
1223*5331Samw 		priv_attr = SE_PRIVILEGE_DISABLED;
1224*5331Samw 	}
1225*5331Samw 
1226*5331Samw 	status = smb_group_priv_set(gname, priv_id, priv_attr);
1227*5331Samw 
1228*5331Samw 	if (status == NT_STATUS_SUCCESS) {
1229*5331Samw 		(void) printf(gettext("succeeded\n"));
1230*5331Samw 		ret = 0;
1231*5331Samw 	} else {
1232*5331Samw 		(void) printf(gettext("failed: %s\n"), xlate_nt_status(status));
1233*5331Samw 		ret = 1;
1234*5331Samw 	}
1235*5331Samw 
1236*5331Samw 	return (ret);
1237*5331Samw }
1238*5331Samw 
1239*5331Samw static int
1240*5331Samw smbadm_group_getpriv(char *gname, uint32_t priv_id, smbadm_prop_t *prop)
1241*5331Samw {
1242*5331Samw 	uint32_t priv_attr;
1243*5331Samw 	uint32_t status;
1244*5331Samw 
1245*5331Samw 	status = smb_group_priv_get(gname, priv_id, &priv_attr);
1246*5331Samw 	if (status != NT_STATUS_SUCCESS) {
1247*5331Samw 		(void) fprintf(stderr, gettext("failed to get %s (%s)\n"),
1248*5331Samw 		    prop->p_name, xlate_nt_status(status));
1249*5331Samw 		return (1);
1250*5331Samw 	}
1251*5331Samw 
1252*5331Samw 	if (priv_attr == SE_PRIVILEGE_ENABLED)
1253*5331Samw 		(void) printf(gettext("\t%s: %s\n"), prop->p_name, "On");
1254*5331Samw 	else if (priv_attr == SE_PRIVILEGE_DISABLED)
1255*5331Samw 		(void) printf(gettext("\t%s: %s\n"), prop->p_name, "Off");
1256*5331Samw 	else
1257*5331Samw 		(void) printf(gettext("\t%s: %s\n"), prop->p_name, "Unknown");
1258*5331Samw 
1259*5331Samw 	return (0);
1260*5331Samw }
1261*5331Samw 
1262*5331Samw static int
1263*5331Samw smbadm_setprop_tkowner(char *gname, smbadm_prop_t *prop)
1264*5331Samw {
1265*5331Samw 	return (smbadm_group_setpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop));
1266*5331Samw }
1267*5331Samw 
1268*5331Samw static int
1269*5331Samw smbadm_getprop_tkowner(char *gname, smbadm_prop_t *prop)
1270*5331Samw {
1271*5331Samw 	return (smbadm_group_getpriv(gname, SE_TAKE_OWNERSHIP_LUID, prop));
1272*5331Samw }
1273*5331Samw 
1274*5331Samw static int
1275*5331Samw smbadm_setprop_backup(char *gname, smbadm_prop_t *prop)
1276*5331Samw {
1277*5331Samw 	return (smbadm_group_setpriv(gname, SE_BACKUP_LUID, prop));
1278*5331Samw }
1279*5331Samw 
1280*5331Samw static int
1281*5331Samw smbadm_getprop_backup(char *gname, smbadm_prop_t *prop)
1282*5331Samw {
1283*5331Samw 	return (smbadm_group_getpriv(gname, SE_BACKUP_LUID, prop));
1284*5331Samw }
1285*5331Samw 
1286*5331Samw static int
1287*5331Samw smbadm_setprop_restore(char *gname, smbadm_prop_t *prop)
1288*5331Samw {
1289*5331Samw 	return (smbadm_group_setpriv(gname, SE_RESTORE_LUID, prop));
1290*5331Samw }
1291*5331Samw 
1292*5331Samw static int
1293*5331Samw smbadm_getprop_restore(char *gname, smbadm_prop_t *prop)
1294*5331Samw {
1295*5331Samw 	return (smbadm_group_getpriv(gname, SE_RESTORE_LUID, prop));
1296*5331Samw }
1297*5331Samw 
1298*5331Samw static boolean_t
1299*5331Samw smbadm_chkprop_priv(smbadm_prop_t *prop)
1300*5331Samw {
1301*5331Samw 	if (prop->p_value == NULL || *prop->p_value == '\0') {
1302*5331Samw 		(void) fprintf(stderr,
1303*5331Samw 		    gettext("missing value for '%s'\n"), prop->p_name);
1304*5331Samw 		return (B_FALSE);
1305*5331Samw 	}
1306*5331Samw 
1307*5331Samw 	if (strcasecmp(prop->p_value, "on") == 0)
1308*5331Samw 		return (B_TRUE);
1309*5331Samw 
1310*5331Samw 	if (strcasecmp(prop->p_value, "off") == 0)
1311*5331Samw 		return (B_TRUE);
1312*5331Samw 
1313*5331Samw 	(void) fprintf(stderr,
1314*5331Samw 	    gettext("%s: unrecognized value for '%s' property\n"),
1315*5331Samw 	    prop->p_value, prop->p_name);
1316*5331Samw 
1317*5331Samw 	return (B_FALSE);
1318*5331Samw }
1319*5331Samw 
1320*5331Samw static const char *
1321*5331Samw smbadm_pwd_strerror(int error)
1322*5331Samw {
1323*5331Samw 	switch (error) {
1324*5331Samw 	case SMB_PWE_SUCCESS:
1325*5331Samw 		return (gettext("Success."));
1326*5331Samw 
1327*5331Samw 	case SMB_PWE_USER_UNKNOWN:
1328*5331Samw 		return (gettext("User does not exist."));
1329*5331Samw 
1330*5331Samw 	case SMB_PWE_USER_DISABLE:
1331*5331Samw 		return (gettext("User is disable."));
1332*5331Samw 
1333*5331Samw 	case SMB_PWE_CLOSE_FAILED:
1334*5331Samw 	case SMB_PWE_OPEN_FAILED:
1335*5331Samw 	case SMB_PWE_WRITE_FAILED:
1336*5331Samw 	case SMB_PWE_UPDATE_FAILED:
1337*5331Samw 		return (gettext("Unexpected failure. "
1338*5331Samw 		    "SMB password database unchanged."));
1339*5331Samw 
1340*5331Samw 	case SMB_PWE_STAT_FAILED:
1341*5331Samw 		return (gettext("stat of SMB password file failed."));
1342*5331Samw 
1343*5331Samw 	case SMB_PWE_BUSY:
1344*5331Samw 		return (gettext("SMB password database busy. "
1345*5331Samw 		    "Try again later."));
1346*5331Samw 
1347*5331Samw 	case SMB_PWE_DENIED:
1348*5331Samw 		return (gettext("Operation not permitted."));
1349*5331Samw 
1350*5331Samw 	case SMB_PWE_SYSTEM_ERROR:
1351*5331Samw 		return (gettext("System error."));
1352*5331Samw 	}
1353*5331Samw 
1354*5331Samw 	return (gettext("Unknown error code."));
1355*5331Samw }
1356*5331Samw 
1357*5331Samw /*
1358*5331Samw  * Enable libumem debugging by default on DEBUG builds.
1359*5331Samw  */
1360*5331Samw #ifdef DEBUG
1361*5331Samw /* LINTED - external libumem symbol */
1362*5331Samw const char *
1363*5331Samw _umem_debug_init(void)
1364*5331Samw {
1365*5331Samw 	return ("default,verbose"); /* $UMEM_DEBUG setting */
1366*5331Samw }
1367*5331Samw 
1368*5331Samw /* LINTED - external libumem symbol */
1369*5331Samw const char *
1370*5331Samw _umem_logging_init(void)
1371*5331Samw {
1372*5331Samw 	return ("fail,contents"); /* $UMEM_LOGGING setting */
1373*5331Samw }
1374*5331Samw #endif
1375