Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 
     27 #include <libgen.h>
     28 #include <stdio.h>
     29 #include <libnvpair.h>
     30 #include <fcntl.h>
     31 #include <sys/types.h>
     32 
     33 #include "mms_mgmt.h"
     34 #include "mgmt_util.h"
     35 #include "mms_cfg.h"
     36 #include "net_cfg_service.h"
     37 
     38 static char *_SrcFile = __FILE__;
     39 #define	HERE _SrcFile, __LINE__
     40 
     41 typedef struct {
     42 	char		*name;
     43 	char		*cfgnam;
     44 	int		svc;
     45 } mms_mgmt_cfgopt_t;
     46 
     47 static mms_mgmt_cfgopt_t  mmscfgopts[] = {
     48 	{O_MMHOST,	MMS_CFG_MGR_HOST,	WCR|MM},
     49 	{O_MMPORT,	MMS_CFG_MGR_PORT,	WCR|MM},
     50 	{O_OBJTYPE,	MMS_CFG_CONFIG_TYPE,	0},
     51 	{O_SSLENABLED,	MMS_CFG_SSL_ENABLED,	WCR|MM},
     52 	{O_CERTFILE,	MMS_CFG_SSL_CERT_FILE,	WCR|MM},
     53 	{O_SSLPASSFILE,	MMS_CFG_SSL_PASS_FILE,	WCR|MM},
     54 	{O_CRLFILE,	MMS_CFG_SSL_CRL_FILE,	WCR|MM},
     55 	{O_PEERFILE,	MMS_CFG_SSL_PEER_FILE,	WCR|MM},
     56 	{O_DHFILE,	MMS_CFG_SSL_DH_FILE,	WCR|MM},
     57 	{"ssl_cipher",	MMS_CFG_SSL_CIPHER,	WCR|MM},
     58 	{O_VERIFY,	MMS_CFG_SSL_VERIFY,	WCR|MM},
     59 	{O_DBHOST,	MMS_CFG_MM_DB_HOST,	MM},
     60 	{O_DBPORT,	MMS_CFG_MM_DB_PORT,	DB|MM},
     61 	{O_DBDIR,	MMS_CFG_DB_DATA,	DB},
     62 	{O_DBLOG,	MMS_CFG_DB_LOG,		DB},
     63 	{"db-user",	MMS_CFG_MM_DB_USER,	MM},
     64 	{O_DBNAME,	MMS_CFG_MM_DB_NAME,	DB},
     65 	{O_TRACELEVEL,	MMS_CFG_MM_TRACE,	MM},
     66 	{O_ACSLSDIR,	MMS_CFG_SSI_PATH,	WCR},
     67 	{NULL,		NULL,			0}
     68 };
     69 
     70 #ifdef	MMS_VAR_CFG
     71 /* MMS Client Options */
     72 static mms_mgmt_setopt_t mms_client_opts[] = {
     73 	{O_MMHOST,	NULL,	NULL,			B_TRUE,	NULL},
     74 	{O_MMPORT,	NULL,	MMS_DEF_MMPORT,		B_TRUE,	val_numonly},
     75 	{O_MMPASS,	NULL,	NULL,			B_TRUE,	val_passwd},
     76 	{O_OBJTYPE,	NULL,	"client", 		B_TRUE,	val_objtype},
     77 	{O_SECURECOMM,	NULL,	"off",			B_TRUE,	NULL},
     78 	{O_SSLENABLED,	NULL,	"false",		B_TRUE, NULL},
     79 	{O_CERTFILE,	NULL,	MMSSSLDIR"/mms.pem",	B_FALSE, val_path},
     80 	{O_SSLPASSFILE,	NULL,	MMSSSLDIR"/mms_pass",	B_FALSE, val_path},
     81 	{O_CRLFILE,	NULL,	MMSSSLDIR"/mms_crl.pem", B_FALSE, val_path},
     82 	{O_PEERFILE,	NULL,	MMSSSLDIR"/mms_cert.pem", B_FALSE, val_path},
     83 	{O_ACSLSDIR,	NULL,	NULL,			B_FALSE, val_path},
     84 	{NULL,	NULL, NULL, B_FALSE, NULL}
     85 };
     86 #define	NUM_CLIENT_OPTS (sizeof (mms_client_opts) / sizeof (mms_mgmt_setopt_t))
     87 #endif	/* MMS_VAR_CFG */
     88 
     89 /* MMS Server Options */
     90 static mms_mgmt_setopt_t mms_server_opts[] = {
     91 	{O_MMHOST,	NULL,	NULL,			B_TRUE,	NULL},
     92 	{O_MMPORT,	NULL,	MMS_DEF_MMPORT,		B_TRUE,	val_numonly},
     93 	{O_MMPASS,	NULL,	NULL,			B_TRUE,	val_passwd},
     94 	{O_OBJTYPE,	NULL,	"server", 		B_TRUE,	val_objtype},
     95 	{O_ACSLSDIR,	NULL,	NULL,			B_TRUE, val_path},
     96 	{O_SECURECOMM,	NULL,	"off",			B_TRUE,	NULL},
     97 	{O_SSLENABLED,	NULL,	"false",		B_TRUE, NULL},
     98 	{O_CERTFILE,	NULL,	MMSSSLDIR"/mms.pem",	B_FALSE, val_path},
     99 	{O_SSLPASSFILE,	NULL,	MMSSSLDIR"/mms_pass",	B_FALSE, val_path},
    100 	{O_CRLFILE,	NULL,	MMSSSLDIR"/mms_crl.pem", B_FALSE, val_path},
    101 	{O_PEERFILE,	NULL,	MMSSSLDIR"/mms_cert.pem", B_FALSE, val_path},
    102 	{O_DHFILE,	NULL,	MMSSSLDIR"/mms_dh1024.pem", B_FALSE, NULL},
    103 	{O_VERIFY,	NULL,	"false",		B_FALSE, NULL},
    104 	{O_LOGLEVEL,	"SystemLogLevel", MMS_DEF_LOGLVL, B_FALSE, val_level},
    105 	{O_LOGFILE,	"SystemLogFile",  MMSLOGDIR"/mm.log", B_FALSE,
    106 	    val_path},
    107 	{O_DBDIR,	NULL,	MMS_DEF_DBDIR,		B_TRUE, val_path},
    108 	{O_DBHOST,	NULL,	"localhost",		B_TRUE, NULL},
    109 	{O_DBPORT,	NULL,	MMS_DEF_DBPORT,		B_TRUE, val_numonly},
    110 	{O_DBLOG,	NULL,	NULL,			B_FALSE, val_path},
    111 	{O_DBNAME,	NULL,	"mms",			B_TRUE, NULL},
    112 	{O_NUMRESTART,	"WatcherStartsLimit", "3",	B_FALSE, val_numonly},
    113 	{O_ATTENDED,	"AttendanceMode", "yes",	B_FALSE, val_yesno},
    114 	{O_NUMSOCKET,	"SocketFdLimit", "-1",		B_FALSE, val_numonly},
    115 	{O_DKTIMEOUT,	"SystemDiskMountTimeout", "0",	B_FALSE, val_numonly},
    116 	{O_TRACELEVEL,	"TraceLevel", NULL,		B_FALSE, val_level},
    117 	{O_TRACESZ,	"TraceFileSize", NULL,		B_FALSE, val_mms_size},
    118 	{O_MSGLEVEL,	"MessageLevel", NULL,		B_FALSE, val_level},
    119 	{NULL, NULL, NULL, B_FALSE, NULL}
    120 };
    121 #define	NUM_SERVER_OPTS (sizeof (mms_server_opts) / sizeof (mms_mgmt_setopt_t))
    122 
    123 static mms_mgmt_setopt_t application_opts[] = {
    124 	{O_NAME,	NULL,	NULL,	B_TRUE, NULL},
    125 	{O_RETENTION,	"Retention",	NULL, B_FALSE, val_numonly},
    126 	{O_VALIDATEEXP,	"ValidateExpirationDate", NULL, B_FALSE, val_truefalse},
    127 	{O_VALIDATEVOL,	"ValidateVolumeID", NULL, B_FALSE, val_truefalse},
    128 	{O_VALIDATEFN,	"ValidateFileName", NULL, B_FALSE, val_truefalse},
    129 	{O_OVERWRITEEXT, "WriteOverExistingData", NULL, B_FALSE, val_truefalse},
    130 	{NULL, NULL, NULL, B_FALSE, NULL}
    131 };
    132 
    133 static int mgmt_set_pass(char *inpw);
    134 #ifdef	MMS_VAR_CFG
    135 static int mgmt_set_ssl(nvlist_t *opts);
    136 #endif	/* MMS_VAR_CFG */
    137 
    138 /*
    139  * The create_mm_clnt() function establishes a session with
    140  * MM.  If "app" is not MMS and "inst" is not "admin", the password must
    141  * also be provided.  "tag" is an optional identifier to be used
    142  * in the session API.
    143  */
    144 int
    145 create_mm_clnt(char *app, char *inst, char *pass, char *tag, void **session)
    146 {
    147 
    148 	int			version;
    149 	int			st;
    150 	mms_network_cfg_t	cfg;
    151 	void			*ssl_data = NULL;
    152 	void			*sess = NULL;
    153 	char			*tagp = "";
    154 #ifdef	MMS_OPENSSL
    155 	mms_err_t		err;
    156 	char			ebuf[1024];
    157 #endif	/* MMS_OPENSSL */
    158 
    159 	if (!session) {
    160 		return (MMS_MGMT_NOARG);
    161 	}
    162 
    163 	*session = NULL;
    164 
    165 	(void) memset(&cfg, 0, sizeof (mms_network_cfg_t));
    166 
    167 	/*
    168 	 * mms_net_cfg_service() expects to fetch information
    169 	 * for MMS admin only.  However, we can use this to
    170 	 * fetch the non-auth information for any app.
    171 	 */
    172 	st = mms_net_cfg_service(&cfg, "admin", "MMP", "1.0");
    173 	if (st == 2) {
    174 		/* password not available */
    175 		if (!pass) {
    176 			st = MMS_MGMT_PASSWORD_REQUIRED;
    177 		} else {
    178 			st = 0;
    179 		}
    180 	} else if (st == 1) {
    181 		st = MMS_MGMT_MMS_NOT_INIT;
    182 	}
    183 
    184 	if (st != 0) {
    185 		mms_trace(MMS_ERR, "Could not get MM connection info");
    186 		return (st);
    187 	}
    188 
    189 	if (app) {
    190 		if (strcasecmp(cfg.cli_name, app) != 0) {
    191 			free(cfg.cli_name);
    192 			cfg.cli_name = strdup(app);
    193 			if (cfg.cli_name == NULL) {
    194 				mms_trace(MMS_ERR, "Out of memory");
    195 				mms_net_cfg_free(&cfg);
    196 				return (ENOMEM);
    197 			}
    198 		}
    199 	}
    200 
    201 	if (inst) {
    202 		if (strcasecmp(cfg.cli_inst, inst) != 0) {
    203 			free(cfg.cli_inst);
    204 			cfg.cli_inst = strdup(app);
    205 			if (cfg.cli_inst == NULL) {
    206 				mms_trace(MMS_ERR, "Out of memory");
    207 				mms_net_cfg_free(&cfg);
    208 				return (ENOMEM);
    209 			}
    210 		}
    211 	}
    212 
    213 	if (pass) {
    214 		if (cfg.cli_pass) {
    215 			free(cfg.cli_pass);
    216 		}
    217 		cfg.cli_pass = strdup(pass);
    218 		if (cfg.cli_pass == NULL) {
    219 			mms_trace(MMS_ERR, "Out of memory");
    220 			mms_net_cfg_free(&cfg);
    221 			return (ENOMEM);
    222 		}
    223 	}
    224 
    225 	if (tag) {
    226 		tagp = tag;
    227 	}
    228 
    229 	if ((st = mms_init(&sess, &version)) != MMS_API_OK) {
    230 		mms_trace(MMS_ERR, "Unable to create a session with MM");
    231 		mms_net_cfg_free(&cfg);
    232 		return (st);
    233 	}
    234 
    235 	mms_trace(MMS_DEBUG, "MM version = %d, expected version = %d",
    236 	    version, MMS_API_VERSION);
    237 
    238 #ifdef	MMS_OPENSSL
    239 	if (cfg.ssl_enabled != 0) {
    240 		st = mms_ssl_client(&cfg, &ssl_data, &err);
    241 		if (st != 0) {
    242 			mms_get_error_string(&err, ebuf, MMS_EBUF_LEN);
    243 			mms_trace(MMS_ERR, "error ssl init - %s", ebuf);
    244 			mms_net_cfg_free(&cfg);
    245 			return (st);
    246 		}
    247 	}
    248 #endif	/* MMS_OPENSSL */
    249 
    250 	st = mms_hello(sess, cfg.cli_host, cfg.cli_port, cfg.cli_name,
    251 	    cfg.cli_inst, tagp, cfg.cli_pass, cfg.mm_pass, ssl_data);
    252 
    253 	if (st != MMS_API_OK) {
    254 		mms_trace(MMS_ERR,
    255 		    "Unable to create a session with MM, ret = %d [%s]",
    256 		    st, mms_sym_code_to_str(st));
    257 		mms_net_cfg_free(&cfg);
    258 
    259 		return (st);
    260 	}
    261 
    262 	*session = sess;
    263 
    264 	mms_trace(MMS_DEBUG, "Created a connection with MM");
    265 	mms_net_cfg_free(&cfg);
    266 
    267 	return (0);
    268 }
    269 
    270 /*
    271  * mms_mgmt_init_host()
    272  *
    273  *  DESCRIPTION:
    274  *
    275  *  Sets all required MMS options, and starts required services.
    276  *
    277  *  On an MMS client system,
    278  *	sets MM host, port and administrative password
    279  *	sets SSL options, if desired
    280  *	starts the Watcher daemon
    281  *
    282  *  On on MMS server system,
    283  *	creates MMS database admin user
    284  *	initializes MMS database and starts database server
    285  *	sets MM options [TBD:  list these with explanation]
    286  *	starts MM daemon and Watcher daemon
    287  *
    288  *  ARGUMENTS:
    289  *	nvlist_t *opts		key/value pairs for requested options
    290  *	nvlist_t **errs		optional - used to return detailed errors
    291  *				about invalid/missing options, and other
    292  *				operational failures during initialization.
    293  *				If 'errs' is non-NULL, a new nvlist will be
    294  *				allocated.  The caller should free this list
    295  *				with nvlist_free().
    296  *
    297  *  RETURN VALUES:
    298  *
    299  *	0		Success
    300  *	MMS_MGMT_NOARG	'opts' argument missing
    301  *	EINVAL		One or more requested options is invalid
    302  *	EALREADY	Host has already been initialized for MMS
    303  *	ENOMEM		Out of memory
    304  *	[others TBD]
    305  */
    306 
    307 int
    308 mms_mgmt_init_host(nvlist_t *opts, nvlist_t **errs)
    309 {
    310 	int			st = 0;
    311 	mms_mgmt_setopt_t	*optp = NULL;
    312 	int			nst = 0;
    313 	char			*val;
    314 	char			*pass = NULL;
    315 	char			*hosttype = NULL;
    316 	char			cfgvar[2048];
    317 	char			buf[2048];
    318 	int			i;
    319 	nvlist_t		*init_errs = NULL;
    320 
    321 	if (!opts) {
    322 		return (MMS_MGMT_NOARG);
    323 	}
    324 
    325 	if (!mgmt_chk_auth("solaris.mms.create")) {
    326 		mms_trace(MMS_DEBUG, "mgmt_chk_auth error");
    327 		return (EACCES);
    328 	}
    329 
    330 #ifdef	MMS_VAR_CFG
    331 	/* make sure we've not already been initialized */
    332 	st = mms_cfg_getvar(MMS_CFG_CONFIG_TYPE, buf);
    333 	if (st != 0) {
    334 		mms_trace(MMS_DEBUG, "mms_cfg_getvar error");
    335 		st = mgmt_xlate_cfgerr(st);
    336 		if (st != ENOENT) {
    337 			return (st);
    338 		}
    339 	} else {
    340 		/* host already configured */
    341 		mms_trace(MMS_DEBUG, "already config error");
    342 		return (EALREADY);
    343 	}
    344 #endif	/* MMS_VAR_CFG */
    345 
    346 	if (errs) {
    347 		*errs = NULL;
    348 		st = nvlist_alloc(&init_errs, NV_UNIQUE_NAME, 0);
    349 		if (st != 0) {
    350 			return (st);
    351 		}
    352 	}
    353 
    354 	st = nvlist_lookup_string(opts, O_OBJTYPE, &hosttype);
    355 	if (st == 0) {
    356 		if (*hosttype == 's') {
    357 			optp = mms_server_opts;
    358 #ifdef	MMS_VAR_CFG
    359 		} else if (*hosttype == 'c') {
    360 			optp = mms_client_opts;
    361 #endif	/* MMS_VAR_CFG */
    362 		} else {
    363 			mms_trace(MMS_DEBUG, "EINVAL error");
    364 			st = EINVAL;
    365 		}
    366 	}
    367 
    368 	if (st != 0) {
    369 		MGMT_ADD_OPTERR(init_errs, O_OBJTYPE, st);
    370 		*errs = init_errs;
    371 		return (st);
    372 	}
    373 
    374 	st = nvlist_lookup_string(opts, O_MMPASS, &pass);
    375 	if (st != 0) {
    376 		MGMT_ADD_OPTERR(init_errs, O_MMPASS, st);
    377 		*errs = init_errs;
    378 		return (st);
    379 	}
    380 
    381 	st = mms_cfg_getvar(MMS_CFG_MM_DB_USER, buf);
    382 	if (st != 0) {
    383 		mms_trace(MMS_DEBUG, "mms_cfg_getvar error");
    384 		st = mgmt_xlate_cfgerr(st);
    385 		if (st == ENOENT) {
    386 			st = mms_cfg_getvar(MMS_CFG_DB_INST
    387 			    "/:properties/method_context/user", buf);
    388 		}
    389 	}
    390 	if (st != 0) {
    391 		/* major configuration error */
    392 		mms_trace(MMS_DEBUG, "major configuration error");
    393 		MGMT_ADD_OPTERR(init_errs,
    394 		    "mmsdb method_context/user",
    395 		    st);
    396 		goto done;
    397 	}
    398 	(void) nvlist_add_string(opts, "db-user", buf);
    399 
    400 	for (i = 0; optp[i].name != NULL; i++) {
    401 #ifndef	MMS_VAR_CFG
    402 		/* We can only set opts in MMP until SMF gets sorted */
    403 		if (optp[i].mmpopt == NULL) {
    404 			continue;
    405 		}
    406 #endif	/* MMS_VAR_CFG */
    407 		nst = nvlist_lookup_string(opts, optp[i].name, &val);
    408 		if (nst == 0) {
    409 			if (optp[i].validate_func) {
    410 				nst = (optp[i].validate_func)(val);
    411 			}
    412 		} else if (nst == ENOENT) {
    413 			if (!(optp[i].required)) {
    414 				nst = 0;
    415 			} else if (optp[i].defval) {
    416 				nst = nvlist_add_string(opts,
    417 				    optp[i].name, optp[i].defval);
    418 			}
    419 		}
    420 
    421 		if (nst != 0) {
    422 			st = nst;
    423 
    424 			if (errs) {
    425 				(void) nvlist_add_int32(init_errs, optp[i].name,
    426 				    nst);
    427 			} else {
    428 				/* fail on first error */
    429 				break;
    430 			}
    431 		}
    432 	}
    433 
    434 	if (st != 0) {
    435 		goto done;
    436 	}
    437 
    438 #ifdef	MMS_VAR_CFG
    439 	/*
    440 	 * special case for DB logdir.  If not specified, should be set to
    441 	 * DBDIR/log
    442 	 */
    443 	if (*hosttype == 's') {
    444 		st = nvlist_lookup_string(opts, O_DBLOG, &val);
    445 		if (st == ENOENT) {
    446 			st = nvlist_lookup_string(opts, O_DBDIR, &val);
    447 			if (st == 0) {
    448 				(void) snprintf(buf, sizeof (buf), "%s/../%s",
    449 				    val, "log");
    450 				st = nvlist_add_string(opts, O_DBLOG, buf);
    451 			}
    452 		}
    453 		if (st != 0) {
    454 			MGMT_ADD_OPTERR(init_errs, O_DBDIR, st);
    455 			goto done;
    456 		}
    457 	}
    458 
    459 	/* TODO:  support ssl enabled */
    460 
    461 	/* have the full complement of required options - set SMF config  */
    462 	for (i = 0; mmscfgopts[i].name != NULL; i++) {
    463 		nst = nvlist_lookup_string(opts,  mmscfgopts[i].name, &val);
    464 		if (nst == 0) {
    465 			mms_cfg_setvar(mmscfgopts[i].cfgnam, val);
    466 		}
    467 	}
    468 #endif	/* MMS_VAR_CFG */
    469 
    470 	/* Set the MMS Admin password */
    471 	st = mgmt_set_pass(pass);
    472 	if (st != 0) {
    473 		goto done;
    474 	}
    475 
    476 	/* If we're setting up the server, configure the DB and start MM */
    477 	if (*hosttype == 's') {
    478 #ifndef	MMS_VAR_CFG
    479 		/*
    480 		 * TEMPORARY:  Fetch variables from SMF, rather than
    481 		 * require them to be passed in.
    482 		 */
    483 		st = mms_cfg_getvar(MMS_CFG_DB_DATA, cfgvar);
    484 		if (st != 0) {
    485 			MGMT_ADD_OPTERR(init_errs, O_DBDIR, st);
    486 			goto done;
    487 		} else {
    488 			(void) nvlist_add_string(opts, O_DBDIR, cfgvar);
    489 
    490 			/* fixed path for log dir */
    491 			(void) strlcat(cfgvar, "/../log", sizeof (cfgvar));
    492 			(void) nvlist_add_string(opts, O_DBLOG, cfgvar);
    493 		}
    494 		st = mms_cfg_getvar(MMS_CFG_MM_DB_PORT, cfgvar);
    495 		if (st == 0) {
    496 			(void) nvlist_add_string(opts, O_DBPORT, cfgvar);
    497 		} else {
    498 			MGMT_ADD_OPTERR(init_errs, O_DBPORT, st);
    499 			goto done;
    500 		}
    501 
    502 		st = mms_cfg_getvar(MMS_CFG_MM_DB_NAME, cfgvar);
    503 		if (st == 0) {
    504 			(void) nvlist_add_string(opts, O_DBNAME, cfgvar);
    505 		} else {
    506 			MGMT_ADD_OPTERR(init_errs, O_DBNAME, st);
    507 			goto done;
    508 		}
    509 
    510 		st = mms_cfg_getvar(MMS_CFG_MM_DB_HOST, cfgvar);
    511 		if (st == 0) {
    512 			(void) nvlist_add_string(opts, O_DBHOST, cfgvar);
    513 		} else {
    514 			MGMT_ADD_OPTERR(init_errs, O_DBHOST, st);
    515 			goto done;
    516 		}
    517 
    518 #endif	/* !MMS_VAR_CFG */
    519 		st = mgmt_set_db_opts(opts, init_errs);
    520 		if (st == 0) {
    521 			/* Database will be functional after this call */
    522 			st = mgmt_db_create(1, 1, opts);
    523 		}
    524 
    525 		if (st != 0) {
    526 			mms_trace(MMS_DEBUG, "mgmt_db_create error");
    527 			goto done;
    528 		}
    529 
    530 		mms_trace(MMS_DEBUG, "enable mm");
    531 		st = mgmt_set_svc_state(MMSVC, ENABLE, NULL);
    532 		if (st != 0)
    533 			mms_trace(MMS_DEBUG,
    534 			    "mgmt_set_svc_state(MMSVC, ENABLE, NULL) "
    535 			    "error");
    536 	}
    537 
    538 	/* Watcher needs to be started for both host types */
    539 	if (st == 0) {
    540 		mms_trace(MMS_DEBUG, "enable wcr");
    541 		st = mgmt_set_svc_state(WCRSVC, ENABLE, NULL);
    542 	}
    543 	if (st != 0)
    544 		mms_trace(MMS_DEBUG,
    545 		    "mgmt_set_svc_state(WCRSVC, ENABLE, NULL) "
    546 		    "error");
    547 
    548 done:
    549 	if (st != 0) {
    550 		if (errs) {
    551 			*errs = init_errs;
    552 		}
    553 		/* don't stop services if we haven't changed anything */
    554 		if (st != EALREADY) {
    555 			(void) mms_mgmt_uninitialize();
    556 		}
    557 	} else if (init_errs) {
    558 		nvlist_free(init_errs);
    559 	}
    560 
    561 	return (st);
    562 }
    563 
    564 /*
    565  * mms_mgmt_get_opts()
    566  */
    567 int
    568 mms_mgmt_get_opts(char *type, nvlist_t **opts)
    569 {
    570 	int			st;
    571 	int			i;
    572 	char			buf[2048];
    573 	void			*session = NULL;
    574 	void			*response = NULL;
    575 	char			tid[64];
    576 	nvlist_t		*sysattrs = NULL;
    577 	nvpair_t		*nvp;
    578 	nvlist_t		*nva;
    579 
    580 	if ((type == NULL) || (opts == NULL)) {
    581 		return (MMS_MGMT_NOARG);
    582 	}
    583 
    584 	/* get MM system vals */
    585 	(void) mms_gen_taskid(tid);
    586 	(void) snprintf(buf, sizeof (buf),
    587 	    "show task['%s'] report[SYSTEM] reportmode[namevalue];", tid);
    588 
    589 	st = create_mm_clnt(NULL, NULL, NULL, NULL, &session);
    590 	if (st != 0) {
    591 		goto done;
    592 	}
    593 
    594 	st = mms_mgmt_send_cmd(session, tid, buf, "get system attrs",
    595 	    &response);
    596 
    597 	(void) mms_goodbye(session, 0);
    598 
    599 	if (st != 0) {
    600 		goto done;
    601 	}
    602 	st = mmp_get_nvattrs(O_NAME, B_TRUE, response, &sysattrs);
    603 	if (st != 0) {
    604 		goto done;
    605 	}
    606 
    607 	nvp = nvlist_next_nvpair(sysattrs, NULL);
    608 	if (nvp == NULL) {
    609 		/* should never happen */
    610 		goto done;
    611 	}
    612 
    613 	st = nvpair_value_nvlist(nvp, &nva);
    614 	if (st != 0) {
    615 		goto done;
    616 	}
    617 
    618 	/* add the SMF variables */
    619 	for (i = 0; mmscfgopts[i].name != NULL; i++) {
    620 		st = mms_cfg_getvar(mmscfgopts[i].cfgnam, buf);
    621 		if (st != 0) {
    622 			/* probably unset, keep going */
    623 			st = 0;
    624 			continue;
    625 		}
    626 		if (!nvlist_exists(nva, mmscfgopts[i].name)) {
    627 			(void) nvlist_add_string(nva, mmscfgopts[i].name, buf);
    628 		}
    629 	}
    630 
    631 	if (st != 0) {
    632 		goto done;
    633 	}
    634 
    635 	if (*opts == NULL) {
    636 		st = nvlist_alloc(opts, NV_UNIQUE_NAME, 0);
    637 		if (st != 0) {
    638 			goto done;
    639 		}
    640 	}
    641 
    642 	/* don't want a proper name for this list */
    643 	(void) nvlist_add_nvlist(*opts, "", nva);
    644 
    645 
    646 done:
    647 
    648 	if (sysattrs) {
    649 		nvlist_free(sysattrs);
    650 	}
    651 
    652 	if (st != 0) {
    653 		nvlist_free(*opts);
    654 		*opts = NULL;
    655 	}
    656 
    657 	return (st);
    658 }
    659 
    660 /*
    661  *  Required opts that are not in inopts, and options with invalid values
    662  *  are added to the argument nvlist "errlist".
    663  */
    664 int
    665 mms_mgmt_set_opts(nvlist_t *optlist, nvlist_t *errlist)
    666 {
    667 	int			st;
    668 	int			i;
    669 	int			errs = 0;
    670 	char			*opt;
    671 	char			*val;
    672 	mms_mgmt_setopt_t	*optp = mms_server_opts;
    673 	nvpair_t		*nvp;
    674 	int			refresh_svcs = 0;
    675 #ifdef	MMS_VAR_CFG
    676 	int			svc_to_check = 0;
    677 #endif	/* MMS_VAR_CFG */
    678 	char			mmtype[2048];
    679 	char			buf[2048];
    680 	char			cmd[8192];
    681 	char			tid[64];
    682 	void			*session = NULL;
    683 	void			*response = NULL;
    684 	int			count = 0;
    685 
    686 	if (optlist == NULL) {
    687 		return (MMS_MGMT_NOARG);
    688 	}
    689 
    690 	if (!mgmt_chk_auth("solaris.mms.modify")) {
    691 		return (EACCES);
    692 	}
    693 
    694 	/* check the type of system we're on */
    695 	st = mms_cfg_getvar(MMS_CFG_CONFIG_TYPE, mmtype);
    696 	if (st != 0) {
    697 		return (ENOTSUP);
    698 	}
    699 
    700 #ifdef	MMS_VAR_CFG
    701 	if (*mmtype == 'c') {
    702 		svc_to_check = WCR;
    703 	} else {
    704 		svc_to_check = MM|DB;
    705 	}
    706 #endif	/* MMS_VAR_CFG */
    707 
    708 	nvp = NULL;
    709 	while ((nvp = nvlist_next_nvpair(optlist, nvp)) != NULL) {
    710 
    711 		opt = nvpair_name(nvp);
    712 
    713 		if (strcmp(opt, O_OBJTYPE) == 0) {
    714 			/* ignore type on 'set' */
    715 			continue;
    716 		}
    717 
    718 		st = nvpair_value_string(nvp, &val);
    719 		if (st != 0) {
    720 			break;
    721 		}
    722 
    723 		/* unrecognized options are ignored */
    724 		for (i = 0; optp[i].name != NULL; i++) {
    725 			if (strcmp(opt, optp[i].name) != 0) {
    726 				continue;
    727 			}
    728 
    729 			st = 0;
    730 
    731 			if (optp[i].validate_func) {
    732 				st = (optp[i].validate_func)(val);
    733 			}
    734 			if (st != 0) {
    735 				errs++;
    736 				if (errlist) {
    737 					(void) nvlist_add_int32(errlist, opt,
    738 					    st);
    739 				}
    740 			}
    741 			break;
    742 		}
    743 
    744 		if ((errs) && (!errlist)) {
    745 			st = EINVAL;
    746 			break;
    747 		}
    748 	}
    749 
    750 	if (st != 0) {
    751 		goto done;
    752 	}
    753 
    754 #ifdef	MMS_VAR_CFG
    755 	/* set SMF config  */
    756 	for (i = 0; mmscfgopts[i].name != NULL; i++) {
    757 		if (strcmp(mmscfgopts[i].name, O_OBJTYPE) == 0) {
    758 			/* again, skip for set */
    759 			continue;
    760 		}
    761 		st = nvlist_lookup_string(optlist,  mmscfgopts[i].name, &val);
    762 		if (st == 0) {
    763 			if (!(svc_to_check & mmscfgopts[i].svc)) {
    764 				st = MMS_MGMT_ERR_SVRONLY;
    765 				MGMT_ADD_ERR(errlist, mmscfgopts[i].name, st);
    766 				continue;
    767 			}
    768 			mms_cfg_setvar(mmscfgopts[i].cfgnam, val);
    769 			refresh_svcs |= mmscfgopts[i].svc;
    770 		}
    771 	}
    772 	st = 0;
    773 
    774 	/* set DB opts, if any were specified */
    775 	if (refresh_svcs & DB) {
    776 		st = mgmt_set_db_opts(optlist, errlist);
    777 
    778 		if (st != 0) {
    779 			goto done;
    780 		}
    781 	}
    782 #endif	/* MMS_VAR_CFG */
    783 
    784 	(void) mms_gen_taskid(tid);
    785 	(void) snprintf(cmd, sizeof (cmd), "attribute task['%s'] ", tid);
    786 
    787 	for (i = 0; mms_server_opts[i].name != NULL; i++) {
    788 		if (mms_server_opts[i].mmpopt == NULL) {
    789 			continue;
    790 		}
    791 		st = nvlist_lookup_string(optlist, mms_server_opts[i].name,
    792 		    &val);
    793 		if (st != 0) {
    794 			continue;
    795 		}
    796 		if (strcmp(val, "") != 0) {
    797 			/* set */
    798 			(void) snprintf(buf, sizeof (buf),
    799 			    " set[SYSTEM.'%s' '%s']",
    800 			    mms_server_opts[i].mmpopt, val);
    801 		} else {
    802 			/* unset */
    803 			(void) snprintf(buf, sizeof (buf),
    804 			    " unset[SYSTEM.'%s']",
    805 			    mms_server_opts[i].mmpopt);
    806 		}
    807 
    808 		(void) strlcat(cmd, buf, sizeof (cmd));
    809 		count++;
    810 	}
    811 	(void) strlcat(cmd, ";", sizeof (cmd));
    812 
    813 	/* if no MM opts specified, nothing to set */
    814 	if (count > 0) {
    815 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &session);
    816 		if (st != 0) {
    817 			goto done;
    818 		}
    819 
    820 		st = mms_mgmt_send_cmd(session, tid, cmd, "set system attrs",
    821 		    &response);
    822 
    823 		(void) mms_goodbye(session, 0);
    824 
    825 		if (st != 0) {
    826 			goto done;
    827 		}
    828 	}
    829 
    830 #ifdef	MMS_VAR_CFG
    831 	/* TODO:  set SSL opts */
    832 	st = mgmt_set_ssl(optlist);
    833 	if (st != 0) {
    834 		goto done;
    835 	}
    836 #endif	/* MMS_VAR_CFG */
    837 
    838 	/* refresh services */
    839 	if (*mmtype == 's') {
    840 		if (refresh_svcs & DB) {
    841 			mms_trace(MMS_DEBUG, "refresh db");
    842 			(void) mgmt_set_svc_state(DBSVC, REFRESH, NULL);
    843 		}
    844 		if (refresh_svcs & MM) {
    845 			mms_trace(MMS_DEBUG, "refresh mm");
    846 			(void) mgmt_set_svc_state(MMSVC, REFRESH, NULL);
    847 		}
    848 	}
    849 
    850 	if (refresh_svcs & WCR) {
    851 		mms_trace(MMS_DEBUG, "refresh wcr");
    852 		(void) mgmt_set_svc_state(WCRSVC, REFRESH, NULL);
    853 	}
    854 
    855 done:
    856 	return (st);
    857 }
    858 
    859 int
    860 mms_mgmt_uninitialize(void)
    861 {
    862 	int		st = 0;
    863 	char		*mmsvcs[] = {WCRSVC, MMSVC, DBSVC, NULL};
    864 	int		i;
    865 
    866 	if (!mgmt_chk_auth("solaris.mms.delete")) {
    867 		return (EACCES);
    868 	}
    869 
    870 	/* stop all running services */
    871 	for (i = 0; mmsvcs[i] != NULL; i++) {
    872 		mms_trace(MMS_DEBUG, "disable %s", mmsvcs[i]);
    873 		st = mgmt_set_svc_state(mmsvcs[i], DISABLE, NULL);
    874 		if (st != 0) {
    875 			break;
    876 		}
    877 	}
    878 
    879 #ifdef	MMS_VAR_CFG
    880 	/* get rid of all the configuration information */
    881 	if (st == 0) {
    882 		mgmt_unsetall_cfgvar();
    883 	}
    884 #endif	/* MMS_VAR_CFG */
    885 
    886 	return (st);
    887 }
    888 
    889 static int
    890 mgmt_set_pass(char *inpw)
    891 {
    892 	int	st = 0;
    893 	int	fd = -1;
    894 	size_t	sz;
    895 	size_t	szi;
    896 	char	*pf = MMSETCDIR"/passwd/hello.new";
    897 	char	*of = MMSETCDIR"/passwd/hello";
    898 
    899 	if (!inpw) {
    900 		return (EINVAL);
    901 	}
    902 
    903 	fd = open64(pf, O_CREAT|O_WRONLY|O_NOFOLLOW|O_NOLINKS|O_SYNC|O_TRUNC,
    904 	    0600);
    905 
    906 	if (fd == -1) {
    907 		return (errno);
    908 	}
    909 
    910 	szi = strlen(inpw) + 1;
    911 	sz = write(fd, inpw, szi);
    912 	if (szi != sz) {
    913 		st = errno;
    914 	}
    915 
    916 	(void) close(fd);
    917 
    918 	if (st == 0) {
    919 		st = rename(pf, of);
    920 	} else {
    921 		(void) unlink(pf);
    922 	}
    923 
    924 	return (st);
    925 }
    926 
    927 #ifdef	MMS_VAR_CFG
    928 static int
    929 mgmt_set_ssl(nvlist_t *opts)
    930 {
    931 	char		*val = NULL;
    932 
    933 
    934 	if (!opts) {
    935 		return (EINVAL);
    936 	}
    937 
    938 	nvlist_lookup_string(opts, O_SSLENABLED, &val);
    939 	if ((!val) || (strcmp(val, "false") == 0)) {
    940 		mms_cfg_setvar(MMS_CFG_SSL_ENABLED, "false");
    941 		mms_cfg_unsetvar(MMS_CFG_SSL_CERT_FILE);
    942 		mms_cfg_unsetvar(MMS_CFG_SSL_PASS_FILE);
    943 		mms_cfg_unsetvar(MMS_CFG_SSL_CRL_FILE);
    944 		mms_cfg_unsetvar(MMS_CFG_SSL_PEER_FILE);
    945 		mms_cfg_unsetvar(MMS_CFG_SSL_DH_FILE);
    946 		mms_cfg_unsetvar(MMS_CFG_SSL_VERIFY);
    947 #if TODO
    948 	} else  {
    949 		/* TODO:  Create the certs, etc. for SSL */
    950 		/* leave existng cfg alone for now  */
    951 #endif
    952 	}
    953 
    954 	return (0);
    955 }
    956 #endif	/* MMS_VAR_CFG */
    957 
    958 int
    959 mms_mgmt_add_application(void *session, nvlist_t *nvl, nvlist_t *errs)
    960 {
    961 	int		st;
    962 	int		nst;
    963 	void		*sess = NULL;
    964 	void		*sessp = session;
    965 	char		tid[64];
    966 	char		cmd[8192];
    967 	char		buf[1024];
    968 	void		*response;
    969 	char		*name;
    970 	char		*val;
    971 	char		*pass;
    972 	int		i;
    973 	mms_mgmt_setopt_t *optp = application_opts;
    974 
    975 	if (!nvl) {
    976 		return (MMS_MGMT_NOARG);
    977 	}
    978 
    979 	if (!mgmt_chk_auth("solaris.mms.create")) {
    980 		return (EACCES);
    981 	}
    982 
    983 	st = nvlist_lookup_string(nvl, O_NAME, &name);
    984 	if (st != 0) {
    985 		if (errs) {
    986 			(void) nvlist_add_int32(errs, O_NAME, st);
    987 		}
    988 		return (st);
    989 	}
    990 
    991 	st = nvlist_lookup_string(nvl, O_MMPASS, &pass);
    992 	if (st != 0) {
    993 		if (errs) {
    994 			(void) nvlist_add_int32(errs, O_MMPASS, st);
    995 		}
    996 		return (st);
    997 	}
    998 
    999 	(void) mms_gen_taskid(tid);
   1000 
   1001 	(void) snprintf(cmd, sizeof (cmd),
   1002 	    "create task['%s'] type[APPLICATION]"
   1003 	    " set[APPLICATION.'ApplicationName' '%s']", tid, name);
   1004 
   1005 	for (i = 0; optp[i].name != NULL; i++) {
   1006 		if (strcmp(optp[i].name, O_NAME) == 0) {
   1007 			continue;
   1008 		}
   1009 		nst = nvlist_lookup_string(nvl, optp[i].name, &val);
   1010 		if (nst == 0) {
   1011 			if (optp[i].validate_func) {
   1012 				nst = (optp[i].validate_func)(val);
   1013 			}
   1014 		} else if (nst == ENOENT) {
   1015 			if (!(optp[i].required)) {
   1016 				nst = 0;
   1017 				continue;
   1018 			} else if (optp[i].defval) {
   1019 				val = optp[i].defval;
   1020 			}
   1021 		}
   1022 
   1023 		if (nst != 0) {
   1024 			st = nst;
   1025 
   1026 			if (errs) {
   1027 				(void) nvlist_add_int32(errs, optp[i].name,
   1028 				    nst);
   1029 			} else {
   1030 				/* fail on first error */
   1031 				break;
   1032 			}
   1033 		} else {
   1034 			(void) snprintf(buf, sizeof (buf),
   1035 			    " set[APPLICATION.'%s' '%s']",
   1036 			    optp[i].mmpopt, val);
   1037 			(void) strlcat(cmd, buf, sizeof (cmd));
   1038 		}
   1039 	}
   1040 	(void) strlcat(cmd, ";", sizeof (cmd));
   1041 
   1042 	if (!session) {
   1043 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1044 		if (st != 0) {
   1045 			return (st);
   1046 		}
   1047 		sessp = sess;
   1048 	}
   1049 
   1050 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "add application", &response);
   1051 
   1052 	if (st == 0) {
   1053 		/* add an application instance for administrative purposes */
   1054 		(void) mms_gen_taskid(tid);
   1055 		(void) snprintf(cmd, sizeof (cmd),
   1056 		    "create task['%s'] type[AI] "
   1057 		    "set[AI.'ApplicationName' '%s'] "
   1058 		    "set[AI.'AIName' 'admin'] "
   1059 		    "set[AI.'SessionsAllowed' 'multiple'];",
   1060 		    tid, name);
   1061 
   1062 		st = mms_mgmt_send_cmd(sessp, tid, cmd,
   1063 		    "add application instance", &response);
   1064 	}
   1065 
   1066 	if (st == 0) {
   1067 		st = mms_mgmt_set_pass(sessp, nvl, errs);
   1068 	}
   1069 
   1070 	if (st != 0) {
   1071 		MGMT_ADD_ERR(errs, name, st);
   1072 		(void) mms_mgmt_remove_application(sessp, nvl, errs);
   1073 	}
   1074 
   1075 	if (sess) {
   1076 		(void) mms_goodbye(sess, 0);
   1077 	}
   1078 
   1079 	return (st);
   1080 }
   1081 
   1082 int
   1083 mms_mgmt_remove_application(void *session, nvlist_t *nvl, nvlist_t *errs)
   1084 {
   1085 	int		st;
   1086 	void		*sess = NULL;
   1087 	void		*sessp = session;
   1088 	char		tid[64];
   1089 	char		cmd[8192];
   1090 	void		*response;
   1091 	char		*name;
   1092 	uint32_t	volcnt = 0;
   1093 
   1094 	if (!nvl) {
   1095 		return (MMS_MGMT_NOARG);
   1096 	}
   1097 
   1098 	if (!mgmt_chk_auth("solaris.mms.delete")) {
   1099 		return (EACCES);
   1100 	}
   1101 
   1102 	st = nvlist_lookup_string(nvl, O_NAME, &name);
   1103 	if (st != 0) {
   1104 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   1105 		return (st);
   1106 	}
   1107 
   1108 	if (!session) {
   1109 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1110 		if (st != 0) {
   1111 			return (st);
   1112 		}
   1113 		sessp = sess;
   1114 	}
   1115 
   1116 	/*
   1117 	 * See if there are any volumes in use by this application
   1118 	 * before removing it.  Fail the op so we don't lose any
   1119 	 * customer data.
   1120 	 */
   1121 	(void) mms_gen_taskid(tid);
   1122 	(void) snprintf(cmd, sizeof (cmd),
   1123 	    "show task['%s'] report[VOLUME] reportmode[number] "
   1124 	    "match[streq(VOLUME.'ApplicationName' '%s')];",
   1125 	    tid, name);
   1126 
   1127 	st = mms_mgmt_send_cmd(sessp, tid, cmd,
   1128 	    "find volumes for app", &response);
   1129 	if (st == 0) {
   1130 		st = mms_mgmt_mmp_count(response, &volcnt);
   1131 		mms_free_rsp(response);
   1132 	}
   1133 
   1134 	if (volcnt != 0) {
   1135 		st = MMS_MGMT_APP_VOLS_EXIST;
   1136 	}
   1137 
   1138 	if (st != 0) {
   1139 		goto done;
   1140 	}
   1141 
   1142 	/* delete any CARTRIDGEGROUPAPPLICATIONS */
   1143 	(void) mms_gen_taskid(tid);
   1144 	(void) snprintf(cmd, sizeof (cmd),
   1145 	    "delete task['%s'] type[CARTRIDGEGROUPAPPLICATION] "
   1146 	    "match[streq(CARTRIDGEGROUPAPPLICATION.'ApplicationName' '%s')];",
   1147 	    tid, name);
   1148 
   1149 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete mpool app",
   1150 	    &response);
   1151 
   1152 	if (st != 0) {
   1153 		goto done;
   1154 	}
   1155 
   1156 	/* delete any DRIVEGROUPAPPLICATIONS */
   1157 	(void) mms_gen_taskid(tid);
   1158 	(void) snprintf(cmd, sizeof (cmd),
   1159 	    "delete task['%s'] type[DRIVEGROUPAPPLICATION] "
   1160 	    "match[streq(DRIVEGROUPAPPLICATION.'ApplicationName' '%s')];",
   1161 	    tid, name);
   1162 
   1163 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete drive app",
   1164 	    &response);
   1165 
   1166 	if (st != 0) {
   1167 		goto done;
   1168 	}
   1169 
   1170 	/* next, delete the application instances. */
   1171 	(void) mms_gen_taskid(tid);
   1172 	(void) snprintf(cmd, sizeof (cmd),
   1173 	    "delete task['%s'] type[AI] "
   1174 	    "match[streq(AI.'ApplicationName' '%s')];", tid, name);
   1175 
   1176 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete app instance",
   1177 	    &response);
   1178 	if (st == 0) {
   1179 
   1180 		/* Finally, the application itself */
   1181 		(void) mms_gen_taskid(tid);
   1182 		(void) snprintf(cmd, sizeof (cmd),
   1183 		    "delete task['%s'] type[APPLICATION]"
   1184 		    " match[streq(APPLICATION.'ApplicationName' '%s')];",
   1185 		    tid, name);
   1186 
   1187 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete application",
   1188 		    &response);
   1189 	}
   1190 
   1191 done:
   1192 
   1193 	if (sess) {
   1194 		(void) mms_goodbye(sess, 0);
   1195 	}
   1196 
   1197 	return (st);
   1198 }
   1199 
   1200 int
   1201 mms_mgmt_modify_application(void *session, nvlist_t *nvl, nvlist_t *errs)
   1202 {
   1203 	int		st;
   1204 	void		*sess = NULL;
   1205 	void		*sessp = session;
   1206 	char		tid[64];
   1207 	char		cmd[8192];
   1208 	char		buf[1024];
   1209 	void		*response;
   1210 	char		*name;
   1211 	char		*val;
   1212 	char		*val2;
   1213 	nvlist_t	*attrs;
   1214 	nvlist_t	*nva;
   1215 	nvpair_t	*nvp;
   1216 	mms_mgmt_setopt_t *optp = application_opts;
   1217 	int		i;
   1218 	int		changed = 0;
   1219 	int		nst;
   1220 
   1221 	if (!nvl) {
   1222 		return (MMS_MGMT_NOARG);
   1223 	}
   1224 
   1225 	if (!mgmt_chk_auth("solaris.mms.modify")) {
   1226 		return (EACCES);
   1227 	}
   1228 
   1229 	st = nvlist_lookup_string(nvl, O_NAME, &name);
   1230 	if (st != 0) {
   1231 		if (errs) {
   1232 			(void) nvlist_add_int32(errs, O_NAME, st);
   1233 		}
   1234 		return (st);
   1235 	}
   1236 
   1237 	(void) mms_gen_taskid(tid);
   1238 
   1239 	(void) snprintf(cmd, sizeof (cmd),
   1240 	    "show task['%s'] report[APPLICATION] reportmode[namevalue]"
   1241 	    " match[streq(APPLICATION.'ApplicationName' '%s')];", tid, name);
   1242 
   1243 	if (!session) {
   1244 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1245 		if (st != 0) {
   1246 			return (st);
   1247 		}
   1248 		sessp = sess;
   1249 	}
   1250 
   1251 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "add application", &response);
   1252 
   1253 	if (st != 0) {
   1254 		goto done;
   1255 	}
   1256 
   1257 	st = mmp_get_nvattrs("ApplicationName", B_FALSE, response, &attrs);
   1258 	if (st != 0) {
   1259 		goto done;
   1260 	}
   1261 
   1262 	nvp = nvlist_next_nvpair(attrs, NULL);
   1263 	if (nvp == NULL) {
   1264 		st = EINVAL;
   1265 		goto done;
   1266 	}
   1267 	st = nvpair_value_nvlist(nvp, &nva);
   1268 	if (st != 0) {
   1269 		goto done;
   1270 	}
   1271 
   1272 	(void) mms_gen_taskid(tid);
   1273 
   1274 	(void) snprintf(cmd, sizeof (cmd),
   1275 	    "attribute task['%s'] "
   1276 	    "match[streq(APPLICATION.'ApplicationName' '%s')] ",
   1277 	    tid, name);
   1278 
   1279 	for (i = 0; optp[i].name != NULL; i++) {
   1280 		if (strcmp(optp[i].name, O_NAME) == 0) {
   1281 			continue;
   1282 		}
   1283 		if ((nvlist_lookup_string(nvl, optp[i].name, &val)) != 0) {
   1284 			continue;
   1285 		}
   1286 
   1287 		if (strcmp(val, "") == 0) {
   1288 			(void) snprintf(buf, sizeof (buf),
   1289 			    " unset[APPLICATION.'%s']", optp[i].mmpopt);
   1290 			(void) strlcat(cmd, buf, sizeof (cmd));
   1291 			changed++;
   1292 		} else {
   1293 			nst = nvlist_lookup_string(nva, optp[i].mmpopt, &val2);
   1294 			if (nst == 0) {
   1295 				if (strcmp(val, val2) == 0) {
   1296 					continue;
   1297 				}
   1298 			}
   1299 			(void) snprintf(buf, sizeof (buf),
   1300 			    " set[APPLICATION.'%s' '%s']",
   1301 			    optp[i].mmpopt, val);
   1302 			(void) strlcat(cmd, buf, sizeof (cmd));
   1303 			changed++;
   1304 		}
   1305 	}
   1306 	(void) strlcat(cmd, ";", sizeof (cmd));
   1307 
   1308 	if (changed == 0) {
   1309 		goto done;
   1310 	}
   1311 
   1312 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "modify application",
   1313 	    &response);
   1314 
   1315 done:
   1316 	if (sess) {
   1317 		(void) mms_goodbye(sess, 0);
   1318 	}
   1319 
   1320 	return (st);
   1321 }
   1322 
   1323 int
   1324 mms_mgmt_set_pass(void *session, nvlist_t *nvl, nvlist_t *errs)
   1325 {
   1326 	int		st;
   1327 	char		*passp = NULL;
   1328 	char		*namep = NULL;
   1329 	void		*sessp = session;
   1330 	void		*sess = NULL;
   1331 	void		*response = NULL;
   1332 	char		tid[64];
   1333 	char		cmd[8192];
   1334 
   1335 	if (!nvl) {
   1336 		return (MMS_MGMT_NOARG);
   1337 	}
   1338 
   1339 	if (!mgmt_chk_auth("solaris.mms.modify")) {
   1340 		return (EACCES);
   1341 	}
   1342 
   1343 	st = nvlist_lookup_string(nvl, O_NAME, &namep);
   1344 	if (st != 0) {
   1345 		if (errs) {
   1346 			(void) nvlist_add_int32(errs, O_NAME, st);
   1347 		}
   1348 		return (st);
   1349 	}
   1350 
   1351 	st = nvlist_lookup_string(nvl, O_MMPASS, &passp);
   1352 	if (st != 0) {
   1353 		MGMT_ADD_OPTERR(errs, O_MMPASS, st);
   1354 		return (st);
   1355 	}
   1356 
   1357 	if (strcasecmp(namep, "admin") == 0) {
   1358 		namep = "MMS";
   1359 	} else if (strcasecmp(namep, "dbadmin") == 0) {
   1360 		/* special case - doesn't modify MM at all */
   1361 		st = mgmt_set_db_pass(passp, errs);
   1362 		return (st);
   1363 	}
   1364 
   1365 	if (!session) {
   1366 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1367 		if (st != 0) {
   1368 			return (st);
   1369 		}
   1370 		sessp = sess;
   1371 	}
   1372 
   1373 	(void) mms_gen_taskid(tid);
   1374 	(void) snprintf(cmd, sizeof (cmd),
   1375 	    "setpassword task['%s'] password['%s'] name['%s'];",
   1376 	    tid, passp, namep);
   1377 
   1378 	st = mms_mgmt_send_cmd(sessp, tid, cmd,
   1379 	    "set password", &response);
   1380 
   1381 	if (sess) {
   1382 		(void) mms_goodbye(sess, 0);
   1383 	}
   1384 
   1385 	if (st != 0) {
   1386 		MGMT_ADD_ERR(errs, O_MMPASS, st);
   1387 	}
   1388 
   1389 	return (st);
   1390 }
   1391 
   1392 int
   1393 mms_mgmt_list_supported_types(void *session, nvlist_t **supported)
   1394 {
   1395 	int		st;
   1396 	void		*sessp = session;
   1397 	void		*sess = NULL;
   1398 	void		*response = NULL;
   1399 	char		tid[64];
   1400 	char		cmd[8192];
   1401 	nvlist_t	*nvl = NULL;
   1402 
   1403 
   1404 	if (!supported) {
   1405 		return (MMS_MGMT_NOARG);
   1406 	}
   1407 
   1408 	st = nvlist_alloc(supported, NV_UNIQUE_NAME, 0);
   1409 	if (st != 0) {
   1410 		return (st);
   1411 	}
   1412 
   1413 	if (!sessp) {
   1414 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1415 		if (st != 0) {
   1416 			return (st);
   1417 		}
   1418 		sessp = sess;
   1419 	}
   1420 
   1421 	(void) mms_gen_taskid(tid);
   1422 	(void) snprintf(cmd, sizeof (cmd),
   1423 	    "show task['%s'] reportmode[namevalue] report[LIBRARYLIST];", tid);
   1424 
   1425 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "list supported", &response);
   1426 	if (st == 0) {
   1427 		st = mmp_get_nvattrs("LibraryString", B_FALSE, response, &nvl);
   1428 		mms_free_rsp(response);
   1429 		if (st == 0) {
   1430 			(void) nvlist_add_nvlist(*supported, "LIBRARY", nvl);
   1431 		}
   1432 		nvlist_free(nvl);
   1433 		nvl = NULL;
   1434 	}
   1435 	if (st != 0) {
   1436 		goto done;
   1437 	}
   1438 
   1439 	(void) mms_gen_taskid(tid);
   1440 	(void) snprintf(cmd, sizeof (cmd),
   1441 	    "show task['%s'] reportmode[namevalue] report[DRIVELIST];", tid);
   1442 
   1443 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "list supported", &response);
   1444 	if (st == 0) {
   1445 		st = mmp_get_nvattrs("DriveString", B_FALSE, response, &nvl);
   1446 		mms_free_rsp(response);
   1447 		if (st == 0) {
   1448 			(void) nvlist_add_nvlist(*supported, "DRIVE", nvl);
   1449 		}
   1450 		nvlist_free(nvl);
   1451 		nvl = NULL;
   1452 	}
   1453 	if (st != 0) {
   1454 		goto done;
   1455 	}
   1456 
   1457 	(void) mms_gen_taskid(tid);
   1458 	(void) snprintf(cmd, sizeof (cmd),
   1459 	    "show task['%s'] reportmode[namevalue] "
   1460 	    "report[CARTRIDGELIST];", tid);
   1461 
   1462 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "list supported", &response);
   1463 	if (st == 0) {
   1464 		st = mmp_get_nvattrs("CartridgeString", B_FALSE, response,
   1465 		    &nvl);
   1466 		mms_free_rsp(response);
   1467 		if (st == 0) {
   1468 			(void) nvlist_add_nvlist(*supported, "CARTRIDGE", nvl);
   1469 		}
   1470 		nvlist_free(nvl);
   1471 		nvl = NULL;
   1472 	}
   1473 
   1474 done:
   1475 	if (sess) {
   1476 		(void) mms_goodbye(sess, 0);
   1477 	}
   1478 
   1479 	return (st);
   1480 }
   1481 
   1482 int
   1483 mms_mgmt_show_apps(void *session, nvlist_t *nvl, nvlist_t **apps)
   1484 {
   1485 	int		st;
   1486 	void		*sessp = session;
   1487 	void		*sess = NULL;
   1488 	void		*response = NULL;
   1489 	char		tid[64];
   1490 	char		cmd[8192];
   1491 	char		buf[2048];
   1492 	char		**names = NULL;
   1493 	int		count = 0;
   1494 	int		i;
   1495 	char		*key = O_NAME;
   1496 
   1497 	if (!nvl || !apps) {
   1498 		return (MMS_MGMT_NOARG);
   1499 	}
   1500 
   1501 	if (!session) {
   1502 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1503 		if (st != 0) {
   1504 			return (st);
   1505 		}
   1506 		sessp = sess;
   1507 	}
   1508 
   1509 	names = mgmt_var_to_array(nvl, O_NAME, &count);
   1510 
   1511 	(void) mms_gen_taskid(tid);
   1512 	if (count == 0) {
   1513 		/* show all, filtering out the MMS Admin application */
   1514 		(void) snprintf(cmd, sizeof (cmd),
   1515 		    "show task['%s'] reportmode[namevalue] "
   1516 		    "match[strne(APPLICATION.'ApplicationName' 'MMS')] "
   1517 		    "report[APPLICATION];",
   1518 		    tid);
   1519 	} else {
   1520 		(void) snprintf(cmd, sizeof (cmd),
   1521 		    "show task['%s'] reportmode[namevalue] "
   1522 		    "report[APPLICATION] ",
   1523 		    tid);
   1524 
   1525 		if (count > 1) {
   1526 			(void) strlcat(cmd, "match[or", sizeof (cmd));
   1527 		} else {
   1528 			(void) strlcat(cmd, "match[", sizeof (cmd));
   1529 		}
   1530 		for (i = 0; i < count; i++) {
   1531 			(void) snprintf(buf, sizeof (buf),
   1532 			    " streq (APPLICATION.'ApplicationName' '%s')",
   1533 			    names[i]);
   1534 			(void) strlcat(cmd, buf, sizeof (cmd));
   1535 		}
   1536 		(void) strlcat(cmd, "];", sizeof (cmd));
   1537 	}
   1538 
   1539 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "show application",
   1540 	    &response);
   1541 	if (st == 0) {
   1542 		st = mmp_get_nvattrs(key, B_TRUE, response, apps);
   1543 		mms_free_rsp(response);
   1544 	}
   1545 
   1546 	if (st != 0) {
   1547 		goto done;
   1548 	}
   1549 
   1550 	mgmt_filter_results(nvl, *apps);
   1551 
   1552 done:
   1553 	if (sess) {
   1554 		(void) mms_goodbye(sess, 0);
   1555 	}
   1556 
   1557 	if (names) {
   1558 		mgmt_free_str_arr(names, count);
   1559 	}
   1560 
   1561 	return (st);
   1562 }
   1563 
   1564 int
   1565 mms_mgmt_show_requests(void *session, nvlist_t *nvl, nvlist_t **reqs)
   1566 {
   1567 	int		st;
   1568 	void		*sessp = session;
   1569 	void		*sess = NULL;
   1570 	void		*response = NULL;
   1571 	char		tid[64];
   1572 	char		cmd[8192];
   1573 	char		buf[2048];
   1574 	char		**names = NULL;
   1575 	int		count = 0;
   1576 	int		i;
   1577 	nvpair_t	*nvp;
   1578 	nvlist_t	*nva;
   1579 	char		*val;
   1580 	char		*key = "request-id";
   1581 	char		*tkey = "requestor-type";
   1582 
   1583 	if (!nvl || !reqs) {
   1584 		return (MMS_MGMT_NOARG);
   1585 	}
   1586 
   1587 	if (!mgmt_chk_auth("solaris.mms.request")) {
   1588 		return (EACCES);
   1589 	}
   1590 
   1591 	if (!session) {
   1592 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1593 		if (st != 0) {
   1594 			return (st);
   1595 		}
   1596 		sessp = sess;
   1597 	}
   1598 
   1599 	names = mgmt_var_to_array(nvl, O_NAME, &count);
   1600 
   1601 	(void) mms_gen_taskid(tid);
   1602 	if (count == 0) {
   1603 		/* show all */
   1604 		(void) snprintf(cmd, sizeof (cmd),
   1605 		    "show task['%s'] reportmode[namevalue] report[REQUEST];",
   1606 		    tid);
   1607 	} else {
   1608 		(void) snprintf(cmd, sizeof (cmd),
   1609 		    "show task['%s'] reportmode[namevalue] report[REQUEST] ",
   1610 		    tid);
   1611 
   1612 		if (count > 1) {
   1613 			(void) strlcat(cmd, "match[or", sizeof (cmd));
   1614 		} else {
   1615 			(void) strlcat(cmd, "match[", sizeof (cmd));
   1616 		}
   1617 		for (i = 0; i < count; i++) {
   1618 			(void) snprintf(buf, sizeof (buf),
   1619 			    " streq (REQUEST.'RequestingClient' '%s')",
   1620 			    names[i]);
   1621 			(void) strlcat(cmd, buf, sizeof (cmd));
   1622 		}
   1623 		(void) strlcat(cmd, "];", sizeof (cmd));
   1624 	}
   1625 
   1626 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "show oper requests",
   1627 	    &response);
   1628 	if (st == 0) {
   1629 		st = mmp_get_nvattrs(key, B_TRUE, response,
   1630 		    reqs);
   1631 		mms_free_rsp(response);
   1632 	}
   1633 
   1634 	if (st != 0) {
   1635 		goto done;
   1636 	}
   1637 
   1638 	nvp = NULL;
   1639 
   1640 	while ((nvp = nvlist_next_nvpair(*reqs, nvp)) != NULL) {
   1641 		st = nvpair_value_nvlist(nvp, &nva);
   1642 		if (st != 0) {
   1643 			continue;
   1644 		}
   1645 		st = nvlist_lookup_string(nva, tkey, &val);
   1646 		if (st == 0) {
   1647 			if (strcmp(val, "LM") == 0) {
   1648 				val = "library";
   1649 			} else if (strcmp(val, "DM") == 0) {
   1650 				val = "drive";
   1651 			} else if (strcmp(val, "MM") == 0) {
   1652 				val = "system";
   1653 			}
   1654 			(void) nvlist_add_string(nva, tkey, val);
   1655 		}
   1656 	}
   1657 
   1658 done:
   1659 	if (sess) {
   1660 		(void) mms_goodbye(sess, 0);
   1661 	}
   1662 
   1663 	if (names) {
   1664 		mgmt_free_str_arr(names, count);
   1665 	}
   1666 
   1667 	return (st);
   1668 }
   1669 
   1670 int
   1671 mms_mgmt_accept_request(void *session, char *reqID, char *text)
   1672 {
   1673 	int		st;
   1674 	void		*sessp = session;
   1675 	void		*sess = NULL;
   1676 	void		*response = NULL;
   1677 	char		tid[64];
   1678 	char		cmd[8192];
   1679 	char		*textp = text;
   1680 
   1681 	if (!reqID) {
   1682 		return (MMS_MGMT_NOARG);
   1683 	}
   1684 
   1685 	if (!mgmt_chk_auth("solaris.mms.request")) {
   1686 		return (EACCES);
   1687 	}
   1688 
   1689 	if (!session) {
   1690 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1691 		if (st != 0) {
   1692 			return (st);
   1693 		}
   1694 		sessp = sess;
   1695 	}
   1696 
   1697 	if (!textp) {
   1698 		textp = "ok";
   1699 	}
   1700 
   1701 	/* accept responsibility for this request, then respond to it */
   1702 
   1703 	(void) mms_gen_taskid(tid);
   1704 	(void) snprintf(cmd, sizeof (cmd),
   1705 	    "accept task['%s'] reqid['%s'];",
   1706 	    tid, reqID);
   1707 
   1708 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "accept oper request",
   1709 	    &response);
   1710 
   1711 	if (st == 0) {
   1712 		(void) mms_gen_taskid(tid);
   1713 		(void) snprintf(cmd, sizeof (cmd),
   1714 		    "respond task['%s'] reqid['%s'] "
   1715 		    "message[id ['SUNW' 'MMS' '1000'] loctext ['EN' '%s']];",
   1716 		    tid, reqID, textp);
   1717 
   1718 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "accept oper request",
   1719 		    &response);
   1720 	}
   1721 
   1722 	if (sess) {
   1723 		(void) mms_goodbye(sess, 0);
   1724 	}
   1725 
   1726 	return (st);
   1727 }
   1728 
   1729 int
   1730 mms_mgmt_reject_request(void *session, char *reqID, char *text)
   1731 {
   1732 	int		st;
   1733 	void		*sessp = session;
   1734 	void		*sess = NULL;
   1735 	void		*response = NULL;
   1736 	char		tid[64];
   1737 	char		cmd[8192];
   1738 	char		*textp = text;
   1739 
   1740 	if (!reqID) {
   1741 		return (MMS_MGMT_NOARG);
   1742 	}
   1743 
   1744 	if (!mgmt_chk_auth("solaris.mms.request")) {
   1745 		return (EACCES);
   1746 	}
   1747 
   1748 	if (!session) {
   1749 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1750 		if (st != 0) {
   1751 			return (st);
   1752 		}
   1753 		sessp = sess;
   1754 	}
   1755 
   1756 	if (!textp) {
   1757 		textp = "rejected";
   1758 	}
   1759 
   1760 	/* accept responsibility for this request, then respond to it */
   1761 
   1762 	(void) mms_gen_taskid(tid);
   1763 	(void) snprintf(cmd, sizeof (cmd),
   1764 	    "accept task['%s'] reqid['%s'];",
   1765 	    tid, reqID);
   1766 
   1767 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "reject oper request",
   1768 	    &response);
   1769 
   1770 	if (st == 0) {
   1771 		(void) mms_gen_taskid(tid);
   1772 		(void) snprintf(cmd, sizeof (cmd),
   1773 		    "respond task['%s'] reqid['%s'] "
   1774 		    "message[id ['SUNW' 'MMS' '1000'] loctext ['EN' '%s']];",
   1775 		    tid, reqID, textp);
   1776 
   1777 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "accept oper request",
   1778 		    &response);
   1779 	}
   1780 
   1781 	if (sess) {
   1782 		(void) mms_goodbye(sess, 0);
   1783 	}
   1784 
   1785 	return (st);
   1786 }
   1787