OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / user / gnugk / gkauth.h
1 //////////////////////////////////////////////////////////////////
2 //
3 // gkauth.h
4 //
5 // Gatekeeper authentication modules
6 //
7 // This work is published under the GNU Public License (GPL)
8 // see file COPYING for details.
9 // We also explicitely grant the right to link this code
10 // with the OpenH323 library.
11 //
12 //////////////////////////////////////////////////////////////////
13
14 #ifndef GKAUTH_H
15 #define GKAUTH_H "@(#) $Id: gkauth.h,v 1.31 2007/03/21 22:30:16 willamowius Exp $"
16
17 #include <map>
18 #include <list>
19 #include "name.h"
20 #include "rwlock.h"
21 #include <h235auth.h>
22
23 class H225_GatekeeperRequest;
24 class H225_GatekeeperConfirm;
25 class H225_RegistrationRequest;
26 class H225_UnregistrationRequest;
27 class H225_AdmissionRequest;
28 class H225_BandwidthRequest;
29 class H225_DisengageRequest;
30 class H225_LocationRequest;
31 class H225_InfoRequest;
32 class H225_ArrayOf_ClearToken;
33 class H225_ArrayOf_CryptoH323Token;
34 class H225_ArrayOf_AliasAddress;
35 class H225_ArrayOf_AuthenticationMechanism;
36 class H225_ArrayOf_PASN_ObjectId;
37 class H225_TransportAddress;
38 class H225_ArrayOf_TransportAddress;
39 class H235_AuthenticationMechanism;
40 class PASN_ObjectId;
41 class H235Authenticators;
42 class H235Authenticator;
43 class Q931;
44 class H225_Setup_UUIE;
45 class SignalingMsg;
46 template <class> class H225SignalingMsg;
47 typedef H225SignalingMsg<H225_Setup_UUIE> SetupMsg;
48
49 class EndpointRec;
50 class CallRec;
51 template<class> class SmartPtr;
52 typedef SmartPtr<EndpointRec> endptr;
53 typedef SmartPtr<CallRec> callptr;
54
55 template<class> class RasPDU;
56 template<class> struct RasInfo;
57
58 namespace Routing {
59 struct Route;
60 }
61
62 /// Data read/written during RRQ processing by all configured 
63 /// authenticator modules
64 struct RRQAuthData
65 {
66         RRQAuthData() : m_rejectReason(-1), m_billingMode(-1) {}
67                 
68         /// -1 if not set, H225_RegistrationRejectReason enum otherwise
69         int m_rejectReason;
70         /// optional user's account balance amount string
71         PString m_amountString;
72         /// H225_CallCreditServiceControl_billingMode or -1, if not defined
73         int m_billingMode;
74 };
75
76 /// Data read/written during ARQ processing by all configured 
77 /// authenticator modules
78 struct ARQAuthData
79 {
80         ARQAuthData(
81                 const ARQAuthData& obj
82                 );
83         ARQAuthData(
84                 const endptr& ep,
85                 const callptr& call
86                 );
87         ~ARQAuthData();
88                 
89         ARQAuthData& operator=(const ARQAuthData& obj);
90                 
91         void SetRouteToAlias(H225_AliasAddress* alias);
92         void SetRouteToAlias(const H225_AliasAddress& alias);
93         void SetRouteToAlias(const PString& alias, int tag = -1);
94                 
95         /// -1 if not set, H225_AdmissionRejectReason enum otherwise
96         int m_rejectReason;
97         /// -1 if not set, max allowe call duration in seconds otherwise
98         long m_callDurationLimit;
99         /// endpoint that sent the request
100         endptr m_requestingEP;
101         /// call associated with the request (if any, only for answering ARQ)
102         callptr m_call;
103         /// input/output - set or get Calling-Station-Id
104         PString m_callingStationId;             
105         /// call party to be billed for the call (if other then Calling-Station-Id)
106         PString m_callLinkage;
107         /// input/output - set or get Called-Station-Id
108         PString m_calledStationId;
109         /// number dialed by the user (Called-Station-Id before rewrite)
110         PString m_dialedNumber;
111         /// optional user's account balance amount string
112         PString m_amountString;
113         /// H225_CallCreditServiceControl_billingMode or -1, if not defined
114         int m_billingMode;
115         /// if not NULL, route the call to the specified alias
116         H225_AliasAddress* m_routeToAlias;
117         /// if not empty, route the call to the specified destinations
118         std::list<Routing::Route> m_destinationRoutes;
119         /// override global proxy setting from the config (see #CallRec::ProxyMode enum#)
120         int m_proxyMode;
121         /// RADIUS Class attribute, if found in Access-Accept/Access-Reject
122         PBYTEArray m_radiusClass;
123         
124 private:
125         ARQAuthData();
126 };
127         
128 /// Data read/written during Q.931/H.225.0 Setup processing 
129 /// by all authenticators
130 struct SetupAuthData
131 {
132         SetupAuthData(
133                 const SetupAuthData& obj
134                 );
135         SetupAuthData(
136                 /// call associated with the message (if any)
137                 const callptr& call,
138                 /// is the Setup message from a registered endpoint
139                 bool fromRegistered
140                 );
141         ~SetupAuthData();
142                 
143         SetupAuthData& operator=(const SetupAuthData& obj);
144         
145         void SetRouteToAlias(H225_AliasAddress* alias);
146         void SetRouteToAlias(const H225_AliasAddress& alias);
147         void SetRouteToAlias(const PString& alias, int tag = -1);
148
149         /// -1 if not set, H225_ReleaseCompleteReason enum otherwise
150         int m_rejectReason;
151         /// -1 if not set, Q931 cause value otherwise
152         int m_rejectCause;
153         /// -1 if not set, max allowe call duration in seconds otherwise
154         long m_callDurationLimit;
155         /// call associated with the message (if any)
156         callptr m_call;
157         /// is the Setup message from a registered endpoint
158         bool m_fromRegistered;
159         /// input/output - set or get Calling-Station-Id
160         PString m_callingStationId;             
161         /// input/output - set or get Called-Station-Id
162         PString m_calledStationId;
163         /// number dialed by the user (Called-Station-Id before rewrite)
164         PString m_dialedNumber;
165         /// if not NULL, route the call to the specified alias
166         H225_AliasAddress* m_routeToAlias;
167         /// if not empty, route the call to the specified destinations
168         std::list<Routing::Route> m_destinationRoutes;
169         /// override global proxy setting from the config (see #CallRec::ProxyMode enum#)
170         int m_proxyMode;
171         /// RADIUS Class attribute, if found in Access-Accept/Access-Reject
172         PBYTEArray m_radiusClass;
173                 
174 private:
175         SetupAuthData();
176 };
177
178 /** The base class for all authenticator modules. Authenticator modules
179     are used to authenticate/authorized RAS and Q.931 messages sent 
180     by endpoints and to check if the endpoints are authorized to use 
181     H.323 network resources.
182         
183     The modules are stackable - each request can be checked by multiple
184     modules to get the final authentication result.
185         
186     Derived classes usually override one or more Check virtual methods
187     to implement specific authentication mechanism.
188 */
189 class GkAuthenticator : public NamedObject
190 {
191 public:
192         /// processing rule for the authenticator
193         enum Control {
194                 /// if this module cannot determine authentication success or failure
195                 /// (due to some missing info, for example), remaining modules will
196                 /// decide about acceptation/rejection of the reqest,
197                 /// otherwise auth processing ends at this module
198                 e_Optional, 
199                 /// the request has to be authenticated by this module
200                 /// and processing is continued with remaining modules
201                 e_Required, 
202                 /// if the request is authenticated by this module, authentication
203                 /// is successful, otherwise the request is rejected
204                 /// (no further modules are processed in both cases)
205                 e_Sufficient 
206         };
207
208         /// authentication status returned from Check methods
209         enum Status {
210                 e_ok = 1, /// the request is authenticated and accepted
211                 e_fail = -1, /// the request is authenticated and rejected
212                 e_next = 0 /// the module could not authenticate the request
213         };
214
215         /// bit masks for event types other than RAS - see miscCheckFlags variable
216         enum MiscCheckEvents {
217                 e_Setup = 0x0001, /// Q.931/H.225 Setup message
218                 e_SetupUnreg = 0x0002 /// Q.931/H.225 Setup message only from an unregistered endpoint
219         };
220
221         
222
223         /** Build a new authenticator object with the given name.
224             It is important to pass proper check flags to signal, which checks
225             are supported/implemented by this authenticator.
226         */
227         GkAuthenticator(
228                 const char* name, /// a name for the module (to be used in the config file)
229                 unsigned supportedRasChecks = ~0U, /// RAS checks supported by this module
230                 unsigned supportedMiscChecks = ~0U /// non-RAS checks supported by this module
231                 );
232                 
233         virtual ~GkAuthenticator();
234
235                 
236         /** @return
237             true if this authenticator provides H.235 compatible security.
238             It simply checks if m_h235Authenticators list is not empty.
239         */
240         virtual bool IsH235Capable() const;
241         
242         /** If the authenticator supports H.235 security,
243             this call returns H.235 security capabilities
244             associated with it. It scans list pointed by m_h235Authenticators.
245                 
246             @return
247             true if H.235 security is supported by this authenticator 
248             and capabilities has been set.
249         */
250         virtual bool GetH235Capability(
251                 /// append supported authentication mechanism to this array
252                 H225_ArrayOf_AuthenticationMechanism& mechanisms,
253                 /// append supported algorithm OIDs for the given authentication
254                 /// mechanism
255                 H225_ArrayOf_PASN_ObjectId& algorithmOIDs
256                 ) const;
257
258         /** Check if this authenticator supports the given
259             H.235 capability (mechanism+algorithmOID) by scanning
260             the m_h235Authenticators list of H.235 capabilities.
261                 
262             @return
263             true if the capability is supported by this module.
264         */
265         virtual bool IsH235Capability(
266                 /// authentication mechanism
267                 const H235_AuthenticationMechanism& mechanism,
268                 /// algorithm OID for the given authentication mechanism
269                 const PASN_ObjectId& algorithmOID
270                 ) const;
271
272         /** @return
273             Control flag determining authenticator behaviour
274             (optional, sufficient, required).
275         */
276         Control GetControlFlag() const { return m_controlFlag; }
277
278         /** @return
279             True if the check is supported (implemented) by this authenticator.
280         */
281         bool IsRasCheckEnabled(
282                 unsigned rasCheck
283                 ) const { return (m_enabledRasChecks & m_supportedRasChecks & rasCheck) == rasCheck; }
284
285         /** @return
286             True if the check is supported (implemented) by this authenticator.
287         */
288         bool IsMiscCheckEnabled(
289                 unsigned miscCheck
290                 ) const { return (m_enabledMiscChecks & m_supportedMiscChecks & miscCheck) == miscCheck; }
291
292         
293         /** Virtual methods overriden in derived classes to perform
294                 the actual authentication. The first parameter is a request
295             to be checked, the second is a H225_XXXRejectReason that can
296             be set if the authentication rejects the request.
297                 
298             @return
299             e_fail - authentication rejected the request
300             e_ok - authentication accepted the request
301             e_next - authentication is not supported for this request
302                      or cannot be determined (SQL failure, no cryptoTokens, ...)
303         */
304         virtual int Check(RasPDU<H225_GatekeeperRequest>& req, unsigned& rejectReason);
305         virtual int Check(RasPDU<H225_UnregistrationRequest>& req, unsigned& rejectReason);
306         virtual int Check(RasPDU<H225_BandwidthRequest>& req, unsigned& rejectReason);
307         virtual int Check(RasPDU<H225_DisengageRequest>& req, unsigned& rejectReason);
308         virtual int Check(RasPDU<H225_LocationRequest>& req, unsigned& rejectReason);
309         virtual int Check(RasPDU<H225_InfoRequest>& req, unsigned& rejectReason);
310
311         /** Authenticate/Authorize RAS or signalling message.
312         
313             @return
314             e_fail - authentication rejected the request
315             e_ok - authentication accepted the request
316             e_next - authentication is not supported for this request
317                      or cannot be determined (SQL failure, no cryptoTokens, ...)
318         */
319         virtual int Check(
320                 /// RRQ to be authenticated/authorized
321                 RasPDU<H225_RegistrationRequest>& request,
322                 /// authorization data (reject reason, ...)
323                 RRQAuthData& authData
324                 );
325         virtual int Check(
326                 /// ARQ to be authenticated/authorized
327                 RasPDU<H225_AdmissionRequest>& request, 
328                 /// authorization data (call duration limit, reject reason, ...)
329                 ARQAuthData& authData
330                 );
331         virtual int Check(
332                 /// Q.931/H.225 Setup to be authenticated
333                 SetupMsg &setup, 
334                 /// authorization data (call duration limit, reject reason, ...)
335                 SetupAuthData& authData
336                 );
337
338 protected:
339         /** @return
340             Default authentication status, if not determined by Check... method.
341         */
342         int GetDefaultStatus() const { return m_defaultStatus; }
343
344         /** @return
345             Config that contains settings for this authenticator.
346         */
347         PConfig* GetConfig() const { return m_config; }
348
349         /// Set bitmasks for checks supported (implemented) by this authenticator
350         void SetSupportedChecks(
351                 unsigned supportedRasChecks, /// RAS checks supported by this module
352                 unsigned supportedMiscChecks /// non-RAS checks supported by this module
353                 );
354
355         /** @return
356             Bitmask for RAS checks supported/implemented by this authenticator.
357         */
358         unsigned GetSupportedRasChecks() const { return m_supportedRasChecks; }
359
360         /** @return
361             Bitmask for non-RAS checks supported/implemented by this authenticator.
362         */
363         unsigned GetSupportedMiscChecks() const { return m_supportedMiscChecks; }
364
365         /** Should be called only from derived constructor to add supported
366             H.235 capabilities (if any).
367         */
368         void AppendH235Authenticator(
369                 H235Authenticator* h235Auth /// H.235 authenticator to append
370                 );
371
372         /** @return
373             A string that can be used to identify an account name
374             associated with the call.
375         */
376         virtual PString GetUsername(
377                 /// RRQ message with additional data
378                 const RasPDU<H225_RegistrationRequest>& request
379                 ) const;
380         virtual PString GetUsername(
381                 /// ARQ message with additional data
382                 const RasPDU<H225_AdmissionRequest>& request,
383                 /// additional data, like call record and requesting endpoint
384                 ARQAuthData& authData
385                 ) const;
386         virtual PString GetUsername(
387                 /// Q.931/H.225 Setup with additional data
388                 const SetupMsg &setup, 
389                 /// additional data
390                 SetupAuthData &authData
391                 ) const;
392
393         /** @return
394             A string that can be used to identify a calling number.
395         */
396         virtual PString GetCallingStationId(
397                 /// ARQ message with additional data
398                 const RasPDU<H225_AdmissionRequest>& request,
399                 /// additional data, like call record and requesting endpoint
400                 ARQAuthData& authData
401                 ) const;
402         virtual PString GetCallingStationId(
403                 /// Q.931/H.225 Setup to be authenticated
404                 const SetupMsg &setup, 
405                 /// additional data
406                 SetupAuthData& authData
407                 ) const;
408
409         /** @return
410             A string that can be used to identify a calling number.
411         */
412         virtual PString GetCalledStationId(
413                 /// ARQ message with additional data
414                 const RasPDU<H225_AdmissionRequest>& request,
415                 /// additional data, like call record and requesting endpoint
416                 ARQAuthData& authData
417                 ) const;
418         virtual PString GetCalledStationId(
419                 /// Q.931/H.225 Setup to be authenticated
420                 const SetupMsg &setup, 
421                 /// additional data
422                 SetupAuthData& authData
423                 ) const;
424
425         /// @return     Number actually dialed by the user (before rewrite)
426         PString GetDialedNumber(
427                 /// ARQ message with additional data
428                 const RasPDU<H225_AdmissionRequest>& request,
429                 /// additional data
430                 ARQAuthData& authData
431                 ) const;
432                 
433         /// @return     Number actually dialed by the user (before rewrite)
434         virtual PString GetDialedNumber(
435                 /// Q.931/H.225 Setup to be authenticated
436                 const SetupMsg &setup, 
437                 /// additional data
438                 SetupAuthData& authData
439                 ) const;
440
441         /// a list of H.235 capabilities supported by this module (if any)
442         H235Authenticators* m_h235Authenticators;
443
444 private:
445         GkAuthenticator();
446         GkAuthenticator(const GkAuthenticator&);
447         GkAuthenticator & operator=(const GkAuthenticator&);
448
449 private:
450         /// default status to be returned, if not determined otherwise
451         Status m_defaultStatus;
452         /// processing rule for this authenticator
453         Control m_controlFlag;
454         /// bit flags for RAS messages to be authenticated (this enforces the limit
455         /// of first 32 RAS messages being supported)
456         unsigned m_enabledRasChecks;
457         /// bit flags with RAS checks supported by a given authenticator
458         unsigned m_supportedRasChecks;
459         /// bit flags for other event types to be authenticated (like Q.931 Setup)
460         unsigned m_enabledMiscChecks;
461         /// bit flags with non-RAS checks supported by a given authenticator
462         unsigned m_supportedMiscChecks;
463         /// authenticator config
464         PConfig* m_config;
465 };
466
467 /** Cache used by some authenticators to remember key-value associations,
468     like username-password. It increases performance, as backend 
469     does not need to be queried each time.
470 */
471 class CacheManager 
472 {
473 public:
474         CacheManager(
475                 long timeout = -1 /// cache timeout - expiry period (seconds)
476                 ) : m_ttl(timeout) {}
477
478         /** Get a value associated with the key.
479         
480             @return
481             true if association has been found and the value is valid,
482             false if the key-value pair is not cached or the cache expired
483         */
484         bool Retrieve(
485                 const PString& key, /// the key to look for
486                 PString& value /// filled with the value on return
487                 ) const;
488                 
489         /// Store a key-value association in the cache
490         void Save(
491                 const PString& key, /// a key to be stored
492                 const PString& value /// a value to be associated with the key
493                 );
494
495         void SetTimeout(
496                 long newTimeout /// new cache expiration timeout
497                 ) { m_ttl = newTimeout; }
498
499 private:
500         CacheManager(const CacheManager&);
501         CacheManager & operator=(const CacheManager&);
502         
503 private:
504         /// cache timeout (seconds), 0 = do not cache, -1 = never expires
505         long m_ttl;
506         /// cached key-value pairs
507         std::map<PString, PString> m_cache;
508         /// timestamps for key-value pair expiration calculation
509         std::map<PString, long> m_ctime;
510         /// mutex for multiple read/mutual write access to the cache
511         mutable PReadWriteMutex m_rwmutex;
512 };      
513
514 /** A base class for all authenticators that only checks if username-password
515     pairs match. This authenticator checks H.235 tokens/cryptoTokens carried
516     inside RAS requests. Currently, only simple MD5 password hash and Cisco CAT
517     authentication token types are supported.
518         
519     Derived authenticators usually override only GetPassword virtual method.
520 */
521 class SimplePasswordAuth : public GkAuthenticator 
522 {
523 public:
524         enum SupportedRasChecks {
525                 /// bitmask of RAS checks implemented by this module
526                 SimplePasswordAuthRasChecks = RasInfo<H225_GatekeeperRequest>::flag
527                         | RasInfo<H225_RegistrationRequest>::flag
528                         | RasInfo<H225_UnregistrationRequest>::flag
529                         | RasInfo<H225_BandwidthRequest>::flag
530                         | RasInfo<H225_DisengageRequest>::flag
531                         | RasInfo<H225_LocationRequest>::flag
532                         | RasInfo<H225_InfoRequest>::flag
533                         | RasInfo<H225_AdmissionRequest>::flag
534         };
535
536         SimplePasswordAuth(
537                 const char* name, /// a name for this module (a config section name)
538                 unsigned supportedRasChecks = SimplePasswordAuthRasChecks,
539                 unsigned supportedMiscChecks = 0 /// none supported
540                 );
541                 
542         virtual ~SimplePasswordAuth();
543
544         // overriden from class GkAuthenticator
545         virtual int Check(RasPDU<H225_GatekeeperRequest>& req, unsigned& rejectReason);
546         virtual int Check(RasPDU<H225_UnregistrationRequest>& req, unsigned& rejectReason);
547         virtual int Check(RasPDU<H225_BandwidthRequest>& req, unsigned& rejectReason);
548         virtual int Check(RasPDU<H225_DisengageRequest>& req, unsigned& rejectReason);
549         virtual int Check(RasPDU<H225_LocationRequest>& req, unsigned& rejectReason);
550         virtual int Check(RasPDU<H225_InfoRequest>& req, unsigned& rejectReason);
551
552         /** Authenticate/Authorize RAS or signalling message. 
553             An override from GkAuthenticator.
554         
555             @return
556             e_fail - authentication rejected the request
557             e_ok - authentication accepted the request
558             e_next - authentication is not supported for this request
559                      or cannot be determined (SQL failure, no cryptoTokens, ...)
560         */
561         virtual int Check(
562                 /// ARQ to be authenticated/authorized
563                 RasPDU<H225_RegistrationRequest>& request, 
564                 /// authorization data (reject reason, ...)
565                 RRQAuthData& authData
566                 );
567         virtual int Check(
568                 /// ARQ to be authenticated/authorized
569                 RasPDU<H225_AdmissionRequest>& request, 
570                 /// authorization data (call duration limit, reject reason, ...)
571                 ARQAuthData& authData
572                 );
573
574 protected:
575         /** Get a password associated with the identifier.
576         
577             @return
578             true if the password is returned, false if the password 
579             could not be found.
580         */
581         virtual bool GetPassword(
582                 const PString& id, /// get the password for this id
583                 PString& passwd /// filled with the password on return
584                 );
585         
586         /** Validate username/password carried inside the tokens. This method
587             supports only CAT and clear text tokens.
588                 
589             @return
590             e_ok if the username/password carried inside the tokens is valid,
591             e_fail if the username/password carried inside the tokens is invalid,
592             e_next if no recognized tokens have been found
593         */
594         virtual int CheckTokens(
595                 /// an array of tokens to be checked
596                 const H225_ArrayOf_ClearToken& tokens,
597                 /// aliases for the endpoint that generated the tokens
598                 const H225_ArrayOf_AliasAddress* aliases
599                 );
600                 
601         /** Validate username/password carried inside the tokens. This method
602             supports only simple MD5 pwdHash cryptoTokens.
603                 
604             @return
605             e_ok if the username/password carried inside the tokens is valid,
606             e_fail if the username/password carried inside the tokens is invalid,
607             e_next if no recognized tokens have been found
608         */
609         virtual int CheckCryptoTokens(
610                 /// an array of cryptoTokens to be checked
611                 const H225_ArrayOf_CryptoH323Token& cryptoTokens, 
612                 /// aliases for the endpoint that generated the tokens
613                 const H225_ArrayOf_AliasAddress* aliases,
614                 /// raw data for RAS PDU - required to validate some tokens
615                 /// like H.235 Auth Procedure I
616                 const PBYTEArray& rawPDU
617                 );
618
619         /** Retrieve username carried inside the tokens. 
620             @return
621             username carried inside the token
622         */
623         bool ResolveUserName(
624                 /// an array of tokens to be checked
625                 const H225_ArrayOf_ClearToken& tokens,
626                 /// aliases for the endpoint that generated the tokens
627             const H225_ArrayOf_CryptoH323Token& crytotokens,
628                 /// UserName detected.
629                 PString & username
630                 );
631
632         /** A family of template functions that check tokens/cryptoTokens
633             inside RAS messages.
634                 
635             @return
636             e_ok if the username/password carried inside the tokens is valid,
637             e_fail if the username/password carried inside the tokens is invalid,
638             e_next if no recognized tokens have been found
639         */
640         template<class RAS> int doCheck(
641                 /// RAS request to be authenticated
642                 const RasPDU<RAS>& request,
643                 /// list of aliases for the endpoint sending the request
644                 const H225_ArrayOf_AliasAddress* aliases = NULL
645                 )
646         {
647                 const RAS& req = request;
648                 bool finalResult = false;
649                 
650 #ifdef OpenH323Factory
651                 PString username = PString();
652                 PString password = PString();
653                 if (!ResolveUserName(req.m_tokens, req.m_cryptoTokens,username)) {
654             PTRACE(4, "GKAUTH\t" << GetName() << " No username resolved from tokens.");
655                         return false;
656                 }
657
658                 if ((aliases == NULL) || (FindAlias(*aliases, username) == P_MAX_INDEX)) {
659             PTRACE(4, "GKAUTH\t" << GetName() << " Token username " << username << " does not match aliases for Endpoint");
660                         return false;
661                 }
662
663                 if (!InternalGetPassword(username, password)) {
664                                 PTRACE(4, "GKAUTH\t" << GetName() << " password not found for " << username );
665                         // do not return false let the authenticator decide whether it requires a password or not.
666                 }
667
668         for (PINDEX i = 0; i < m_h235Authenticators->GetSize();  i++) {
669           H235Authenticator * authenticator = (H235Authenticator *)(*m_h235Authenticators)[i].Clone();
670
671                   authenticator->SetLocalId(username);
672                   authenticator->SetPassword(password);
673
674           H235Authenticator::ValidationResult result = authenticator->ValidateTokens(req.m_tokens, 
675                                                                                 req.m_cryptoTokens, request->m_rasPDU);
676           switch (result) {
677              case H235Authenticator::e_OK :
678                PTRACE(4, "GKAUTH\tAuthenticator " << authenticator << " succeeded");
679                return e_ok;
680
681              case H235Authenticator::e_Absent :
682                PTRACE(6, "GKAUTH\tAuthenticator " << authenticator << " absent from PDU");
683                break;
684
685              case H235Authenticator::e_Disabled :
686                PTRACE(6, "GKAUTH\tAuthenticator " << authenticator << " disabled");
687                break;
688
689              default : // Various other failure modes
690                PTRACE(6, "GKAUTH\tAuthenticator " << authenticator << " failed: " << (int)result);
691                return e_fail;
692            }
693
694          }
695 #else
696                 int result;
697                 if (req.HasOptionalField(RAS::e_cryptoTokens)) {
698                         if ((result = CheckCryptoTokens(req.m_cryptoTokens, aliases, 
699                                         request->m_rasPDU)) == e_fail)
700                                 return e_fail;
701                         finalResult = (result == e_ok);
702                 }
703                 if (req.HasOptionalField(RAS::e_tokens)) {
704                         if ((result = CheckTokens(req.m_tokens, aliases)) == e_fail)
705                                 return e_fail;
706                         finalResult = finalResult || (result == e_ok);
707                 }
708 #endif
709                 return finalResult ? e_ok : GetDefaultStatus();
710         }
711
712         /// Set new timeout for username/password pairs cache
713         void SetCacheTimeout(
714                 long newTimeout
715                 ) { m_cache->SetTimeout(newTimeout); }
716
717         /** @return
718             True if usernames should match one of endpoint aliases.
719         */
720         bool GetCheckID() const { return m_checkID; }
721
722 private:
723         /** Get password for the given user. Examine password cache first.
724         
725             @return
726             true if the password has been found.
727     */
728         bool InternalGetPassword(
729                 const PString& id, /// get the password for this id
730                 PString& passwd /// filled with the password on return
731                 );
732
733         SimplePasswordAuth();
734         SimplePasswordAuth(const SimplePasswordAuth&);
735         SimplePasswordAuth& operator=(const SimplePasswordAuth&);
736         
737 private:
738         /// an encryption key used to decrypt passwords from the config file
739         int m_encryptionKey;
740         /// if true, generalID has to be also in the endpoint alias list
741         bool m_checkID;
742         /// cache for username/password pairs
743         CacheManager* m_cache;
744 };
745
746
747 /** A base class for all authenticators that validate endpoints (requests)
748     by alias and/or IP address only.
749         
750     Derived authenticators usually override GetAuthConditionString virtual 
751     method only.
752 */
753 class AliasAuth : public GkAuthenticator 
754 {
755 public:
756         enum SupportedRasChecks {
757                 /// bitmask of RAS checks implemented by this module
758                 AliasAuthRasChecks = RasInfo<H225_RegistrationRequest>::flag
759         };
760
761         AliasAuth(
762                 const char* name, /// a name for this module (a config section name)
763                 unsigned supportedRasChecks = AliasAuthRasChecks,
764                 unsigned supportedMiscChecks = 0
765                 );
766
767         virtual ~AliasAuth();
768         
769         /// an override from GkAuthenticator
770         virtual int Check(
771                 /// ARQ to be authenticated/authorized
772                 RasPDU<H225_RegistrationRequest>& request, 
773                 /// authorization data (reject reason, ...)
774                 RRQAuthData& authData
775                 );
776
777 protected:
778         /** Validate that the signalling addresses match the given condition.
779             The condition consists of one or more auth rules.
780                 
781             @return
782             true if the signalling addresses match the condition.
783         */
784         virtual bool doCheck(
785                 /// an array of source signalling addresses for an endpoint that sent the request
786                 const H225_ArrayOf_TransportAddress& sigaddr,
787                 /// auth condition string as returned by GetAuthConditionString
788                 const PString& condition
789                 );
790                 
791         /** Validate that the signalling address matches the given auth rule.
792         
793             @return
794             true if the signal address matches the rule.
795         */
796         virtual bool CheckAuthRule(
797                 /// a signalling address for the endpoint that sent the request
798                 const H225_TransportAddress& sigaddr,
799                 /// the auth rule to be used for checking
800                 const PString& authrule
801                 );
802
803         /** Get AliasAuth condition string for the given alias. 
804             This implementation searches RasSrv::RRQAuth section for the string.
805             The string is then used to accept/reject the request, optionally
806             checking its source signaliing addresses. The string consists of
807             one or more auth rules separated by '|' or '&' character.
808                 
809                 @return
810                 The AliasAuth condition string for the given alias.
811          */
812         virtual bool GetAuthConditionString(
813                 /// an alias the condition string is to be retrieved for
814                 const PString& alias,
815                 /// filled with auth condition string that has been found
816                 PString& authCond
817                 );
818
819         /// Set new timeout for username/password pairs cache
820         void SetCacheTimeout(
821                 long newTimeout
822                 ) { m_cache->SetTimeout(newTimeout); }
823                 
824 private:
825         /** Get auth condition string for the given user. 
826             Examine the cache first.
827         
828             @return
829             true if the auth condition string has been found.
830     */
831         bool InternalGetAuthConditionString(
832                 const PString& id, /// get the password for this id
833                 PString& authCond /// filled with the auth condition string on return
834                 );
835                 
836         AliasAuth();
837         AliasAuth(const AliasAuth&);
838         AliasAuth& operator=(const AliasAuth&);
839         
840 private:
841         /// cache for username/password pairs
842         CacheManager* m_cache;
843 };
844
845
846 /** A list of authenticators. Usually created as a single global object
847     by the RasServer.
848 */
849 class GkAuthenticatorList 
850 {
851 public:
852         /// creates an empty list - OnRealod builds the actual stack of authenticator
853         GkAuthenticatorList();
854         ~GkAuthenticatorList();
855
856         /// read the config file and build a new stack of authenticator modules
857         void OnReload();
858         
859         /** Select H.235 authentication mechanisms supported both by the endpoint
860             sending GRQ and all the authenticators, and copy these into GCF.
861             If no common H.235 capabilities can be found, do not select 
862             any authentication mechanisms with GCF.
863         */
864         void SelectH235Capability(
865                 const H225_GatekeeperRequest& grq, 
866                 H225_GatekeeperConfirm& gcf
867                 );
868
869         /** Authenticate the request through all configured authenticators.
870             Currently, only RAS requests are supported.
871                                 
872             @return
873             true if the request should be accepted, false to reject the request.
874         */
875         template<class RAS> bool Validate(
876                 /// the request to be validated by authenticators
877                 RasPDU<RAS>& request,
878                 /// H225_RegistrationRejectReason to be set if the request is rejected
879                 unsigned& rejectReason
880                 )
881         {
882                 ReadLock lock(m_reloadMutex);
883                 std::list<GkAuthenticator*>::const_iterator i = m_authenticators.begin();
884                 while (i != m_authenticators.end()) {
885                         GkAuthenticator* auth = *i++;
886                         if (auth->IsRasCheckEnabled(RasInfo<RAS>::flag)) {
887                                 const int result = auth->Check(request, rejectReason);
888                                 if (result == GkAuthenticator::e_ok) {
889                                         PTRACE(3, "GKAUTH\t" << auth->GetName() << ' ' 
890                                                 << request.GetTagName() << " check ok"
891                                                 );
892                                         if (auth->GetControlFlag() != GkAuthenticator::e_Required)
893                                                 return true;
894                                 } else if (result == GkAuthenticator::e_fail) {
895                                         PTRACE(3, "GKAUTH\t" << auth->GetName() << ' '
896                                                 << request.GetTagName() << " check failed"
897                                                 );
898                                         return false;
899                                 }
900                         }
901                 }
902                 return true;
903         }
904         
905         /** Authenticate and authorize RRQ through all configured authenticators.
906                                 
907             @return
908             true if the endpoint should be registered, false to send RRJ.
909         */
910         bool Validate(
911                 /// RRQ to be validated by authenticators
912                 RasPDU<H225_RegistrationRequest>& request,
913                 /// authorization data (reject reason, ...)
914                 RRQAuthData& authData
915                 );
916                 
917         /** Authenticate and authorize (set call duration limit) ARQ 
918             through all configured authenticators.
919                                 
920             @return
921             true if the call should be admitted, false to send ARJ.
922         */
923         bool Validate(
924                 /// ARQ to be validated by authenticators
925                 RasPDU<H225_AdmissionRequest>& request,
926                 /// authorization data (call duration limit, reject reason, ...)
927                 ARQAuthData& authData
928                 );
929         
930         /** Authenticate and authorize (set call duration limit) Q.931/H.225 Setup 
931             through all configured authenticators.
932                                 
933             @return
934             true if the call should be accepted, false to send ReleaseComplete.
935         */
936         bool Validate(
937                 /// Q.931/H.225 Setup to be authenticated
938                 SetupMsg &setup, 
939                 /// authorization data (call duration limit, reject reason, ...)
940                 SetupAuthData& authData
941                 );
942
943 private:
944         GkAuthenticatorList(const GkAuthenticatorList&);
945         GkAuthenticatorList& operator=(const GkAuthenticatorList&);
946
947 private:
948         /// a list of all configured authenticators
949         std::list<GkAuthenticator*> m_authenticators;
950         /// reload/destroy mutex
951         PReadWriteMutex m_reloadMutex;
952         /// the most common authentication capabilities 
953         /// shared by all authenticators on the list
954         H225_ArrayOf_AuthenticationMechanism* m_mechanisms;
955         H225_ArrayOf_PASN_ObjectId* m_algorithmOIDs;
956 };
957
958 /** A factory template for authenticator objects. When you create
959     your own authenticator class (derived from GkAuthenticator),
960     you need to register it and tell the gatekeeper how to instantiate it.
961     You can do it by putting the following code:
962         
963     namespace {
964         GkAuthCreator<MyAuthClass> MY_AUTH_FACTORY("MyAuthClass");
965     }
966         
967     This registers "MyAuthClass" string as the name to be used in the config
968     for MyAuthClass authenticator. Of course, authenticator name 
969     and class name do not have to be the same.
970 */
971 template<class Auth>
972 struct GkAuthCreator : public Factory<GkAuthenticator>::Creator0 {
973         GkAuthCreator(const char *n) : Factory<GkAuthenticator>::Creator0(n) {}
974         virtual GkAuthenticator *operator()() const { return new Auth(m_id); }
975 };
976
977 #endif  // GKAUTH_H