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]
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
27 #include <netinet/in.h>
31 #include <sys/types.h>
35 usage_create(boolean_t 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"
58 "\t[-z <ssl_session_cache_size>]\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
);
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()));
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."
86 (void) fprintf(stderr
, gettext(
87 "Unexpected fatal libscf error: %s. Exiting.\n"),
88 scf_strerror(scf_error()));
92 KSSL_DEBUG("property group created\n");
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
);
108 KSSL_DEBUG("scf_entry_create failed: %s\n",
109 scf_strerror(scf_error()));
112 KSSL_DEBUG("scf_entry_create succeeded\n");
114 value
= scf_value_create(handle
);
118 KSSL_DEBUG("scf_value_create succeeded\n");
120 if (scf_transaction_property_new(tx
, entry
, prop_name
, type
) != 0) {
123 KSSL_DEBUG("scf_transaction_property_new succeeded\n");
125 if (scf_value_set_from_string(value
, type
, val
) != 0) {
128 KSSL_DEBUG("scf_value_set_from_string \'%s\' succeeded\n", val
);
130 if (scf_entry_add_value(entry
, value
) != 0) {
132 "scf_entry_add_value failed: %s\n",
133 scf_strerror(scf_error()));
136 KSSL_DEBUG("scf_entry_add_value succeeded\n");
141 if (status
!= SUCCESS
)
142 (void) fprintf(stderr
, gettext(
143 "Unexpected fatal libscf error: %s. Exiting.\n"),
144 scf_strerror(scf_error()));
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
))
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
)
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
);
191 /* flag is false to suppress duplicate error messages */
195 KSSL_DEBUG("%s method added\n", pg_name
);
197 tran
= scf_transaction_create(handle
);
199 KSSL_DEBUG("scf_transaction_create failed: %s\n",
200 scf_strerror(scf_error()));
204 KSSL_DEBUG("scf_transaction_create succeeded\n");
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"));
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
);
223 KSSL_DEBUG("scf_transaction_start succeeded\n");
225 if (strcmp(pg_name
, "stop") == 0)
226 base_command
= "/usr/lib/kssladm delete";
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
) {
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
) {
249 if (add_new_property(handle
, SCF_PROPERTY_TIMEOUT
,
250 SCF_TYPE_COUNT
, "60", tran
) != SUCCESS
)
253 if (set_method_context(handle
, tran
, value_str
) != SUCCESS
)
256 rv
= scf_transaction_commit(tran
);
259 KSSL_DEBUG("scf_transaction_commit succeeded\n");
263 scf_transaction_reset(tran
);
264 if (scf_pg_update(pg
) == -1) {
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"));
284 scf_transaction_reset(tran
);
286 scf_transaction_destroy_children(tran
);
287 scf_transaction_destroy(tran
);
292 (void) fprintf(stderr
, gettext(
293 "Unexpected fatal libscf error: %s. Exiting.\n"),
294 scf_strerror(scf_error()));
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
;
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
) {
312 KSSL_DEBUG("scf_instance_create failed: %s\n",
313 scf_strerror(scf_error()));
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
;
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
;
332 KSSL_DEBUG("scf_service_add_instance failed: %s\n",
333 scf_strerror(scf_error()));
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
);
348 /* enabling the instance */
349 max_fmri_len
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
);
350 if ((buf
= malloc(max_fmri_len
+ 1)) == NULL
)
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) {
358 "smf_enable_instance failed: %s\n",
359 scf_strerror(scf_error()));
366 if (instance
!= NULL
)
367 scf_instance_destroy(instance
);
369 (void) fprintf(stderr
, gettext(
370 "Unexpected fatal libscf error: %s. Exiting.\n"),
371 scf_strerror(scf_error()));
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
;
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()));
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()));
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()));
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()));
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
);
427 status
= create_instance(handle
, svc
, instance_name
, kssl_entry
,
428 command
, username
, inaddr_any_name
);
431 scf_service_destroy(svc
);
433 scf_scope_destroy(scope
);
435 (void) scf_handle_unbind(handle
);
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()));
449 do_create(int argc
, char *argv
[])
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
;
461 boolean_t quote_next
;
462 char address_port
[MAX_ADRPORT_LEN
+ 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) {
492 token_label
= optarg
;
514 if (format
== NULL
|| proxy_port
== NULL
) {
518 if (get_portnum(proxy_port
, NULL
) == 0) {
519 (void) fprintf(stderr
,
520 gettext("Error: Invalid proxy port value %s\n"),
525 if (strcmp(format
, "pkcs11") == 0) {
526 if (token_label
== NULL
|| certname
== NULL
) {
529 } else if (strcmp(format
, "pkcs12") == 0 ||
530 strcmp(format
, "pem") == 0) {
531 if (filename
== NULL
) {
538 pcnt
= argc
- optind
;
540 if (strlen(argv
[optind
]) < MAX_ADRPORT_LEN
) {
541 (void) strcpy(address_port
, argv
[optind
]);
543 (void) fprintf(stderr
, gettext(
544 "argument too long -- %s\n"),
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]);
555 (void) fprintf(stderr
, gettext(
556 "arguments too long -- %s %s\n"),
557 argv
[optind
], argv
[optind
+ 1]);
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.
573 for (i
= 1; i
< optind
; i
++) {
574 len
+= strlen(argv
[i
]) + 3;
577 if ((buf
= malloc(len
)) == NULL
) {
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) {
592 (void) snprintf(ptr
, len
, "\"%s\" ", argv
[i
]);
593 quote_next
= B_FALSE
;
596 (void) snprintf(ptr
, len
, "%s ", argv
[i
]);
599 quote_next
= (strncmp(argv
[i
], "-T", 2) == 0 ||
600 strncmp(argv
[i
], "-C", 2) == 0);
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
) {
613 KSSL_DEBUG("instance_name=%s\n", instance_name
);
614 KSSL_DEBUG("inaddr_any_name=%s\n", inaddr_any_name
);
616 if (username
== NULL
)
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"),
632 free(inaddr_any_name
);
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
,
645 "Error: Can not delete existing instance %s.\n"),
648 (void) fprintf(stdout
, gettext(
649 "Note: reconfiguring the existing instance %s.\n"),
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) {
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()));
670 free(inaddr_any_name
);
675 usage_create(B_TRUE
);
676 return (ERROR_USAGE
);