xref: /titanic_41/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c (revision 445f2479fe3d7435daab18bf2cdc310b86cd6738)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <arpa/inet.h> /* inet_addr() */
30 #include <ctype.h>
31 #include <libscf.h>
32 #include <netdb.h> /* hostent */
33 #include <netinet/in.h> /* ip_addr_t */
34 #include <stdio.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <stdlib.h>
38 #include <fcntl.h>
39 #include <strings.h>
40 #include <sys/varargs.h>
41 #include "ksslcfg.h"
42 
43 /*
44  * ksslcfg(1M)
45  *
46  * ksslcfg manages smf(5) instances for the Kernel SSL proxy module.
47  * It makes use of kssladm(1M) which does the grunt work.
48  */
49 
50 #define	KSSLCFG_VERSION "1.0"
51 
52 boolean_t verbose = B_FALSE;
53 const char *SERVICE_NAME = "network/ssl/proxy";
54 
55 void
56 KSSL_DEBUG(const char *format, ...)
57 {
58 	va_list ap;
59 
60 	if (verbose) {
61 		va_start(ap, format);
62 		(void) vprintf(format, ap);
63 		va_end(ap);
64 	}
65 }
66 
67 int
68 get_portnum(const char *s, ushort_t *rport)
69 {
70 	unsigned long port;
71 
72 	errno = 0;
73 	port = strtoul(s, NULL, 10);
74 	if (port > USHRT_MAX || port == 0 || errno != 0) {
75 		return (0);
76 	}
77 
78 	if (rport != NULL)
79 		*rport = (ushort_t)port;
80 	return (1);
81 }
82 
83 #define	ANY_ADDR	"INADDR_ANY"
84 
85 /*
86  * An instance name is formed using either the host name in the fully
87  * qualified domain name form (FQDN) which should map to a specific IP address
88  * or using INADDR_ANY which means all IP addresses.
89  *
90  * We do a lookup or reverse lookup to get the host name. It is assumed that
91  * the returned name is in the FQDN form. i.e. DNS is used.
92  */
93 char *
94 create_instance_name(const char *arg, char **inaddr_any_name,
95     boolean_t is_create)
96 {
97 	int len;
98 	uint16_t port;
99 	char *cname;
100 	in_addr_t addr;
101 	char *instance_name;
102 	const char *prefix = "kssl-";
103 	char *first_space = strchr(arg, ' ');
104 
105 	if (first_space == NULL) {
106 		if (get_portnum(arg, &port) == 0) {
107 			(void) fprintf(stderr,
108 			    gettext("Error: Invalid port value -- %s\n"),
109 			    arg);
110 			return (NULL);
111 		}
112 		KSSL_DEBUG("port=%d\n", port);
113 		if ((cname = strdup(ANY_ADDR)) == NULL)
114 			return (NULL);
115 	} else {
116 		char *temp_str;
117 		char *ptr;
118 		struct hostent *hp;
119 		boolean_t do_warn;
120 
121 		if (get_portnum(first_space + 1, &port) == 0) {
122 			(void) fprintf(stderr,
123 			    gettext("Error: Invalid port value -- %s\n"),
124 			    first_space + 1);
125 			return (NULL);
126 		}
127 		KSSL_DEBUG("port=%d\n", port);
128 
129 		if ((temp_str = strdup(arg)) == NULL)
130 			return (NULL);
131 		*(strchr(temp_str, ' ')) = '\0';
132 
133 		if ((int)(addr = inet_addr(temp_str)) == -1) {
134 			if ((hp = gethostbyname(temp_str)) == NULL) {
135 				(void) fprintf(stderr,
136 				    gettext("Error: Unknown host -- %s\n"),
137 				    temp_str);
138 				free(temp_str);
139 				return (NULL);
140 			}
141 		} else {
142 			/* This is an IP address. Do a reverse lookup. */
143 			if ((hp = gethostbyaddr((char *)&addr, 4, AF_INET))
144 			    == NULL) {
145 				(void) fprintf(stderr,
146 				    gettext("Error: Unknown host -- %s\n"),
147 				    temp_str);
148 				free(temp_str);
149 				return (NULL);
150 			}
151 		}
152 
153 		if ((ptr = cname = strdup(hp->h_name)) == NULL) {
154 			free(temp_str);
155 			return (NULL);
156 		}
157 		do_warn = B_TRUE;
158 		/* "s/./-/g" */
159 		while ((ptr = strchr(ptr, '.')) != NULL) {
160 			if (do_warn)
161 				do_warn = B_FALSE;
162 			*ptr = '-';
163 			ptr++;
164 		}
165 
166 		if (do_warn && is_create) {
167 			(void) fprintf(stderr,
168 			    gettext("Warning: %s does not appear to have a"
169 			    " registered DNS name.\n"), temp_str);
170 		}
171 
172 		free(temp_str);
173 	}
174 
175 	KSSL_DEBUG("Cannonical host name =%s\n", cname);
176 
177 	len = strlen(prefix) + strlen(cname) + 10;
178 	if ((instance_name = malloc(len)) == NULL) {
179 		(void) fprintf(stderr,
180 		    gettext("Error: memory allocation failure.\n"));
181 		return (NULL);
182 	}
183 	(void) snprintf(instance_name, len, "%s%s-%d", prefix, cname, port);
184 
185 	if (is_create) {
186 		len = strlen(prefix) + strlen(ANY_ADDR) + 10;
187 		if ((*inaddr_any_name = malloc(len)) == NULL) {
188 			(void) fprintf(stderr,
189 			    gettext("Error: memory allocation failure.\n"));
190 			free(cname);
191 			return (NULL);
192 		}
193 
194 		(void) snprintf(*inaddr_any_name, len,
195 		    "%s%s-%d", prefix, ANY_ADDR, port);
196 	}
197 
198 	free(cname);
199 	KSSL_DEBUG("instance_name=%s\n", instance_name);
200 	return (instance_name);
201 }
202 
203 static void
204 usage_all(void)
205 {
206 	(void) fprintf(stderr, gettext("Usage:\n"));
207 	usage_create(B_FALSE);
208 	usage_delete(B_FALSE);
209 	(void) fprintf(stderr, "ksslcfg -V\n");
210 	(void) fprintf(stderr, "ksslcfg -?\n");
211 }
212 
213 
214 int
215 main(int argc, char **argv)
216 {
217 	int rv = SUCCESS;
218 
219 	(void) setlocale(LC_ALL, "");
220 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
221 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
222 #endif
223 	(void) textdomain(TEXT_DOMAIN);
224 
225 	if (argc < 2) {
226 		usage_all();
227 		return (ERROR_USAGE);
228 	}
229 
230 	if (strcmp(argv[1], "create") == 0) {
231 		rv = do_create(argc, argv);
232 	} else if (strcmp(argv[1], "delete") == 0) {
233 		rv = do_delete(argc, argv);
234 	} else if (strcmp(argv[1], "-V") == 0) {
235 		(void) printf("%s\n", KSSLCFG_VERSION);
236 	} else if (strcmp(argv[1], "-?") == 0) {
237 		usage_all();
238 	} else {
239 		(void) fprintf(stderr,
240 		    gettext("Error: Unknown subcommand -- %s\n"), argv[1]);
241 		usage_all();
242 		rv = ERROR_USAGE;
243 	}
244 
245 	return (rv);
246 }
247