OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / user / gnugk / ipauth.cxx
1 /*
2  * ipauth.cxx
3  *
4  * IP based authentication modules
5  *
6  * @(#) $Id: ipauth.cxx,v 1.4 2006/07/06 15:25:13 willamowius Exp $
7  *
8  * Copyright (c) 2005, Michal Zygmuntowicz
9  *
10  * This work is published under the GNU Public License (GPL)
11  * see file COPYING for details.
12  * We also explicitely grant the right to link this code
13  * with the OpenH323 library.
14  */
15 #include <ptlib.h>
16 #include <h225.h>
17
18 #include "gk_const.h"
19 #include "h323util.h"
20 #include "stl_supp.h"
21 #include "Toolkit.h"
22 #include "RasPDU.h"
23 #include "RasTbl.h"
24 #include "sigmsg.h"
25 #include "ipauth.h"
26
27 class IPAuthPrefix {
28 public:
29         IPAuthPrefix();
30         IPAuthPrefix(bool a, const PString &);
31         IPAuthPrefix(const IPAuthPrefix &);
32
33         void AddPrefix(const PString &);
34         void SortPrefix(bool greater = true);
35         int PrefixMatch(const PString &) const;
36         std::string PrintOn(void) const;
37         std::string PrintPrefix(void) const;
38
39         IPAuthPrefix& operator=(const IPAuthPrefix&);
40         IPAuthPrefix& operator=(bool);
41
42         typedef std::vector<std::string>::iterator prefix_iterator;
43         typedef std::vector<std::string>::const_iterator const_prefix_iterator;
44
45         bool auth;
46
47 protected:
48         std::vector<std::string> Prefixs;
49 };
50
51 /// Text file based IP authentication
52 class FileIPAuth : public IPAuthBase {
53 public:
54         typedef std::pair<NetworkAddress, IPAuthPrefix> IPAuthEntry;
55
56         
57         /// Create text file based authenticator
58         FileIPAuth( 
59                 /// authenticator name from Gatekeeper::Auth section
60                 const char *authName
61                 );
62
63         /// Destroy the authenticator
64         virtual ~FileIPAuth();
65
66 protected:
67         /// Overriden from IPAuthBase
68         virtual int CheckAddress(
69                 const PIPSocket::Address &addr, /// IP address the request comes from
70                 WORD port, /// port number the request comes from
71                 const PString &number
72                 );
73                                 
74 private:
75         FileIPAuth();
76         /* No copy constructor allowed */
77         FileIPAuth(const FileIPAuth&);
78         /* No operator= allowed */
79         FileIPAuth& operator=(const FileIPAuth&);
80         
81 private:
82         typedef std::vector<IPAuthEntry> IPAuthList;
83
84         IPAuthList m_authList;
85 };
86
87
88 IPAuthBase::IPAuthBase( 
89         /// authenticator name from Gatekeeper::Auth section
90         const char *authName,
91         /// bitmask with supported RAS checks
92         unsigned supportedRasChecks,
93         /// bitmask with supported non-RAS checks
94         unsigned supportedMiscChecks
95         ) : GkAuthenticator(authName, supportedRasChecks, supportedMiscChecks)
96 {
97 }
98
99 IPAuthBase::~IPAuthBase()
100 {
101 }
102
103 int IPAuthBase::Check(
104         /// GRQ RAS message to be authenticated
105         RasPDU<H225_GatekeeperRequest> &grqPdu, 
106         /// gatekeeper request reject reason
107         unsigned &rejectReason
108         )
109 {
110         return CheckAddress(grqPdu->m_peerAddr, grqPdu->m_peerPort, PString());
111 }
112
113 int IPAuthBase::Check(
114         /// RRQ RAS message to be authenticated
115         RasPDU<H225_RegistrationRequest> &rrqPdu, 
116         /// authorization data (reject reason, ...)
117         RRQAuthData &authData
118         )
119 {
120         return CheckAddress(rrqPdu->m_peerAddr, rrqPdu->m_peerPort, PString());
121 }
122
123 int IPAuthBase::Check(
124         /// LRQ nessage to be authenticated
125         RasPDU<H225_LocationRequest> &lrqPdu, 
126         /// location request reject reason
127         unsigned &rejectReason
128         )
129 {
130         return CheckAddress(lrqPdu->m_peerAddr, lrqPdu->m_peerPort, PString());
131 }
132
133 int IPAuthBase::Check(
134         /// Q.931/H.225 Setup message to be authenticated
135         SetupMsg &setup,
136         /// authorization data (call duration limit, reject reason, ...)
137         SetupAuthData& authData
138         )
139 {
140         PIPSocket::Address addr;
141         WORD port = 0;
142         setup.GetPeerAddr(addr, port);
143         PString number;
144         setup.GetQ931().GetCalledPartyNumber(number);
145
146         return CheckAddress(addr, port, number);
147 }
148
149
150 /////////////
151 // FileIPAuth
152 /////////////
153
154 namespace {
155 const char *FileIPAuthSecName = "FileIPAuth";
156
157 struct IPAuthEntry_greater : public binary_function<FileIPAuth::IPAuthEntry, FileIPAuth::IPAuthEntry, bool> {
158
159         bool operator()(
160                 const FileIPAuth::IPAuthEntry &a,
161                 const FileIPAuth::IPAuthEntry &b
162                 ) const 
163         {
164                 const int diff = a.first.Compare(b.first);
165                 if (diff == 0)
166                         return !a.second.auth;
167                 return diff > 0;
168         }
169 };
170
171 } /* anonymous namespace */
172
173 FileIPAuth::FileIPAuth( 
174         /// authenticator name from Gatekeeper::Auth section
175         const char *authName
176         ) : IPAuthBase(authName)
177 {
178         bool dynamicCfg = false;
179         PConfig *cfg = GkConfig();
180         
181         if (cfg->HasKey(FileIPAuthSecName, "include")) {
182                 const PFilePath fp(cfg->GetString(FileIPAuthSecName, "include", ""));
183                 if (!PFile::Exists(fp)) {
184                         PTRACE(0, GetName() << "\tCould not read the include file '"
185                                 << fp << "': the file does not exist"
186                                 );
187                         return;
188                 }
189                 cfg = new PConfig(fp, authName);
190                 dynamicCfg = true;
191         }
192
193         PStringToString kv = cfg->GetAllKeyValues(FileIPAuthSecName);
194         
195         m_authList.reserve(kv.GetSize());
196         
197         for (PINDEX i = 0; i < kv.GetSize(); i++) {
198                 const PString &key = kv.GetKeyAt(i);
199                 int position = 0;
200                 if (key[0] == '#')
201                         continue;
202                 
203                 IPAuthEntry entry;
204                 
205                 entry.first = (key == "*" || key == "any") ? NetworkAddress() : NetworkAddress(key);
206
207                 PString auth(kv.GetDataAt(i));
208                 PString prefix(".");
209
210                 if ((position = auth.Find(';', position)) != P_MAX_INDEX) {
211                         position++;
212                         prefix = auth(position, auth.GetLength());
213                         position--;
214                         auth.Delete(position, auth.GetLength() - position);
215                 }
216
217                 entry.second.auth = PCaselessString("allow") == auth;
218                 entry.second.AddPrefix(prefix);
219                 entry.second.SortPrefix(false);
220                 
221                 m_authList.push_back(entry);
222         }
223
224         std::stable_sort(m_authList.begin(), m_authList.end(), IPAuthEntry_greater());
225         
226         PTRACE(5, GetName() << "\t" << m_authList.size() << " entries loaded");
227
228 #if PTRACING
229         if (PTrace::CanTrace(6)) {
230                 ostream &strm = PTrace::Begin(6, __FILE__, __LINE__);
231                 strm << GetName() << " entries:\n";
232                 IPAuthList::const_iterator entry = m_authList.begin();
233                 while (entry != m_authList.end()) {
234                         strm << "\t" << entry->first.AsString() << " = " 
235                                 << (entry->second.auth ? "allow" : "reject")
236                                 << (entry->second.auth ? entry->second.PrintOn() : "") << endl;
237                         entry++;
238                 }
239                 PTrace::End(strm);
240         }
241 #endif
242
243         if (dynamicCfg) {
244                 delete cfg;
245                 cfg = NULL;
246         }
247 }
248
249 FileIPAuth::~FileIPAuth()
250 {
251 }
252
253 int FileIPAuth::CheckAddress(
254         const PIPSocket::Address &addr, /// IP address the request comes from
255         WORD port, /// port number the request comes from
256         const PString &number
257         )
258 {
259         IPAuthList::const_iterator entry = m_authList.begin();
260         while (entry != m_authList.end()) {
261                 if (entry->first.IsAny() || addr << entry->first) {
262                         if (entry->second.auth && !number.IsEmpty()) {
263                                 int len = entry->second.PrefixMatch(number);
264                                 PTRACE(5, GetName() << "\tIP " << addr.AsString() 
265                                         << (len ? " accepted" : " rejected")
266                                         << " for Called " << number
267                                         );
268                                 return len ? e_ok : e_fail;
269                         }
270                         return entry->second.auth ? e_ok : e_fail;
271                 }
272                 entry++;
273         }
274         return GetDefaultStatus();
275 }
276
277
278 IPAuthPrefix::IPAuthPrefix() :
279         auth(false)
280 {}
281
282 IPAuthPrefix::IPAuthPrefix(bool a, const PString & prefixes)
283 {
284         auth = a;
285         AddPrefix(prefixes);
286 }
287
288 IPAuthPrefix::IPAuthPrefix(const IPAuthPrefix & obj)
289 {
290         auth = obj.auth;
291
292         const_prefix_iterator Iter = obj.Prefixs.begin();
293         const_prefix_iterator eIter = obj.Prefixs.end();
294         while (Iter != eIter) {
295                 Prefixs.push_back(Iter->c_str());
296                 ++Iter;
297         }
298 }
299
300 IPAuthPrefix& IPAuthPrefix::operator=(const IPAuthPrefix & obj)
301 {
302         auth = obj.auth;
303         Prefixs.clear();
304
305         const_prefix_iterator Iter = obj.Prefixs.begin();
306         const_prefix_iterator eIter = obj.Prefixs.end();
307         while (Iter != eIter) {
308                 Prefixs.push_back(Iter->c_str());
309                 ++Iter;
310         }
311
312         return *this;
313 }
314
315 IPAuthPrefix& IPAuthPrefix::operator=(bool a)
316 {
317         auth = a;
318         return *this;
319 }
320
321 void IPAuthPrefix::AddPrefix(const PString & prefixes)
322 {
323         PStringArray p(prefixes.Tokenise(" ,;\t\n", false));
324         for (PINDEX i = 0; i < p.GetSize(); ++i)
325                 Prefixs.push_back((const char *)p[i]);
326 }
327
328 void IPAuthPrefix::SortPrefix(bool greater)
329 {
330         // remove duplicate aliases
331         if (greater)
332                 sort(Prefixs.begin(), Prefixs.end(), str_prefix_greater());
333         else
334                 sort(Prefixs.begin(), Prefixs.end(), str_prefix_lesser());
335         prefix_iterator Iter = std::unique(Prefixs.begin(), Prefixs.end());
336         Prefixs.erase(Iter, Prefixs.end());
337 }
338
339 int IPAuthPrefix::PrefixMatch(const PString & number) const
340 {
341         if (number.IsEmpty())
342                 return 0;
343
344         const char * alias = (const char*)(number);
345
346         if (!alias)
347                 return 0;
348
349         const_prefix_iterator Iter = Prefixs.begin();
350         const_prefix_iterator eIter = Prefixs.end();
351
352         if (Iter == eIter)
353                 return 1;
354
355         while (Iter != eIter) {
356                 const int len = MatchPrefix(alias, Iter->c_str());
357                 if (len > 0) {
358                         return len;
359                 }
360                 ++Iter;
361         }
362
363         return 0;
364 }
365
366 std::string IPAuthPrefix::PrintOn(void) const
367 {
368         if (!auth)
369                 return std::string(" to called any");
370
371         std::string prefix = PrintPrefix();
372
373         if (prefix == ".")
374                 prefix = "any";
375         std::string ret(" to called ");
376         ret += prefix;
377         return ret;
378 }
379
380 std::string IPAuthPrefix::PrintPrefix(void) const
381 {
382         std::string prefix;
383         const_prefix_iterator Iter = Prefixs.begin();
384         const_prefix_iterator eIter = Prefixs.end();
385         while (Iter != eIter) {
386                 prefix += *Iter;
387                 prefix += ",";
388                 ++Iter;
389         }
390
391         return prefix;
392 }
393                                 
394 namespace { // anonymous namespace
395         GkAuthCreator<FileIPAuth> FileIPAuthCreator("FileIPAuth");
396 } // end of anonymous namespace