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