Fixed registration bug.

git-svn-id: http://yate.null.ro/svn/yate/trunk@1075 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2006-10-14 10:51:52 +00:00
parent 1618048429
commit c87c32f5d0
1 changed files with 96 additions and 52 deletions

View File

@ -230,10 +230,11 @@ public:
* @param transTimeout Timeout (in seconds) on remote request of transactions belonging to this engine
* @param maxFullFrameDataLen Max full frame IE list (buffer) length
* @param trunkSendInterval Send trunk meta frame interval
* @param authRequired Automatically challenge all clients for authentication
*/
YIAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval,
u_int16_t authTimeout, u_int16_t transTimeout,
u_int16_t maxFullFrameDataLen, u_int32_t trunkSendInterval);
u_int16_t maxFullFrameDataLen, u_int32_t trunkSendInterval, bool authRequired);
virtual ~YIAXEngine()
{}
@ -286,8 +287,11 @@ protected:
/*
* Event handler for incoming registration transactions.
* @param event The event.
* @param first True if this is the first request.
* False if it is a response to an authentication request.
*/
void processRemoteReg(IAXEvent* event);
void processRemoteReg(IAXEvent* event,bool first);
/*
* Send Register/Unregister messages to Engine
@ -345,6 +349,15 @@ public:
// @return False if formtas is not 0 and the result is 0 (no intersection)
bool updateCodecsFromRoute(u_int32_t& codecs, const char* formats);
// Dispatch user.auth
// @tr The IAX transaction
// @param response True if it is a response.
// @param requestAuth True on exit: the caller should request authentication
// @param invalidAuth True on exit: authentication response is incorrect
// @return False if not authenticated
bool userAuth(IAXTransaction* tr, bool response, bool& requestAuth,
bool& invalidAuth);
protected:
YIAXEngine* m_iaxEngine;
u_int32_t m_defaultCodec;
@ -785,10 +798,13 @@ void YIAXTrunking::run()
/**
* YIAXEngine
*/
YIAXEngine::YIAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval,
u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, u_int32_t trunkSendInterval)
: IAXEngine(iface,port,transListCount,retransCount,retransInterval,authTimeout,transTimeout,
maxFullFrameDataLen,iplugin.defaultCodec(),iplugin.codecs(),trunkSendInterval),
YIAXEngine::YIAXEngine(const char* iface, int port, u_int16_t transListCount,
u_int16_t retransCount, u_int16_t retransInterval, u_int16_t authTimeout,
u_int16_t transTimeout, u_int16_t maxFullFrameDataLen,
u_int32_t trunkSendInterval, bool authRequired)
: IAXEngine(iface,port,transListCount,retransCount,retransInterval,authTimeout,
transTimeout,maxFullFrameDataLen,iplugin.defaultCodec(),iplugin.codecs(),
trunkSendInterval,authRequired),
m_threadsCreated(false)
{
}
@ -914,8 +930,8 @@ void YIAXEngine::processEvent(IAXEvent* event)
break;
case IAXTransaction::RegReq:
case IAXTransaction::RegRel:
if (event->type() == IAXEvent::New)
processRemoteReg(event);
if (event->type() == IAXEvent::New || event->type() == IAXEvent::AuthRep)
processRemoteReg(event,(event->type() == IAXEvent::New));
else
if (event->getTransaction()->getUserData())
s_lines.handleEvent(event);
@ -926,38 +942,44 @@ void YIAXEngine::processEvent(IAXEvent* event)
}
// Process events for remote users registering to us
void YIAXEngine::processRemoteReg(IAXEvent* event)
void YIAXEngine::processRemoteReg(IAXEvent* event, bool first)
{
IAXTransaction* tr = event->getTransaction();
Debug(this,DebugAll,"processRemoteReg: %s username: '%s'",
tr->type() == IAXTransaction::RegReq?"Register":"Unregister",tr->username().c_str());
Message msg("user.auth");
msg.addParam("username",tr->username());
msg.addParam("ip_host",tr->remoteAddr().host());
msg.addParam("ip_port",String(tr->remoteAddr().port()));
if (!Engine::dispatch(msg)) {
// Not authenticated
Debug(this,DebugAll,"processRemoteReg. Not authenticated. Reject");
tr->sendReject();
// Check for automatomatically authentication request if it's the first request
if (first && iplugin.getEngine()->authRequired()) {
Debug(this,DebugAll,"processRemoteReg. Request authentication");
tr->sendAuth();
return;
}
String password = msg.retValue();
if (password.null()) {
// Authenticated, no password. Try to (un)register
// Authenticated: register/unregister
bool requestAuth = false, invalidAuth = false;
if (iplugin.userAuth(tr,!first,requestAuth,invalidAuth)) {
// Authenticated. Try to (un)register
if (userreg(tr,event->subclass() == IAXControl::RegRel)) {
Debug(this,DebugAll,"processRemoteReg. Authenticated and (un)registered. Ack");
tr->sendAccept();
}
else {
Debug(this,DebugAll,"processRemoteReg. Authenticated but not (un)registered. Reject");
tr->sendReject();
tr->sendReject("not registered");
}
return;
}
// Authenticated, password required
Debug(this,DebugAll,"processRemoteReg. Request authentication");
tr->sendAuth(password);
// First request: check if we should request auth
const char* reason = 0;
if (first && requestAuth) {
Debug(this,DebugAll,"processRemoteReg. Request authentication");
tr->sendAuth();
return;
}
else if (invalidAuth)
reason = IAXTransaction::s_iax_modInvalidAuth;
if (!reason)
reason = "not authenticated";
Debug(this,DebugAll,"processRemoteReg. Not authenticated ('%s'). Reject",reason);
tr->sendReject(reason);
}
// Build and dispatch the user.(un)register message
@ -1044,6 +1066,7 @@ void YIAXDriver::initialize()
// Port and interface
m_port = s_cfg.getIntValue("general","port",4569);
String iface = s_cfg.getValue("general","addr");
bool authReq = s_cfg.getBoolValue("registrar","auth_required",true);
unlock();
setup();
// We need channels to be dropped on shutdown
@ -1060,7 +1083,7 @@ void YIAXDriver::initialize()
if (!m_iaxEngine) {
Engine::install(new YIAXRegDataHandler);
m_iaxEngine = new YIAXEngine(iface,m_port,transListCount,retransCount,retransInterval,authTimeout,
transTimeout,maxFullFrameDataLen,trunkSendInterval);
transTimeout,maxFullFrameDataLen,trunkSendInterval,authReq);
m_iaxEngine->debugChain(this);
int tos = s_cfg.getIntValue("general","tos",dict_tos,0);
if (tos) {
@ -1193,6 +1216,42 @@ bool YIAXDriver::updateCodecsFromRoute(u_int32_t& codecs, const char* formats)
return codecs != 0;
}
bool YIAXDriver::userAuth(IAXTransaction* tr, bool response, bool& requestAuth,
bool& invalidAuth)
{
requestAuth = invalidAuth = false;
// Create and dispatch user.auth
Message msg("user.auth");
msg.addParam("protocol","iax");
msg.addParam("username",tr->username());
msg.addParam("called",tr->calledNo());
msg.addParam("caller",tr->callingNo());
msg.addParam("callername",tr->callingName());
msg.addParam("ip_host",tr->remoteAddr().host());
msg.addParam("ip_port",String(tr->remoteAddr().port()));
if (response) {
msg.addParam("nonce",tr->challenge());
msg.addParam("response",tr->authdata());
}
if (!Engine::dispatch(msg))
return false;
String pwd = msg.retValue();
// We have a password
if (pwd) {
// Not a response: request authentication
if (!response) {
requestAuth = true;
return false;
}
// Check response
if (!IAXEngine::isMD5ChallengeCorrect(tr->authdata(),tr->challenge(),pwd)) {
invalidAuth = true;
return false;
}
}
return true;
}
/**
* IAXConsumer
*/
@ -1293,14 +1352,13 @@ void YIAXConnection::callRejected(const char* error, const char* reason, const M
reason = error;
DDebug(this,DebugInfo,"callRejected [%p]. Error: '%s'",this,error);
String s(error);
m_mutexTrans.lock();
Lock lock(m_mutexTrans);
if (m_transaction && (s == "noauth") && safeRefIncrease()) {
Debug(this,DebugAll,"callRejected [%p]. Requesting authentication",this);
m_transaction->sendAuth(m_password);
m_mutexTrans.unlock();
Debug(this,DebugAll,"callRejected [%p]. Request authentication",this);
m_transaction->sendAuth();
return;
}
m_mutexTrans.unlock();
lock.drop();
hangup(reason,true);
}
@ -1556,29 +1614,15 @@ void YIAXConnection::startAudioOut()
void YIAXConnection::evAuthRep(IAXEvent* event)
{
DDebug(this,DebugAll,"YIAXConnection - AUTHREP");
IAXTransaction* tr = event->getTransaction();
// Try to obtain a password from Engine
Message msg("user.auth");
msg.addParam("username",tr->username());
if (!Engine::dispatch(msg)) {
// NOT Authenticated
hangup(event,"",true);
bool requestAuth, invalidAuth;
if (iplugin.userAuth(event->getTransaction(),true,requestAuth,invalidAuth)) {
// Authenticated. Route the user.
route(true);
return;
}
String pwd = msg.retValue();
if (pwd.null()) {
// Authenticated
tr->sendAccept();
return;
}
if (!IAXEngine::isMD5ChallengeCorrect(tr->authdata(),tr->challenge(),pwd)) {
// Incorrect data received
DDebug(this,DebugAll,"AUTHREP - Incorrect MD5 answer. Reject.");
hangup(event,IAXTransaction::s_iax_modInvalidAuth,true);
return;
}
// Password is correct. Route the user.
route(true);
const char* reason = invalidAuth ? IAXTransaction::s_iax_modInvalidAuth : "not authenticated";
DDebug(this,DebugAll,"Not authenticated. Reason: '%s'. Reject.",reason);
hangup(event,reason,true);
}
// Get rid of the extra reference