Commit c7a8e720 authored by Guillaume Beraudo's avatar Guillaume Beraudo

Trusted certificate

parent 8eeb9402
......@@ -238,6 +238,17 @@ bool RequestSipEvent::findIncomingSubject(const char *searched) {
return !!tport_subject_search(searched, strlst);
}
const char *RequestSipEvent::findIncomingSubject(const list<string> &in) {
if (in.empty()) return false;
auto strlst = tport_delivered_from_subjects(mIncomingTport.get(), mMsgSip->mOriginalMsg);
for (auto it =in.cbegin(); it != in.cend(); ++it) {
if (tport_subject_search(it->c_str(), strlst)) return it->c_str();
}
return NULL;
}
bool findIncomingSubject(const list<string> &in);
ResponseSipEvent::ResponseSipEvent(shared_ptr<OutgoingAgent> outgoingAgent, const shared_ptr<MsgSip> &msgSip) :
SipEvent(msgSip), mPopVia(false) {
mOutgoingAgent = outgoingAgent;
......
......@@ -20,6 +20,7 @@
#define event_hh
#include <memory>
#include <list>
#include <string>
#include <ostream>
#include <functional>
......@@ -196,6 +197,7 @@ public:
/** Find if incoming tport TLS client certificate contains a given entry */
bool findIncomingSubject(const char *searched);
const char *findIncomingSubject(const std::list<std::string> &in);
bool mRecordRouteAdded;
private:
void linkTransactions();
......
......@@ -194,11 +194,22 @@ private:
bool mImmediateRetrievePassword;
bool mNewAuthOn407;
list<string> mUseClientCertificates;
list< string > mTrustedClientCertificates;
void static flexisip_auth_method_digest(auth_mod_t *am,
auth_status_t *as, msg_auth_t *au, auth_challenger_t const *ach);
void static flexisip_auth_check_digest(auth_mod_t *am,
auth_status_t *as, auth_response_t *ar, auth_challenger_t const *ach);
const char *findIncomingSubjectInTrusted(shared_ptr<RequestSipEvent> &ev, const char* fromDomain) {
if (mTrustedClientCertificates.empty()) return NULL;
list<string> toCheck;
for (auto it = mTrustedClientCertificates.cbegin(); it != mTrustedClientCertificates.cend(); ++it) {
if (it->find("@") != string::npos) toCheck.push_back(*it);
else toCheck.push_back(*it + "@" + string(fromDomain));
}
const char *res=ev->findIncomingSubject(toCheck);
return res;
}
public:
StatCounter64 *mCountAsyncRetrieve;
......@@ -248,6 +259,7 @@ public:
{ StringList , "trusted-hosts" , "List of whitespace separated IP which will not be challenged.", "" },
{ StringList , "client-certificates-domains" , "List of whitespace separated domain names to check using client certificates."
" CN may contain user@domain or alternate name with URI=sip:user@domain", "" },
{ StringList , "trusted-client-certificates" , "List of whitespace separated username or username@domain CN which will trusted. If no domain is given it is computed.", "" },
{ String , "db-implementation" , "Database backend implementation [odbc, file, fixed].", "fixed" },
{ String , "datasource" , "Odbc connection string to use for connecting to database. "
"ex1: DSN=myodbc3; where 'myodbc3' is the datasource name. "
......@@ -309,6 +321,7 @@ public:
mImmediateRetrievePassword = mc->get<ConfigBoolean>("immediate-retrieve-password")->read();
mNewAuthOn407 = mc->get<ConfigBoolean>("new-auth-on-407")->read();
mUseClientCertificates = mc->get<ConfigStringList>("client-certificates-domains")->read();
mTrustedClientCertificates = mc->get<ConfigStringList>("trusted-client-certificates")->read();
}
auth_mod_t *findAuthModule(const char *name) {
......@@ -320,30 +333,13 @@ public:
return it->second;
}
bool containsDomain(const list<string> &d, const char *name) {
static bool containsDomain(const list<string> &d, const char *name) {
return find(d.cbegin(), d.cend(), "*") != d.end() || find(d.cbegin(), d.cend(), name) != d.end();
}
void onRequest(shared_ptr<RequestSipEvent> &ev) {
const shared_ptr<MsgSip> &ms = ev->getMsgSip();
sip_t *sip = ms->getSip();
// Do it first to make sure no transaction is created which
// would send an unappropriate 100 trying response.
if (sip->sip_request->rq_method == sip_method_ack || sip->sip_request->rq_method == sip_method_cancel) {
/*ack and cancel shall never be challenged according to the RFC.*/
return;
}
// Check for the existence of username, reject if absent.
if (sip->sip_from->a_url->url_user==NULL){
LOGI("From has no username, cannot authenticate.");
ev->reply(SIP_488_NOT_ACCEPTABLE,
SIPTAG_SERVER_STR(getAgent()->getServerString()),
TAG_END());
return;
}
bool isTrustedPeer(shared_ptr<RequestSipEvent> &ev) {
sip_t *sip = ev->getSip();
if (sip->sip_request->rq_method == sip_method_register) return false;
// Check for trusted host
sip_via_t *via=sip->sip_via;
......@@ -352,10 +348,10 @@ public:
for (;trustedHostsIt != mTrustedHosts.end(); ++trustedHostsIt) {
if (*trustedHostsIt == receivedHost) {
LOGD("Allowing message from trusted host %s", receivedHost);
return;
return true;
}
}
// Check TLS certificate
const char *fromDomain = sip->sip_from->a_url[0].url_host;
shared_ptr<tport_t> inTport = ev->getIncomingTport();
......@@ -365,6 +361,8 @@ public:
snprintf(searched, sizeof(searched), "sip:%s@%s", from->url_user, fromDomain);
if (ev->findIncomingSubject(searched)) {
SLOGD << "Allowing message from matching TLS certificate";
} else if (const char * res = findIncomingSubjectInTrusted(ev, fromDomain)) {
SLOGD << "Allowing message from trusted TLS certificate " << res;
} else {
SLOGE << "Client certificate do not match " << searched;
ev->reply( SIP_488_NOT_ACCEPTABLE,
......@@ -372,11 +370,39 @@ public:
SIPTAG_SERVER_STR(getAgent()->getServerString()),
TAG_END());
}
return true;
}
return false;
}
void onRequest(shared_ptr<RequestSipEvent> &ev) {
const shared_ptr<MsgSip> &ms = ev->getMsgSip();
sip_t *sip = ms->getSip();
// Do it first to make sure no transaction is created which
// would send an unappropriate 100 trying response.
if (sip->sip_request->rq_method == sip_method_ack || sip->sip_request->rq_method == sip_method_cancel) {
/*ack and cancel shall never be challenged according to the RFC.*/
return;
}
// Check for the existence of username, reject if absent.
if (sip->sip_from->a_url->url_user==NULL){
LOGI("From has no username, cannot authenticate.");
ev->reply(SIP_488_NOT_ACCEPTABLE,
SIPTAG_SERVER_STR(getAgent()->getServerString()),
TAG_END());
return;
}
// Check trusted peer
if (isTrustedPeer(ev)) return;
// Check for auth module for this domain
const char *fromDomain = sip->sip_from->a_url[0].url_host;
auth_mod_t *am=findAuthModule(fromDomain);
if (am==NULL) {
LOGI("Unknown domain [%s]", fromDomain);
......
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