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