xref: /titanic_52/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg_create.c (revision dd49f125507979bb2ab505a8daf2a46d1be27051)
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 /*
23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <libscf.h>
27 #include <netinet/in.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <sys/types.h>
32 #include "ksslcfg.h"
33 
34 void
35 usage_create(boolean_t do_print)
36 {
37 	if (do_print)
38 		(void) fprintf(stderr, gettext("Usage:\n"));
39 	(void) fprintf(stderr, "ksslcfg create"
40 	    " -f pkcs11 [-d softtoken_directory] -T <token_label>"
41 	    " -C <certificate_label> -x <proxy_port>"
42 	    " [-h <ca_certchain_file>]"
43 	    " [options] [<server_address>] <server_port>\n");
44 
45 	(void) fprintf(stderr, "ksslcfg create"
46 	    " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
47 	    " [options] [<server_address>] <server_port>\n");
48 
49 	(void) fprintf(stderr, "ksslcfg create"
50 	    " -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
51 	    " [options] [<server_address>] <server_port>\n");
52 
53 	(void) fprintf(stderr, gettext("options are:\n"));
54 	(void) fprintf(stderr, "\t[-c <ciphersuites>]\n"
55 	    "\t[-p <password_file>]\n"
56 	    "\t[-t <ssl_session_cache_timeout>]\n"
57 	    "\t[-u <username>]\n"
58 	    "\t[-z <ssl_session_cache_size>]\n"
59 	    "\t[-v]\n");
60 }
61 
62 static scf_propertygroup_t *
63 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance,
64     const char *pg_name, const char *pg_type)
65 {
66 	scf_propertygroup_t *pg;
67 
68 	pg = scf_pg_create(handle);
69 	if (pg == NULL) {
70 		KSSL_DEBUG("scf_pg_create failed: %s\n",
71 		    scf_strerror(scf_error()));
72 		(void) fprintf(stderr, gettext(
73 		    "Unexpected fatal libscf error: %s. Exiting.\n"),
74 		    scf_strerror(scf_error()));
75 		return (NULL);
76 	}
77 
78 	if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) {
79 		KSSL_DEBUG("ERROR: scf_instance_add_pg failed: %s\n",
80 		    scf_strerror(scf_error()));
81 		if (scf_error() == SCF_ERROR_EXISTS)
82 			(void) fprintf(stderr, gettext(
83 			    "Error: another process is modifying this instance."
84 			    " Exiting.\n"));
85 		else
86 			(void) fprintf(stderr, gettext(
87 			    "Unexpected fatal libscf error: %s. Exiting.\n"),
88 			    scf_strerror(scf_error()));
89 		scf_pg_destroy(pg);
90 		return (NULL);
91 	} else {
92 		KSSL_DEBUG("property group created\n");
93 	}
94 
95 	return (pg);
96 }
97 
98 static int
99 add_new_property(scf_handle_t *handle, const char *prop_name,
100     scf_type_t type, const char *val, scf_transaction_t *tx)
101 {
102 	scf_value_t *value = NULL;
103 	scf_transaction_entry_t *entry = NULL;
104 	int status = FAILURE;
105 
106 	entry = scf_entry_create(handle);
107 	if (entry == NULL) {
108 		KSSL_DEBUG("scf_entry_create failed: %s\n",
109 		    scf_strerror(scf_error()));
110 		goto out;
111 	}
112 	KSSL_DEBUG("scf_entry_create succeeded\n");
113 
114 	value = scf_value_create(handle);
115 	if (value == NULL) {
116 		goto out;
117 	}
118 	KSSL_DEBUG("scf_value_create succeeded\n");
119 
120 	if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) {
121 		goto out;
122 	}
123 	KSSL_DEBUG("scf_transaction_property_new succeeded\n");
124 
125 	if (scf_value_set_from_string(value, type, val) != 0) {
126 		goto out;
127 	}
128 	KSSL_DEBUG("scf_value_set_from_string \'%s\' succeeded\n", val);
129 
130 	if (scf_entry_add_value(entry, value) != 0) {
131 		KSSL_DEBUG(
132 		    "scf_entry_add_value failed: %s\n",
133 		    scf_strerror(scf_error()));
134 		goto out;
135 	}
136 	KSSL_DEBUG("scf_entry_add_value succeeded\n");
137 
138 	status = SUCCESS;
139 
140 out:
141 	if (status != SUCCESS)
142 		(void) fprintf(stderr, gettext(
143 		    "Unexpected fatal libscf error: %s. Exiting.\n"),
144 		    scf_strerror(scf_error()));
145 	return (status);
146 }
147 
148 static int
149 set_method_context(scf_handle_t *handle, scf_transaction_t *tran,
150     const char *value_str)
151 {
152 	if ((add_new_property(handle, SCF_PROPERTY_USE_PROFILE,
153 	    SCF_TYPE_BOOLEAN, "false", tran) != SUCCESS) ||
154 	    (add_new_property(handle, SCF_PROPERTY_USER, SCF_TYPE_ASTRING,
155 	    value_str, tran) != SUCCESS) ||
156 	    (add_new_property(handle, SCF_PROPERTY_GROUP, SCF_TYPE_ASTRING,
157 	    ":default", tran) != SUCCESS) ||
158 	    (add_new_property(handle, SCF_PROPERTY_LIMIT_PRIVILEGES,
159 	    SCF_TYPE_ASTRING, ":default", tran) != SUCCESS) ||
160 	    (add_new_property(handle, SCF_PROPERTY_WORKING_DIRECTORY,
161 	    SCF_TYPE_ASTRING, ":default", tran) != SUCCESS) ||
162 	    (add_new_property(handle, SCF_PROPERTY_SUPP_GROUPS,
163 	    SCF_TYPE_ASTRING, ":default", tran) != SUCCESS) ||
164 	    (add_new_property(handle, SCF_PROPERTY_RESOURCE_POOL,
165 	    SCF_TYPE_ASTRING, ":default", tran) != SUCCESS) ||
166 	    (add_new_property(handle, SCF_PROPERTY_PROJECT, SCF_TYPE_ASTRING,
167 	    ":default", tran) != SUCCESS) ||
168 	    (add_new_property(handle, SCF_PROPERTY_PRIVILEGES,
169 	    SCF_TYPE_ASTRING, "basic,sys_net_config", tran) != SUCCESS))
170 		return (FAILURE);
171 
172 	return (SUCCESS);
173 }
174 
175 static int
176 add_pg_method(scf_handle_t *handle, scf_instance_t *instance,
177     const char *kssl_entry, const char *pg_name, const char *flags,
178     const char *value_str)
179 {
180 	int len, rv;
181 	char *command;
182 	const char *base_command;
183 	int status = FAILURE;
184 	boolean_t errflag = B_FALSE;
185 	scf_transaction_t *tran;
186 	scf_propertygroup_t *pg;
187 
188 	pg = add_property_group_to_instance(handle, instance,
189 	    pg_name, SCF_GROUP_METHOD);
190 	if (pg == NULL) {
191 		/* flag is false to suppress duplicate error messages */
192 		errflag = B_FALSE;
193 		goto out0;
194 	}
195 	KSSL_DEBUG("%s method added\n", pg_name);
196 
197 	tran = scf_transaction_create(handle);
198 	if (tran == NULL) {
199 		KSSL_DEBUG("scf_transaction_create failed: %s\n",
200 		    scf_strerror(scf_error()));
201 		errflag = B_TRUE;
202 		goto out0;
203 	}
204 	KSSL_DEBUG("scf_transaction_create succeeded\n");
205 
206 	do {
207 		if (scf_transaction_start(tran, pg) != 0) {
208 			KSSL_DEBUG("scf_transaction_start failed: %s\n",
209 			    scf_strerror(scf_error()));
210 			if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
211 				(void) fprintf(stderr, gettext(
212 				    "Error: Permission denied.\n"));
213 				errflag = B_FALSE;
214 			} else if (scf_error() ==  SCF_ERROR_DELETED) {
215 				(void) fprintf(stderr, gettext(
216 				    "Error: property group %s has"
217 				    " been deleted.\n"), pg_name);
218 				errflag = B_FALSE;
219 			} else
220 				errflag = B_TRUE;
221 			goto out1;
222 		}
223 		KSSL_DEBUG("scf_transaction_start succeeded\n");
224 
225 		if (strcmp(pg_name, "stop") == 0)
226 			base_command = "/usr/lib/kssladm delete";
227 		else
228 			base_command = "/usr/lib/kssladm create";
229 
230 		len = strlen(base_command) + strlen(flags) +
231 		    strlen(kssl_entry) + 3;
232 
233 		command = malloc(len);
234 		if (command == NULL) {
235 			goto out2;
236 		}
237 
238 		(void) snprintf(command, len, "%s %s %s",
239 		    base_command, flags, kssl_entry);
240 		KSSL_DEBUG("command=%s\n", command);
241 
242 		if (add_new_property(handle, SCF_PROPERTY_EXEC,
243 		    SCF_TYPE_ASTRING, command, tran) != SUCCESS) {
244 			free(command);
245 			goto out2;
246 		}
247 		free(command);
248 
249 		if (add_new_property(handle, SCF_PROPERTY_TIMEOUT,
250 		    SCF_TYPE_COUNT, "60", tran) != SUCCESS)
251 			goto out2;
252 
253 		if (set_method_context(handle, tran, value_str) != SUCCESS)
254 			goto out2;
255 
256 		rv = scf_transaction_commit(tran);
257 		switch (rv) {
258 		case 1:
259 			KSSL_DEBUG("scf_transaction_commit succeeded\n");
260 			status = SUCCESS;
261 			goto out2;
262 		case 0:
263 			scf_transaction_reset(tran);
264 			if (scf_pg_update(pg) == -1) {
265 				goto out2;
266 			}
267 			break;
268 		case -1:
269 		default:
270 			KSSL_DEBUG("ERROR: scf_transaction_commit failed: %s\n",
271 			    scf_strerror(scf_error()));
272 			if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
273 				(void) fprintf(stderr, gettext(
274 				    "Error: Permission denied.\n"));
275 				errflag = B_FALSE;
276 			} else {
277 				errflag = B_TRUE;
278 			}
279 			goto out2;
280 		}
281 	} while (rv == 0);
282 
283 out2:
284 	scf_transaction_reset(tran);
285 out1:
286 	scf_transaction_destroy_children(tran);
287 	scf_transaction_destroy(tran);
288 out0:
289 	if (pg != NULL)
290 		scf_pg_destroy(pg);
291 	if (errflag)
292 		(void) fprintf(stderr, gettext(
293 		    "Unexpected fatal libscf error: %s. Exiting.\n"),
294 		    scf_strerror(scf_error()));
295 	return (status);
296 }
297 
298 static int
299 create_instance(scf_handle_t *handle, scf_service_t *svc,
300     const char *instance_name, const char *kssl_entry, const char *command,
301     const char *username, char *inaddr_any_name)
302 {
303 	int status = FAILURE;
304 	char *buf;
305 	boolean_t errflag = B_FALSE;
306 	ssize_t max_fmri_len;
307 	scf_instance_t *instance;
308 
309 	instance = scf_instance_create(handle);
310 	if (instance == NULL) {
311 		errflag = B_TRUE;
312 		KSSL_DEBUG("scf_instance_create failed: %s\n",
313 		    scf_strerror(scf_error()));
314 		goto out;
315 	}
316 	KSSL_DEBUG("scf_instance_create succeeded\n");
317 
318 	if (scf_service_get_instance(svc, inaddr_any_name, instance) == 0) {
319 		/* Let the caller deal with the duplicate instance */
320 		status = INSTANCE_ANY_EXISTS;
321 		goto out;
322 	}
323 
324 	if (scf_service_add_instance(svc, instance_name, instance) != 0) {
325 		if (scf_error() == SCF_ERROR_EXISTS) {
326 			/* Let the caller deal with the duplicate instance */
327 			status = INSTANCE_OTHER_EXISTS;
328 			goto out;
329 		}
330 
331 		errflag = B_TRUE;
332 		KSSL_DEBUG("scf_service_add_instance failed: %s\n",
333 		    scf_strerror(scf_error()));
334 		goto out;
335 	}
336 	KSSL_DEBUG("scf_service_add_instance succeeded\n");
337 
338 	if ((add_pg_method(handle, instance, kssl_entry, "start",
339 	    command, username) != SUCCESS) ||
340 	    (add_pg_method(handle, instance, kssl_entry, "refresh",
341 	    command, username) != SUCCESS) ||
342 	    (add_pg_method(handle, instance, kssl_entry, "stop",
343 	    "", username) != SUCCESS)) {
344 		scf_instance_destroy(instance);
345 		return (status);
346 	}
347 
348 	/* enabling the instance */
349 	max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
350 	if ((buf = malloc(max_fmri_len + 1)) == NULL)
351 		goto out;
352 
353 	if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) {
354 		KSSL_DEBUG("instance_fmri=%s\n", buf);
355 		if (smf_enable_instance(buf, 0) != 0) {
356 			errflag = B_TRUE;
357 			KSSL_DEBUG(
358 			    "smf_enable_instance failed: %s\n",
359 			    scf_strerror(scf_error()));
360 			goto out;
361 		}
362 		status = SUCCESS;
363 	}
364 
365 out:
366 	if (instance != NULL)
367 		scf_instance_destroy(instance);
368 	if (errflag)
369 		(void) fprintf(stderr, gettext(
370 		    "Unexpected fatal libscf error: %s. Exiting.\n"),
371 		    scf_strerror(scf_error()));
372 	return (status);
373 }
374 
375 static int
376 create_service(const char *instance_name, const char *kssl_entry,
377     const char *command, const char *username, char *inaddr_any_name)
378 {
379 	int status = FAILURE;
380 	scf_scope_t *scope;
381 	scf_service_t *svc;
382 	scf_handle_t *handle;
383 	boolean_t errflag = B_TRUE;
384 
385 	handle = scf_handle_create(SCF_VERSION);
386 	if (handle == NULL) {
387 		KSSL_DEBUG("scf_handle_create failed: %s\n",
388 		    scf_strerror(scf_error()));
389 		goto out1;
390 	}
391 	KSSL_DEBUG("scf_handle_create succeeded\n");
392 
393 	if (scf_handle_bind(handle) == -1) {
394 		KSSL_DEBUG("scf_handle_bind failed: %s\n",
395 		    scf_strerror(scf_error()));
396 		goto out1;
397 	}
398 	KSSL_DEBUG("scf_handle_bind succeeded\n");
399 
400 	if ((scope = scf_scope_create(handle)) == NULL) {
401 		KSSL_DEBUG("scf_scope_create failed: %s\n",
402 		    scf_strerror(scf_error()));
403 		goto out2;
404 	}
405 	KSSL_DEBUG("scf_scope_create succeeded\n");
406 
407 	if ((svc = scf_service_create(handle)) == NULL) {
408 		KSSL_DEBUG("scf_service_create failed: %s\n",
409 		    scf_strerror(scf_error()));
410 		goto out3;
411 	}
412 	KSSL_DEBUG("scf_service_create succeeded\n");
413 
414 	if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc,
415 	    NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) {
416 		KSSL_DEBUG("scf_handle_decode_fmri failed: %s\n",
417 		    scf_strerror(scf_error()));
418 		if (scf_error() == SCF_ERROR_NOT_FOUND) {
419 			(void) fprintf(stderr, gettext(
420 			    "service %s not found in the repository."
421 			    " Exiting.\n"), SERVICE_NAME);
422 			errflag = B_FALSE;
423 		}
424 		goto out4;
425 	}
426 
427 	status = create_instance(handle, svc, instance_name, kssl_entry,
428 	    command, username, inaddr_any_name);
429 
430 out4:
431 	scf_service_destroy(svc);
432 out3:
433 	scf_scope_destroy(scope);
434 out2:
435 	(void) scf_handle_unbind(handle);
436 out1:
437 	if (handle != NULL)
438 		scf_handle_destroy(handle);
439 
440 	if (status != SUCCESS && status != INSTANCE_OTHER_EXISTS &&
441 	    status != INSTANCE_ANY_EXISTS && errflag)
442 		(void) fprintf(stderr, gettext(
443 		    "Unexpected fatal libscf error: %s. Exiting.\n"),
444 		    scf_strerror(scf_error()));
445 	return (status);
446 }
447 
448 int
449 do_create(int argc, char *argv[])
450 {
451 	char c;
452 	char *buf, *ptr, *instance_name;
453 	char *inaddr_any_name = NULL;
454 	int i, status, len, pcnt;
455 	const char *token_label = NULL;
456 	const char *filename = NULL;
457 	const char *certname = NULL;
458 	const char *username = NULL;
459 	const char *proxy_port = NULL;
460 	char *format = NULL;
461 	boolean_t quote_next;
462 	char address_port[MAX_ADRPORT_LEN + 1];
463 
464 	argc -= 1;
465 	argv += 1;
466 
467 	/*
468 	 * Many of these arguments are passed on to kssladm command
469 	 * in the start method of the SMF instance created. So, we do only
470 	 * the basic usage checks here and let kssladm check the validity
471 	 * of the arguments. This is the reason we ignore optarg
472 	 * for some of the cases below.
473 	 */
474 	while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:u:x:z:")) != -1) {
475 		switch (c) {
476 		case 'd':
477 			break;
478 		case 'c':
479 			break;
480 		case 'C':
481 			certname = optarg;
482 			break;
483 		case 'f':
484 			format = optarg;
485 			break;
486 		case 'h':
487 			break;
488 		case 'i':
489 			filename = optarg;
490 			break;
491 		case 'T':
492 			token_label = optarg;
493 			break;
494 		case 'p':
495 			break;
496 		case 't':
497 			break;
498 		case 'u':
499 			username = optarg;
500 			break;
501 		case 'x':
502 			proxy_port = optarg;
503 			break;
504 		case 'v':
505 			verbose = B_TRUE;
506 			break;
507 		case 'z':
508 			break;
509 		default:
510 			goto err;
511 		}
512 	}
513 
514 	if (format == NULL || proxy_port == NULL) {
515 		goto err;
516 	}
517 
518 	if (get_portnum(proxy_port, NULL) == 0) {
519 		(void) fprintf(stderr,
520 		    gettext("Error: Invalid proxy port value %s\n"),
521 		    proxy_port);
522 		goto err;
523 	}
524 
525 	if (strcmp(format, "pkcs11") == 0) {
526 		if (token_label == NULL || certname == NULL) {
527 			goto err;
528 		}
529 	} else if (strcmp(format, "pkcs12") == 0 ||
530 	    strcmp(format, "pem") == 0) {
531 		if (filename == NULL) {
532 			goto err;
533 		}
534 	} else {
535 		goto err;
536 	}
537 
538 	pcnt = argc - optind;
539 	if (pcnt == 1) {
540 		if (strlen(argv[optind]) < MAX_ADRPORT_LEN) {
541 			(void) strcpy(address_port, argv[optind]);
542 		} else {
543 			(void) fprintf(stderr, gettext(
544 			    "argument too long -- %s\n"),
545 			    argv[optind]);
546 			return (FAILURE);
547 		}
548 	} else if (pcnt == 2) {
549 		if ((len = strlen(argv[optind])) +
550 		    (strlen(argv[optind + 1])) < MAX_ADRPORT_LEN) {
551 			(void) strcpy(address_port, argv[optind]);
552 			address_port[len] = ' ';
553 			(void) strcpy(address_port + len + 1, argv[optind + 1]);
554 		} else {
555 			(void) fprintf(stderr, gettext(
556 			    "arguments too long -- %s %s\n"),
557 			    argv[optind], argv[optind + 1]);
558 			return (FAILURE);
559 		}
560 	} else {
561 		goto err;
562 	}
563 
564 	/*
565 	 * We need to create the kssladm command line in
566 	 * the SMF instance from the current arguments.
567 	 *
568 	 * Construct a buffer with all the arguments except
569 	 * the -u argument. We have to quote the string arguments,
570 	 * -T and -C, as they can contain white space.
571 	 */
572 	len = 0;
573 	for (i = 1; i < optind; i++) {
574 		len += strlen(argv[i]) + 3;
575 	}
576 
577 	if ((buf = malloc(len)) == NULL) {
578 		return (FAILURE);
579 	}
580 
581 	ptr = buf;
582 	quote_next = B_FALSE;
583 	for (i = 1; i < optind; i++) {
584 		int arglen =  strlen(argv[i]) + 1;
585 
586 		if (strncmp(argv[i], "-u", 2) == 0) {
587 			i++;
588 			continue;
589 		}
590 
591 		if (quote_next) {
592 			(void) snprintf(ptr, len, "\"%s\" ", argv[i]);
593 			quote_next = B_FALSE;
594 			arglen += 2;
595 		} else {
596 			(void) snprintf(ptr, len, "%s ", argv[i]);
597 		}
598 
599 		quote_next = (strncmp(argv[i], "-T", 2) == 0 ||
600 		    strncmp(argv[i], "-C", 2) == 0);
601 
602 		ptr += arglen;
603 		len -= arglen;
604 	}
605 	KSSL_DEBUG("buf=%s\n", buf);
606 
607 	instance_name = create_instance_name(address_port,
608 	    &inaddr_any_name, B_TRUE);
609 	if (instance_name == NULL || inaddr_any_name == NULL) {
610 		free(buf);
611 		return (FAILURE);
612 	}
613 	KSSL_DEBUG("instance_name=%s\n", instance_name);
614 	KSSL_DEBUG("inaddr_any_name=%s\n", inaddr_any_name);
615 
616 	if (username == NULL)
617 		username = "root";
618 	status = create_service(instance_name, address_port,
619 	    buf, username, inaddr_any_name);
620 	if (status == INSTANCE_OTHER_EXISTS || status == INSTANCE_ANY_EXISTS) {
621 		if (status == INSTANCE_ANY_EXISTS &&
622 		    (strcmp(instance_name, inaddr_any_name) != SUCCESS)) {
623 			/*
624 			 * The following could result in a misconfiguration.
625 			 * Better bail out with an error.
626 			 */
627 			(void) fprintf(stderr,
628 			    gettext("Error: INADDR_ANY instance exists."
629 			    " Can not create a new instance %s.\n"),
630 			    instance_name);
631 			free(instance_name);
632 			free(inaddr_any_name);
633 			free(buf);
634 			return (status);
635 		}
636 
637 		/*
638 		 * Delete the existing instance and create a new instance
639 		 * with the supplied arguments.
640 		 */
641 		KSSL_DEBUG("Deleting duplicate instance\n");
642 		if (delete_instance(instance_name) != SUCCESS) {
643 			(void) fprintf(stderr,
644 			    gettext(
645 			    "Error: Can not delete existing instance %s.\n"),
646 			    instance_name);
647 		} else {
648 			(void) fprintf(stdout, gettext(
649 			    "Note: reconfiguring the existing instance %s.\n"),
650 			    instance_name);
651 			status = create_service(instance_name, address_port,
652 			    buf, username, inaddr_any_name);
653 		}
654 	}
655 
656 	/*
657 	 * network/ssl/proxy depends on network/socket-filter:kssl;
658 	 * enable that service now.
659 	 */
660 	if (smf_enable_instance(KSSL_FILTER_SVC_NAME, 0) != 0) {
661 		KSSL_DEBUG(
662 		    "smf_enable_instance failed: %s\n" KSSL_FILTER_SVC_NAME);
663 		(void) fprintf(stderr, gettext(
664 		    "Unable to enable required service \"%s\". Error: %s"),
665 		    KSSL_FILTER_SVC_NAME, scf_strerror(scf_error()));
666 		status = FAILURE;
667 	}
668 
669 	free(instance_name);
670 	free(inaddr_any_name);
671 	free(buf);
672 	return (status);
673 
674 err:
675 	usage_create(B_TRUE);
676 	return (ERROR_USAGE);
677 }
678