Commit e8225e64 authored by Guillaume Beraudo's avatar Guillaume Beraudo

Basic client certificates API

parent 782cac1b
......@@ -22,6 +22,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
typedef struct belle_sip_certificates_chain_t _SalCertificatesChain;
typedef struct belle_sip_signing_key_t _SalSigningKey;
/*
rfc3323
4.2 Expressing Privacy Preferences
......@@ -367,14 +371,16 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans
}
static void process_auth_requested(void *sal, belle_sip_auth_event_t *auth_event) {
SalAuthInfo* auth_info = sal_auth_info_create(auth_event);
static void process_auth_requested(void *sal, belle_sip_auth_event_t *event) {
SalAuthInfo* auth_info = sal_auth_info_create(event);
((Sal*)sal)->callbacks.auth_requested(sal,auth_info);
belle_sip_auth_event_set_passwd(auth_event,(const char*)auth_info->password);
belle_sip_auth_event_set_ha1(auth_event,(const char*)auth_info->ha1);
belle_sip_auth_event_set_userid(auth_event,(const char*)auth_info->userid);
belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password);
belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1);
belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid);
belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key);
belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates);
sal_auth_info_delete(auth_info);
return;
}
Sal * sal_init(){
......@@ -699,9 +705,21 @@ SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) {
auth_info->realm = ms_strdup(belle_sip_auth_event_get_realm(event));
auth_info->username = ms_strdup(belle_sip_auth_event_get_username(event));
auth_info->domain = ms_strdup(belle_sip_auth_event_get_domain(event));
auth_info->mode = belle_sip_auth_event_get_mode(event);
return auth_info;
}
SalAuthMode sal_auth_info_get_mode(const SalAuthInfo* auth_info) { return auth_info->mode; }
SalSigningKey *sal_auth_info_get_signing_key(const SalAuthInfo* auth_info) { return auth_info->key; }
SalCertificatesChain *sal_auth_info_get_certificates_chain(const SalAuthInfo* auth_info) { return auth_info->certificates; }
void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode) { auth_info->mode = mode; }
void sal_certificates_chain_delete(SalCertificatesChain *chain) {
belle_sip_object_unref((belle_sip_object_t *)chain);
}
void sal_signing_key_delete(SalSigningKey *key) {
belle_sip_object_unref((belle_sip_object_t *)key);
}
const char* sal_op_type_to_string(const SalOpType type) {
switch(type) {
case SalOpRegister: return "SalOpRegister";
......@@ -852,3 +870,23 @@ void sal_resolve_cancel(Sal *sal, SalResolverContext* ctx){
void sal_enable_unconditional_answer(Sal *sal,int value) {
belle_sip_provider_enable_unconditional_answer(sal->prov,value);
}
/** Parse a file containing either a certificate chain order in PEM format or a single DER cert
* @param auth_info structure where to store the result of parsing
* @param path path to certificate chain file
* @param format either PEM or DER
*/
void sal_certificates_chain_parse_file(SalAuthInfo* auth_info, const char* path, SalCertificateRawFormat format) {
auth_info->certificates = (SalCertificatesChain*) belle_sip_certificates_chain_parse_file(path, format); //
if (auth_info->certificates) belle_sip_object_ref((belle_sip_object_t *) auth_info->certificates);
}
/**
* Parse a file containing either a private or public rsa key
* @param auth_info structure where to store the result of parsing
* @param passwd password (optionnal)
*/
void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const char *passwd) {
auth_info->key = (SalSigningKey *) belle_sip_signing_key_parse_file(path, passwd);
if (auth_info->key) belle_sip_object_ref((belle_sip_object_t *) auth_info->key);
}
......@@ -25,6 +25,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/mediastream.h"
#include "lpconfig.h"
// stat
#ifndef WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details);
static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) {
......@@ -901,6 +908,46 @@ static void ping_reply(SalOp *op){
}
}
static const char *get_client_cert_path(LinphoneCore *lc) {
static char cldir[200] = {0};
#ifdef HAVE_GETENV
if (!cldir[0]) {
static char default_path[200] = {0};
snprintf(default_path, sizeof(default_path), "%s%s", getenv("HOME"), "/linphone_certs");
snprintf(cldir, sizeof(cldir), "%s", lp_config_get_string(lc->config,"sip","client_certificates_dir", default_path));
}
#endif
return cldir;
}
static bool_t fill_auth_info_with_client_certificate(LinphoneCore *lc, SalAuthInfo* sai) {
char chain_file[200];
char key_file[200];
const char *path = get_client_cert_path(lc);
snprintf(chain_file, sizeof(chain_file), "%s%s", path, "/chain.pem");
snprintf(key_file, sizeof(key_file), "%s%s", path, "/key.pem");
#ifndef WIN32
{
// optinal check for files
struct stat st;
if (stat(key_file,&st)) {
ms_warning("No client certificate key found in %s", key_file);
return FALSE;
}
if (stat(chain_file,&st)) {
ms_warning("No client certificate chain found in %s", chain_file);
return FALSE;
}
}
#endif
sal_certificates_chain_parse_file(sai, chain_file, SAL_CERTIFICATE_RAW_FORMAT_PEM );
sal_signing_key_parse_file(sai, key_file, "");
return sai->certificates && sai->key;
}
static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) {
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,sai->realm,sai->username,sai->domain);
if (ai) {
......@@ -916,18 +963,25 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) {
}
static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) {
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
if (fill_auth_info(lc,sai)) {
return TRUE;
} else {
if (lc->vtable.auth_info_requested) {
lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain);
if (fill_auth_info(lc,sai)) {
return TRUE;
if (sai->mode == SalAuthModeHttpDigest) {
if (fill_auth_info(lc,sai)) {
return TRUE;
} else {
if (lc->vtable.auth_info_requested) {
lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain);
if (fill_auth_info(lc,sai)) {
return TRUE;
}
}
return FALSE;
}
} else if (sai->mode == SalAuthModeTls) {
return fill_auth_info_with_client_certificate(lc,sai);
} else {
return FALSE;
}
}
static void notify_refer(SalOp *op, SalReferStatus status){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op);
......
......@@ -483,6 +483,8 @@ void sal_auth_info_delete(SalAuthInfo* auth_info) {
if (auth_info->realm) ms_free(auth_info->realm);
if (auth_info->domain) ms_free(auth_info->domain);
if (auth_info->password) ms_free(auth_info->password);
if (auth_info->certificates) sal_certificates_chain_delete(auth_info->certificates);
if (auth_info->key) sal_signing_key_delete(auth_info->key);
ms_free(auth_info);
}
......
......@@ -331,6 +331,29 @@ typedef enum SalTextDeliveryStatus{
SalTextDeliveryFailed
}SalTextDeliveryStatus;
/**
* auth event mode
* */
typedef enum SalAuthMode {
SalAuthModeHttpDigest, /** Digest authentication requested*/
SalAuthModeTls /** Client certificate requested*/
}SalAuthMode;
struct _SalCertificatesChain;
typedef struct _SalCertificatesChain SalCertificatesChain;
struct _SalSigningKey;
typedef struct _SalSigningKey SalSigningKey;
/**
* Format of certificate buffer
* */
typedef enum SalCertificateRawFormat {
SAL_CERTIFICATE_RAW_FORMAT_PEM, /** PEM format*/
SAL_CERTIFICATE_RAW_FORMAT_DER /** ASN.1 raw format*/
}SalCertificateRawFormat;
typedef struct SalAuthInfo{
char *username;
char *userid;
......@@ -338,6 +361,9 @@ typedef struct SalAuthInfo{
char *realm;
char *domain;
char *ha1;
SalAuthMode mode;
SalSigningKey *key;
SalCertificatesChain *certificates;
}SalAuthInfo;
typedef struct SalBody{
......@@ -424,6 +450,29 @@ SalAuthInfo* sal_auth_info_new();
SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info);
void sal_auth_info_delete(SalAuthInfo* auth_info);
LINPHONE_PUBLIC int sal_auth_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]);
SalAuthMode sal_auth_info_get_mode(const SalAuthInfo* auth_info);
SalSigningKey *sal_auth_info_get_signing_key(const SalAuthInfo* auth_info);
SalCertificatesChain *sal_auth_info_get_certificates_chain(const SalAuthInfo* auth_info);
void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode);
/** Parse a file containing either a certificate chain order in PEM format or a single DER cert
* @param auth_info structure where to store the result of parsing
* @param path path to certificate chain file
* @param format either PEM or DER
*/
void sal_certificates_chain_parse_file(SalAuthInfo* auth_info, const char* path, SalCertificateRawFormat format);
/**
* Parse a file containing either a private or public rsa key
* @param auth_info structure where to store the result of parsing
* @param passwd password (optionnal)
*/
void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const char *passwd);
void sal_certificates_chain_delete(SalCertificatesChain *chain);
void sal_signing_key_delete(SalSigningKey *key);
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs);
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment