xref: /titanic_50/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c (revision 8f588c8376a0fa02470fc4554ec83442b305020f)
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 #include <arpa/inet.h> /* inet_addr() */
27 #include <ctype.h>
28 #include <libscf.h>
29 #include <netdb.h> /* hostent */
30 #include <netinet/in.h> /* ip_addr_t */
31 #include <stdio.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <stdlib.h>
35 #include <fcntl.h>
36 #include <strings.h>
37 #include <sys/varargs.h>
38 #include "ksslcfg.h"
39 
40 /*
41  * ksslcfg(1M)
42  *
43  * ksslcfg manages smf(5) instances for the Kernel SSL proxy module.
44  * It makes use of kssladm(1M) which does the grunt work.
45  */
46 
47 /*
48  * This version number is rather meaningless. In any case,
49  * version 2.0 adds support for IPv6 addresses.
50  */
51 #define	KSSLCFG_VERSION "Version 2.0"
52 
53 boolean_t verbose = B_FALSE;
54 const char *SERVICE_NAME = "network/ssl/proxy";
55 
56 void
57 KSSL_DEBUG(const char *format, ...)
58 {
59 	va_list ap;
60 
61 	if (verbose) {
62 		va_start(ap, format);
63 		(void) vprintf(format, ap);
64 		va_end(ap);
65 	}
66 }
67 
68 int
69 get_portnum(const char *s, ushort_t *rport)
70 {
71 	unsigned long port;
72 
73 	errno = 0;
74 	port = strtoul(s, NULL, 10);
75 	if (port > USHRT_MAX || port == 0 || errno != 0) {
76 		return (0);
77 	}
78 
79 	if (rport != NULL)
80 		*rport = (ushort_t)port;
81 	return (1);
82 }
83 
84 #define	ANY_ADDR	"INADDR_ANY"
85 
86 /*
87  * An instance name is formed using either the host name in the fully
88  * qualified domain name form (FQDN) which should map to a specific IP address
89  * or using INADDR_ANY which means all IP addresses.
90  *
91  * We do a lookup or reverse lookup to get the host name. It is assumed that
92  * the returned name is in the FQDN form. i.e. DNS is used.
93  */
94 char *
95 create_instance_name(const char *arg, char **inaddr_any_name,
96     boolean_t is_create)
97 {
98 	int len;
99 	uint16_t port;
100 	char *cname;
101 	char *instance_name;
102 	const char *prefix = "kssl-";
103 	char *first_space;
104 
105 	first_space = strchr(arg, ' ');
106 	if (first_space == NULL) {	/* No host name. Use INADDR_ANY. */
107 		if (get_portnum(arg, &port) == 0) {
108 			(void) fprintf(stderr,
109 			    gettext("Error: Invalid port value -- %s\n"),
110 			    arg);
111 			return (NULL);
112 		}
113 		KSSL_DEBUG("port=%d\n", port);
114 		if ((cname = strdup(ANY_ADDR)) == NULL)
115 			return (NULL);
116 	} else {
117 		char *temp_str;
118 		char *ptr;
119 		struct hostent *hp;
120 		boolean_t do_warn;
121 		int error_num;
122 		in_addr_t v4addr;
123 		in6_addr_t v6addr;
124 
125 		if (get_portnum(first_space + 1, &port) == 0) {
126 			(void) fprintf(stderr,
127 			    gettext("Error: Invalid port value -- %s\n"),
128 			    first_space + 1);
129 			return (NULL);
130 		}
131 		KSSL_DEBUG("port=%d\n", port);
132 
133 		if ((temp_str = strdup(arg)) == NULL)
134 			return (NULL);
135 		*(strchr(temp_str, ' ')) = '\0';
136 
137 		if (inet_pton(AF_INET6, temp_str, &v6addr) == 1) {
138 			/* Do a reverse lookup for the IPv6 address */
139 			hp = getipnodebyaddr(&v6addr, sizeof (v6addr),
140 			    AF_INET6, &error_num);
141 		} else if (inet_pton(AF_INET, temp_str, &v4addr) == 1) {
142 			/* Do a reverse lookup for the IPv4 address */
143 			hp = getipnodebyaddr(&v4addr, sizeof (v4addr),
144 			    AF_INET, &error_num);
145 		} else {
146 			/* Do a lookup for the host name */
147 			hp = getipnodebyname(temp_str, AF_INET6, AI_DEFAULT,
148 			    &error_num);
149 		}
150 
151 		if (hp == NULL) {
152 			(void) fprintf(stderr,
153 			    gettext("Error: Unknown host -- %s\n"), temp_str);
154 			free(temp_str);
155 			return (NULL);
156 		}
157 
158 		if ((ptr = cname = strdup(hp->h_name)) == NULL) {
159 			freehostent(hp);
160 			free(temp_str);
161 			return (NULL);
162 		}
163 
164 		freehostent(hp);
165 
166 		do_warn = B_TRUE;
167 		/* "s/./-/g" */
168 		while ((ptr = strchr(ptr, '.')) != NULL) {
169 			if (do_warn)
170 				do_warn = B_FALSE;
171 			*ptr = '-';
172 			ptr++;
173 		}
174 
175 		if (do_warn && is_create) {
176 			(void) fprintf(stderr,
177 			    gettext("Warning: %s does not appear to have a"
178 			    " registered DNS name.\n"), temp_str);
179 		}
180 
181 		free(temp_str);
182 	}
183 
184 	KSSL_DEBUG("Cannonical host name =%s\n", cname);
185 
186 	len = strlen(prefix) + strlen(cname) + 10;
187 	if ((instance_name = malloc(len)) == NULL) {
188 		(void) fprintf(stderr,
189 		    gettext("Error: memory allocation failure.\n"));
190 		return (NULL);
191 	}
192 	(void) snprintf(instance_name, len, "%s%s-%d", prefix, cname, port);
193 
194 	if (is_create) {
195 		len = strlen(prefix) + strlen(ANY_ADDR) + 10;
196 		if ((*inaddr_any_name = malloc(len)) == NULL) {
197 			(void) fprintf(stderr,
198 			    gettext("Error: memory allocation failure.\n"));
199 			free(cname);
200 			return (NULL);
201 		}
202 
203 		(void) snprintf(*inaddr_any_name, len,
204 		    "%s%s-%d", prefix, ANY_ADDR, port);
205 	}
206 
207 	free(cname);
208 	KSSL_DEBUG("instance_name=%s\n", instance_name);
209 	return (instance_name);
210 }
211 
212 static void
213 usage_all(void)
214 {
215 	(void) fprintf(stderr, gettext("Usage:\n"));
216 	usage_create(B_FALSE);
217 	usage_delete(B_FALSE);
218 	(void) fprintf(stderr, "ksslcfg -V\n");
219 	(void) fprintf(stderr, "ksslcfg -?\n");
220 }
221 
222 
223 int
224 main(int argc, char **argv)
225 {
226 	int rv = SUCCESS;
227 
228 	(void) setlocale(LC_ALL, "");
229 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
230 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
231 #endif
232 	(void) textdomain(TEXT_DOMAIN);
233 
234 	if (argc < 2) {
235 		usage_all();
236 		return (ERROR_USAGE);
237 	}
238 
239 	if (strcmp(argv[1], "create") == 0) {
240 		rv = do_create(argc, argv);
241 	} else if (strcmp(argv[1], "delete") == 0) {
242 		rv = do_delete(argc, argv);
243 	} else if (strcmp(argv[1], "-V") == 0) {
244 		(void) printf("%s\n", KSSLCFG_VERSION);
245 	} else if (strcmp(argv[1], "-?") == 0) {
246 		usage_all();
247 	} else {
248 		(void) fprintf(stderr,
249 		    gettext("Error: Unknown subcommand -- %s\n"), argv[1]);
250 		usage_all();
251 		rv = ERROR_USAGE;
252 	}
253 
254 	return (rv);
255 }
256