8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / kssl / ksslcfg / ksslcfg_create.c
blob87c789fd9252bc837f7a30aedf3b998227e7b8e0
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
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"
34 void
35 usage_create(boolean_t do_print)
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");
45 (void) fprintf(stderr, "ksslcfg create"
46 " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
47 " [options] [<server_address>] <server_port>\n");
49 (void) fprintf(stderr, "ksslcfg create"
50 " -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
51 " [options] [<server_address>] <server_port>\n");
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");
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)
66 scf_propertygroup_t *pg;
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);
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");
95 return (pg);
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)
102 scf_value_t *value = NULL;
103 scf_transaction_entry_t *entry = NULL;
104 int status = FAILURE;
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;
112 KSSL_DEBUG("scf_entry_create succeeded\n");
114 value = scf_value_create(handle);
115 if (value == NULL) {
116 goto out;
118 KSSL_DEBUG("scf_value_create succeeded\n");
120 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) {
121 goto out;
123 KSSL_DEBUG("scf_transaction_property_new succeeded\n");
125 if (scf_value_set_from_string(value, type, val) != 0) {
126 goto out;
128 KSSL_DEBUG("scf_value_set_from_string \'%s\' succeeded\n", val);
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;
136 KSSL_DEBUG("scf_entry_add_value succeeded\n");
138 status = SUCCESS;
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);
148 static int
149 set_method_context(scf_handle_t *handle, scf_transaction_t *tran,
150 const char *value_str)
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);
172 return (SUCCESS);
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)
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;
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;
195 KSSL_DEBUG("%s method added\n", pg_name);
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;
204 KSSL_DEBUG("scf_transaction_create succeeded\n");
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;
223 KSSL_DEBUG("scf_transaction_start succeeded\n");
225 if (strcmp(pg_name, "stop") == 0)
226 base_command = "/usr/lib/kssladm delete";
227 else
228 base_command = "/usr/lib/kssladm create";
230 len = strlen(base_command) + strlen(flags) +
231 strlen(kssl_entry) + 3;
233 command = malloc(len);
234 if (command == NULL) {
235 goto out2;
238 (void) snprintf(command, len, "%s %s %s",
239 base_command, flags, kssl_entry);
240 KSSL_DEBUG("command=%s\n", command);
242 if (add_new_property(handle, SCF_PROPERTY_EXEC,
243 SCF_TYPE_ASTRING, command, tran) != SUCCESS) {
244 free(command);
245 goto out2;
247 free(command);
249 if (add_new_property(handle, SCF_PROPERTY_TIMEOUT,
250 SCF_TYPE_COUNT, "60", tran) != SUCCESS)
251 goto out2;
253 if (set_method_context(handle, tran, value_str) != SUCCESS)
254 goto out2;
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;
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;
279 goto out2;
281 } while (rv == 0);
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);
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)
303 int status = FAILURE;
304 char *buf;
305 boolean_t errflag = B_FALSE;
306 ssize_t max_fmri_len;
307 scf_instance_t *instance;
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;
316 KSSL_DEBUG("scf_instance_create succeeded\n");
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;
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;
331 errflag = B_TRUE;
332 KSSL_DEBUG("scf_service_add_instance failed: %s\n",
333 scf_strerror(scf_error()));
334 goto out;
336 KSSL_DEBUG("scf_service_add_instance succeeded\n");
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);
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;
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;
362 status = SUCCESS;
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);
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)
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;
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;
391 KSSL_DEBUG("scf_handle_create succeeded\n");
393 if (scf_handle_bind(handle) == -1) {
394 KSSL_DEBUG("scf_handle_bind failed: %s\n",
395 scf_strerror(scf_error()));
396 goto out1;
398 KSSL_DEBUG("scf_handle_bind succeeded\n");
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;
405 KSSL_DEBUG("scf_scope_create succeeded\n");
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;
412 KSSL_DEBUG("scf_service_create succeeded\n");
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;
424 goto out4;
427 status = create_instance(handle, svc, instance_name, kssl_entry,
428 command, username, inaddr_any_name);
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);
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);
449 do_create(int argc, char *argv[])
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];
464 argc -= 1;
465 argv += 1;
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.
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;
514 if (format == NULL || proxy_port == NULL) {
515 goto err;
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;
525 if (strcmp(format, "pkcs11") == 0) {
526 if (token_label == NULL || certname == NULL) {
527 goto err;
529 } else if (strcmp(format, "pkcs12") == 0 ||
530 strcmp(format, "pem") == 0) {
531 if (filename == NULL) {
532 goto err;
534 } else {
535 goto err;
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);
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);
560 } else {
561 goto err;
565 * We need to create the kssladm command line in
566 * the SMF instance from the current arguments.
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.
572 len = 0;
573 for (i = 1; i < optind; i++) {
574 len += strlen(argv[i]) + 3;
577 if ((buf = malloc(len)) == NULL) {
578 return (FAILURE);
581 ptr = buf;
582 quote_next = B_FALSE;
583 for (i = 1; i < optind; i++) {
584 int arglen = strlen(argv[i]) + 1;
586 if (strncmp(argv[i], "-u", 2) == 0) {
587 i++;
588 continue;
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]);
599 quote_next = (strncmp(argv[i], "-T", 2) == 0 ||
600 strncmp(argv[i], "-C", 2) == 0);
602 ptr += arglen;
603 len -= arglen;
605 KSSL_DEBUG("buf=%s\n", buf);
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);
613 KSSL_DEBUG("instance_name=%s\n", instance_name);
614 KSSL_DEBUG("inaddr_any_name=%s\n", inaddr_any_name);
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)) {
624 * The following could result in a misconfiguration.
625 * Better bail out with an error.
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);
638 * Delete the existing instance and create a new instance
639 * with the supplied arguments.
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);
657 * network/ssl/proxy depends on network/socket-filter:kssl;
658 * enable that service now.
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;
669 free(instance_name);
670 free(inaddr_any_name);
671 free(buf);
672 return (status);
674 err:
675 usage_create(B_TRUE);
676 return (ERROR_USAGE);