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