xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c (revision 12784:5f02bbe06309)
1898Skais /*
2898Skais  * CDDL HEADER START
3898Skais  *
4898Skais  * The contents of this file are subject to the terms of the
51933Skrishna  * Common Development and Distribution License (the "License").
61933Skrishna  * You may not use this file except in compliance with the License.
7898Skais  *
8898Skais  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9898Skais  * or http://www.opensolaris.org/os/licensing.
10898Skais  * See the License for the specific language governing permissions
11898Skais  * and limitations under the License.
12898Skais  *
13898Skais  * When distributing Covered Code, include this CDDL HEADER in each
14898Skais  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15898Skais  * If applicable, add the following below this CDDL HEADER, with the
16898Skais  * fields enclosed by brackets "[]" replaced with your own identifying
17898Skais  * information: Portions Copyright [yyyy] [name of copyright owner]
18898Skais  *
19898Skais  * CDDL HEADER END
20898Skais  */
21898Skais /*
2212381SVladimir.Kotal@Sun.COM  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23898Skais  */
24898Skais 
25898Skais #include <arpa/inet.h> /* inet_addr() */
26898Skais #include <ctype.h>
27898Skais #include <libscf.h>
28898Skais #include <netdb.h> /* hostent */
29898Skais #include <netinet/in.h> /* ip_addr_t */
30898Skais #include <stdio.h>
31898Skais #include <errno.h>
32898Skais #include <limits.h>
33898Skais #include <stdlib.h>
34898Skais #include <fcntl.h>
35898Skais #include <strings.h>
36898Skais #include <sys/varargs.h>
37*12784SVladimir.Kotal@Sun.COM #include <zone.h>
38898Skais #include "ksslcfg.h"
39898Skais 
40898Skais /*
41898Skais  * ksslcfg(1M)
42898Skais  *
43898Skais  * ksslcfg manages smf(5) instances for the Kernel SSL proxy module.
44898Skais  * It makes use of kssladm(1M) which does the grunt work.
45898Skais  */
46898Skais 
4710520SBhargava.Yenduri@Sun.COM /*
4810520SBhargava.Yenduri@Sun.COM  * This version number is rather meaningless. In any case,
4910520SBhargava.Yenduri@Sun.COM  * version 2.0 adds support for IPv6 addresses.
5010520SBhargava.Yenduri@Sun.COM  */
5110520SBhargava.Yenduri@Sun.COM #define	KSSLCFG_VERSION "Version 2.0"
52898Skais 
53898Skais boolean_t verbose = B_FALSE;
54898Skais const char *SERVICE_NAME = "network/ssl/proxy";
55898Skais 
56898Skais void
KSSL_DEBUG(const char * format,...)57898Skais KSSL_DEBUG(const char *format, ...)
58898Skais {
59898Skais 	va_list ap;
60898Skais 
61898Skais 	if (verbose) {
62898Skais 		va_start(ap, format);
63898Skais 		(void) vprintf(format, ap);
64898Skais 		va_end(ap);
65898Skais 	}
66898Skais }
67898Skais 
6812381SVladimir.Kotal@Sun.COM /*
6912381SVladimir.Kotal@Sun.COM  * Convert string to port number and check for errors. Return 0 on error,
7012381SVladimir.Kotal@Sun.COM  * 1 on success.
7112381SVladimir.Kotal@Sun.COM  */
72898Skais int
get_portnum(const char * s,ushort_t * rport)73898Skais get_portnum(const char *s, ushort_t *rport)
74898Skais {
7512381SVladimir.Kotal@Sun.COM 	long long tmp_port;
7612381SVladimir.Kotal@Sun.COM 	char *ep;
77898Skais 
78898Skais 	errno = 0;
7912381SVladimir.Kotal@Sun.COM 	tmp_port = strtoll(s, &ep, 10);
8012381SVladimir.Kotal@Sun.COM 	if (s == ep || *ep != '\0' || errno != 0)
81898Skais 		return (0);
8212381SVladimir.Kotal@Sun.COM 	if (tmp_port < 1 || tmp_port > 65535)
8312381SVladimir.Kotal@Sun.COM 		return (0);
84898Skais 
85898Skais 	if (rport != NULL)
8612381SVladimir.Kotal@Sun.COM 		*rport = (ushort_t)tmp_port;
8712381SVladimir.Kotal@Sun.COM 
88898Skais 	return (1);
89898Skais }
90898Skais 
91898Skais #define	ANY_ADDR	"INADDR_ANY"
92898Skais 
93898Skais /*
94898Skais  * An instance name is formed using either the host name in the fully
95898Skais  * qualified domain name form (FQDN) which should map to a specific IP address
96898Skais  * or using INADDR_ANY which means all IP addresses.
97898Skais  *
98898Skais  * We do a lookup or reverse lookup to get the host name. It is assumed that
99898Skais  * the returned name is in the FQDN form. i.e. DNS is used.
100898Skais  */
101898Skais char *
create_instance_name(const char * arg,char ** inaddr_any_name,boolean_t is_create)102898Skais create_instance_name(const char *arg, char **inaddr_any_name,
103898Skais     boolean_t is_create)
104898Skais {
105898Skais 	int len;
106898Skais 	uint16_t port;
107898Skais 	char *cname;
108898Skais 	char *instance_name;
109898Skais 	const char *prefix = "kssl-";
11010520SBhargava.Yenduri@Sun.COM 	char *first_space;
111898Skais 
11210520SBhargava.Yenduri@Sun.COM 	first_space = strchr(arg, ' ');
11310520SBhargava.Yenduri@Sun.COM 	if (first_space == NULL) {	/* No host name. Use INADDR_ANY. */
114898Skais 		if (get_portnum(arg, &port) == 0) {
115898Skais 			(void) fprintf(stderr,
116898Skais 			    gettext("Error: Invalid port value -- %s\n"),
117898Skais 			    arg);
118898Skais 			return (NULL);
119898Skais 		}
120898Skais 		KSSL_DEBUG("port=%d\n", port);
121898Skais 		if ((cname = strdup(ANY_ADDR)) == NULL)
122898Skais 			return (NULL);
123898Skais 	} else {
124898Skais 		char *temp_str;
125898Skais 		char *ptr;
126898Skais 		struct hostent *hp;
127898Skais 		boolean_t do_warn;
12810520SBhargava.Yenduri@Sun.COM 		int error_num;
12910520SBhargava.Yenduri@Sun.COM 		in_addr_t v4addr;
13010520SBhargava.Yenduri@Sun.COM 		in6_addr_t v6addr;
131898Skais 
132898Skais 		if (get_portnum(first_space + 1, &port) == 0) {
133898Skais 			(void) fprintf(stderr,
134898Skais 			    gettext("Error: Invalid port value -- %s\n"),
135898Skais 			    first_space + 1);
136898Skais 			return (NULL);
137898Skais 		}
138898Skais 		KSSL_DEBUG("port=%d\n", port);
139898Skais 
140898Skais 		if ((temp_str = strdup(arg)) == NULL)
141898Skais 			return (NULL);
142898Skais 		*(strchr(temp_str, ' ')) = '\0';
143898Skais 
14410520SBhargava.Yenduri@Sun.COM 		if (inet_pton(AF_INET6, temp_str, &v6addr) == 1) {
14510520SBhargava.Yenduri@Sun.COM 			/* Do a reverse lookup for the IPv6 address */
14610520SBhargava.Yenduri@Sun.COM 			hp = getipnodebyaddr(&v6addr, sizeof (v6addr),
14710520SBhargava.Yenduri@Sun.COM 			    AF_INET6, &error_num);
14810520SBhargava.Yenduri@Sun.COM 		} else if (inet_pton(AF_INET, temp_str, &v4addr) == 1) {
14910520SBhargava.Yenduri@Sun.COM 			/* Do a reverse lookup for the IPv4 address */
15010520SBhargava.Yenduri@Sun.COM 			hp = getipnodebyaddr(&v4addr, sizeof (v4addr),
15110520SBhargava.Yenduri@Sun.COM 			    AF_INET, &error_num);
152898Skais 		} else {
15310520SBhargava.Yenduri@Sun.COM 			/* Do a lookup for the host name */
15410520SBhargava.Yenduri@Sun.COM 			hp = getipnodebyname(temp_str, AF_INET6, AI_DEFAULT,
15510520SBhargava.Yenduri@Sun.COM 			    &error_num);
15610520SBhargava.Yenduri@Sun.COM 		}
15710520SBhargava.Yenduri@Sun.COM 
15810520SBhargava.Yenduri@Sun.COM 		if (hp == NULL) {
15910520SBhargava.Yenduri@Sun.COM 			(void) fprintf(stderr,
16010520SBhargava.Yenduri@Sun.COM 			    gettext("Error: Unknown host -- %s\n"), temp_str);
16110520SBhargava.Yenduri@Sun.COM 			free(temp_str);
16210520SBhargava.Yenduri@Sun.COM 			return (NULL);
163898Skais 		}
164898Skais 
165898Skais 		if ((ptr = cname = strdup(hp->h_name)) == NULL) {
16610520SBhargava.Yenduri@Sun.COM 			freehostent(hp);
167898Skais 			free(temp_str);
168898Skais 			return (NULL);
169898Skais 		}
17010520SBhargava.Yenduri@Sun.COM 
17110520SBhargava.Yenduri@Sun.COM 		freehostent(hp);
17210520SBhargava.Yenduri@Sun.COM 
173898Skais 		do_warn = B_TRUE;
174898Skais 		/* "s/./-/g" */
175898Skais 		while ((ptr = strchr(ptr, '.')) != NULL) {
176898Skais 			if (do_warn)
177898Skais 				do_warn = B_FALSE;
178898Skais 			*ptr = '-';
179898Skais 			ptr++;
180898Skais 		}
181898Skais 
182898Skais 		if (do_warn && is_create) {
183898Skais 			(void) fprintf(stderr,
184898Skais 			    gettext("Warning: %s does not appear to have a"
185898Skais 			    " registered DNS name.\n"), temp_str);
186898Skais 		}
187898Skais 
188898Skais 		free(temp_str);
189898Skais 	}
190898Skais 
191898Skais 	KSSL_DEBUG("Cannonical host name =%s\n", cname);
192898Skais 
193898Skais 	len = strlen(prefix) + strlen(cname) + 10;
194898Skais 	if ((instance_name = malloc(len)) == NULL) {
195898Skais 		(void) fprintf(stderr,
196898Skais 		    gettext("Error: memory allocation failure.\n"));
197898Skais 		return (NULL);
198898Skais 	}
199898Skais 	(void) snprintf(instance_name, len, "%s%s-%d", prefix, cname, port);
200898Skais 
201898Skais 	if (is_create) {
202898Skais 		len = strlen(prefix) + strlen(ANY_ADDR) + 10;
203898Skais 		if ((*inaddr_any_name = malloc(len)) == NULL) {
204898Skais 			(void) fprintf(stderr,
205898Skais 			    gettext("Error: memory allocation failure.\n"));
20612696SVladimir.Kotal@Sun.COM 			free(instance_name);
207898Skais 			free(cname);
208898Skais 			return (NULL);
209898Skais 		}
210898Skais 
211898Skais 		(void) snprintf(*inaddr_any_name, len,
212898Skais 		    "%s%s-%d", prefix, ANY_ADDR, port);
213898Skais 	}
214898Skais 
215898Skais 	free(cname);
216898Skais 	KSSL_DEBUG("instance_name=%s\n", instance_name);
217898Skais 	return (instance_name);
218898Skais }
219898Skais 
220898Skais static void
usage_all(void)221898Skais usage_all(void)
222898Skais {
223898Skais 	(void) fprintf(stderr, gettext("Usage:\n"));
224898Skais 	usage_create(B_FALSE);
225898Skais 	usage_delete(B_FALSE);
226898Skais 	(void) fprintf(stderr, "ksslcfg -V\n");
227898Skais 	(void) fprintf(stderr, "ksslcfg -?\n");
228898Skais }
229898Skais 
230898Skais 
231898Skais int
main(int argc,char ** argv)232898Skais main(int argc, char **argv)
233898Skais {
234898Skais 	int rv = SUCCESS;
235898Skais 
236898Skais 	(void) setlocale(LC_ALL, "");
237898Skais #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
238898Skais #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
239898Skais #endif
240898Skais 	(void) textdomain(TEXT_DOMAIN);
241898Skais 
242*12784SVladimir.Kotal@Sun.COM 	/* Running from within a non-global zone is not supported yet. */
243*12784SVladimir.Kotal@Sun.COM 	if (getzoneid() != GLOBAL_ZONEID) {
244*12784SVladimir.Kotal@Sun.COM 		(void) fprintf(stderr,
245*12784SVladimir.Kotal@Sun.COM 		    gettext("Error: Configuring KSSL from within a non-global "
246*12784SVladimir.Kotal@Sun.COM 		    "zone is not supported.\nPlease run the command from "
247*12784SVladimir.Kotal@Sun.COM 		    "the global zone.\n"));
248*12784SVladimir.Kotal@Sun.COM 		return (ERROR_USAGE);
249*12784SVladimir.Kotal@Sun.COM 	}
250*12784SVladimir.Kotal@Sun.COM 
251898Skais 	if (argc < 2) {
252898Skais 		usage_all();
253898Skais 		return (ERROR_USAGE);
254898Skais 	}
255898Skais 
256898Skais 	if (strcmp(argv[1], "create") == 0) {
257898Skais 		rv = do_create(argc, argv);
258898Skais 	} else if (strcmp(argv[1], "delete") == 0) {
259898Skais 		rv = do_delete(argc, argv);
260898Skais 	} else if (strcmp(argv[1], "-V") == 0) {
261898Skais 		(void) printf("%s\n", KSSLCFG_VERSION);
262898Skais 	} else if (strcmp(argv[1], "-?") == 0) {
263898Skais 		usage_all();
264898Skais 	} else {
265898Skais 		(void) fprintf(stderr,
266898Skais 		    gettext("Error: Unknown subcommand -- %s\n"), argv[1]);
267898Skais 		usage_all();
268898Skais 		rv = ERROR_USAGE;
269898Skais 	}
270898Skais 
271898Skais 	return (rv);
272898Skais }
273