Handle SSL-client auth. Fix crash on del_conn when the link never got connected at all.

This commit is contained in:
Arnaud Cornet 2008-01-20 18:49:44 +01:00
parent c90578103c
commit f1cc6451f5
9 changed files with 63 additions and 17 deletions

View File

@ -246,6 +246,12 @@ allows a "ssh-like" private key generation scheme. Note that in basic mode:
\fBssl_check_store\fP (default: \fBnot set\fP)
This repository is browsed by BIP when a SSL certificate or CA check is needed.
.TP
\fBssl_client_certfile\fP (default: \fBnot set\fP)
Some networks (OFTC at least) allow you to authenticate to nickserv services
using a client side certificate. Make this variable point to the .pem file to
use this feature.
.SH CONNECTION SUB-SECTION
Each connection section associates a user to the networks he wants to connect

View File

@ -85,8 +85,9 @@ user {
# bipmkpw
password = "3880f2b39b3b9cb507b052b695d2680859bfc327";
# Set this to true if you want "bip4ever" to have admin privileges on bip
# He'll be able to RELOAD bip and see all users' configuration (except pass)
# Set this to true if you want "bip4ever" to have admin privileges on
# bip He'll be able to RELOAD bip and see all users' configuration
# (except pass)
admin = true;
# When bip_use_notice is true, bip will send internal messages like
@ -114,6 +115,12 @@ user {
# `c_rehash .' in it
ssl_check_store = "/home/bip4ever/.bip/trustedcerts.txt";
# Some networks (OFTC at least) allow you to authenticate to nickserv
# using client side certificates, see
# http://www.oftc.net/oftc/NickServ/CertFP
# This is where you put your user's certificate.
# ssl_client_certfile = "/home/bip4ever/.bip/bip4ever_client_auth.pem";
# These will be the default for each connections
default_nick = "bip4ever";
default_user = "bip4ever";

View File

@ -684,6 +684,7 @@ static int add_user(bip_t *bip, list_t *data, struct historical_directives *hds)
FREE(u->default_realname);
#ifdef HAVE_LIBSSL
FREE(u->ssl_check_store);
FREE(u->ssl_client_certfile);
#endif
}
@ -753,7 +754,11 @@ static int add_user(bip_t *bip, list_t *data, struct historical_directives *hds)
case LEX_SSL_CHECK_STORE:
MOVE_STRING(u->ssl_check_store, t->pdata);
break;
case LEX_SSL_CLIENT_CERTFILE:
MOVE_STRING(u->ssl_client_certfile, t->pdata);
break;
#else
case LEX_SSL_CLIENT_CERTFILE:
case LEX_SSL_CHECK_MODE:
case LEX_SSL_CHECK_STORE:
mylog(LOG_WARN, "Found SSL option whereas bip is "
@ -878,6 +883,7 @@ void user_kill(bip_t *bip, struct user *user)
#ifdef HAVE_LIBSSL
MAYFREE(user->ssl_check_store);
MAYFREE(user->ssl_client_certfile);
#endif
free(user);
}
@ -1522,6 +1528,9 @@ noroom:
bip_notify(ic, "SSL check mode '%s', stored into '%s'",
checkmode2text(u->ssl_check_mode),
STRORNULL(u->ssl_check_store));
if (u->ssl_client_certfile)
bip_notify(ic, "SSL client certificate stored into '%s'",
u->ssl_client_certfile);
#endif
bip_notify(ic, "Defaults nick: %s, user: %s, realname: %s",
STRORNULL(u->default_nick), STRORNULL(u->default_username),

View File

@ -68,7 +68,7 @@ struct tuple *tuple_l_new(int type, void *p)
%}
%token LEX_IP LEX_EQ LEX_PORT LEX_CSS LEX_SEMICOLON LEX_CONNECTION LEX_NETWORK LEX_LBRA LEX_RBRA LEX_USER LEX_NAME LEX_NICK LEX_SERVER LEX_PASSWORD LEX_SRCIP LEX_HOST LEX_VHOST LEX_SOURCE_PORT LEX_NONE LEX_COMMENT LEX_BUNCH LEX_REALNAME LEX_SSL LEX_SSL_CHECK_MODE LEX_SSL_CHECK_STORE LEX_CHANNEL LEX_KEY LEX_LOG_ROOT LEX_LOG_FORMAT LEX_LOG_LEVEL LEX_BACKLOG_LINES LEX_BACKLOG_NO_TIMESTAMP LEX_BACKLOG LEX_LOG LEX_LOG_SYSTEM LEX_LOG_SYNC_INTERVAL LEX_FOLLOW_NICK LEX_ON_CONNECT_SEND LEX_AWAY_NICK LEX_PID_FILE LEX_IGN_FIRST_NICK LEX_ALWAYS_BACKLOG LEX_BLRESET_ON_TALK LEX_DEFAULT_USER LEX_DEFAULT_NICK LEX_DEFAULT_REALNAME LEX_NO_CLIENT_AWAY_MSG LEX_BL_MSG_ONLY LEX_ADMIN LEX_BIP_USE_NOTICE LEX_CSS_PEM
%token LEX_IP LEX_EQ LEX_PORT LEX_CSS LEX_SEMICOLON LEX_CONNECTION LEX_NETWORK LEX_LBRA LEX_RBRA LEX_USER LEX_NAME LEX_NICK LEX_SERVER LEX_PASSWORD LEX_SRCIP LEX_HOST LEX_VHOST LEX_SOURCE_PORT LEX_NONE LEX_COMMENT LEX_BUNCH LEX_REALNAME LEX_SSL LEX_SSL_CHECK_MODE LEX_SSL_CHECK_STORE LEX_SSL_CLIENT_CERTFILE LEX_CHANNEL LEX_KEY LEX_LOG_ROOT LEX_LOG_FORMAT LEX_LOG_LEVEL LEX_BACKLOG_LINES LEX_BACKLOG_NO_TIMESTAMP LEX_BACKLOG LEX_LOG LEX_LOG_SYSTEM LEX_LOG_SYNC_INTERVAL LEX_FOLLOW_NICK LEX_ON_CONNECT_SEND LEX_AWAY_NICK LEX_PID_FILE LEX_IGN_FIRST_NICK LEX_ALWAYS_BACKLOG LEX_BLRESET_ON_TALK LEX_DEFAULT_USER LEX_DEFAULT_NICK LEX_DEFAULT_REALNAME LEX_NO_CLIENT_AWAY_MSG LEX_BL_MSG_ONLY LEX_ADMIN LEX_BIP_USE_NOTICE LEX_CSS_PEM
%union {
int number;
@ -150,6 +150,8 @@ usr_command:
LEX_SSL_CHECK_MODE, $3); }
| LEX_SSL_CHECK_STORE LEX_EQ LEX_STRING { $$ = tuple_s_new(
LEX_SSL_CHECK_STORE, $3); }
| LEX_SSL_CLIENT_CERTFILE LEX_EQ LEX_STRING { $$ = tuple_s_new(
LEX_SSL_CLIENT_CERTFILE, $3); }
| LEX_DEFAULT_USER LEX_EQ LEX_STRING {
$$ = tuple_s_new(LEX_DEFAULT_USER, $3); }
| LEX_DEFAULT_NICK LEX_EQ LEX_STRING {

View File

@ -1057,6 +1057,14 @@ connection_t *accept_new(connection_t *cn)
connection_free(conn);
return NULL;
}
if (!SSL_CTX_use_certificate_chain_file(sslctx,
conf_ssl_certfile))
mylog(LOG_WARN, "SSL: Unable to load "
"certificate file");
if (!SSL_CTX_use_PrivateKey_file(sslctx,
conf_ssl_certfile,
SSL_FILETYPE_PEM))
mylog(LOG_WARN, "SSL: Unable to load key file");
}
conn->ssl_h = SSL_new(sslctx);
@ -1154,14 +1162,8 @@ prng_end:
/* allocated by function */
ctx = SSL_CTX_new(SSLv23_method());
if (!SSL_CTX_use_certificate_chain_file(ctx,conf_ssl_certfile))
mylog(LOG_WARN, "SSL: Unable to load certificate file");
if (!SSL_CTX_use_PrivateKey_file(ctx, conf_ssl_certfile,
SSL_FILETYPE_PEM))
mylog(LOG_WARN, "SSL: Unable to load key file");
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
SSL_CTX_set_timeout(ctx,(long)60);
SSL_CTX_set_timeout(ctx, (long)60);
SSL_CTX_set_options(ctx, SSL_OP_ALL);
return ctx;
@ -1321,7 +1323,7 @@ static int SSLize(connection_t *cn, int *nc)
static connection_t *_connection_new_SSL(char *dsthostname, char *dstport,
char *srchostname, char *srcport, int check_mode,
char *check_store, int timeout)
char *check_store, char *ssl_client_certfile, int timeout)
{
connection_t *conn;
@ -1330,6 +1332,7 @@ static connection_t *_connection_new_SSL(char *dsthostname, char *dstport,
mylog(LOG_ERROR, "SSL context initialization failed");
return conn;
}
conn->cert = NULL;
conn->ssl_check_mode = check_mode;
@ -1368,6 +1371,18 @@ static connection_t *_connection_new_SSL(char *dsthostname, char *dstport,
fatal("Unknown SSL cert check mode.");
}
if (ssl_client_certfile) {
if (!SSL_CTX_use_certificate_chain_file(conn->ssl_ctx_h,
ssl_client_certfile))
mylog(LOG_WARN, "SSL: Unable to load certificate file");
else if (!SSL_CTX_use_PrivateKey_file(conn->ssl_ctx_h,
ssl_client_certfile, SSL_FILETYPE_PEM))
mylog(LOG_WARN, "SSL: Unable to load key file");
else
mylog(LOG_INFO, "SSL: using %s pem file as client SSL "
"certificate", ssl_client_certfile);
}
conn->ssl_h = SSL_new(conn->ssl_ctx_h);
if (conn->ssl_h == NULL) {
mylog(LOG_ERROR, "Unable to allocate SSL structures");
@ -1392,7 +1407,7 @@ static connection_t *_connection_new_SSL(char *dsthostname, char *dstport,
connection_t *connection_new(char *dsthostname, int dstport, char *srchostname,
int srcport, int ssl, int ssl_check_mode, char *ssl_check_store,
int timeout)
char *ssl_client_certfile, int timeout)
{
char dstportbuf[20], srcportbuf[20], *tmp;
#ifndef HAVE_LIBSSL
@ -1412,7 +1427,8 @@ connection_t *connection_new(char *dsthostname, int dstport, char *srchostname,
#ifdef HAVE_LIBSSL
if (ssl)
return _connection_new_SSL(dsthostname, dstportbuf, srchostname,
tmp, ssl_check_mode, ssl_check_store, timeout);
tmp, ssl_check_mode, ssl_check_store,
ssl_client_certfile, timeout);
else
#endif
return _connection_new(dsthostname, dstportbuf, srchostname,

View File

@ -92,7 +92,7 @@ typedef struct connection {
connection_t *connection_new(char *dsthostname, int dstport, char *srchostname,
int srcport, int ssl, int ssl_check_mode,
char *ssl_check_store,int timeout);
char *ssl_check_store, char *ssl_client_certfile, int timeout);
connection_t *listen_new(char *hostname, int port, int ssl);
connection_t *accept_new(connection_t *cn);
void connection_free(connection_t *cn);

View File

@ -2053,6 +2053,7 @@ connection_t *irc_server_connect(struct link *link)
#ifdef HAVE_LIBSSL
link->network->ssl, link->ssl_check_mode,
link->user->ssl_check_store,
link->user->ssl_client_certfile,
#else
0, 0, NULL,
#endif
@ -2470,9 +2471,12 @@ struct link *irc_link_new()
void link_kill(bip_t *bip, struct link *link)
{
list_remove(&bip->conn_list, CONN(link->l_server));
server_cleanup(link->l_server);
irc_server_free(link->l_server);
/* in case in never got connected */
if (link->l_server) {
list_remove(&bip->conn_list, CONN(link->l_server));
server_cleanup(link->l_server);
irc_server_free(link->l_server);
}
while (link->l_clientc) {
struct link_client *lc = link->l_clientv[0];
if (lc == bip->reloading_client)

View File

@ -88,6 +88,7 @@ struct user {
#ifdef HAVE_LIBSSL
int ssl_check_mode;
char *ssl_check_store;
char *ssl_client_certfile;
#endif
hash_t connections;

View File

@ -87,6 +87,7 @@ list_t *parse_conf(FILE *file, int *err)
"ssl" { return LEX_SSL; }
"ssl_check_mode" { return LEX_SSL_CHECK_MODE; }
"ssl_check_store" { return LEX_SSL_CHECK_STORE; }
"ssl_client_certfile" { return LEX_SSL_CLIENT_CERTFILE; }
"key" { return LEX_KEY; }
"channel" { return LEX_CHANNEL; }
"log_level" { return LEX_LOG_LEVEL; }