mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-02-04 04:19:35 +00:00
Basic client certificates API
This commit is contained in:
parent
782cac1b9e
commit
e8225e64b9
4 changed files with 156 additions and 13 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue