/* * sqlauth.cxx * * SQL authentication/authorization modules for GNU Gatekeeper * * $Id: sqlauth.cxx,v 1.10 2006/04/14 13:56:19 willamowius Exp $ * * Copyright (c) 2004, Michal Zygmuntowicz * * This work is published under the GNU Public License (GPL) * see file COPYING for details. * We also explicitely grant the right to link this code * with the OpenH323 library. */ #if defined(_WIN32) && (_MSC_VER <= 1200) #pragma warning(disable:4786) // warning about too long debug symbol off #pragma warning(disable:4284) #endif #include #include #include #include #include #include "gk_const.h" #include "h323util.h" #include "stl_supp.h" #include "RasTbl.h" #include "RasPDU.h" #include "Routing.h" #include "Toolkit.h" #include "RasSrv.h" #include "gksql.h" #include "sigmsg.h" #include "h323util.h" #include "Neighbor.h" #include "gkauth.h" using Routing::Route; /// Generic SQL authenticator for H.235 enabled endpoints class SQLPasswordAuth : public SimplePasswordAuth { public: /// build authenticator reading settings from the config SQLPasswordAuth( /// name for this authenticator and for the config section to read settings from const char* authName ); virtual ~SQLPasswordAuth(); protected: /** Override from SimplePasswordAuth. @return True if the password has been found for the given alias. */ virtual bool GetPassword( /// alias to check the password for const PString& alias, /// password string, if the match is found PString& password ); private: SQLPasswordAuth(); SQLPasswordAuth(const SQLPasswordAuth&); SQLPasswordAuth& operator=(const SQLPasswordAuth&); protected: /// connection to the SQL database GkSQLConnection* m_sqlConn; /// parametrized query string for password retrieval PString m_query; }; /// Generic SQL authenticator for alias/IP based authentication class SQLAliasAuth : public AliasAuth { public: /// build authenticator reading settings from the config SQLAliasAuth( /// name for this authenticator and for the config section to read settings from const char* authName ); virtual ~SQLAliasAuth(); protected: /** Get auth condition string for the given alias. This implementation searches the SQL database for the string. Override from AliasAuth. @return The AliasAuth condition string for the given alias. */ virtual bool GetAuthConditionString( /// an alias the condition string is to be retrieved for const PString& alias, /// filled with auth condition string that has been found PString& authCond ); private: SQLAliasAuth(); SQLAliasAuth(const SQLAliasAuth&); SQLAliasAuth& operator=(const SQLAliasAuth&); protected: /// connection to the SQL database GkSQLConnection* m_sqlConn; /// parametrized query string for the auth condition string retrieval PString m_query; }; /// Generic SQL authenticator for non-password, SQL based authentication class SQLAuth : public GkAuthenticator { public: enum SupportedChecks { SQLAuthRasChecks = RasInfo::flag | RasInfo::flag | RasInfo::flag, SQLAuthMiscChecks = e_Setup | e_SetupUnreg }; /// build authenticator reading settings from the config SQLAuth( /// name for this authenticator and for the config section to read settings from const char* authName, /// RAS check events supported by this module unsigned supportedRasChecks = SQLAuthRasChecks, /// Misc check events supported by this module unsigned supportedMiscChecks = SQLAuthMiscChecks ); virtual ~SQLAuth(); /** Authenticate using data from RRQ RAS message. @return: #GkAuthenticator::Status enum# with the result of authentication. */ virtual int Check( /// RRQ RAS message to be authenticated RasPDU& rrqPdu, /// authorization data (reject reason, ...) RRQAuthData& authData ); /** Authenticate using data from ARQ RAS message. @return: #GkAuthenticator::Status enum# with the result of authentication. */ virtual int Check( /// ARQ nessage to be authenticated RasPDU & arqPdu, /// authorization data (call duration limit, reject reason, ...) ARQAuthData& authData ); /** Authenticate using data from LRQ RAS message. @return: #GkAuthenticator::Status enum# with the result of authentication. */ virtual int Check( RasPDU& req, unsigned& rejectReason ); /** Authenticate using data from Q.931 Setup message. @return: #GkAuthenticator::Status enum# with the result of authentication. */ virtual int Check( /// Q.931/H.225 Setup message to be authenticated SetupMsg &setup, /// authorization data (call duration limit, reject reason, ...) SetupAuthData& authData ); private: SQLAuth(); SQLAuth(const SQLAuth&); SQLAuth& operator=(const SQLAuth&); protected: /// connection to the SQL database GkSQLConnection* m_sqlConn; /// parametrized query string for RRQ auth PString m_regQuery; /// parametrized query string for LRQ auth PString m_nbQuery; /// parametrized query string for ARQ/Setup auth PString m_callQuery; }; namespace { /// a common wrapper for SELECT query execution and result retrieval bool RunQuery( const PString &traceStr, GkSQLConnection *conn, const PString &query, const std::map& params, GkSQLResult::ResultRow& resultRow, long timeout ) { resultRow.clear(); if (conn == NULL) { PTRACE(2, traceStr << ": query failed - SQL connection not active"); return false; } if (query.IsEmpty()) { PTRACE(2, traceStr << ": query failed - query string not configured"); return false; } GkSQLResult* result = conn->ExecuteQuery(query, params, timeout); if (result == NULL) { PTRACE(2, traceStr << ": query failed - timeout or fatal error"); return false; } if (!result->IsValid()) { PTRACE(2, traceStr << ": query failed (" << result->GetErrorCode() << ") - " << result->GetErrorMessage() ); delete result; return false; } if (result->GetNumRows() < 1) PTRACE(3, traceStr << ": query returned no rows"); else if (result->GetNumFields() < 1) PTRACE(2, traceStr << ": bad-formed query - " "no columns found in the result set" ); else if (!result->FetchRow(resultRow) || resultRow.empty()) PTRACE(2, traceStr << ": query failed - could not fetch the result row"); else { delete result; return true; } delete result; return false; } inline GkSQLResult::ResultRow::iterator FindField( GkSQLResult::ResultRow& result, const PString& fieldName ) { GkSQLResult::ResultRow::iterator i = result.begin(); while (i != result.end() && i->second != fieldName) i++; return i; } } /* namespace */ SQLPasswordAuth::SQLPasswordAuth( const char* authName ) : SimplePasswordAuth(authName), m_sqlConn(NULL) { PConfig* cfg = GetConfig(); const PString driverName = cfg->GetString(authName, "Driver", ""); if (driverName.IsEmpty()) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "no SQL driver selected" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } m_sqlConn = GkSQLConnection::Create(driverName, authName); if (m_sqlConn == NULL) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "could not find " << driverName << " database driver" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } SetCacheTimeout(cfg->GetInteger(authName, "CacheTimeout", 0)); m_query = cfg->GetString(authName, "Query", ""); if (m_query.IsEmpty()) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "no query configured" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } else PTRACE(4, "SQLAUTH\t" << GetName() << " query: " << m_query); if (!m_sqlConn->Initialize(cfg, authName)) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "could not connect to the database" ); return; } } SQLPasswordAuth::~SQLPasswordAuth() { delete m_sqlConn; } bool SQLPasswordAuth::GetPassword( const PString& alias, PString& password ) { GkSQLResult::ResultRow result; std::map params; params["1"] = alias; params["u"] = alias; params["2"] = Toolkit::GKName(); params["g"] = Toolkit::GKName(); if (!RunQuery("SQLAUTH\t" + GetName() + "('" + alias + "')", m_sqlConn, m_query, params, result, -1)) return false; password = result[0].first; return true; } SQLAliasAuth::SQLAliasAuth( const char* authName ) : AliasAuth(authName), m_sqlConn(NULL) { PConfig* cfg = GetConfig(); const PString driverName = cfg->GetString(authName, "Driver", ""); if (driverName.IsEmpty()) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "no SQL driver selected" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } m_sqlConn = GkSQLConnection::Create(driverName, authName); if (m_sqlConn == NULL) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "could not find " << driverName << " database driver" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } SetCacheTimeout(cfg->GetInteger(authName, "CacheTimeout", 0)); m_query = cfg->GetString(authName, "Query", ""); if (m_query.IsEmpty()) { PTRACE(1, "SQLAUTH\t" << GetName() << " module creation failed: " "no query configured" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } else PTRACE(4, "SQLAUTH\t" << GetName() << " query: " << m_query); if (!m_sqlConn->Initialize(cfg, authName)) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "could not connect to the database" ); return; } } SQLAliasAuth::~SQLAliasAuth() { delete m_sqlConn; } bool SQLAliasAuth::GetAuthConditionString( const PString& alias, PString& authCond ) { GkSQLResult::ResultRow result; std::map params; params["1"] = alias; params["u"] = alias; params["2"] = Toolkit::GKName(); params["g"] = Toolkit::GKName(); if (!RunQuery("SQLAUTH\t" + GetName() + "('" + alias + "')", m_sqlConn, m_query, params, result, -1)) return false; authCond = result[0].first; return true; } SQLAuth::SQLAuth( const char* authName, unsigned supportedRasChecks, unsigned supportedMiscChecks ) : GkAuthenticator(authName, supportedRasChecks, supportedMiscChecks), m_sqlConn(NULL) { PConfig* cfg = GetConfig(); const PString driverName = cfg->GetString(authName, "Driver", ""); if (driverName.IsEmpty()) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "no SQL driver selected" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } m_sqlConn = GkSQLConnection::Create(driverName, authName); if (m_sqlConn == NULL) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "could not find " << driverName << " database driver" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } m_regQuery = cfg->GetString(authName, "RegQuery", ""); if (m_regQuery.IsEmpty() && IsRasCheckEnabled(RasInfo::flag)) { PTRACE(1, "SQLAUTH\t" << GetName() << " module creation failed: " "no RRQ query configured" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } else if (!m_regQuery) PTRACE(4, "SQLAUTH\t" << GetName() << " RRQ query: " << m_regQuery); m_nbQuery = cfg->GetString(authName, "NbQuery", ""); if (m_nbQuery.IsEmpty() && IsRasCheckEnabled(RasInfo::flag)) { PTRACE(1, "SQLAUTH\t" << GetName() << " module creation failed: " "no LRQ query configured" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } else if (!m_nbQuery) PTRACE(4, "SQLAUTH\t" << GetName() << " LRQ query: " << m_nbQuery); m_callQuery = cfg->GetString(authName, "CallQuery", ""); if (m_callQuery.IsEmpty() && (IsRasCheckEnabled(RasInfo::flag) || IsMiscCheckEnabled(e_Setup) || IsMiscCheckEnabled(e_SetupUnreg))) { PTRACE(1, "SQLAUTH\t" << GetName() << " module creation failed: " "no ARQ/Setup query configured" ); PTRACE(0, "SQLAUTH\tFATAL: Shutting down"); RasServer::Instance()->Stop(); return; } else if (!m_callQuery) PTRACE(4, "SQLAUTH\t" << GetName() << " ARQ/Setup query: " << m_callQuery); if (!m_sqlConn->Initialize(cfg, authName)) { PTRACE(0, "SQLAUTH\t" << GetName() << " module creation failed: " "could not connect to the database" ); return; } } SQLAuth::~SQLAuth() { delete m_sqlConn; } int SQLAuth::Check( /// RRQ RAS message to be authenticated RasPDU& rrqPdu, /// authorization data (reject reason, ...) RRQAuthData& authData ) { H225_RegistrationRequest &rrq = rrqPdu; std::map params; // get the username for User-Name attribute params["u"] = GetUsername(rrqPdu); params["g"] = Toolkit::GKName(); PIPSocket::Address addr = (rrqPdu.operator->())->m_peerAddr; const PString traceStr = "SQLAUTH\t" + GetName() + "(RRQ from " + addr.AsString() + " Username=" + params["u"] + ")"; params["callerip"] = addr.AsString(); addr = (rrqPdu.operator->())->m_localAddr; params["gkip"] = addr.AsString(); if (rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias)) { PString aliasList; for (PINDEX i = 0; i < rrq.m_terminalAlias.GetSize(); i++) { if(i > 0) aliasList += ","; aliasList += AsString(rrq.m_terminalAlias[i], FALSE); } params["aliases"] = aliasList; } GkSQLResult::ResultRow result; if (!RunQuery(traceStr, m_sqlConn, m_regQuery, params, result, -1)) { authData.m_rejectReason = H225_RegistrationRejectReason::e_resourceUnavailable; return GetDefaultStatus(); } if (!Toolkit::AsBool(result[0].first)) { authData.m_rejectReason = H225_RegistrationRejectReason::e_securityDenial; return e_fail; } GkSQLResult::ResultRow::const_iterator iter = FindField(result, "billingmode"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { if (strspn((const char*)s,"0123456789.") == (size_t)s.GetLength()) { const int intVal = s.AsInteger(); if (intVal == 0) authData.m_billingMode = H225_CallCreditServiceControl_billingMode::e_credit; else if (intVal == 1 || intVal == 2) authData.m_billingMode = H225_CallCreditServiceControl_billingMode::e_debit; } else { PTRACE(3, traceStr << " - invalid billingmode attribute '" << s << '\'' ); } } } iter = FindField(result, "creditamount"); if (iter != result.end()) { if (!iter->first) authData.m_amountString = iter->first; } iter = FindField(result, "aliases"); if (iter != result.end()) { PStringArray aliases = iter->first.Tokenise(","); if (aliases.GetSize() > 0 && rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias)) { PINDEX i = 0; while (i < rrq.m_terminalAlias.GetSize()) { PINDEX j = aliases.GetStringsIndex(AsString(rrq.m_terminalAlias[i], FALSE)); if( j == P_MAX_INDEX ) rrq.m_terminalAlias.RemoveAt(i); else { i++; aliases.RemoveAt(j); } } } for (PINDEX i = 0; i < aliases.GetSize(); i++) { if (rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias)) rrq.m_terminalAlias.SetSize(rrq.m_terminalAlias.GetSize()+1); else { rrq.IncludeOptionalField(H225_RegistrationRequest::e_terminalAlias); rrq.m_terminalAlias.SetSize(1); } H323SetAliasAddress(aliases[i], rrq.m_terminalAlias[rrq.m_terminalAlias.GetSize()-1]); } } return e_ok; } int SQLAuth::Check( /// ARQ nessage to be authenticated RasPDU & arqPdu, /// authorization data (call duration limit, reject reason, ...) ARQAuthData& authData ) { const H225_AdmissionRequest &arq = arqPdu; std::map params; PIPSocket::Address addr = (arqPdu.operator->())->m_peerAddr; const PString traceStr = "SQLAUTH\t" + GetName() + "(ARQ from " + addr.AsString() + " CRV=" + PString(arq.m_callReferenceValue.GetValue() & 0x7fff) + ")"; params["callerip"] = addr.AsString(); // get the username for User-Name attribute params["u"] = GetUsername(arqPdu, authData); params["g"] = Toolkit::GKName(); addr = (arqPdu.operator->())->m_localAddr; params["gkip"] = addr.AsString(); params["Calling-Station-Id"] = GetCallingStationId(arqPdu, authData); params["Called-Station-Id"] = GetCalledStationId(arqPdu, authData); params["Dialed-Number"] = GetDialedNumber(arqPdu, authData); params["bandwidth"] = PString(arq.m_bandWidth.GetValue()); params["answer"] = arq.m_answerCall ? "1" : "0"; params["arq"] = "1"; GkSQLResult::ResultRow result; if (!RunQuery(traceStr, m_sqlConn, m_callQuery, params, result, -1)) { authData.m_rejectReason = H225_AdmissionRejectReason::e_resourceUnavailable; return GetDefaultStatus(); } if (!Toolkit::AsBool(result[0].first)) { authData.m_rejectReason = H225_AdmissionRejectReason::e_securityDenial; return e_fail; } GkSQLResult::ResultRow::const_iterator iter = FindField(result, "billingmode"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { if (strspn((const char*)s,"0123456789.") == (size_t)s.GetLength()) { const int intVal = s.AsInteger(); if (intVal == 0) authData.m_billingMode = H225_CallCreditServiceControl_billingMode::e_credit; else if (intVal == 1 || intVal == 2) authData.m_billingMode = H225_CallCreditServiceControl_billingMode::e_debit; } else { PTRACE(3, traceStr << " - invalid billingmode attribute '" << s << '\'' ); } } } iter = FindField(result, "creditamount"); if (iter != result.end()) { if (!iter->first) authData.m_amountString = iter->first; } iter = FindField(result, "credittime"); if (iter != result.end()) { const PString &s = iter->first; if (s.GetLength() > 0 && strspn((const char*)s, "0123456789") == (size_t)s.GetLength()) { PUInt64 limit = s.AsUnsigned64(); if (limit > PUInt64(std::numeric_limits::max())) authData.m_callDurationLimit = std::numeric_limits::max(); else authData.m_callDurationLimit = static_cast(limit); PTRACE(5, traceStr << " - duration limit set to " << authData.m_callDurationLimit ); if (authData.m_callDurationLimit == 0) { authData.m_rejectReason = H225_AdmissionRejectReason::e_securityDenial; return e_fail; } } } iter = FindField(result, "redirectnumber"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { authData.SetRouteToAlias(s); PTRACE(5, traceStr << " - call redirected to the number " << s); } } iter = FindField(result, "redirectip"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { PStringArray tokens(s.Tokenise("; \t", FALSE)); for (PINDEX i = 0; i < tokens.GetSize(); ++i) { PIPSocket::Address addr; WORD port = 0; if (GetTransportAddress(tokens[i], GK_DEF_ENDPOINT_SIGNAL_PORT, addr, port) && addr.IsValid() && port != 0) { Route route("SQL", addr, port); route.m_destEndpoint = RegistrationTable::Instance()->FindBySignalAdr( SocketToH225TransportAddr(addr, port) ); authData.m_destinationRoutes.push_back(route); PTRACE(5, traceStr << " - call redirected to the address " << route.AsString() ); } } } } iter = FindField(result, "proxy"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { authData.m_proxyMode = Toolkit::AsBool(s) ? CallRec::ProxyEnabled : CallRec::ProxyDisabled; PTRACE(5, traceStr << " - proxy mode " << (authData.m_proxyMode == CallRec::ProxyEnabled ? "enabled" : "disabled") ); } } return e_ok; } int SQLAuth::Check( RasPDU& lrqPdu, unsigned& rejectReason ) { H225_LocationRequest &lrq = lrqPdu; std::map params; PIPSocket::Address addr = (lrqPdu.operator->())->m_peerAddr; const PString traceStr = "SQLAUTH\t" + GetName() + "(LRQ from " + addr.AsString() + ")"; params["nbip"] = addr.AsString(); params["nbid"] = RasServer::Instance()->GetNeighbors()->GetNeighborIdBySigAdr(addr); params["g"] = Toolkit::GKName(); addr = (lrqPdu.operator->())->m_localAddr; params["gkip"] = addr.AsString(); if (lrq.HasOptionalField(H225_LocationRequest::e_sourceInfo)) { params["Calling-Station-Id"] = GetBestAliasAddressString(lrq.m_sourceInfo, false, AliasAddressTagMask(H225_AliasAddress::e_dialedDigits) | AliasAddressTagMask(H225_AliasAddress::e_partyNumber) ); params["src-info"] = AsString(lrq.m_sourceInfo); } params["Called-Station-Id"] = GetBestAliasAddressString(lrq.m_destinationInfo, false, AliasAddressTagMask(H225_AliasAddress::e_dialedDigits) | AliasAddressTagMask(H225_AliasAddress::e_partyNumber) ); params["dest-info"] = AsString(lrq.m_destinationInfo); if (lrq.HasOptionalField(H225_LocationRequest::e_bandWidth)) params["bandwidth"] = PString(lrq.m_bandWidth.GetValue()); GkSQLResult::ResultRow result; if (!RunQuery(traceStr, m_sqlConn, m_nbQuery, params, result, -1)) { rejectReason = H225_LocationRejectReason::e_resourceUnavailable; return GetDefaultStatus(); } if (!Toolkit::AsBool(result[0].first)) { rejectReason = H225_LocationRejectReason::e_securityDenial; return e_fail; } GkSQLResult::ResultRow::const_iterator iter = FindField(result, "destination"); if (iter != result.end()) { PStringArray aliases = iter->first.Tokenise(","); if (aliases.GetSize() > 0) { PINDEX i = 0; while (i < lrq.m_destinationInfo.GetSize()) { PINDEX j = aliases.GetStringsIndex(AsString(lrq.m_destinationInfo[i], FALSE)); if( j == P_MAX_INDEX ) lrq.m_destinationInfo.RemoveAt(i); else { i++; aliases.RemoveAt(j); } } } for (PINDEX i = 0; i < aliases.GetSize(); i++) { const PINDEX sz = lrq.m_destinationInfo.GetSize(); lrq.m_destinationInfo.SetSize(sz + 1); H323SetAliasAddress(aliases[i], lrq.m_destinationInfo[sz]); } } return e_ok; } int SQLAuth::Check( /// Q.931/H.225 Setup message to be authenticated SetupMsg &setup, /// authorization data (call duration limit, reject reason, ...) SetupAuthData& authData ) { std::map params; PIPSocket::Address addr; setup.GetPeerAddr(addr); const PString traceStr = "SQLAUTH\t" + GetName() + "(Setup from " + addr.AsString() + " CRV=" + PString(setup.GetQ931().GetCallReference()) + ")"; params["callerip"] = addr.AsString(); // get the username for User-Name attribute params["u"] = GetUsername(setup, authData); params["g"] = Toolkit::GKName(); setup.GetLocalAddr(addr); params["gkip"] = addr.AsString(); params["Calling-Station-Id"] = GetCallingStationId(setup, authData); params["Called-Station-Id"] = GetCalledStationId(setup, authData); params["Dialed-Number"] = GetDialedNumber(setup, authData); params["answer"] = "0"; params["arq"] = "0"; if (authData.m_call) params["bandwidth"] = PString(authData.m_call->GetBandwidth()); GkSQLResult::ResultRow result; if (!RunQuery(traceStr, m_sqlConn, m_callQuery, params, result, -1)) { authData.m_rejectCause = Q931::TemporaryFailure; return GetDefaultStatus(); } if (!Toolkit::AsBool(result[0].first)) { authData.m_rejectCause = Q931::CallRejected; return e_fail; } GkSQLResult::ResultRow::const_iterator iter = FindField(result, "credittime"); if (iter != result.end()) { const PString &s = iter->first; if (s.GetLength() > 0 && strspn((const char*)s, "0123456789") == (size_t)s.GetLength()) { PUInt64 limit = s.AsUnsigned64(); if (limit > PUInt64(std::numeric_limits::max())) authData.m_callDurationLimit = std::numeric_limits::max(); else authData.m_callDurationLimit = static_cast(limit); PTRACE(5, traceStr << " - duration limit set to " << authData.m_callDurationLimit ); if (authData.m_callDurationLimit == 0) { authData.m_rejectCause = Q931::CallRejected; return e_fail; } } } iter = FindField(result, "redirectnumber"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { authData.SetRouteToAlias(s); PTRACE(5, traceStr << " - call redirected to the number " << s); } } iter = FindField(result, "redirectip"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { PStringArray tokens(s.Tokenise("; \t", FALSE)); for (PINDEX i = 0; i < tokens.GetSize(); ++i) { PIPSocket::Address addr; WORD port = 0; if (GetTransportAddress(tokens[i], GK_DEF_ENDPOINT_SIGNAL_PORT, addr, port) && addr.IsValid() && port != 0) { Route route("SQL", addr, port); route.m_destEndpoint = RegistrationTable::Instance()->FindBySignalAdr( SocketToH225TransportAddr(addr, port) ); authData.m_destinationRoutes.push_back(route); PTRACE(5, traceStr << " - call redirected to the address " << route.AsString() ); } } } } iter = FindField(result, "proxy"); if (iter != result.end()) { const PString &s = iter->first; if (!s) { authData.m_proxyMode = Toolkit::AsBool(s) ? CallRec::ProxyEnabled : CallRec::ProxyDisabled; PTRACE(5, traceStr << " - proxy mode " << (authData.m_proxyMode == CallRec::ProxyEnabled ? "enabled" : "disabled") ); } } return e_ok; } namespace { // anonymous namespace GkAuthCreator SQLPasswordAuthCreator("SQLPasswordAuth"); GkAuthCreator SQLAliasAuthCreator("SQLAliasAuth"); GkAuthCreator SQLAuthCreator("SQLAuth"); } // end of anonymous namespace