usr/src/cmd/rad/mod/xport_tls/mod_xport_tls.c
author David Powell <David.Powell@sun.com>
Wed, 16 Dec 2009 19:06:12 -0800
changeset 401 fc1223edbd8d
parent 391 71abce159a62
child 426 2cc50564cd5f
permissions -rw-r--r--
13421 apache: o.o.o.rad.ContainerException: system error: error talking to slave 13426 TLS transport auto-generates readable private keys 13429 file browsing API hard codes incorrect attributes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
391
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     1
/*
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     2
 * CDDL HEADER START
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     3
 *
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     5
 * Common Development and Distribution License (the "License").
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     6
 * You may not use this file except in compliance with the License.
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     7
 *
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    11
 * and limitations under the License.
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    12
 *
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    18
 *
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    19
 * CDDL HEADER END
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    20
 */
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    21
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    22
/*
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    23
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    24
 * Use is subject to license terms.
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    25
 */
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    26
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    27
#include <openssl/ssl.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    28
#include <openssl/err.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    29
#include <sys/types.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    30
#include <sys/socket.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    31
#include <sys/utsname.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    32
#include <sys/stat.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    33
#include <sys/wait.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    34
#include <stdio.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    35
#include <string.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    36
#include <stdlib.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    37
#include <errno.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    38
#include <unistd.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    39
#include <spawn.h>
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    40
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    41
#include "rad_object.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    42
#include "rad_modapi.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    43
#include "rad_modapi_xport.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    44
#include "rad_connection.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    45
#include "rad_util.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    46
#include "rad_xport.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    47
#include "rad_log.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    48
#include "../rad_listen.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    49
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    50
#include "api_tls.h"
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    51
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    52
typedef struct ssldata {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    53
	SSL *ssl;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    54
	int fd;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    55
} ssldata_t;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    56
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    57
static int
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    58
rad_tls_read(radmod_connection_t *conn, char *buf, int len)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    59
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    60
	ssldata_t *sdata = conn->rm_conn_xport_data;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    61
	int res = SSL_read(sdata->ssl, buf, len);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    62
	if (res == 0)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    63
		conn->rm_conn_state = RCS_EOF; /* XXX: Not necessarily true? */
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    64
	return (res > 0 ? res : -1);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    65
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    66
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    67
static int
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    68
rad_tls_write(radmod_connection_t *conn, char *buf, int len)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    69
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    70
	ssldata_t *sdata = conn->rm_conn_xport_data;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    71
	return (SSL_write(sdata->ssl, buf, len));
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    72
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    73
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    74
static void
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    75
rad_tls_close(radmod_connection_t *conn)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    76
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    77
	ssldata_t *sdata = conn->rm_conn_xport_data;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    78
	SSL_shutdown(sdata->ssl);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    79
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    80
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    81
static void
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    82
rad_tls_free(radmod_connection_t *conn)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    83
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    84
	ssldata_t *sdata = conn->rm_conn_xport_data;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    85
	SSL_free(sdata->ssl);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    86
	(void) close(sdata->fd);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    87
	free(sdata);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    88
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    89
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    90
static boolean_t
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    91
generate_cert(const char *cert, const char *key)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    92
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    93
	struct utsname name;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    94
	struct stat st;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    95
	pid_t pid;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    96
	char buffer[1024];
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    97
	const char *args[] = {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    98
	    "/usr/bin/openssl", "req", "-x509", "-newkey", "rsa:1024",
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
    99
	    "-days", "3650", "-sha1", "-nodes", "-keyout", key,
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   100
	    "-out", cert, "-subj", buffer, NULL };
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   101
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   102
	if (stat(cert, &st) != -1 && stat(key, &st) != -1)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   103
		return (B_TRUE);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   104
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   105
	(void) uname(&name);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   106
	(void) snprintf(buffer, 1024, "/CN=Remote Administration Daemon @ %s",
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   107
	    name.nodename);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   108
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   109
	rad_log(RL_WARN, "generating key/certificate pair\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   110
	if (posix_spawn(&pid, args[0], NULL, NULL, (char **)args, NULL) != 0) {
401
fc1223edbd8d 13421 apache: o.o.o.rad.ContainerException: system error: error talking to slave
David Powell <David.Powell@sun.com>
parents: 391
diff changeset
   111
		rad_log(RL_ERROR, "failed to create key pair\n");
391
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   112
		return (B_FALSE);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   113
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   114
	while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   115
		;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   116
401
fc1223edbd8d 13421 apache: o.o.o.rad.ContainerException: system error: error talking to slave
David Powell <David.Powell@sun.com>
parents: 391
diff changeset
   117
	if (chmod(cert, 0644) == -1)
fc1223edbd8d 13421 apache: o.o.o.rad.ContainerException: system error: error talking to slave
David Powell <David.Powell@sun.com>
parents: 391
diff changeset
   118
		rad_log(RL_WARN, "failed to chmod '%s'; "
fc1223edbd8d 13421 apache: o.o.o.rad.ContainerException: system error: error talking to slave
David Powell <David.Powell@sun.com>
parents: 391
diff changeset
   119
		    "certificate only readable by owner: %s", strerror(errno));
fc1223edbd8d 13421 apache: o.o.o.rad.ContainerException: system error: error talking to slave
David Powell <David.Powell@sun.com>
parents: 391
diff changeset
   120
391
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   121
	return (B_TRUE);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   122
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   123
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   124
static radmod_transport_t transport = {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   125
	rad_tls_read,
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   126
	rad_tls_write,
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   127
	rad_tls_close,
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   128
	rad_tls_free
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   129
};
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   130
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   131
static void
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   132
tls_run(void *arg)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   133
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   134
	radmod_connection_t *conn = arg;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   135
	rad_proto_handle(conn);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   136
	free(conn);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   137
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   138
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   139
static rad_moderr_t
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   140
tls_listen(rad_thread_t *arg)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   141
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   142
	SSL_CTX *context;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   143
	SSL *ssl;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   144
	int fd;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   145
	data_t *d, *data = rad_thread_arg(arg);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   146
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   147
	int port = struct_get(data, "port")->d_data.integer;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   148
	d = struct_get(data, "proto");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   149
	const char *protostr = d != NULL ? d->d_data.string : "rad";
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   150
	d = struct_get(data, "localonly");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   151
	boolean_t local = d != NULL ? d->d_data.boolean : B_FALSE;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   152
	d = struct_get(data, "certificate");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   153
	const char *cert = d->d_data.string;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   154
	d = struct_get(data, "privatekey");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   155
	const char *key = d->d_data.string;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   156
	d = struct_get(data, "generate");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   157
	boolean_t generate = d != NULL ? d->d_data.boolean : B_FALSE;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   158
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   159
	if (generate && !generate_cert(cert, key)) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   160
		rad_log(RL_ERROR, "Failed to generate certificate.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   161
		return (rm_system);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   162
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   163
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   164
	rad_protocol_t *proto = rad_proto_find(protostr);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   165
	if (proto == NULL) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   166
		rad_log(RL_ERROR, "Unable to find protocol \"%s\".\n",
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   167
		    protostr);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   168
		return (rm_config);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   169
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   170
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   171
	if ((fd = listen_on_port(port, local)) < 0) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   172
		rad_log(RL_ERROR, "Error starting server on port %d\n",
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   173
		    port);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   174
		return (rm_system);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   175
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   176
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   177
	rad_log(RL_DEBUG, "Initializing SSL library.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   178
	(void) SSL_library_init();
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   179
	(void) SSL_load_error_strings();
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   180
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   181
	rad_log(RL_DEBUG, "Creating SSL context.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   182
	context = SSL_CTX_new(SSLv23_method());
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   183
	if (context == NULL) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   184
		rad_log(RL_ERROR, "Unable to create SSL context.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   185
		return (rm_system);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   186
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   187
	SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   188
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   189
	if (SSL_CTX_use_certificate_chain_file(context, cert) == 0) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   190
		rad_log(RL_ERROR, "Unable to use cert file: %s\n", cert);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   191
		ERR_print_errors_fp(stderr);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   192
		return (rm_system);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   193
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   194
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   195
	if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_PEM) == 0) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   196
		rad_log(RL_ERROR, "Unable to use privatekey file: %s\n", key);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   197
		ERR_print_errors_fp(stderr);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   198
		return (rm_system);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   199
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   200
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   201
	rad_thread_ack(arg, rm_ok);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   202
	for (;;) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   203
		int afd, result;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   204
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   205
		rad_log(RL_DEBUG, "Waiting for connection.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   206
		if ((afd = accept(fd, 0, 0)) == -1) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   207
			rad_log(RL_WARN, "Error in accept(): %s\n",
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   208
			    strerror(errno));
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   209
			continue;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   210
		}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   211
		rad_log(RL_DEBUG, "Connection accepted.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   212
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   213
		rad_log(RL_DEBUG, "Creating SSL.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   214
		ssl = SSL_new(context);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   215
		if (ssl == NULL) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   216
			rad_log(RL_WARN, "Unable to create SSL.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   217
			(void) close(afd);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   218
			continue;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   219
		}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   220
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   221
		rad_log(RL_DEBUG, "Initiating SSL connection.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   222
		if (!SSL_set_fd(ssl, afd)) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   223
			rad_log(RL_WARN, "Unable to set SSL fd.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   224
			goto close;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   225
		}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   226
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   227
		rad_subject_t *subject = rad_subject_create_fd(afd, B_FALSE);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   228
		if (subject == NULL) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   229
			rad_log(RL_WARN, "Unable to allocate subject.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   230
			goto close;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   231
		}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   232
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   233
		while ((result = SSL_accept(ssl)) != 1) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   234
			result = SSL_get_error(ssl, result);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   235
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   236
			/* Shouldn't happen, but just in case: */
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   237
			if (result == SSL_ERROR_WANT_READ ||
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   238
			    result == SSL_ERROR_WANT_WRITE)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   239
				continue;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   240
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   241
			ERR_print_errors_fp(stderr);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   242
			rad_log(RL_WARN,
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   243
			    "Unable to establish connection: %d\n", result);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   244
			goto close;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   245
		}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   246
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   247
		rad_log(RL_DEBUG, "Connection accepted.\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   248
		ssldata_t *sdata = zalloc(sizeof (ssldata_t));
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   249
		sdata->ssl = ssl;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   250
		sdata->fd = afd;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   251
		radmod_connection_t *conn = rad_conn_create();
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   252
		conn->rm_conn_xport_ops = &transport;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   253
		conn->rm_conn_xport_data = sdata;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   254
		conn->rm_conn_proto_ops = proto;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   255
		conn->rm_conn_subject = subject;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   256
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   257
		if (rad_thread_create_async(tls_run, conn) != rm_ok) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   258
			rad_conn_close(conn);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   259
			free(conn);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   260
		}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   261
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   262
		continue;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   263
close:
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   264
		SSL_free(ssl);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   265
		(void) close(afd);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   266
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   267
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   268
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   269
static rad_moderr_t
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   270
starter(data_t *data)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   271
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   272
	/*
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   273
	 * Verify parameters.
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   274
	 */
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   275
	data_t *d;
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   276
	if ((d = struct_get(data, "port")) == NULL) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   277
		rad_log(RL_ERROR, "Port required\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   278
		return (rm_config);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   279
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   280
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   281
	if ((d = struct_get(data, "certificate")) == NULL) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   282
		rad_log(RL_ERROR, "Cert required\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   283
		return (rm_config);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   284
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   285
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   286
	if ((d = struct_get(data, "privatekey")) == NULL) {
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   287
		rad_log(RL_ERROR, "Private key required\n");
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   288
		return (rm_config);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   289
	}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   290
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   291
	return (rad_thread_create(tls_listen, data));
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   292
}
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   293
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   294
static rad_modinfo_t modinfo = { "xport_tls", "TLS socket transport module" };
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   295
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   296
int
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   297
_rad_init(void *handle)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   298
{
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   299
	if (rad_module_register(handle, RAD_MODVERSION, &modinfo) == -1)
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   300
		return (-1);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   301
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   302
	rad_xport_register("tls", &t__tls, starter);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   303
	return (0);
71abce159a62 13357 rad
David Powell <David.Powell@sun.com>
parents:
diff changeset
   304
}