Commit 9e88cfe4 authored by Simon Morlat's avatar Simon Morlat

implement a setting in Auth module in order to always send 401 or 407 in case...

implement a setting in Auth module in order to always send 401 or 407 in case of auth failure (no-403)
The property takes in input a boolean expression, so that the behavior can be enabled only for particular types of request.
This is mainly for liblinphone test suite.
parent 28f4ed40
......@@ -402,6 +402,7 @@ void GenericStruct::deprecateChild(const char *name){
void GenericStruct::addChildrenValues(ConfigItemDescriptor *items){
addChildrenValues(items,true);
}
void GenericStruct::addChildrenValues(ConfigItemDescriptor *items, bool hashed){
oid cOid=1;
for (;items->name!=NULL;items++){
......@@ -420,6 +421,9 @@ void GenericStruct::addChildrenValues(ConfigItemDescriptor *items, bool hashed){
case StringList:
val=new ConfigStringList(items->name,items->help,items->default_value,cOid);
break;
case BooleanExpr:
val=new ConfigBooleanExpression(items->name,items->help,items->default_value,cOid);
break;
default:
LOGA("Bad ConfigValue type %u for %s!", items->type, items->name);
break;
......@@ -622,6 +626,14 @@ list<string> ConfigStringList::read()const{
return parse(get().c_str());
}
ConfigBooleanExpression::ConfigBooleanExpression(const string &name, const string &help, const string &default_value,oid oid_index)
: ConfigValue(name,BooleanExpr,help,default_value,oid_index){
}
shared_ptr<BooleanExpression> ConfigBooleanExpression::read()const{
return BooleanExpression::parse(get());
}
GenericManager *GenericManager::sInstance=0;
......
......@@ -54,6 +54,8 @@
typedef unsigned long oid;
#endif
#include "expressionparser.hh"
enum class ConfigState {Check, Changed, Reset, Commited};
class ConfigValue;
class ConfigValueListener {
......@@ -72,6 +74,7 @@ enum GenericValueType{
String,
StringList,
Struct,
BooleanExpr,
Notification,
RuntimeError
};
......@@ -414,6 +417,12 @@ public:
private:
};
class ConfigBooleanExpression : public ConfigValue{
public:
ConfigBooleanExpression(const std::string &name, const std::string &help, const std::string &default_value,oid oid_index);
std::shared_ptr<BooleanExpression> read()const;
};
template <typename _retType>
_retType *GenericStruct::get(const char *name)const{
GenericEntry *e=find(name);
......@@ -423,7 +432,7 @@ _retType *GenericStruct::get(const char *name)const{
}
_retType *ret=dynamic_cast<_retType *>(e);
if (ret==NULL){
LOGA("Config entry %s in struct %s does not have the expected type",name,e->getParent()->getName().c_str());
LOGA("Config entry '%s' in struct '%s' does not have the expected type",name,e->getParent()->getName().c_str());
return NULL;
}
return ret;
......
......@@ -32,7 +32,7 @@ ConfigItemDescriptor config[]={
{ Boolean, "enabled", "Indicate whether the module is activated.", "true"},
{ String, "from-domains", "Deprecated: List of domain names in sip from allowed to enter the module.", "*"},
{ String, "to-domains", "Deprecated: List of domain names in sip to allowed to enter the module.", "*"},
{ String, "filter", "A request/response enters module if the boolean filter evaluates to true. Ex:"
{ BooleanExpr, "filter", "A request/response enters module if the boolean filter evaluates to true. Ex:"
" from.uri.domain contains 'sip.linphone.org', from.uri.domain in 'a.org b.org c.org',"
" (to.uri.domain in 'a.org b.org c.org') && (user-agent == 'Linphone v2')",
""},
......@@ -48,7 +48,8 @@ void ConfigEntryFilter::declareConfig(GenericStruct *module_config){
}
void ConfigEntryFilter::loadConfig(const GenericStruct *mc){
string filter=mc->get<ConfigString>("filter")->read();
string filter=mc->get<ConfigValue>("filter")->get();
if (filter.empty()) {
string fromDomains=mc->get<ConfigString>("from-domains")->read();
if (!fromDomains.empty() && fromDomains != "*") {
......
......@@ -28,6 +28,14 @@ long BooleanExpression::ptr() {
return (long)this;
}
#ifndef NO_SOFIA
bool BooleanExpression::eval ( const sip_t* sip ) {
SipAttributes attr(sip);
return eval(&attr);
}
#endif
class EmptyBooleanExpression : public BooleanExpression {
public:
EmptyBooleanExpression() {}
......@@ -348,7 +356,7 @@ shared_ptr<Variable> buildVariable(const string & expr, size_t *newpos){
return make_shared<Variable>(var);
}
shared_ptr<Constant> buildConstant(const string & expr, size_t *newpos){
static shared_ptr<Constant> buildConstant(const string & expr, size_t *newpos){
LOGPARSE << "buildConstant working on XX" << expr << "XX";
while (expr[*newpos]==' ') *newpos+=1;
......@@ -366,7 +374,7 @@ shared_ptr<Constant> buildConstant(const string & expr, size_t *newpos){
}
}
shared_ptr<VariableOrConstant> buildVariableOrConstant(const string & expr, size_t *newpos){
static shared_ptr<VariableOrConstant> buildVariableOrConstant(const string & expr, size_t *newpos){
LOGPARSE << "buildVariableOrConstant working on XX" << expr << "XX";
while (expr[*newpos]==' ') *newpos+=1;
......@@ -392,7 +400,7 @@ static size_t find_matching_closing_parenthesis(const string &expr, size_t offse
return string::npos;
}
bool isKeyword(const string &expr, size_t *newpos, const string &keyword) {
static bool isKeyword(const string &expr, size_t *newpos, const string &keyword) {
size_t pos=*newpos;
size_t keyLen=keyword.size();
size_t availableLen=expr.size()-pos;
......
......@@ -19,6 +19,10 @@
#ifndef expressionparser_hh
#define expressionparser_hh
#ifndef NO_SOFIA
#include "sofia-sip/sip.h"
#endif
#include <string>
#include <memory>
......@@ -31,6 +35,9 @@ class BooleanExpression{
protected:
BooleanExpression(){};
public:
#ifndef NO_SOFIA
bool eval(const sip_t *sip);
#endif
virtual bool eval(const SipAttributes *args)=0;
virtual ~BooleanExpression(){};
static std::shared_ptr<BooleanExpression> parse(const std::string &str);
......
......@@ -141,6 +141,7 @@ private:
bool mPasswordFound;
public:
bool mImmediateRetrievePass;
bool mNo403;
auth_response_t mAr;
AuthenticationListener(Agent *, shared_ptr<RequestSipEvent>, bool);
virtual ~AuthenticationListener(){};
......@@ -166,6 +167,7 @@ private:
auth_challenger_t mRegistrarChallenger;
auth_challenger_t mProxyChallenger;
auth_scheme_t* mOdbcAuthScheme;
shared_ptr<BooleanExpression> mNo403Expr;
static int authPluginInit(auth_mod_t *am,
auth_scheme_t *base,
su_root_t *root,
......@@ -279,6 +281,7 @@ public:
{ Boolean , "immediate-retrieve-password" , "Retrieve password immediately so that it is cached when an authenticated request arrives.", "true"},
{ Boolean , "hashed-passwords" , "True if retrieved passwords from the database are hashed. HA1=MD5(A1) = MD5(username:realm:pass).", "false" },
{ Boolean , "new-auth-on-407" , "When receiving a proxy authenticate challenge, generate a new challenge for this proxy.", "false" },
{ BooleanExpr, "no-403", "Don't reply 403, but 401 or 407 even in case of wrong authentication.", ""},
config_item_end
};
......@@ -322,6 +325,7 @@ public:
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();
mNo403Expr = mc->get<ConfigBooleanExpression>("no-403")->read();
}
auth_mod_t *findAuthModule(const char *name) {
......@@ -439,6 +443,7 @@ public:
AuthenticationListener *listener = new AuthenticationListener(getAgent(), ev, dbUseHashedPasswords);
listener->mImmediateRetrievePass = mImmediateRetrievePassword;
listener->mNo403= mNo403Expr->eval(ev->getSip());
as->as_magic=listener;
......@@ -502,6 +507,7 @@ ModuleInfo<Authentication> Authentication::sInfo("Authentication",
Authentication::AuthenticationListener::AuthenticationListener(Agent *ag, shared_ptr<RequestSipEvent> ev, bool hashedPasswords):
mAgent(ag),mEv(ev),mAm(NULL),mAs(NULL),mAch(NULL),mHashedPass(hashedPasswords),mPasswordFound(false){
memset(&mAr, '\0', sizeof(mAr)), mAr.ar_size=sizeof(mAr);
mNo403=false;
}
void Authentication::AuthenticationListener::setData(auth_mod_t *am, auth_status_t *as, auth_challenger_t const *ach){
......@@ -577,7 +583,7 @@ void Authentication::AuthenticationListener::checkPassword(const char* passwd) {
if (!passwd || strcmp(response, mAr.ar_response)) {
if (mAm->am_forbidden) {
if (mAm->am_forbidden && !mNo403) {
mAs->as_status = 403, mAs->as_phrase = "Forbidden";
mAs->as_response = NULL;
mAs->as_blacklist = mAm->am_blacklist;
......
......@@ -47,7 +47,7 @@ public:
void onDeclare(GenericStruct *mc) {
mc->get<ConfigBoolean>("enabled")->setDefault("false");
mc->get<ConfigString>("filter")->setDefault("false");
mc->get<ConfigValue>("filter")->setDefault("false");
}
private:
static ModuleInfo<ModuleGarbageIn> sInfo;
......
......@@ -104,7 +104,7 @@ static string callid_get(const string &key, size_t pos, const sip_call_id_s *cal
throw runtime_error("callid_get: unhandled arg '" + id + "' in " + key);
}
static bool is_request(sip_t *sip) {
static bool is_request(const sip_t *sip) {
return sip_is_request((sip_header_t *)sip->sip_request);
}
......
......@@ -31,9 +31,9 @@ public:
#ifdef NO_SOFIA
SipAttributes(std::string &attributes);
#else
SipAttributes(sip_t *sip) : sip(sip){};
SipAttributes(const sip_t *sip) : sip(sip){};
private:
sip_t *sip;
const sip_t *sip;
#endif
public:
~SipAttributes(){};
......
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