reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
AclStore.cxx
Go to the documentation of this file.
1
2#if defined(HAVE_CONFIG_H)
3 #include "config.h"
4#endif
5
6#include "rutil/Socket.hxx"
7#include "rutil/Logger.hxx"
9#include "rutil/DnsUtil.hxx"
10#include "rutil/Lock.hxx"
12#include "resip/stack/Uri.hxx"
15
16#include "repro/AclStore.hxx"
17
18#ifdef USE_SSL
21#endif
22
23using namespace resip;
24using namespace repro;
25using namespace std;
26
27
28#define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
29
31 mDb(db)
32{
33 AbstractDb::Key key = mDb.firstAclKey();
34 while ( !key.empty() )
35 {
36 AbstractDb::AclRecord rec = mDb.getAcl(key);
37 if(rec.mTlsPeerName.empty()) // If there is no TlsPeerName then record is an Address ACL
38 {
39 AddressRecord addressRecord(rec.mAddress, rec.mPort, (resip::TransportType)rec.mTransport);
40 addressRecord.mMask = rec.mMask;
41 addressRecord.key = buildKey(Data::Empty, rec.mAddress, rec.mMask, rec.mPort, rec.mFamily, rec.mTransport);
42 mAddressList.push_back(addressRecord);
43 }
44 else
45 {
46 TlsPeerNameRecord tlsPeerNameRecord;
47 tlsPeerNameRecord.mTlsPeerName = rec.mTlsPeerName;
48 tlsPeerNameRecord.key = buildKey(rec.mTlsPeerName, Data::Empty, 0, 0, 0, 0);
49 mTlsPeerNameList.push_back(tlsPeerNameRecord);
50 }
51 key = mDb.nextAclKey();
52 }
53 mTlsPeerNameCursor = mTlsPeerNameList.begin();
54 mAddressCursor = mAddressList.begin();
55}
56
60
61bool
62AclStore::addAcl(const resip::Data& tlsPeerName,
63 const resip::Data& address,
64 const short& mask,
65 const short& port,
66 const short& family,
67 const short& transport)
68{
69 Data key = buildKey(tlsPeerName, address, mask, port, family, transport);
70 InfoLog( << "Add ACL: key=" << key);
71
72 // Check if key exists already
73 if(key.prefix(":")) // a key that starts with a : has no peer name - thus a Address key
74 {
75 ReadLock lock(mMutex);
76 if(findAddressKey(key))
77 {
78 // Key already exists - don't add again
79 return false;
80 }
81 }
82 else
83 {
84 ReadLock lock(mMutex);
85 if(findTlsPeerNameKey(key))
86 {
87 // Key already exists - don't add again
88 return false;
89 }
90 }
91
92 // Key doesn't exist - add it
94 rec.mTlsPeerName = tlsPeerName;
95 rec.mAddress = address;
96 rec.mMask = mask;
97 rec.mPort = port;
98 rec.mFamily = family;
99 rec.mTransport = transport;
100
101 // Add DB record
102 if(!mDb.addAcl(key, rec))
103 {
104 return false;
105 }
106
107 // Add local storage
108 if(rec.mTlsPeerName.empty()) // If there is no TlsPeerName then record is an Address ACL
109 {
110 AddressRecord addressRecord(rec.mAddress, rec.mPort, (resip::TransportType)rec.mTransport);
111 addressRecord.mMask = rec.mMask;
112 addressRecord.key = key;
113 {
114 WriteLock lock(mMutex);
115 mAddressList.push_back(addressRecord);
116 mAddressCursor = mAddressList.begin(); // Put cursor back at start
117 }
118 }
119 else
120 {
121 TlsPeerNameRecord tlsPeerNameRecord;
122 tlsPeerNameRecord.mTlsPeerName = rec.mTlsPeerName;
123 tlsPeerNameRecord.key = key;
124 {
125 WriteLock lock(mMutex);
126 mTlsPeerNameList.push_back(tlsPeerNameRecord);
127 mTlsPeerNameCursor = mTlsPeerNameList.begin(); // Put cursor back at start
128 }
129 }
130 return true;
131}
132
133
134bool
135AclStore::addAcl(const resip::Data& tlsPeerNameOrAddress,
136 const short& port,
137 const short& transport)
138{
139 // Input can be in any of these formats
140 // localhost localhost (becomes 127.0.0.1/8, ::1/128 and fe80::1/64)
141 // bare hostname server1
142 // FQDN server1.example.com
143 // IPv4 address 192.168.1.100
144 // IPv4 + mask 192.168.1.0/24
145 // IPv6 address :341:0:23:4bb:0011:2435:abcd
146 // IPv6 + mask :341:0:23:4bb:0011:2435:abcd/80
147 // IPv6 reference [:341:0:23:4bb:0011:2435:abcd]
148 // IPv6 ref + mask [:341:0:23:4bb:0011:2435:abcd]/64
149
150 try
151 {
152 ParseBuffer pb(tlsPeerNameOrAddress);
153 const char* anchor = pb.start();
154
155 bool ipv4 = false;
156 bool ipv6 = false;
157 Data hostOrIp;
158 //u_char in[28];
159 struct in_addr in4;
160#ifdef USE_IPV6
161 struct in6_addr in6;
162#endif
163 int mask;
164
165 if (*pb.position() == '[') // encountered beginning of IPv6 reference
166 {
167 anchor = pb.skipChar();
168 pb.skipToEndQuote(']');
169
170 pb.data(hostOrIp, anchor); // copy the presentation form of the IPv6 address
171 anchor = pb.skipChar();
172
173 // try to convert into IPv6 network form
174#ifdef USE_IPV6
175 if (!DnsUtil::inet_pton( hostOrIp.c_str(), in6))
176#endif
177 {
178 return false;
179 }
180 ipv6 = true;
181 }
182 else
183 {
184 pb.skipToOneOf(".:");
185 if (pb.position() == pb.end()) // We probably have a bare hostname
186 {
187 pb.data(hostOrIp, anchor);
188 if (hostOrIp.lowercase() == "localhost")
189 {
190 // add special localhost addresses for v4 and v6 to list and return
191 addAcl(Data::Empty, "127.0.0.1", 8, port, resip::V4, transport);
192 addAcl(Data::Empty, "::1", 128, port, resip::V6, transport);
193 return addAcl(Data::Empty, "fe80::1", 64, port, resip::V6, transport);
194 }
195 else
196 {
197 // hostOrIp += default domain name (future)
198 return addAcl(hostOrIp, Data::Empty, 0, 0, 0, 0);
199 }
200 }
201 else if (*pb.position() == ':') // Must be an IPv6 address
202 {
203 pb.skipToChar('/');
204 pb.data(hostOrIp, anchor); // copy the presentation form of the IPv6 address
205
206 // try to convert into IPv6 network form
207#ifdef USE_IPV6
208 if (!DnsUtil::inet_pton( hostOrIp.c_str(), in6))
209#endif
210 {
211 return false;
212 }
213 ipv6 = true;
214 }
215 else // *pb.position() == '.'
216 {
217 // Could be either an IPv4 address or an FQDN
218 pb.skipToChar('/');
219 pb.data(hostOrIp, anchor); // copy the presentation form of the address
220
221 // try to interpret as an IPv4 address, if that fails look it up in DNS
222 if (DnsUtil::inet_pton( hostOrIp.c_str(), in4))
223 {
224 // it was an IPv4 address
225 ipv4 = true;
226 }
227 else
228 {
229 // hopefully it is a legal FQDN, try it.
230 return addAcl(hostOrIp, Data::Empty, 0, 0, 0, 0);
231 }
232 }
233 }
234
235 if (!pb.eof() && *pb.position() == '/') // grab the mask as well
236 {
237 anchor = pb.skipChar();
238 mask = pb.integer();
239
240 if (ipv4)
241 {
242 if (mask < 8 || mask > 32)
243 {
244 return false;
245 }
246 }
247 else if (ipv6)
248 {
249 if (mask < 64 || mask > 128)
250 {
251 return false;
252 }
253 }
254 }
255 else
256 {
257 if (ipv4)
258 {
259 mask = 32;
260 }
261 else // ipv6
262 {
263 mask = 128;
264 }
265 }
266
267 if(pb.eof())
268 {
269 bool ret;
270 if (ipv6)
271 {
272 ret = addAcl(Data::Empty, hostOrIp, mask, port, resip::V6, transport);
273 }
274
275 if (ipv4)
276 {
277 ret = addAcl(Data::Empty, hostOrIp, mask, port, resip::V4, transport);
278 }
279 return ret;
280 }
281 }
282 catch(ParseException& e)
283 {
284 ErrLog(<< "Exception caught:" << e);
285 }
286 return false;
287}
288
289void AclStore::eraseAcl(const resip::Data& tlsPeerName,
290 const resip::Data& address,
291 const short& mask,
292 const short& port,
293 const short& family,
294 const short& transport)
295{
296 Data key = buildKey(tlsPeerName, address, mask, port, family, transport);
297 InfoLog( << "Erase ACL: key=" << key);
298 eraseAcl(key);
299}
300
301void
303{
304 // Erase DB record
305 mDb.eraseAcl( key );
306
307 // Erase local storage
308 if(key.prefix(":")) // a key that starts with a : has no peer name - thus a Address key
309 {
310 WriteLock lock(mMutex);
311 if(findAddressKey(key))
312 {
313 mAddressCursor = mAddressList.erase(mAddressCursor);
314 }
315 }
316 else
317 {
318 WriteLock lock(mMutex);
319 if(findTlsPeerNameKey(key))
320 {
321 mTlsPeerNameCursor = mTlsPeerNameList.erase(mTlsPeerNameCursor);
322 }
323 }
324}
325
326
328AclStore::buildKey(const resip::Data& tlsPeerName,
329 const resip::Data& address,
330 const short& mask,
331 const short& port,
332 const short& family,
333 const short& transport) const
334{
335 Data pKey = tlsPeerName+":"+address+"/"+Data(mask)+":"+Data(port)+":"+Data(family)+":"+Data(transport);
336 return pKey;
337}
338
339
342{
343 ReadLock lock(mMutex);
344 mTlsPeerNameCursor = mTlsPeerNameList.begin();
345 if ( mTlsPeerNameCursor == mTlsPeerNameList.end() )
346 {
347 return Key( Data::Empty );
348 }
349
350 return mTlsPeerNameCursor->key;
351}
352
353
354bool
355AclStore::findTlsPeerNameKey(const Key& key)
356{
357 // check if cursor happens to be at the key
358 if ( mTlsPeerNameCursor != mTlsPeerNameList.end() )
359 {
360 if ( mTlsPeerNameCursor->key == key )
361 {
362 return true;
363 }
364 }
365
366 // search for the key
367 mTlsPeerNameCursor = mTlsPeerNameList.begin();
368 while ( mTlsPeerNameCursor != mTlsPeerNameList.end() )
369 {
370 if ( mTlsPeerNameCursor->key == key )
371 {
372 return true; // found the key
373 }
374 mTlsPeerNameCursor++;
375 }
376 return false; // key was not found
377}
378
379
382{
383 ReadLock lock(mMutex);
384 if ( !findTlsPeerNameKey(key) )
385 {
386 return Key(Data::Empty);
387 }
388
389 mTlsPeerNameCursor++;
390
391 if ( mTlsPeerNameCursor == mTlsPeerNameList.end() )
392 {
393 return Key( Data::Empty );
394 }
395
396 return mTlsPeerNameCursor->key;
397}
398
399
402{
403 ReadLock lock(mMutex);
404 mAddressCursor = mAddressList.begin();
405 if ( mAddressCursor == mAddressList.end() )
406 {
407 return Key( Data::Empty );
408 }
409
410 return mAddressCursor->key;
411}
412
413
414bool
415AclStore::findAddressKey(const Key& key)
416{
417 // check if cursor happens to be at the key
418 if ( mAddressCursor != mAddressList.end() )
419 {
420 if ( mAddressCursor->key == key )
421 {
422 return true;
423 }
424 }
425
426 // search for the key
427 mAddressCursor = mAddressList.begin();
428 while ( mAddressCursor != mAddressList.end() )
429 {
430 if ( mAddressCursor->key == key )
431 {
432 return true; // found the key
433 }
434 mAddressCursor++;
435 }
436 return false; // key was not found
437}
438
439
442{
443 ReadLock lock(mMutex);
444 if ( !findAddressKey(key) )
445 {
446 return Key(Data::Empty);
447 }
448
449 mAddressCursor++;
450
451 if ( mAddressCursor == mAddressList.end() )
452 {
453 return Key( Data::Empty );
454 }
455
456 return mAddressCursor->key;
457}
458
459
462{
463 ReadLock lock(mMutex);
464 if ( !findTlsPeerNameKey(key) )
465 {
466 return Data::Empty;
467 }
468 return mTlsPeerNameCursor->mTlsPeerName;
469}
470
471
474{
475 ReadLock lock(mMutex);
476 if ( !findAddressKey(key) )
477 {
478 return Tuple();
479 }
480 return mAddressCursor->mAddressTuple;
481}
482
483
484short
486{
487 ReadLock lock(mMutex);
488 if ( !findAddressKey(key) )
489 {
490 return 0;
491 }
492 return mAddressCursor->mMask;
493}
494
495
496bool
497AclStore::isTlsPeerNameTrusted(const std::list<Data>& tlsPeerNames)
498{
499 ReadLock lock(mMutex);
500 for(std::list<Data>::const_iterator it = tlsPeerNames.begin(); it != tlsPeerNames.end(); it++)
501 {
502 for(TlsPeerNameList::iterator i = mTlsPeerNameList.begin(); i != mTlsPeerNameList.end(); i++)
503 {
504 if(isEqualNoCase(i->mTlsPeerName, *it))
505 {
506 InfoLog (<< "AclStore - Tls peer name IS trusted: " << *it);
507 return true;
508 }
509 }
510 }
511 return false;
512}
513
514
515bool
517{
518 ReadLock lock(mMutex);
519 for(AddressList::iterator i = mAddressList.begin(); i != mAddressList.end(); i++)
520 {
521 if(i->mAddressTuple.isEqualWithMask(address, i->mMask, i->mAddressTuple.getPort() == 0))
522 {
523 return true;
524 }
525 }
526 return false;
527}
528
529
530// check the sender of the message via source IP address or identity from TLS
531bool
533{
534 bool trusted = false;
535 Tuple source = request.getSource();
536
537 // check if the request came over a secure channel and sucessfully authenticated
538 // (ex: TLS or DTLS)
539 TransportType receivedTransport = toTransportType(
540 request.header(h_Vias).front().transport());
541#ifdef USE_SSL
542 if(isSecure(receivedTransport))
543 {
544 StackLog(<<"Not checking the TLS peer certificate names, that is now done by CertificateAuthenticator if enabled");
545 }
546#endif
547
548 // check the source address against the TrustedNode list
549 if(!trusted)
550 {
551 if(isAddressTrusted(source))
552 {
553 InfoLog (<< "AclStore - source address IS trusted: " << source.presentationFormat() << ":" << source.getPort() << " " << Tuple::toData(source.getType()));
554 trusted = true;
555 }
556 else
557 {
558 InfoLog (<< "AclStore - source address NOT trusted: " << source.presentationFormat() << ":" << source.getPort() << " " << Tuple::toData(source.getType()));
559 }
560 }
561
562 return trusted;
563}
564
565
566/* ====================================================================
567 * The Vovida Software License, Version 1.0
568 *
569 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
570 *
571 * Redistribution and use in source and binary forms, with or without
572 * modification, are permitted provided that the following conditions
573 * are met:
574 *
575 * 1. Redistributions of source code must retain the above copyright
576 * notice, this list of conditions and the following disclaimer.
577 *
578 * 2. Redistributions in binary form must reproduce the above copyright
579 * notice, this list of conditions and the following disclaimer in
580 * the documentation and/or other materials provided with the
581 * distribution.
582 *
583 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
584 * and "Vovida Open Communication Application Library (VOCAL)" must
585 * not be used to endorse or promote products derived from this
586 * software without prior written permission. For written
587 * permission, please contact vocal@vovida.org.
588 *
589 * 4. Products derived from this software may not be called "VOCAL", nor
590 * may "VOCAL" appear in their name, without prior written
591 * permission of Vovida Networks, Inc.
592 *
593 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
594 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
595 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
596 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
597 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
598 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
599 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
600 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
601 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
602 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
603 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
604 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
605 * DAMAGE.
606 *
607 * ====================================================================
608 */
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
Handles cross-platform sockets compatibility.
virtual Key firstAclKey()
virtual AclRecord getAcl(const Key &key) const
virtual bool addAcl(const Key &key, const AclRecord &rec)
virtual void eraseAcl(const Key &key)
virtual Key nextAclKey()
resip::Data Key
Definition AclStore.hxx:33
void eraseAcl(const resip::Data &tlsPeerName, const resip::Data &address, const short &mask, const short &port, const short &family, const short &transport)
Definition AclStore.cxx:289
resip::Data getTlsPeerName(const resip::Data &key)
Definition AclStore.cxx:461
bool isRequestTrusted(const resip::SipMessage &request)
Definition AclStore.cxx:532
short getAddressMask(const resip::Data &key)
Definition AclStore.cxx:485
Key getNextTlsPeerNameKey(Key &key)
Definition AclStore.cxx:381
Key getFirstTlsPeerNameKey()
Definition AclStore.cxx:341
bool isAddressTrusted(const resip::Tuple &address)
Definition AclStore.cxx:516
Key getNextAddressKey(Key &key)
Definition AclStore.cxx:441
resip::Tuple getAddressTuple(const resip::Data &key)
Definition AclStore.cxx:473
bool isTlsPeerNameTrusted(const std::list< resip::Data > &tlsPeerNames)
Definition AclStore.cxx:497
Key getFirstAddressKey()
Definition AclStore.cxx:401
AclStore(AbstractDb &db)
Definition AclStore.cxx:30
bool addAcl(const resip::Data &tlsPeerName, const resip::Data &address, const short &mask, const short &port, const short &family, const short &transport)
Definition AclStore.cxx:62
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
bool prefix(const Data &pre) const noexcept
Returns true if this Data starts with the bytes indicated by the passed-in Data.
Definition Data.cxx:1888
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
Data & lowercase()
Converts this Data to lowercase.
Definition Data.cxx:1635
static int inet_pton(const Data &printableIp, struct in_addr &dst)
Convert from the presentation format of the IPv4 address to struct in_addr.
Definition DnsUtil.cxx:275
Provides string-parsing functionality with protection from buffer overflow.
Pointer start() const
Pointer end() const
CurrentPosition skipToChar(char c)
CurrentPosition position() const
CurrentPosition skipToOneOf(const char *cs)
CurrentPosition skipChar()
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
const char * skipToEndQuote(char quote='"')
BaseException used to indicate parse failures.
Represents a SIP message.
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
const Tuple & getSource() const
Returns the source tuple that the message was received from only makes sense for messages received fr...
Represents a network address.
Definition Tuple.hxx:59
Data presentationFormat() const
Wrapper around the inet_top() method.
Definition Tuple.cxx:426
static const Data & toData(TransportType)
Converts the TransportType to a string representation of the transport type, e.g.
Definition Tuple.cxx:927
int getPort() const
Definition Tuple.cxx:466
TransportType getType() const
Definition Tuple.hxx:122
This Class is used to implement a primitive form of RPC using loose XML formatting.
dcm! – add UnusedChecking(_enum) below;
bool isEqualNoCase(const Data &left, const Data &right)
Definition Data.hxx:1116
TransportType toTransportType(const resip::Data &transportName)
bool isSecure(TransportType type)
Returns true if passed in transport type is a secure transport protocol.
TransportType
An enumeration of transport protocols.