1 //////////////////////////////////////////////////////////////////
5 // This work is published under the GNU Public License (GPL)
6 // see file COPYING for details.
7 // We also explicitely grant the right to link this code
8 // with the OpenH323 library.
10 //////////////////////////////////////////////////////////////////
12 #if defined(_WIN32) && (_MSC_VER <= 1200)
13 #pragma warning(disable:4786) // warning about too long debug symbol off
14 #pragma warning(disable:4284)
31 #include "pwlib_compat.h"
34 const char* const GkAuthSectionName = "Gatekeeper::Auth";
35 const char OID_CAT[] = "1.2.840.113548.10.1.2.1";
38 using std::stable_sort;
43 ARQAuthData::ARQAuthData(
44 /// an endpoint requesting admission
46 /// call record matching this ARQ (if any)
48 ) : m_rejectReason(-1), m_callDurationLimit(-1),
49 m_requestingEP(ep), m_call(call), m_billingMode(-1),
50 m_routeToAlias(NULL), m_proxyMode(CallRec::ProxyDetect)
54 ARQAuthData::ARQAuthData(
55 const ARQAuthData& obj
56 ) : m_rejectReason(obj.m_rejectReason),
57 m_callDurationLimit(obj.m_callDurationLimit),
58 m_requestingEP(obj.m_requestingEP), m_call(obj.m_call),
59 m_billingMode(obj.m_billingMode), m_routeToAlias(NULL),
60 m_destinationRoutes(obj.m_destinationRoutes), m_proxyMode(obj.m_proxyMode)
62 if (obj.m_routeToAlias)
63 m_routeToAlias = new H225_AliasAddress(*obj.m_routeToAlias);
66 ARQAuthData& ARQAuthData::operator=(const ARQAuthData& obj)
68 m_callDurationLimit = obj.m_callDurationLimit;
69 m_requestingEP = obj.m_requestingEP;
71 m_billingMode = obj.m_billingMode;
72 m_proxyMode = obj.m_proxyMode;
74 delete m_routeToAlias;
75 m_routeToAlias = NULL;
76 if (obj.m_routeToAlias)
77 m_routeToAlias = new H225_AliasAddress(*obj.m_routeToAlias);
79 m_destinationRoutes = obj.m_destinationRoutes;
84 ARQAuthData::~ARQAuthData()
86 delete m_routeToAlias;
87 m_routeToAlias = NULL;
90 void ARQAuthData::SetRouteToAlias(H225_AliasAddress* alias)
92 delete m_routeToAlias;
93 m_routeToAlias = alias;
96 void ARQAuthData::SetRouteToAlias(const H225_AliasAddress& alias)
98 SetRouteToAlias(new H225_AliasAddress(alias));
101 void ARQAuthData::SetRouteToAlias(const PString& alias, int tag)
103 SetRouteToAlias(new H225_AliasAddress);
104 H323SetAliasAddress(alias, *m_routeToAlias, tag);
107 SetupAuthData::SetupAuthData(
108 /// call associated with the message (if any)
110 /// is the Setup message from a registered endpoint
112 ) : m_rejectReason(-1), m_rejectCause(-1), m_callDurationLimit(-1),
113 m_call(call), m_fromRegistered(fromRegistered),
114 m_routeToAlias(NULL), m_proxyMode(CallRec::ProxyDetect)
118 SetupAuthData::SetupAuthData(
119 const SetupAuthData& obj
120 ) : m_rejectReason(obj.m_rejectReason), m_rejectCause(obj.m_rejectCause),
121 m_callDurationLimit(obj.m_callDurationLimit), m_call(obj.m_call),
122 m_fromRegistered(obj.m_fromRegistered),
123 m_routeToAlias(NULL), m_destinationRoutes(obj.m_destinationRoutes),
124 m_proxyMode(obj.m_proxyMode)
126 if (obj.m_routeToAlias)
127 m_routeToAlias = new H225_AliasAddress(*obj.m_routeToAlias);
130 SetupAuthData& SetupAuthData::operator=(const SetupAuthData& obj)
132 m_rejectReason = obj.m_rejectReason;
133 m_rejectCause = obj.m_rejectCause;
134 m_callDurationLimit = obj.m_callDurationLimit;
136 m_fromRegistered = obj.m_fromRegistered;
137 m_proxyMode = obj.m_proxyMode;
139 delete m_routeToAlias;
140 m_routeToAlias = NULL;
141 if (obj.m_routeToAlias)
142 m_routeToAlias = new H225_AliasAddress(*obj.m_routeToAlias);
144 m_destinationRoutes = obj.m_destinationRoutes;
149 SetupAuthData::~SetupAuthData()
151 delete m_routeToAlias;
152 m_routeToAlias = NULL;
155 void SetupAuthData::SetRouteToAlias(H225_AliasAddress* alias)
157 delete m_routeToAlias;
158 m_routeToAlias = alias;
161 void SetupAuthData::SetRouteToAlias(const H225_AliasAddress& alias)
163 SetRouteToAlias(new H225_AliasAddress(alias));
166 void SetupAuthData::SetRouteToAlias(const PString& alias, int tag)
168 SetRouteToAlias(new H225_AliasAddress);
169 H323SetAliasAddress(alias, *m_routeToAlias, tag);
173 // class GkAuthenticator
174 GkAuthenticator::GkAuthenticator(
175 const char* name, /// a name for the module (to be used in the config file)
176 unsigned supportedRasChecks, /// RAS checks supported by this module
177 unsigned supportedMiscChecks /// non-RAS checks supported by this module
179 : NamedObject(name), m_defaultStatus(e_fail), m_controlFlag(e_Required),
180 m_enabledRasChecks(~0U), m_supportedRasChecks(supportedRasChecks),
181 m_enabledMiscChecks(~0U), m_supportedMiscChecks(supportedMiscChecks),
184 const PStringArray control(
185 m_config->GetString(GkAuthSectionName, name, "").Tokenise(";,")
187 if (control.GetSize() > 0) {
188 const PString controlStr = control[0].Trim();
189 if (strcasecmp(name, "default") == 0)
190 m_controlFlag = e_Sufficient,
191 m_defaultStatus = Toolkit::AsBool(controlStr) ? e_ok : e_fail;
192 else if (controlStr *= "optional")
193 m_controlFlag = e_Optional, m_defaultStatus = e_next;
194 else if (controlStr *= "required")
195 m_controlFlag = e_Required, m_defaultStatus = e_fail;
196 else if (controlStr *= "sufficient")
197 m_controlFlag = e_Sufficient, m_defaultStatus = e_fail;
199 PTRACE(1, "GKAUTH\tInvalid control flag '" << controlStr
200 << "' specified in the config for " << GetName()
203 PTRACE(1, "GKAUTH\tNo control flag specified in the config for module '"
207 std::map<PString, unsigned> rasmap;
208 rasmap["GRQ"] = RasInfo<H225_GatekeeperRequest>::flag,
209 rasmap["RRQ"] = RasInfo<H225_RegistrationRequest>::flag,
210 rasmap["URQ"] = RasInfo<H225_UnregistrationRequest>::flag,
211 rasmap["ARQ"] = RasInfo<H225_AdmissionRequest>::flag,
212 rasmap["BRQ"] = RasInfo<H225_BandwidthRequest>::flag,
213 rasmap["DRQ"] = RasInfo<H225_DisengageRequest>::flag,
214 rasmap["LRQ"] = RasInfo<H225_LocationRequest>::flag,
215 rasmap["IRQ"] = RasInfo<H225_InfoRequest>::flag;
217 std::map<PString, unsigned> miscmap;
218 miscmap["SETUP"] = e_Setup;
219 miscmap["SETUPUNREG"] = e_SetupUnreg;
221 if (control.GetSize() > 1) {
222 m_enabledRasChecks = 0;
223 m_enabledMiscChecks = 0;
225 for (PINDEX i = 1; i < control.GetSize(); ++i) {
226 const PString checkStr = control[i].Trim().ToUpper();
227 if (rasmap.find(checkStr) != rasmap.end()) {
228 m_enabledRasChecks |= rasmap[checkStr];
229 if ((m_supportedRasChecks & rasmap[checkStr]) != rasmap[checkStr])
230 PTRACE(1, "GKAUTH\t" << GetName() << " does not support '"
231 << control[i] << "' check"
233 } else if(miscmap.find(checkStr) != miscmap.end()) {
234 m_enabledMiscChecks |= miscmap[checkStr];
235 if ((m_supportedMiscChecks & miscmap[checkStr]) != miscmap[checkStr])
236 PTRACE(1, "GKAUTH\t" << GetName() << " does not support '"
237 << control[i] << "' check"
240 PTRACE(1, "GKAUTH\tInvalid check flag '" << control[i]
241 << "' specified in the config for " << GetName()
244 if ((m_enabledRasChecks & m_supportedRasChecks) == 0
245 && (m_enabledMiscChecks & m_supportedMiscChecks) == 0)
246 PTRACE(1, "GKAUTH\tNo check flags have been specified "
247 "in the config for " << GetName() << " - it will be disabled"
252 // convert bit flags to human readable names
253 PString rasFlagsStr, miscFlagsStr;
255 std::map<PString, unsigned>::const_iterator iter = rasmap.begin();
256 while (iter != rasmap.end()) {
257 if (m_enabledRasChecks & iter->second) {
260 rasFlagsStr += iter->first;
265 iter = miscmap.begin();
266 while (iter != miscmap.end()) {
267 if (m_enabledMiscChecks & iter->second) {
270 miscFlagsStr += iter->first;
275 if (rasFlagsStr.IsEmpty())
276 rasFlagsStr = "NONE";
277 if (miscFlagsStr.IsEmpty())
278 miscFlagsStr = "NONE";
280 PTRACE(1, "GKAUTH\t" << GetName() << " rule added to check RAS: "
281 << rasFlagsStr << ", OTHER: " << miscFlagsStr
285 m_h235Authenticators = NULL;
288 GkAuthenticator::~GkAuthenticator()
290 delete m_h235Authenticators;
291 PTRACE(1, "GKAUTH\t" << GetName() << " rule removed");
294 int GkAuthenticator::Check(RasPDU<H225_GatekeeperRequest> &, unsigned &)
296 return IsRasCheckEnabled(RasInfo<H225_GatekeeperRequest>::flag)
297 ? m_defaultStatus : e_next;
300 int GkAuthenticator::Check(
301 /// a request to be authenticated
302 RasPDU<H225_RegistrationRequest>& /*request*/,
303 /// authorization data (reject reason, ...)
304 RRQAuthData& /*authData*/
307 return IsRasCheckEnabled(RasInfo<H225_RegistrationRequest>::flag)
308 ? m_defaultStatus : e_next;
311 int GkAuthenticator::Check(RasPDU<H225_UnregistrationRequest> &, unsigned &)
313 return IsRasCheckEnabled(RasInfo<H225_UnregistrationRequest>::flag)
314 ? m_defaultStatus : e_next;
317 int GkAuthenticator::Check(
318 /// a request to be authenticated
319 RasPDU<H225_AdmissionRequest>& /*req*/,
320 /// authorization data (call duration limit, reject reason, ...)
321 ARQAuthData& /*authData*/
324 return IsRasCheckEnabled(RasInfo<H225_AdmissionRequest>::flag)
325 ? m_defaultStatus : e_next;
328 int GkAuthenticator::Check(RasPDU<H225_BandwidthRequest> &, unsigned &)
330 return IsRasCheckEnabled(RasInfo<H225_BandwidthRequest>::flag)
331 ? m_defaultStatus : e_next;
334 int GkAuthenticator::Check(RasPDU<H225_DisengageRequest> &, unsigned &)
336 return IsRasCheckEnabled(RasInfo<H225_DisengageRequest>::flag)
337 ? m_defaultStatus : e_next;
340 int GkAuthenticator::Check(RasPDU<H225_LocationRequest> &, unsigned &)
342 return IsRasCheckEnabled(RasInfo<H225_LocationRequest>::flag)
343 ? m_defaultStatus : e_next;
346 int GkAuthenticator::Check(RasPDU<H225_InfoRequest> &, unsigned &)
348 return IsRasCheckEnabled(RasInfo<H225_InfoRequest>::flag)
349 ? m_defaultStatus : e_next;
352 int GkAuthenticator::Check(
354 /// authorization data (call duration limit, reject reason, ...)
355 SetupAuthData& /*authData*/
358 return (IsMiscCheckEnabled(e_Setup) || IsMiscCheckEnabled(e_SetupUnreg))
359 ? m_defaultStatus : e_next;
362 bool GkAuthenticator::GetH235Capability(
363 /// append supported authentication mechanism to this array
364 H225_ArrayOf_AuthenticationMechanism& mechanisms,
365 /// append supported algorithm OIDs for the given authentication
367 H225_ArrayOf_PASN_ObjectId& algorithmOIDs
370 if (m_h235Authenticators && m_h235Authenticators->GetSize() > 0) {
371 for (PINDEX i = 0; i < m_h235Authenticators->GetSize(); i++)
372 (*m_h235Authenticators)[i].SetCapability(mechanisms, algorithmOIDs);
378 bool GkAuthenticator::IsH235Capability(
379 /// authentication mechanism
380 const H235_AuthenticationMechanism& mechanism,
381 /// algorithm OID for the given authentication mechanism
382 const PASN_ObjectId& algorithmOID
385 if (m_h235Authenticators)
386 for (PINDEX i = 0; i < m_h235Authenticators->GetSize(); i++)
387 if ((*m_h235Authenticators)[i].IsCapability(mechanism, algorithmOID))
392 bool GkAuthenticator::IsH235Capable() const
394 return m_h235Authenticators && m_h235Authenticators->GetSize() > 0;
397 void GkAuthenticator::SetSupportedChecks(
398 unsigned supportedRasChecks, /// RAS checks supported by this module
399 unsigned supportedMiscChecks /// non-RAS checks supported by this module
402 m_supportedRasChecks = supportedRasChecks;
403 m_supportedMiscChecks = supportedMiscChecks;
406 void GkAuthenticator::AppendH235Authenticator(
407 H235Authenticator* h235Auth /// H.235 authenticator to append
411 if (m_h235Authenticators == NULL)
412 m_h235Authenticators = new H235Authenticators();
413 m_h235Authenticators->Append(h235Auth);
417 PString GkAuthenticator::GetUsername(
418 /// RRQ message with additional data
419 const RasPDU<H225_RegistrationRequest>& request
422 const H225_RegistrationRequest& rrq = request;
426 if (rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias))
427 username = GetBestAliasAddressString(rrq.m_terminalAlias, false,
428 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
429 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
430 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
433 if (username.IsEmpty()) {
434 PIPSocket::Address addr;
435 if (rrq.m_callSignalAddress.GetSize() > 0
436 && GetIPFromTransportAddr(rrq.m_callSignalAddress[0], addr)
438 username = addr.AsString();
439 else if (rrq.m_rasAddress.GetSize() > 0
440 && GetIPFromTransportAddr(rrq.m_rasAddress[0], addr)
442 username = addr.AsString();
448 PString GkAuthenticator::GetUsername(
449 /// ARQ message with additional data
450 const RasPDU<H225_AdmissionRequest>& request,
452 ARQAuthData& authData
455 const H225_AdmissionRequest& arq = request;
456 const bool hasCall = authData.m_call.operator->() != NULL;
459 /// try to find h323_ID, email_ID or url_ID to use for User-Name
460 if (!arq.m_answerCall)
461 username = GetBestAliasAddressString(arq.m_srcInfo, true,
462 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
463 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
464 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
467 username = GetBestAliasAddressString(authData.m_call->GetSourceAddress(), true,
468 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
469 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
470 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
473 if (authData.m_requestingEP && (username.IsEmpty()
474 || FindAlias(authData.m_requestingEP->GetAliases(), username) == P_MAX_INDEX))
475 username = GetBestAliasAddressString(authData.m_requestingEP->GetAliases(), false,
476 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
477 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
478 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
481 /// if no h323_ID, email_ID or url_ID has been found, try to find any alias
482 if (username.IsEmpty())
483 if (!arq.m_answerCall)
484 username = GetBestAliasAddressString(arq.m_srcInfo, false,
485 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
486 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
487 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
490 username = GetBestAliasAddressString(
491 authData.m_call->GetSourceAddress(), true,
492 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
493 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
494 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
498 if (username.IsEmpty()) {
499 PIPSocket::Address addr;
500 if (arq.HasOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress)
501 && GetIPFromTransportAddr(arq.m_srcCallSignalAddress, addr)
503 username = addr.AsString();
504 else if (authData.m_requestingEP
505 && GetIPFromTransportAddr(authData.m_requestingEP->GetCallSignalAddress(), addr)
507 username = addr.AsString();
513 PString GkAuthenticator::GetUsername(
514 const SetupMsg &setup,
516 SetupAuthData& authData
519 const bool hasCall = authData.m_call.operator->() != NULL;
522 Q931& q931pdu = setup.GetQ931();
523 H225_Setup_UUIE &setupBody = setup.GetUUIEBody();
526 callingEP = authData.m_call->GetCallingParty();
528 if (setupBody.HasOptionalField(H225_Setup_UUIE::e_sourceAddress)) {
529 username = GetBestAliasAddressString(setupBody.m_sourceAddress, true,
530 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
531 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
532 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
534 if (!username && callingEP
535 && FindAlias(callingEP->GetAliases(), username) == P_MAX_INDEX)
536 username = PString();
539 if (username.IsEmpty() && hasCall) {
540 username = GetBestAliasAddressString(
541 authData.m_call->GetSourceAddress(), true,
542 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
543 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
544 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
546 if (!username && callingEP
547 && FindAlias(callingEP->GetAliases(), username) == P_MAX_INDEX)
548 username = PString();
551 if (username.IsEmpty() && callingEP)
552 username = GetBestAliasAddressString(callingEP->GetAliases(), false,
553 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
554 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
555 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
558 if (username.IsEmpty() && hasCall)
559 username = GetBestAliasAddressString(
560 authData.m_call->GetSourceAddress(), false,
561 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
562 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
563 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
566 if (username.IsEmpty() && setupBody.HasOptionalField(H225_Setup_UUIE::e_sourceAddress))
567 username = GetBestAliasAddressString(setupBody.m_sourceAddress, false,
568 AliasAddressTagMask(H225_AliasAddress::e_h323_ID),
569 AliasAddressTagMask(H225_AliasAddress::e_email_ID)
570 | AliasAddressTagMask(H225_AliasAddress::e_url_ID)
573 if (username.IsEmpty())
574 q931pdu.GetCallingPartyNumber(username);
576 if (username.IsEmpty()) {
577 PIPSocket::Address addr(0);
579 bool addrValid = false;
582 addrValid = authData.m_call->GetSrcSignalAddr(addr, port) && addr.IsValid();
584 if (!addrValid && setupBody.HasOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress))
585 addrValid = GetIPFromTransportAddr(setupBody.m_sourceCallSignalAddress, addr)
588 if (!addrValid && callingEP)
589 addrValid = GetIPFromTransportAddr(callingEP->GetCallSignalAddress(), addr)
593 username = addr.AsString();
599 PString GkAuthenticator::GetCallingStationId(
600 /// ARQ message with additional data
601 const RasPDU<H225_AdmissionRequest> &/*request*/,
603 ARQAuthData &authData
606 return authData.m_callingStationId;
609 PString GkAuthenticator::GetCallingStationId(
610 const SetupMsg &/*setup*/,
612 SetupAuthData &authData
615 return authData.m_callingStationId;
618 PString GkAuthenticator::GetCalledStationId(
619 /// ARQ message with additional data
620 const RasPDU<H225_AdmissionRequest> &/*request*/,
622 ARQAuthData &authData
625 return authData.m_calledStationId;
628 PString GkAuthenticator::GetCalledStationId(
629 const SetupMsg &/*setup*/,
631 SetupAuthData &authData
634 return authData.m_calledStationId;
637 PString GkAuthenticator::GetDialedNumber(
638 /// ARQ message with additional data
639 const RasPDU<H225_AdmissionRequest> &/*request*/,
641 ARQAuthData &authData
644 return authData.m_dialedNumber;
647 PString GkAuthenticator::GetDialedNumber(
648 const SetupMsg &/*setup*/,
650 SetupAuthData &authData
653 return authData.m_dialedNumber;
657 // class GkAuthenticatorList
658 GkAuthenticatorList::GkAuthenticatorList()
659 : m_mechanisms(new H225_ArrayOf_AuthenticationMechanism),
660 m_algorithmOIDs(new H225_ArrayOf_PASN_ObjectId)
664 GkAuthenticatorList::~GkAuthenticatorList()
666 WriteLock lock(m_reloadMutex);
667 DeleteObjectsInContainer(m_authenticators);
668 m_authenticators.clear();
670 delete m_algorithmOIDs;
673 void GkAuthenticatorList::OnReload()
675 // lock here to prevent too early authenticator destruction
676 // from another thread
677 WriteLock lock(m_reloadMutex);
679 // first destroy old authenticators
680 DeleteObjectsInContainer(m_authenticators);
681 m_authenticators.clear();
683 std::list<GkAuthenticator*> authenticators;
684 GkAuthenticator *auth;
686 const PStringArray authRules = GkConfig()->GetKeys(GkAuthSectionName);
687 for (PINDEX r = 0; r < authRules.GetSize(); r++) {
688 auth = Factory<GkAuthenticator>::Create(authRules[r]);
690 authenticators.push_back(auth);
693 m_authenticators = authenticators;
695 H225_ArrayOf_AuthenticationMechanism mechanisms;
696 H225_ArrayOf_PASN_ObjectId algorithmOIDs;
701 // scan all authenticators that are either "required" or "sufficient"
702 // (skip "optional") and fill #mechanisms# and #algorithmOIDs# arrays
703 // with H.235 capabilities that are supported by all these authenticators
705 std::list<GkAuthenticator*>::const_iterator iter = authenticators.begin();
707 while (iter != authenticators.end()) {
709 if (auth->IsH235Capable()
710 && (auth->GetControlFlag() == GkAuthenticator::e_Required
711 || auth->GetControlFlag() == GkAuthenticator::e_Sufficient)) {
712 if (mechanisms.GetSize() == 0) {
713 // append H.235 capability to empty arrays
714 auth->GetH235Capability(mechanisms, algorithmOIDs);
715 // should never happen, but we should check just for a case
716 if (algorithmOIDs.GetSize() == 0)
717 mechanisms.RemoveAll();
723 // Already have H.235 capabilities - check the current
724 // authenticator if it supports any of the capabilities.
725 // Remove capabilities that are not supported
727 H225_ArrayOf_AuthenticationMechanism matchedMechanisms;
729 for (i = 0; i < algorithmOIDs.GetSize(); i++) {
730 bool matched = false;
732 for (j = 0; j < mechanisms.GetSize(); j++)
733 if (auth->IsH235Capability(mechanisms[j], algorithmOIDs[i])) {
734 for (k = 0; k < matchedMechanisms.GetSize(); k++)
735 if (matchedMechanisms[k].GetTag() == mechanisms[j].GetTag())
737 if (k == matchedMechanisms.GetSize()) {
738 matchedMechanisms.SetSize(k+1);
739 matchedMechanisms[k].SetTag(mechanisms[j].GetTag());
745 PTRACE(5, "GKAUTH\tAlgorithm OID: " << algorithmOIDs[i]
746 << " removed from GCF list"
748 algorithmOIDs.RemoveAt(i--);
752 for (i = 0; i < mechanisms.GetSize(); i++) {
753 for (j = 0; j < matchedMechanisms.GetSize(); j++)
754 if (mechanisms[i].GetTag() == matchedMechanisms[j].GetTag())
756 if (j == matchedMechanisms.GetSize()) {
757 PTRACE(5, "GKAUTH\tAuth method: " << mechanisms[i]
758 << " removed from GCF list"
760 mechanisms.RemoveAt(i--);
764 if (mechanisms.GetSize() == 0 || algorithmOIDs.GetSize() == 0)
769 // Scan "optional" authenticators if the above procedure has not found
770 // any H.235 capabilities or has found more than one
771 if ((!found) || mechanisms.GetSize() > 1 || algorithmOIDs.GetSize() > 1) {
772 iter = authenticators.begin();
773 while (iter != authenticators.end()) {
775 if (auth->IsH235Capable()
776 && auth->GetControlFlag() == GkAuthenticator::e_Optional) {
777 if (mechanisms.GetSize() == 0) {
778 auth->GetH235Capability(mechanisms, algorithmOIDs);
779 if (algorithmOIDs.GetSize() == 0 )
780 mechanisms.RemoveAll();
786 H225_ArrayOf_AuthenticationMechanism matchedMechanisms;
788 for (i = 0; i < algorithmOIDs.GetSize(); i++) {
789 bool matched = false;
791 for (j = 0; j < mechanisms.GetSize(); j++)
792 if (auth->IsH235Capability(mechanisms[j], algorithmOIDs[i])) {
793 for (k = 0; k < matchedMechanisms.GetSize(); k++)
794 if (matchedMechanisms[k].GetTag() == mechanisms[j].GetTag())
796 if (k == matchedMechanisms.GetSize()) {
797 matchedMechanisms.SetSize(k+1);
798 matchedMechanisms[k].SetTag(mechanisms[j].GetTag());
804 PTRACE(5, "GKAUTH\tAlgorithm OID: " << algorithmOIDs[i]
805 << " removed from GCF list"
807 algorithmOIDs.RemoveAt(i--);
811 for (i = 0; i < mechanisms.GetSize(); i++) {
812 for (j = 0; j < matchedMechanisms.GetSize(); j++)
813 if (mechanisms[i].GetTag() == matchedMechanisms[j].GetTag())
815 if (j == matchedMechanisms.GetSize()) {
816 PTRACE(5, "GKAUTH\tAuth method: " << mechanisms[i]
817 << " removed from GCF list"
819 mechanisms.RemoveAt(i--);
823 if ((mechanisms.GetSize() == 0) || (algorithmOIDs.GetSize() == 0))
829 if (mechanisms.GetSize() > 0 && algorithmOIDs.GetSize() > 0) {
830 if (PTrace::CanTrace(4)) {
832 ostream& strm = PTrace::Begin(4,__FILE__,__LINE__);
833 strm <<"GkAuth\tH.235 capabilities selected for GCF:\n";
834 strm <<"\tAuthentication mechanisms: \n";
835 for (i = 0; i < mechanisms.GetSize(); i++)
836 strm << "\t\t" << mechanisms[i] << '\n';
837 strm <<"\tAuthentication algorithm OIDs: \n";
838 for (i = 0; i < algorithmOIDs.GetSize(); i++)
839 strm << "\t\t" << algorithmOIDs[i] << '\n';
844 PTRACE(4, "GKAUTH\tH.235 security is not active or conflicting "
845 "H.235 capabilities are active - GCF will not select "
846 "any particular capability"
848 mechanisms.RemoveAll();
849 algorithmOIDs.RemoveAll();
852 // now switch to new setting
853 *m_mechanisms = mechanisms;
854 *m_algorithmOIDs = algorithmOIDs;
857 void GkAuthenticatorList::SelectH235Capability(
858 const H225_GatekeeperRequest& grq,
859 H225_GatekeeperConfirm& gcf
862 ReadLock lock(m_reloadMutex);
864 if (m_authenticators.empty())
867 // if GRQ does not contain a list of authentication mechanisms simply return
868 if (!(grq.HasOptionalField(H225_GatekeeperRequest::e_authenticationCapability)
869 && grq.HasOptionalField(H225_GatekeeperRequest::e_algorithmOIDs)
870 && grq.m_authenticationCapability.GetSize() > 0
871 && grq.m_algorithmOIDs.GetSize() > 0))
874 H225_ArrayOf_AuthenticationMechanism & mechanisms = *m_mechanisms;
875 H225_ArrayOf_PASN_ObjectId & algorithmOIDs = *m_algorithmOIDs;
877 // And now match H.235 capabilities found with those from GRQ
878 // to find the one to be returned in GCF
879 for (int i = 0; i < grq.m_authenticationCapability.GetSize(); i++)
880 for (int j = 0; j < mechanisms.GetSize(); j++)
881 if (grq.m_authenticationCapability[i].GetTag() == mechanisms[j].GetTag())
882 for (int l = 0; l < algorithmOIDs.GetSize(); l++)
883 for (int k = 0; k < grq.m_algorithmOIDs.GetSize(); k++)
884 if (grq.m_algorithmOIDs[k] == algorithmOIDs[l]) {
885 std::list<GkAuthenticator*>::const_iterator iter = m_authenticators.begin();
886 while (iter != m_authenticators.end()) {
887 GkAuthenticator* auth = *iter++;
888 if (auth->IsH235Capable() && auth->IsH235Capability(mechanisms[j], algorithmOIDs[l])) {
889 gcf.IncludeOptionalField(H225_GatekeeperConfirm::e_authenticationMode);
890 gcf.m_authenticationMode = mechanisms[j];
891 gcf.IncludeOptionalField(H225_GatekeeperConfirm::e_algorithmOID);
892 gcf.m_algorithmOID = algorithmOIDs[l];
894 PTRACE(4, "GKAUTH\tGCF will select authentication "
895 "mechanism: " << mechanisms[j]
896 << " and algorithm OID: "<< algorithmOIDs[l]
902 PTRACE(5, "GKAUTH\tAuthentication mechanism: "
903 << mechanisms[j] << " and algorithm OID: "
904 << algorithmOIDs[l] << " removed from GCF list"
909 bool GkAuthenticatorList::Validate(
910 /// RRQ to be validated by authenticators
911 RasPDU<H225_RegistrationRequest>& request,
912 /// authorization data (reject reason, ...)
913 RRQAuthData& authData
916 ReadLock lock(m_reloadMutex);
917 std::list<GkAuthenticator*>::const_iterator i = m_authenticators.begin();
918 while (i != m_authenticators.end()) {
919 GkAuthenticator* auth = *i++;
920 if (auth->IsRasCheckEnabled(RasInfo<H225_RegistrationRequest>::flag)) {
921 const int result = auth->Check(request, authData);
922 if (result == GkAuthenticator::e_ok) {
923 PTRACE(3, "GKAUTH\t" << auth->GetName() << " RRQ check ok");
924 if (auth->GetControlFlag() != GkAuthenticator::e_Required)
926 } else if (result == GkAuthenticator::e_fail) {
927 PTRACE(3, "GKAUTH\t" << auth->GetName() << " RRQ check failed");
935 bool GkAuthenticatorList::Validate(
936 /// ARQ to be validated by authenticators
937 RasPDU<H225_AdmissionRequest>& request,
938 /// authorization data (call duration limit, reject reason, ...)
939 ARQAuthData& authData
942 ReadLock lock(m_reloadMutex);
943 std::list<GkAuthenticator*>::const_iterator i = m_authenticators.begin();
944 while (i != m_authenticators.end()) {
945 GkAuthenticator* auth = *i++;
946 if (auth->IsRasCheckEnabled(RasInfo<H225_AdmissionRequest>::flag)) {
947 const long oldDurationLimit = authData.m_callDurationLimit;
948 const int result = auth->Check(request, authData);
949 if (authData.m_callDurationLimit == 0) {
950 PTRACE(3, "GKAUTH\t" << auth->GetName() << " ARQ check failed: "
955 if (authData.m_callDurationLimit >= 0 && oldDurationLimit >= 0)
956 authData.m_callDurationLimit = PMIN(
957 authData.m_callDurationLimit, oldDurationLimit
960 authData.m_callDurationLimit = PMAX(
961 authData.m_callDurationLimit, oldDurationLimit
963 if (result == GkAuthenticator::e_ok) {
964 PTRACE(3, "GKAUTH\t" << auth->GetName() << " ARQ check ok");
965 if (auth->GetControlFlag() != GkAuthenticator::e_Required)
967 } else if (result == GkAuthenticator::e_fail) {
968 PTRACE(3, "GKAUTH\t" << auth->GetName() << " ARQ check failed");
976 bool GkAuthenticatorList::Validate(
978 /// authorization data (call duration limit, reject reason, ...)
979 SetupAuthData& authData
982 ReadLock lock(m_reloadMutex);
983 std::list<GkAuthenticator*>::const_iterator i = m_authenticators.begin();
984 while (i != m_authenticators.end()) {
985 GkAuthenticator* auth = *i++;
986 if (auth->IsMiscCheckEnabled(GkAuthenticator::e_Setup)
987 || (!authData.m_fromRegistered
988 && auth->IsMiscCheckEnabled(GkAuthenticator::e_SetupUnreg))) {
989 const long oldDurationLimit = authData.m_callDurationLimit;
990 const int result = auth->Check(setup, authData);
991 if (authData.m_callDurationLimit == 0) {
992 PTRACE(3, "GKAUTH\t" << auth->GetName() << " Setup check failed: "
993 "call duration limit 0"
997 if (authData.m_callDurationLimit >= 0 && oldDurationLimit >= 0)
998 authData.m_callDurationLimit = PMIN(
999 authData.m_callDurationLimit, oldDurationLimit
1002 authData.m_callDurationLimit = PMAX(
1003 authData.m_callDurationLimit, oldDurationLimit
1005 if (result == GkAuthenticator::e_ok) {
1006 PTRACE(3, "GKAUTH\t" << auth->GetName() << " Setup check ok");
1007 if (auth->GetControlFlag() != GkAuthenticator::e_Required)
1009 } else if (result == GkAuthenticator::e_fail) {
1010 PTRACE(3, "GKAUTH\t" << auth->GetName() << " Setup check failed");
1018 // class CacheManager
1019 bool CacheManager::Retrieve(
1020 const PString& key, /// the key to look for
1021 PString& value /// filled with the value on return
1028 ReadLock lock(m_rwmutex);
1030 std::map<PString, PString>::const_iterator iter = m_cache.find(key);
1031 if (iter == m_cache.end())
1034 std::map<PString, long>::const_iterator i = m_ctime.find(key);
1035 if (i == m_ctime.end() || (time(NULL) - i->second) >= m_ttl)
1036 return false; // cache expired
1038 value = (const char *)(iter->second);
1042 void CacheManager::Save(
1043 const PString& key, /// a key to be stored
1044 const PString& value /// a value to be associated with the key
1048 WriteLock lock(m_rwmutex);
1049 m_cache[key] = (const char*)value;
1050 m_ctime[key] = time(NULL);
1055 // class SimplePasswordAuth
1056 SimplePasswordAuth::SimplePasswordAuth(
1058 unsigned supportedRasChecks,
1059 unsigned supportedMiscChecks
1061 : GkAuthenticator(name, supportedRasChecks, supportedMiscChecks),
1064 if (!GetConfig()->HasKey(name, "KeyFilled"))
1065 PTRACE(1, "GKAUTH\t" << GetName() << " KeyFilled config variable "
1068 m_encryptionKey = GetConfig()->GetInteger(name, "KeyFilled", 0);
1069 m_checkID = Toolkit::AsBool(GetConfig()->GetString(name, "CheckID", "0"));
1070 m_cache = new CacheManager(GetConfig()->GetInteger(name, "PasswordTimeout", -1));
1072 #ifdef OpenH323Factory
1073 PFactory<H235Authenticator>::KeyList_T keyList = PFactory<H235Authenticator>::GetKeyList();
1074 PFactory<H235Authenticator>::KeyList_T::const_iterator r;
1075 for (r = keyList.begin(); r != keyList.end(); ++r) {
1076 H235Authenticator * Auth = PFactory<H235Authenticator>::CreateInstance(*r);
1077 AppendH235Authenticator(Auth);
1080 H235Authenticator* authenticator;
1082 authenticator = new H235AuthSimpleMD5;
1083 authenticator->SetLocalId("dummy");
1084 authenticator->SetRemoteId("dummy");
1085 authenticator->SetPassword("dummy");
1086 AppendH235Authenticator(authenticator);
1087 authenticator = new H235AuthCAT;
1088 authenticator->SetLocalId("dummy");
1089 authenticator->SetRemoteId("dummy");
1090 authenticator->SetPassword("dummy");
1091 AppendH235Authenticator(authenticator);
1094 // authenticator = new H235AuthProcedure1;
1095 // authenticator->SetLocalId("dummy");
1096 // authenticator->SetRemoteId("dummy");
1097 // authenticator->SetPassword("dummy");
1098 // AppendH235Authenticator(authenticator);
1105 SimplePasswordAuth::~SimplePasswordAuth()
1110 int SimplePasswordAuth::Check(RasPDU<H225_GatekeeperRequest> & request, unsigned &)
1112 return doCheck(request);
1115 int SimplePasswordAuth::Check(
1116 RasPDU<H225_RegistrationRequest> & request,
1117 RRQAuthData& /*authData*/
1120 H225_RegistrationRequest& rrq = request;
1121 return doCheck(request,
1122 rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias)
1123 ? &rrq.m_terminalAlias : NULL
1127 int SimplePasswordAuth::Check(RasPDU<H225_UnregistrationRequest> & request, unsigned &)
1129 return doCheck(request);
1132 int SimplePasswordAuth::Check(RasPDU<H225_BandwidthRequest> & request, unsigned &)
1134 return doCheck(request);
1137 int SimplePasswordAuth::Check(RasPDU<H225_DisengageRequest> & request, unsigned &)
1139 return doCheck(request);
1142 int SimplePasswordAuth::Check(RasPDU<H225_LocationRequest> & request, unsigned &)
1144 return doCheck(request);
1147 int SimplePasswordAuth::Check(RasPDU<H225_InfoRequest> & request, unsigned &)
1149 return doCheck(request);
1152 int SimplePasswordAuth::Check(
1153 /// ARQ to be authenticated/authorized
1154 RasPDU<H225_AdmissionRequest>& request,
1155 /// authorization data (call duration limit, reject reason, ...)
1156 ARQAuthData& /*authData*/
1159 H225_AdmissionRequest& arq = request;
1160 return doCheck(request, &arq.m_srcInfo);
1163 bool SimplePasswordAuth::GetPassword(
1164 const PString& id, /// get the password for this id
1165 PString& passwd /// filled with the password on return
1170 if (!GetConfig()->HasKey(GetName(), id))
1172 if (strcasecmp(id, "KeyFilled") == 0 || strcasecmp(id, "CheckID") == 0
1173 || strcasecmp(id, "PasswordTimeout") == 0) {
1174 PTRACE(2, "GKAUTH\t" << GetName() << " trying to get password for "
1175 " the forbidden alias '" << id << '\''
1179 passwd = Toolkit::Instance()->ReadPassword(GetName(), id, true);
1183 bool SimplePasswordAuth::InternalGetPassword(
1184 const PString& id, /// get the password for this id
1185 PString& passwd /// filled with the password on return
1188 if (m_cache->Retrieve(id, passwd)) {
1189 PTRACE(5, "GKAUTH\t" << GetName() << " cached password found for '"
1194 if (GetPassword(id, passwd)) {
1195 m_cache->Save(id, passwd);
1201 int SimplePasswordAuth::CheckTokens(
1202 /// an array of tokens to be checked
1203 const H225_ArrayOf_ClearToken& tokens,
1204 /// aliases for the endpoint that generated the tokens
1205 const H225_ArrayOf_AliasAddress* aliases
1208 for (PINDEX i = 0; i < tokens.GetSize(); i++) {
1209 H235_ClearToken& token = tokens[i];
1211 // check for Cisco Access Token
1212 if (token.m_tokenOID == OID_CAT) {
1213 if (!token.HasOptionalField(H235_ClearToken::e_generalID)) {
1214 PTRACE(3, "GKAUTH\t" << GetName() << " generalID field "
1215 "not found inside CAT token"
1219 const PString id = token.m_generalID;
1220 if (m_checkID && (aliases == NULL || FindAlias(*aliases, id) == P_MAX_INDEX)) {
1221 PTRACE(3, "GKAUTH\t" << GetName() << " generalID '" << id
1222 << "' of CAT token does not match any alias for the endpoint"
1228 if (!InternalGetPassword(id, passwd)) {
1229 PTRACE(3, "GKAUTH\t" << GetName() << " password not found for '"
1235 H235AuthCAT authCAT;
1236 authCAT.SetLocalId(id);
1237 authCAT.SetPassword(passwd);
1238 if (authCAT.ValidateClearToken(token) == H235Authenticator::e_OK) {
1239 PTRACE(5, "GKAUTH\t" << GetName() << " CAT password match for '"
1247 if (token.HasOptionalField(H235_ClearToken::e_password)) {
1248 if (!token.HasOptionalField(H235_ClearToken::e_generalID)) {
1249 PTRACE(3, "GKAUTH\t"<< GetName() << " generalID field not found"
1250 <<" inside the clear text token"
1254 const PString id = token.m_generalID;
1255 if (m_checkID && (aliases == NULL || FindAlias(*aliases, id) == P_MAX_INDEX)) {
1256 PTRACE(3, "GKAUTH\t" << GetName() << " generalID '"
1257 <<"' does not match any alias for the endpoint"
1263 if (!InternalGetPassword(id, passwd)) {
1264 PTRACE(3, "GKAUTH\t" << GetName() << " password not found for '"
1270 const PString tokenpasswd = token.m_password;
1271 if (passwd == tokenpasswd) {
1272 PTRACE(5, "GKAUTH\t" << GetName() << " clear text password "
1273 "match for '" << id << '\''
1283 int SimplePasswordAuth::CheckCryptoTokens(
1284 /// an array of cryptoTokens to be checked
1285 const H225_ArrayOf_CryptoH323Token& tokens,
1286 /// aliases for the endpoint that generated the tokens
1287 const H225_ArrayOf_AliasAddress* aliases,
1288 /// raw data for RAS PDU - required to validate some tokens
1289 /// like H.235 Auth Procedure I
1290 const PBYTEArray& rawPDU
1293 for (PINDEX i = 0; i < tokens.GetSize(); i++) {
1294 if (tokens[i].GetTag() == H225_CryptoH323Token::e_cryptoEPPwdHash) {
1295 H225_CryptoH323Token_cryptoEPPwdHash& pwdhash = tokens[i];
1296 const PString id = AsString(pwdhash.m_alias, false);
1297 if (m_checkID && (aliases == NULL || FindAlias(*aliases, id) == P_MAX_INDEX)) {
1298 PTRACE(3, "GKAUTH\t" << GetName() << " alias '" << id
1299 << "' of the cryptoEPPwdHash token does not match "
1300 "any alias for the endpoint"
1306 if (!InternalGetPassword(id, passwd)) {
1307 PTRACE(3, "GKAUTH\t" << GetName() << " password not found for '"
1313 H235AuthSimpleMD5 authMD5;
1314 authMD5.SetLocalId(id);
1315 authMD5.SetPassword(passwd);
1316 if (authMD5.ValidateCryptoToken(tokens[i], rawPDU) == H235Authenticator::e_OK) {
1317 PTRACE(5, "GKAUTH\t" << GetName() << " MD5 password match for '"
1324 } else if (tokens[i].GetTag() == H225_CryptoH323Token::e_nestedcryptoToken) {
1325 const H235_CryptoToken& nestedCryptoToken = tokens[i];
1327 if (nestedCryptoToken.GetTag() != H235_CryptoToken::e_cryptoHashedToken)
1330 const H235_CryptoToken_cryptoHashedToken& cryptoHashedToken = nestedCryptoToken;
1331 const H235_ClearToken& clearToken = cryptoHashedToken.m_hashedVals;
1333 if (!clearToken.HasOptionalField(H235_ClearToken::e_sendersID)) {
1334 PTRACE(5, "GKAUTH\t" << GetName() << " hashedVals of nested "
1335 " cryptoHashedToken do not contain sendersID"
1340 PString id = clearToken.m_sendersID;
1341 if (m_checkID && (aliases == NULL || FindAlias(*aliases, id) == P_MAX_INDEX)) {
1342 PTRACE(3, "GKAUTH\t" << GetName() << " sendersID '" << id
1343 << "' of the cryptoHashedToken hasgedVals does not match "
1344 "any alias for the endpoint"
1350 bool passwordFound = InternalGetPassword(id, passwd);
1352 //if a password is not found: senderID == endpointIdentifier?
1353 if (!passwordFound) {
1354 H225_EndpointIdentifier epId;
1356 endptr ep = RegistrationTable::Instance()->FindByEndpointId(epId);
1358 PTRACE(3, "GKAUTH\t" << GetName() << " sendersID '" << id
1359 << "' of the cryptoHashedToken hashedVals does not match "
1360 "any endpoint identifier"
1365 // check all endpoint aliases for a password
1366 const H225_ArrayOf_AliasAddress aliases = ep->GetAliases();
1367 for (PINDEX i = 0; i < aliases.GetSize(); i++) {
1368 id = AsString(aliases[i], FALSE);
1369 passwordFound = InternalGetPassword(id, passwd);
1375 if (!passwordFound) {
1376 PTRACE(3, "GKAUTH\t" << GetName() << " password not found for '"
1382 H235AuthProcedure1 authProcedure1;
1383 authProcedure1.SetLocalId(Toolkit::GKName());
1384 authProcedure1.SetPassword(passwd);
1385 const int result = authProcedure1.ValidateCryptoToken(tokens[i], rawPDU);
1386 if (result == H235Authenticator::e_OK) {
1387 PTRACE(5, "GKAUTH\t" << GetName() << " SHA-1 password match for '"
1391 } else if (result == H235Authenticator::e_Absent)
1401 bool SimplePasswordAuth::ResolveUserName(
1402 const H225_ArrayOf_ClearToken& tokens,
1403 const H225_ArrayOf_CryptoH323Token& cryptotokens,
1407 for (PINDEX i = 0; i < cryptotokens.GetSize(); i++) {
1409 if (cryptotokens[i].GetTag() == H225_CryptoH323Token::e_cryptoEPPwdHash) {
1410 H225_CryptoH323Token_cryptoEPPwdHash& pwdhash = cryptotokens[i];
1411 username = AsString(pwdhash.m_alias, false);
1413 } else if (cryptotokens[i].GetTag() == H225_CryptoH323Token::e_nestedcryptoToken) {
1414 H235_ClearToken clearToken;
1416 const H235_CryptoToken& nestedCryptoToken = cryptotokens[i];
1419 if (nestedCryptoToken.GetTag() == H235_CryptoToken::e_cryptoHashedToken) {
1420 const H235_CryptoToken_cryptoHashedToken& cryptoHashedToken = nestedCryptoToken;
1421 clearToken = cryptoHashedToken.m_hashedVals;
1425 if (nestedCryptoToken.GetTag() == H235_CryptoToken::e_cryptoSignedToken) {
1426 const H235_CryptoToken_cryptoSignedToken & cryptoSignedToken = nestedCryptoToken;
1427 H235_SIGNED<H235_EncodedGeneralToken> m_Signed = cryptoSignedToken.m_token;
1428 m_Signed.m_toBeSigned.DecodeSubType(clearToken);
1432 if (found && (clearToken.HasOptionalField(H235_ClearToken::e_sendersID))) {
1433 username = clearToken.m_sendersID;
1439 for (PINDEX j = 0; j < cryptotokens.GetSize(); j++) {
1440 H235_ClearToken& token = tokens[j];
1442 if (token.HasOptionalField(H235_ClearToken::e_generalID)) {
1443 username = token.m_generalID;
1452 AliasAuth::AliasAuth(
1454 unsigned supportedRasChecks,
1455 unsigned supportedMiscChecks
1457 : GkAuthenticator(name, supportedRasChecks, supportedMiscChecks),
1460 m_cache = new CacheManager(GetConfig()->GetInteger(name, "CacheTimeout", -1));
1463 AliasAuth::~AliasAuth()
1468 int AliasAuth::Check(
1469 RasPDU<H225_RegistrationRequest>& request,
1470 RRQAuthData& /*authData*/
1473 H225_RegistrationRequest& rrq = request;
1475 if (!rrq.HasOptionalField(H225_RegistrationRequest::e_terminalAlias)) {
1476 PTRACE(3, "GKAUTH\t" << GetName() << " - terminalAlias field not found "
1479 return GetDefaultStatus();
1482 const H225_ArrayOf_AliasAddress& aliases = rrq.m_terminalAlias;
1484 for (PINDEX i = 0; i <= aliases.GetSize(); i++) {
1485 const PString alias = (i < aliases.GetSize())
1486 ? AsString(aliases[i], false) : PString("default");
1488 if (InternalGetAuthConditionString(alias, authcond)) {
1489 if (doCheck(rrq.m_callSignalAddress, authcond)) {
1490 PTRACE(5, "GKAUTH\t" << GetName() << " auth condition '"
1491 << authcond <<"' accepted RRQ from '" << alias << '\''
1495 PTRACE(3, "GKAUTH\t" << GetName() << " auth condition '"
1496 << authcond <<"' rejected RRQ from '" << alias << '\''
1501 PTRACE(4, "GKAUTH\t" << GetName() << " auth condition not found "
1502 << "for alias '" << alias << '\''
1505 return GetDefaultStatus();
1508 bool AliasAuth::GetAuthConditionString(
1509 /// an alias the condition string is to be retrieved for
1510 const PString& alias,
1511 /// filled with auth condition string that has been found
1515 if (alias.IsEmpty())
1517 if (!GetConfig()->HasKey("RasSrv::RRQAuth", alias))
1519 if (strcasecmp(alias, "CacheTimeout") == 0) {
1520 PTRACE(2, "GKAUTH\t" << GetName() << " trying to get auth condition "
1521 " string for the forbidden alias '" << alias << '\''
1525 authCond = GetConfig()->GetString("RasSrv::RRQAuth", alias, "");
1529 bool AliasAuth::InternalGetAuthConditionString(
1530 const PString& id, /// get the password for this id
1531 PString& authCond /// filled with the auth condition string on return
1534 if (m_cache->Retrieve(id, authCond)) {
1535 PTRACE(5, "GKAUTH\t" << GetName() << " cached auth condition string "
1536 "found for '" << id << '\''
1540 if (GetAuthConditionString(id, authCond)) {
1541 m_cache->Save(id, authCond);
1547 bool AliasAuth::doCheck(
1548 /// an array of source signalling addresses for an endpoint that sent the request
1549 const H225_ArrayOf_TransportAddress& sigaddr,
1550 /// auth condition string as returned by GetAuthConditionString
1551 const PString& condition
1554 const PStringArray authrules(condition.Tokenise("&|", FALSE));
1556 if (authrules.GetSize() < 1) {
1557 PTRACE(2, "GKAUTH\t" << GetName() << " contains an empty auth condition");
1561 for (PINDEX i = 0; i < authrules.GetSize(); ++i)
1562 for (PINDEX j = 0; j < sigaddr.GetSize(); ++j)
1563 if (CheckAuthRule(sigaddr[j], authrules[i])) {
1564 PTRACE(5, "GKAUTH\t" << GetName() << " auth rule '"
1565 << authrules[i] << "' applied successfully to RRQ "
1566 " from " << AsDotString(sigaddr[j])
1573 bool AliasAuth::CheckAuthRule(
1574 /// a signalling address for the endpoint that sent the request
1575 const H225_TransportAddress& sigaddr,
1576 /// the auth rule to be used for checking
1577 const PString& authrule
1580 const PStringArray rule = authrule.Tokenise(":", false);
1581 if (rule.GetSize() < 1) {
1582 PTRACE(1, "GKAUTH\t" << GetName() << " found invalid empty auth rule '"
1588 // authrule = rName[:params...]
1589 const PString rName = rule[0].Trim();
1591 if (strcasecmp(rName, "confirm") == 0 || strcasecmp(rName, "allow") == 0)
1593 else if (strcasecmp(rName, "reject") == 0 || strcasecmp(rName, "deny") == 0
1594 || strcasecmp(rName, "forbid") == 0)
1596 else if (strcasecmp(rName, "sigaddr") == 0) {
1597 // condition 'sigaddr' example:
1598 // sigaddr:.*ipAddress .* ip = .* c3 47 e2 a2 .*port = 1720.*
1599 if (rule.GetSize() < 2) {
1600 PTRACE(1, "GKAUTH\t" << GetName() << " found invalid empty sigaddr "
1601 "auth rule '" << authrule << '\''
1605 return Toolkit::MatchRegex(AsString(sigaddr), rule[1].Trim()) != 0;
1606 } else if (strcasecmp(rName, "sigip") == 0) {
1607 // condition 'sigip' example:
1608 // sigip:195.71.129.69:1720
1609 if (rule.GetSize() < 2) {
1610 PTRACE(1, "GKAUTH\t" << GetName() << " found invalid empty sigip "
1611 "auth rule '" << authrule << '\''
1615 PIPSocket::Address ip;
1616 PIPSocket::GetHostAddress(rule[1].Trim(), ip);
1617 const WORD port = (WORD)((rule.GetSize() < 3)
1618 ? GK_DEF_ENDPOINT_SIGNAL_PORT : rule[2].Trim().AsInteger());
1619 return (sigaddr == SocketToH225TransportAddr(ip, port));
1621 PTRACE(1, "GKAUTH\t" << GetName() << " found unknown auth rule '"
1630 // Initial author: Michael Rubashenkkov 2002/01/14 (GkAuthorize)
1631 // Completely rewrite by Chih-Wei Huang 2002/05/01
1636 class PrefixAuth : public GkAuthenticator
1639 typedef std::map< PString, AuthRule *, greater<PString> > Rules;
1641 enum SupportedRasChecks {
1642 PrefixAuthRasChecks = RasInfo<H225_AdmissionRequest>::flag
1643 | RasInfo<H225_LocationRequest>::flag
1648 unsigned supportedRasChecks = PrefixAuthRasChecks,
1649 unsigned supportedMiscChecks = 0
1652 virtual ~PrefixAuth();
1654 // override from class GkAuthenticator
1655 virtual int Check(RasPDU<H225_LocationRequest>& request, unsigned& rejectReason);
1657 /** Authenticate/Authorize ARQ message. Override from GkAuthenticator.
1660 e_fail - authentication failed
1661 e_ok - authenticated with this authenticator
1662 e_next - authentication could not be determined
1665 /// ARQ to be authenticated/authorized
1666 RasPDU<H225_AdmissionRequest>& request,
1667 /// authorization data (call duration limit, reject reason, ...)
1668 ARQAuthData& authData
1672 virtual int doCheck(
1678 PrefixAuth(const PrefixAuth&);
1679 PrefixAuth& operator=(const PrefixAuth&);
1686 // Help classes for PrefixAuth
1687 class AuthObj // abstract class
1690 virtual ~AuthObj() {}
1692 virtual bool IsValid() const { return true; }
1694 virtual PStringArray GetPrefixes() const = 0;
1696 virtual PIPSocket::Address GetIP() const = 0;
1697 virtual PString GetAliases() const = 0;
1700 class ARQAuthObj : public AuthObj
1704 const H225_AdmissionRequest& arq
1707 virtual bool IsValid() const { return m_ep; }
1709 virtual PStringArray GetPrefixes() const;
1711 virtual PIPSocket::Address GetIP() const;
1712 virtual PString GetAliases() const;
1716 ARQAuthObj(const ARQAuthObj&);
1717 ARQAuthObj& operator=(const ARQAuthObj&);
1720 const H225_AdmissionRequest& m_arq;
1724 class LRQAuthObj : public AuthObj
1728 const H225_LocationRequest& lrq
1731 virtual PStringArray GetPrefixes() const;
1733 virtual PIPSocket::Address GetIP() const;
1734 virtual PString GetAliases() const;
1738 LRQAuthObj(const LRQAuthObj&);
1739 LRQAuthObj& operator=(const LRQAuthObj&);
1742 const H225_LocationRequest& m_lrq;
1743 PIPSocket::Address m_ipAddress;
1746 class AuthRule : public NamedObject
1758 ) : m_priority(1000), m_fate(fate), m_inverted(inverted), m_next(NULL) {}
1760 virtual ~AuthRule() { delete m_next; }
1772 ) const { return m_priority < obj.m_priority; }
1776 ) { m_next = next; }
1780 AuthRule(const AuthRule&);
1781 AuthRule& operator=(const AuthRule&);
1784 /// the lesser the value, the higher the priority
1793 class NullRule : public AuthRule
1796 NullRule() : AuthRule(e_nomatch, false) { SetName("NULL"); }
1799 const AuthObj& /*aobj*/
1803 NullRule(const NullRule&);
1804 NullRule& operator=(const NullRule&);
1807 class IPv4AuthRule : public AuthRule
1812 const PString& ipStr,
1822 IPv4AuthRule(const IPv4AuthRule&);
1823 IPv4AuthRule& operator=(const IPv4AuthRule&);
1826 PIPSocket::Address m_network, m_netmask;
1829 class AliasAuthRule : public AuthRule
1834 const PString& aliasStr,
1836 ) : AuthRule(fate, inverted), m_pattern(aliasStr)
1840 SetName(PString((fate == e_allow) ? "allow alias" : "deny alias")
1841 + (inverted ? ":!" : ":") + aliasStr
1852 AliasAuthRule(const AliasAuthRule&);
1853 AliasAuthRule& operator=(const AliasAuthRule&);
1860 ARQAuthObj::ARQAuthObj(
1861 const H225_AdmissionRequest& arq
1863 : m_arq(arq), m_ep(RegistrationTable::Instance()->FindByEndpointId(arq.m_endpointIdentifier))
1867 PStringArray ARQAuthObj::GetPrefixes() const
1870 if (m_arq.HasOptionalField(H225_AdmissionRequest::e_destinationInfo)) {
1871 const PINDEX ss = m_arq.m_destinationInfo.GetSize();
1874 for (PINDEX i = 0; i < ss; ++i)
1875 array[i] = AsString(m_arq.m_destinationInfo[i], false);
1878 if (array.GetSize() == 0)
1879 array.AppendString(PString());
1883 PIPSocket::Address ARQAuthObj::GetIP() const
1885 PIPSocket::Address result;
1886 const H225_TransportAddress& addr =
1887 m_arq.HasOptionalField(H225_AdmissionRequest::e_srcCallSignalAddress)
1888 ? m_arq.m_srcCallSignalAddress : m_ep->GetCallSignalAddress();
1889 GetIPFromTransportAddr(addr, result);
1893 PString ARQAuthObj::GetAliases() const
1895 return AsString(m_ep->GetAliases());
1898 LRQAuthObj::LRQAuthObj(
1899 const H225_LocationRequest& lrq
1903 GetIPFromTransportAddr(m_lrq.m_replyAddress, m_ipAddress);
1906 PStringArray LRQAuthObj::GetPrefixes() const
1909 const PINDEX ss = m_lrq.m_destinationInfo.GetSize();
1912 for (PINDEX i = 0; i < ss; ++i)
1913 array[i] = AsString(m_lrq.m_destinationInfo[i], false);
1918 PIPSocket::Address LRQAuthObj::GetIP() const
1923 PString LRQAuthObj::GetAliases() const
1925 return m_lrq.HasOptionalField(H225_LocationRequest::e_sourceInfo)
1926 ? AsString(m_lrq.m_sourceInfo) : PString();
1929 int AuthRule::Check(
1933 if (Match(aobj) ^ m_inverted) {
1934 PTRACE(5, "GKAUTH\tPrefix auth rule '" << GetName() << "' matched");
1937 return m_next ? m_next->Check(aobj) : e_nomatch;
1940 inline void delete_rule(PrefixAuth::Rules::value_type r)
1946 IPv4AuthRule::IPv4AuthRule(
1948 const PString& ipStr,
1951 : AuthRule(fate, inverted)
1953 Toolkit::GetNetworkFromString(ipStr, m_network, m_netmask);
1954 DWORD n = ~PIPSocket::Net2Host(DWORD(m_netmask));
1955 for (m_priority = 0; n; n >>= 1)
1958 SetName(PString((fate == e_allow) ? "allow ipv4(" : "deny ipv4(")
1959 + PString(m_priority) + (inverted ? "):!" : "):") + ipStr
1964 bool IPv4AuthRule::Match(
1968 return ((aobj.GetIP() & m_netmask) == m_network);
1971 bool AliasAuthRule::Match(
1975 return aobj.GetAliases().FindRegEx(m_pattern) != P_MAX_INDEX;
1978 inline bool is_inverted(const PString & cfg, PINDEX p)
1980 return (p > 1) ? cfg[p-1] == '!' : false;
1983 inline bool comp_authrule_priority(AuthRule *a1, AuthRule *a2)
1989 const char* const prfflag="prf:";
1990 const char* const allowflag="allow";
1991 const char* const denyflag="deny";
1992 const char* const ipflag="ipv4:";
1993 const char* const aliasflag="alias:";
1997 PrefixAuth::PrefixAuth(
1999 unsigned supportedRasChecks,
2000 unsigned supportedMiscChecks
2002 : GkAuthenticator(name, supportedRasChecks, supportedMiscChecks)
2004 m_defaultRule = GetDefaultStatus();
2006 const int ipfl = strlen(ipflag);
2007 const int aliasfl = strlen(aliasflag);
2009 const PStringToString cfgs = GetConfig()->GetAllKeyValues(name);
2010 for (PINDEX i = 0; i < cfgs.GetSize(); ++i) {
2011 PString key = cfgs.GetKeyAt(i);
2012 if (key *= "default") {
2013 m_defaultRule = Toolkit::AsBool(cfgs.GetDataAt(i)) ? e_ok : e_fail;
2015 } else if (key *= "ALL") {
2016 // use space (0x20) as the key so it will be the last resort
2019 if (m_prefrules.find(key) != m_prefrules.end()) {
2020 PTRACE(1, "GKAUTH\t" << GetName() << " duplicate entry for "
2021 "destination '" << key << '\''
2023 continue; //rule already exists? ignore
2026 const PStringArray rules = cfgs.GetDataAt(i).Tokenise("|", false);
2027 const PINDEX sz = rules.GetSize();
2029 PTRACE(1, "GKAUTH\t" << GetName() << " no rules found for "
2030 "destination '" << key << '\''
2034 //AuthRule *rls[sz];
2035 AuthRule **rls = new AuthRule *[sz];
2036 for (PINDEX j = 0; j < sz; ++j) {
2037 // if not allowed, assume denial
2038 const AuthRule::Result fate = (rules[j].Find(allowflag) != P_MAX_INDEX)
2039 ? AuthRule::e_allow : AuthRule::e_deny;
2041 if ((pp = rules[j].Find(ipflag)) != P_MAX_INDEX)
2042 rls[j] = new IPv4AuthRule(fate, rules[j].Mid(pp + ipfl).Trim(),
2043 is_inverted(rules[j], pp)
2045 else if ((pp = rules[j].Find(aliasflag)) != P_MAX_INDEX)
2046 rls[j] = new AliasAuthRule(fate, rules[j].Mid(pp+aliasfl).Trim(),
2047 is_inverted(rules[j], pp)
2050 rls[j] = new NullRule;
2054 // sort the rules by priority
2055 stable_sort(rls, rls + sz, comp_authrule_priority);
2056 for (PINDEX k = 1; k < sz; ++k)
2057 rls[k-1]->SetNext(rls[k]);
2058 m_prefrules[key] = rls[0];
2063 if (m_prefrules.size() == 0)
2064 PTRACE(1, "GKAUTH\t" << GetName() << " contains no rules - "
2069 PrefixAuth::~PrefixAuth()
2071 for_each(m_prefrules.begin(), m_prefrules.end(), delete_rule);
2074 int PrefixAuth::Check(RasPDU<H225_LocationRequest> & request, unsigned &)
2076 LRQAuthObj tmpObj((const H225_LocationRequest&)request); // fix for GCC 3.4.2
2077 return doCheck(tmpObj);
2080 int PrefixAuth::Check(
2081 /// ARQ to be authenticated/authorized
2082 RasPDU<H225_AdmissionRequest>& request,
2083 /// authorization data (call duration limit, reject reason, ...)
2084 ARQAuthData& /*authData*/
2087 H225_AdmissionRequest& arq = request;
2088 if (arq.m_answerCall
2089 && arq.HasOptionalField(H225_AdmissionRequest::e_callIdentifier)
2090 && CallTable::Instance()->FindCallRec(arq.m_callIdentifier)) {
2091 PTRACE(5, "GKAUTH\t" << GetName() << " ARQ check skipped - call "
2092 " already admitted and present in the call table"
2096 ARQAuthObj tmpObj(arq); // fix for GCC 3.4.2
2097 return doCheck(tmpObj);
2100 struct comp_pref { // function object
2101 comp_pref(const PString & s) : value(s) {}
2102 bool operator()(const PrefixAuth::Rules::value_type & v) const;
2103 const PString & value;
2106 inline bool comp_pref::operator()(const PrefixAuth::Rules::value_type & v) const
2108 return (value.Find(v.first) == 0) || (v.first *= " ");
2111 int PrefixAuth::doCheck(
2115 if (!aobj.IsValid())
2118 const PStringArray destinationInfo(aobj.GetPrefixes());
2119 for (PINDEX i = 0; i < destinationInfo.GetSize(); ++i) {
2120 // find the first match rule
2121 // since prefrules is descendently sorted
2122 // it must be the most specific prefix
2123 for (Rules::iterator j = m_prefrules.begin(); j != m_prefrules.end(); ++j) {
2124 Rules::iterator iter = find_if(j, m_prefrules.end(),
2125 comp_pref(destinationInfo[i])
2127 if (iter == m_prefrules.end())
2129 switch (iter->second->Check(aobj))
2131 case AuthRule::e_allow:
2132 PTRACE(4, "GKAUTH\t" << GetName() << " rule matched and "
2133 "accepted destination prefix '"
2134 << ((iter->first == " ") ? PString("ALL") : iter->first)
2135 << "' for alias '" << destinationInfo[i] << '\''
2139 case AuthRule::e_deny:
2140 PTRACE(4, "GKAUTH\t" << GetName() << " rule matched and "
2141 "rejected destination prefix '"
2142 << ((iter->first == " ") ? PString("ALL") : iter->first)
2143 << "' for alias '" << destinationInfo[i] << '\''
2147 default: // try next prefix...
2149 PTRACE(4, "GKAUTH\t" << GetName() << " rule matched and "
2150 " could not reject or accept destination prefix '"
2151 << ((iter->first == " ") ? PString("ALL") : iter->first)
2152 << "' for alias '" << destinationInfo[i] << '\''
2158 if (m_defaultRule == e_ok)
2159 PTRACE(4, "GKAUTH\t" << GetName() << " default rule accepted "
2162 else if (m_defaultRule == e_fail)
2163 PTRACE(4, "GKAUTH\t" << GetName() << " default rule rejected "
2167 PTRACE(4, "GKAUTH\t" << GetName() << " could not reject or "
2168 "accept the request"
2171 return m_defaultRule;
2174 namespace { // anonymous namespace
2175 GkAuthCreator<GkAuthenticator> DefaultAuthenticatorCreator("default");
2176 GkAuthCreator<SimplePasswordAuth> SimplePasswordAuthCreator("SimplePasswordAuth");
2177 GkAuthCreator<AliasAuth> AliasAuthCreator("AliasAuth");
2178 GkAuthCreator<PrefixAuth> PrefixAuthCreator("PrefixAuth");
2179 } // end of anonymous namespace