iostream-openssl-context.c revision e98de01b5644c88b6053e2921eb5e9a506fe263f
/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "safe-memset.h"
#include "iostream-openssl.h"
struct ssl_iostream_password_context {
const char *password;
const char *key_source;
};
static bool ssl_global_initialized = FALSE;
static void ssl_iostream_init_global(void);
const char *ssl_iostream_error(void)
{
unsigned long err;
char *buf;
err = ERR_get_error();
if (err == 0) {
if (errno != 0)
return "Unknown error";
}
return buf;
}
const char *ssl_iostream_key_load_error(void)
{
unsigned long err = ERR_peek_error();
return "Key is for a different cert than ssl_cert";
else
return ssl_iostream_error();
}
{
}
{
struct ssl_iostream *ssl_io;
/* Well, I'm not exactly sure why the logic in here is this.
It's the same as in Postfix, so it can't be too wrong. */
else
}
static int
void *userdata)
{
i_error("%s: SSL private key file is password protected, "
return 0;
}
i_error("%s: SSL private key password is too long",
ctx->key_source);
return 0;
}
}
{
struct ssl_iostream_password_context ctx;
char *key;
return -1;
}
i_error("%s: Couldn't parse private SSL key: %s",
}
}
static int
const struct ssl_iostream_settings *set)
{
int ret = 0;
return -1;
i_error("%s: Can't load SSL private key: %s",
ret = -1;
}
return ret;
}
static bool is_pem_key(const char *cert)
{
}
const char *ssl_iostream_get_use_certificate_error(const char *cert)
{
unsigned long err;
err = ERR_peek_error();
return ssl_iostream_error();
else if (is_pem_key(cert)) {
return "The file contains a private key "
"(you've mixed ssl_cert and ssl_key settings)";
} else {
return "There is no certificate.";
}
}
{
/* mostly just copy&pasted from SSL_CTX_use_certificate_chain_file() */
X509 *x;
int ret = 0;
i_fatal("BIO_new_mem_buf() failed");
if (x == NULL)
goto end;
if (ERR_peek_error() != 0)
ret = 0;
if (ret != 0) {
/* If we could set up our certificate, now proceed to
* the CA certificates.
*/
int r;
unsigned long err;
if (!r) {
ret = 0;
goto end;
}
}
/* When the while loop ends, it's usually just EOF. */
err = ERR_peek_last_error();
else
ret = 0; /* some real error */
}
end:
return ret;
}
{
/* mostly just copy&pasted from X509_load_cert_crl_file() */
int i;
i_fatal("BIO_new_mem_buf() failed");
return -1;
i_fatal("sk_X509_NAME_new_null() failed");
for(i = 0; i < sk_X509_INFO_num(inf); i++) {
}
}
return 0;
}
static int
{
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
#endif
return 0;
}
static struct ssl_iostream_settings *
const struct ssl_iostream_settings *old_set)
{
struct ssl_iostream_settings *new_set;
return new_set;
}
static int
const struct ssl_iostream_settings *set)
{
i_error("%s: Can't set cipher list to '%s': %s",
return -1;
}
}
return -1;
}
/* set trusted CA certs */
if (!set->verify_remote_cert) {
/* no CA */
return -1;
}
return -1;
i_error("%s: Can't load CA certs from directory %s: %s",
return -1;
}
} else {
i_error("%s: Can't verify remote certs without CA",
return -1;
}
i_error("%s: Invalid cert_username_field: %s",
}
}
return 0;
}
static int
const char *source,
const struct ssl_iostream_settings *set)
{
}
int ssl_iostream_context_init_client(const char *source,
const struct ssl_iostream_settings *set,
struct ssl_iostream_context **ctx_r)
{
struct ssl_iostream_context *ctx;
return -1;
}
return -1;
}
return 0;
}
int ssl_iostream_context_init_server(const char *source,
const struct ssl_iostream_settings *set,
struct ssl_iostream_context **ctx_r)
{
struct ssl_iostream_context *ctx;
return -1;
}
return -1;
}
return 0;
}
{
}
static void ssl_iostream_deinit_global(void)
{
EVP_cleanup();
}
static void ssl_iostream_init_global(void)
{
static char dovecot[] = "dovecot";
unsigned char buf;
return;
does it before chrooting. We might not have enough entropy at
the first try, so this function may fail. It's still been
initialized though. */
}