mms_ssl.c revision cee0fb94c0d4227de0a00efc162fb2739844b641
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifdef MMS_OPENSSL
#define MMS_OPENSSL_THREAD_DEFINES
#include <openssl/opensslconf.h>
#include <unistd.h>
#include <pthread.h>
#include "mms_network.h"
#include "mms_sym.h"
#include "mms_sock.h"
#include <mms_trace.h>
#define UNWELCOME_SSL "unwelcome \"SSAI_E_SSL\";"
#define UNWELCOME_ACCESS_SSL "unwelcome \"SSAI_E_ACCESS_DENIED\" " \
"\"SSAI_E_SSL\";"
#define MMS_SSL_CIPHER "EDH-RSA-DES-CBC3-SHA"
typedef struct mms_ssl_data mms_ssl_t;
struct mms_ssl_data {
char *mms_cipher;
int mms_verify;
int mms_nchain;
};
typedef struct mms_ssl_conn mms_sc_t;
struct mms_ssl_conn {
};
static void mms_ssl_data_free(void *ssl_data);
int
{
if (net->ssl_enabled) {
if (mms_ssl_init(err)) {
return (1);
}
NULL,
err)) {
return (1);
}
return (1);
}
}
return (0);
}
int
{
if (net->ssl_enabled) {
if (mms_ssl_init(err)) {
return (1);
}
err)) {
return (1);
}
return (1);
}
}
return (0);
}
static int
{
return (1);
}
if (data->mms_cipher) {
}
return (0);
}
return (1);
}
return (0);
}
char *
{
} else {
if (data->mms_cipher) {
} else {
}
}
}
return (cipher);
}
static void
{
if (mode & CRYPTO_LOCK) {
if (pthread_mutex_lock(&mms_ssl_mutex[n]) != 0) {
}
} else {
if (pthread_mutex_unlock(&mms_ssl_mutex[n]) != 0) {
}
}
}
static ulong_t
mms_ssl_id(void)
{
return ((ulong_t)pthread_self());
}
static int
{
int i;
#if defined(OPENSSL_THREADS)
CRYPTO_num_locks());
sizeof (pthread_mutex_t))) == NULL) {
return (1);
}
for (i = 0; i < CRYPTO_num_locks(); i++) {
for (i -= 1; i >= 0; i--) {
(void) pthread_mutex_destroy(&mms_ssl_mutex[i]);
}
return (1);
}
}
#endif
return (0);
}
static void
mms_ssl_lock_cleanup(void)
{
int i;
#if defined(OPENSSL_THREADS)
if (mms_ssl_mutex) {
CRYPTO_num_locks());
for (i = 0; i < CRYPTO_num_locks(); i++) {
(void) pthread_mutex_destroy(&mms_ssl_mutex[i]);
}
}
#endif
}
int
{
/* openssl needs locks for multithreaded applications */
if (mms_ssl_lock_setup(err)) {
return (1);
}
(void) SSL_library_init();
return (0);
}
void
mms_ssl_finish(void *ssl_data)
{
if (ssl_data) {
}
}
int
{
int rc;
/*
* Client connects to SSL server.
*/
goto error;
}
goto error;
}
goto error;
}
goto error;
}
goto error;
}
"unauthenticated ssl connection, "
"no server certificate");
goto error;
}
goto error;
}
/* verify connection cert matches expected peer cert */
goto error;
}
return (0);
return (1);
}
int
{
int rc;
/*
* Server accepts client SSL connection.
*/
goto error;
}
goto error;
}
goto error;
}
goto error;
}
goto error_no_ssl;
}
if (data->mms_verify) {
goto error_ssl;
}
"unauthenticated ssl connection, "
"no client certificate");
goto error_ssl;
}
return (0);
/*
* Assume problem is non-ssl client.
* Attempt to send unwelcome ssl to client.
*/
return (1);
/*
* Problem is client ssl validation.
* Attempt to send unwelcome access deined ssl to client.
*/
return (1);
/*
* Don't know if connection is ssl or non-ssl.
*/
return (1);
}
int
{
int rc;
int n;
/* data is decrypted by ssl read */
if (rc <= 0) {
return (-1);
}
}
return (n);
}
int
{
return (0); /* continue reading */
}
return (1); /* stop reading */
}
int
{
int rc;
int i;
int n;
int total = 0;
/* data is encrypted by ssl write */
for (i = 0; i < iovcnt; i++) {
if (rc <= 0) {
return (-1);
}
}
total += n;
}
return (total);
}
int
{
return (0); /* continue writing */
}
return (1); /* stop writing */
}
void
{
/*
* Close SSL connection.
*/
return;
}
if (sc->mms_sc_ssl) {
} else {
}
}
if (sc->mms_sc_cert) {
}
}
static void
{
}
static void
{
}
/* Get error string */
void
{
int id;
char buf[MMS_EBUF_LEN];
id = MMS_ERR_NONE;
/* no ssl error */
} else {
/* ssl error string */
buf);
}
}
}
/* ARGSUSED0 */
static int
{
char *file = (char *)u;
char *ptr;
/*
* Read private key password pharse from file.
*/
return (0);
}
return (0);
}
return (0);
}
*ptr = '\0';
}
}
static int
{
int depth;
int err;
char issuer[256];
char subject[256];
if (!ok) {
"Certificate Store Error:\n"
"\tdepth %d\n"
"\tissuer %s\n"
"\tsubject %s\n"
"\terror %s\n",
}
return (ok);
}
static int
{
int rc;
/*
* Verify certificate.
*/
return (0);
}
return (1);
}
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
return (1);
}
#else
#endif
}
return (!rc);
}
int
{
int rc;
return (0);
}
/*
* Release previous CRL.
*/
}
}
/*
* Get updated CRL.
*/
if (crl_file) {
} else {
}
}
return (rc);
}
int
mms_ssl_has_crl(void *ssl_data)
{
return (0); /* no crl */
}
return (1); /* has valid crl */
}
int
{
int rc;
/*
* Check conn certs against updated CRL.
*/
return (0);
}
}
return (rc);
}
static int
{
int i;
return (1);
}
return (1);
}
return (1);
}
return (1);
}
return (1);
}
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
#endif
for (i = 0; i < data->mms_nchain; i++) {
if (mms_ssl_check_cert(data,
crl_file, i);
return (1);
}
}
}
return (0);
}
/*
* Source SSL data from files.
*
* To source SSL data not from files, write a function to load the
* ssl data from your SSL source. The other ssl calls remain the same.
*
* Two-way authentication, server and client both have the following
* PEM-encoded certificate file structure:
* 1. RSA certificate
* 2. Private key
* 3. CA RSA Certificate Chain
*
* One-way authentication, the server has a RSA certificate, private key,
* and CA RSA certificate chain. The client only has the server's
* CA RSA certificate chain in the following PEM-encoded certificate
* file structure:
* 1. Optional for client
* 2. Certificate Chain
*
* The RSA certificate private key password pharse:
* 1. Optional
* 2. password argument
* 3. password file argument
*
* The CRL file is optional.
*/
static int
mms_ssl_data_use_files(void **ssl_data,
char *cert_file,
char *pass,
char *pass_file,
char *dh_file,
char *crl_file,
{
long off;
/*
* Load PEM-encoded files into SSL structures.
*/
return (NULL);
}
/*
* User Certificate or CA Certificate
*/
/*
* User wants unauthenticated connection.
*/
return (0);
}
goto error;
}
goto error;
}
goto error;
}
/*
* Private Key Password Pharse
*/
goto error;
}
if (pass) {
} else if (pass_file) {
} else {
}
if (rc = ERR_get_error()) {
switch (ERR_GET_REASON(rc)) {
case PEM_R_NO_START_LINE:
break;
default:
"read private key %s %d %d",
goto error;
}
}
/* one-way authentication */
goto error;
}
} else {
}
/*
* Certificate Chain Hierarchy
*/
goto error;
}
data->mms_nchain);
}
if (rc = ERR_get_error()) {
switch (ERR_GET_REASON(rc)) {
case PEM_R_NO_START_LINE:
break;
default:
"read cert chain %s %d %d\n",
goto error;
}
}
/*
* Optional Certificate Revocation List
*/
goto error;
}
/*
* Diffie-Hellman required for server, client does not use.
*/
if (dh_file) {
int code;
goto error;
}
goto error;
}
goto error;
}
}
return (0);
if (cert)
return (1);
}
static int
{
/*
* Optional, clients only, load the mm peer certificate.
* This certificate is compared to the ssl connection peer
* certificate obtained from the ssl connection and will
* prevent the client from sending the password to a mm
* imposter.
*/
return (0);
}
}
if (peer_cert_file == NULL) {
return (0);
}
return (1);
}
return (1);
}
return (1);
}
return (0);
}
static void
mms_ssl_data_free(void *ssl_data)
{
int i;
/*
* Free SSL connection context data.
*/
if (data) {
for (i = 0; i < data->mms_nchain; i++) {
}
}
}
}
static int
{
int depth;
int err;
char issuer[256];
char subject[256];
if (!ok) {
if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
ok = 1;
} else {
"Certificate Verify Error:\n"
"\tdepth %d\n"
"\tissuer %s\n"
"\tsubject %s\n"
"\terror %s\n",
}
}
return (ok);
}
void
{
if (data) {
}
}
static int
{
char *cipher_name = MMS_SSL_CIPHER;
int i;
/*
* Create server SSL connection context.
*/
return (1);
}
return (1);
}
return (1);
}
return (1);
}
}
return (1);
}
if (data->mms_verify == 0) {
} else {
}
return (1);
}
if (data->mms_cipher)
return (1);
}
return (0);
}
static int
{
char *cipher_name = MMS_SSL_CIPHER;
int i;
/*
* Create client SSL connection context.
*/
return (1);
}
if (data->mms_nchain) {
return (1);
}
}
return (1);
}
}
return (1);
}
}
if (data->mms_nchain) {
}
if (data->mms_cipher)
return (1);
}
return (0);
}
static char *
{
int len;
int i;
int n;
/*
* Convert x509 certificate structure to text certficate.
*/
goto error;
}
goto error;
}
goto error;
}
len = 4096;
goto error;
}
goto error;
}
buf[n] = '\0';
/* remove trailing newlines */
if (buf[i] == '-')
break;
buf[i] = '\0';
}
return (buf);
if (bio)
if (buf)
return (NULL);
}
static X509 *
{
int len;
int n;
/*
* Convert text certificate to x509 certificate structure.
*/
goto error;
}
goto error;
}
if (n <= 0 || n != len) {
goto error;
}
goto error;
}
return (cert_x509);
if (bio)
return (NULL);
}
static int
{
int rc = 1;
goto out;
goto out;
goto out;
}
out:
return (rc);
}
static char *
{
int outl;
int tmplen;
/* base64 encode */
if (buf) {
} else {
}
}
return ((char *)out);
}
static uchar_t *
{
int outl;
int tmplen;
/* base64 decode */
if (buf) {
} else {
goto failed;
}
&tmplen) == -1) {
goto failed;
}
}
}
return (out);
return (NULL);
}
static int
{
int eklen;
int ivlen;
int enclen;
int tmplen;
int i;
int rc = 1;
/* public key encrypt */
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
rc = 0;
out:
if (rc) {
for (i = 0; i < 4; i++) {
}
}
(void) EVP_CIPHER_CTX_cleanup(&cipher_ctx);
return (rc);
}
static char *
{
int len;
int eklen;
int ivlen;
int enclen;
int tmplen;
int rc = 1;
/* private key decrypt */
(void) EVP_CIPHER_CTX_init(&cipher_ctx);
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
&tmplen) != 1) {
goto out;
}
rc = 0;
out:
if (rc) {
}
(void) EVP_CIPHER_CTX_cleanup(&cipher_ctx);
return (password);
}
static int
{
int signlen;
int i;
int rc = 1;
/* private key sign */
(void) EVP_MD_CTX_init(&md_ctx);
goto out;
}
goto out;
}
for (i = 0; i < 3; i++) {
goto out;
}
}
goto out;
}
goto out;
}
rc = 0;
out:
(void) EVP_MD_CTX_cleanup(&md_ctx);
return (rc);
}
static int
{
int signlen;
int i;
int rc = 1;
/* public key verify sign */
(void) EVP_MD_CTX_init(&md_ctx);
goto out;
}
goto out;
}
for (i = 0; i < 3; i++) {
goto out;
}
}
goto out;
}
rc = 0;
out:
(void) EVP_MD_CTX_cleanup(&md_ctx);
return (rc);
}
int
{
/*
* my certificate, my private key and
* other guy's certificate
*/
if (data->mms_nchain > 0 &&
}
}
}
int
char *password,
char **cert,
char **auth)
{
char *mydata[4] = {0, 0, 0, 0};
int i;
int len;
int rc = 1;
/* create certificate clause */
/* my private key */
goto out;
}
goto out;
}
/* my certificate */
goto out;
}
/* get other guy's public key */
}
goto out;
}
/* encrypt password using other guy's public key */
goto out;
}
/* sign password using my private key */
goto out;
}
/* build authenticaton message */
len = 0;
for (i = 0; i < 4; i++) {
}
goto out;
}
rc = 0;
out:
if (rc) {
}
for (i = 0; i < 4; i++) {
}
if (pkey)
return (rc);
}
int
char *cert_pem,
char *auth,
char **password)
{
char *mydata[4] = {0, 0, 0, 0};
int i;
int rc = 1;
/* verify certificate clause */
/* my private key */
goto out;
}
goto out;
}
/* get certificate from other guy's certificate text */
goto out;
}
/* check other guy's cert */
goto out;
}
/* get other guy's public key */
goto out;
}
/* parse authentication message */
goto out;
}
for (i = 1; i < 4; i++) {
goto out;
}
mydata[i][0] = 0;
mydata[i]++;
}
/* verify other guy's signature */
goto out;
}
/* decrypt password using my private key */
goto out;
}
rc = 0;
out:
if (cert)
if (pkey)
if (mydata[0])
return (rc);
}
#endif /* MMS_OPENSSL */