4 * IP based authentication modules
6 * @(#) $Id: ipauth.cxx,v 1.4 2006/07/06 15:25:13 willamowius Exp $
8 * Copyright (c) 2005, Michal Zygmuntowicz
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.
30 IPAuthPrefix(bool a, const PString &);
31 IPAuthPrefix(const IPAuthPrefix &);
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;
39 IPAuthPrefix& operator=(const IPAuthPrefix&);
40 IPAuthPrefix& operator=(bool);
42 typedef std::vector<std::string>::iterator prefix_iterator;
43 typedef std::vector<std::string>::const_iterator const_prefix_iterator;
48 std::vector<std::string> Prefixs;
51 /// Text file based IP authentication
52 class FileIPAuth : public IPAuthBase {
54 typedef std::pair<NetworkAddress, IPAuthPrefix> IPAuthEntry;
57 /// Create text file based authenticator
59 /// authenticator name from Gatekeeper::Auth section
63 /// Destroy the authenticator
64 virtual ~FileIPAuth();
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
76 /* No copy constructor allowed */
77 FileIPAuth(const FileIPAuth&);
78 /* No operator= allowed */
79 FileIPAuth& operator=(const FileIPAuth&);
82 typedef std::vector<IPAuthEntry> IPAuthList;
84 IPAuthList m_authList;
88 IPAuthBase::IPAuthBase(
89 /// authenticator name from Gatekeeper::Auth section
91 /// bitmask with supported RAS checks
92 unsigned supportedRasChecks,
93 /// bitmask with supported non-RAS checks
94 unsigned supportedMiscChecks
95 ) : GkAuthenticator(authName, supportedRasChecks, supportedMiscChecks)
99 IPAuthBase::~IPAuthBase()
103 int IPAuthBase::Check(
104 /// GRQ RAS message to be authenticated
105 RasPDU<H225_GatekeeperRequest> &grqPdu,
106 /// gatekeeper request reject reason
107 unsigned &rejectReason
110 return CheckAddress(grqPdu->m_peerAddr, grqPdu->m_peerPort, PString());
113 int IPAuthBase::Check(
114 /// RRQ RAS message to be authenticated
115 RasPDU<H225_RegistrationRequest> &rrqPdu,
116 /// authorization data (reject reason, ...)
117 RRQAuthData &authData
120 return CheckAddress(rrqPdu->m_peerAddr, rrqPdu->m_peerPort, PString());
123 int IPAuthBase::Check(
124 /// LRQ nessage to be authenticated
125 RasPDU<H225_LocationRequest> &lrqPdu,
126 /// location request reject reason
127 unsigned &rejectReason
130 return CheckAddress(lrqPdu->m_peerAddr, lrqPdu->m_peerPort, PString());
133 int IPAuthBase::Check(
134 /// Q.931/H.225 Setup message to be authenticated
136 /// authorization data (call duration limit, reject reason, ...)
137 SetupAuthData& authData
140 PIPSocket::Address addr;
142 setup.GetPeerAddr(addr, port);
144 setup.GetQ931().GetCalledPartyNumber(number);
146 return CheckAddress(addr, port, number);
155 const char *FileIPAuthSecName = "FileIPAuth";
157 struct IPAuthEntry_greater : public binary_function<FileIPAuth::IPAuthEntry, FileIPAuth::IPAuthEntry, bool> {
160 const FileIPAuth::IPAuthEntry &a,
161 const FileIPAuth::IPAuthEntry &b
164 const int diff = a.first.Compare(b.first);
166 return !a.second.auth;
171 } /* anonymous namespace */
173 FileIPAuth::FileIPAuth(
174 /// authenticator name from Gatekeeper::Auth section
176 ) : IPAuthBase(authName)
178 bool dynamicCfg = false;
179 PConfig *cfg = GkConfig();
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"
189 cfg = new PConfig(fp, authName);
193 PStringToString kv = cfg->GetAllKeyValues(FileIPAuthSecName);
195 m_authList.reserve(kv.GetSize());
197 for (PINDEX i = 0; i < kv.GetSize(); i++) {
198 const PString &key = kv.GetKeyAt(i);
205 entry.first = (key == "*" || key == "any") ? NetworkAddress() : NetworkAddress(key);
207 PString auth(kv.GetDataAt(i));
210 if ((position = auth.Find(';', position)) != P_MAX_INDEX) {
212 prefix = auth(position, auth.GetLength());
214 auth.Delete(position, auth.GetLength() - position);
217 entry.second.auth = PCaselessString("allow") == auth;
218 entry.second.AddPrefix(prefix);
219 entry.second.SortPrefix(false);
221 m_authList.push_back(entry);
224 std::stable_sort(m_authList.begin(), m_authList.end(), IPAuthEntry_greater());
226 PTRACE(5, GetName() << "\t" << m_authList.size() << " entries loaded");
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;
249 FileIPAuth::~FileIPAuth()
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
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
268 return len ? e_ok : e_fail;
270 return entry->second.auth ? e_ok : e_fail;
274 return GetDefaultStatus();
278 IPAuthPrefix::IPAuthPrefix() :
282 IPAuthPrefix::IPAuthPrefix(bool a, const PString & prefixes)
288 IPAuthPrefix::IPAuthPrefix(const IPAuthPrefix & obj)
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());
300 IPAuthPrefix& IPAuthPrefix::operator=(const IPAuthPrefix & obj)
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());
315 IPAuthPrefix& IPAuthPrefix::operator=(bool a)
321 void IPAuthPrefix::AddPrefix(const PString & prefixes)
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]);
328 void IPAuthPrefix::SortPrefix(bool greater)
330 // remove duplicate aliases
332 sort(Prefixs.begin(), Prefixs.end(), str_prefix_greater());
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());
339 int IPAuthPrefix::PrefixMatch(const PString & number) const
341 if (number.IsEmpty())
344 const char * alias = (const char*)(number);
349 const_prefix_iterator Iter = Prefixs.begin();
350 const_prefix_iterator eIter = Prefixs.end();
355 while (Iter != eIter) {
356 const int len = MatchPrefix(alias, Iter->c_str());
366 std::string IPAuthPrefix::PrintOn(void) const
369 return std::string(" to called any");
371 std::string prefix = PrintPrefix();
375 std::string ret(" to called ");
380 std::string IPAuthPrefix::PrintPrefix(void) const
383 const_prefix_iterator Iter = Prefixs.begin();
384 const_prefix_iterator eIter = Prefixs.end();
385 while (Iter != eIter) {
394 namespace { // anonymous namespace
395 GkAuthCreator<FileIPAuth> FileIPAuthCreator("FileIPAuth");
396 } // end of anonymous namespace