/[resiprocate]/main/resip/dum/TlsPeerAuthManager.cxx
ViewVC logotype

Contents of /main/resip/dum/TlsPeerAuthManager.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10830 - (show annotations) (download)
Sun Jan 5 11:14:56 2014 UTC (5 years, 10 months ago) by Dpocock
File size: 8780 byte(s)
resip, repro: certificate auth: separate source check from identity check
1 #include <cassert>
2
3 #include "resip/dum/DumFeature.hxx"
4 #include "resip/dum/DumFeatureChain.hxx"
5 #include "resip/dum/DialogUsageManager.hxx"
6 #include "resip/dum/TargetCommand.hxx"
7 #include "resip/dum/TlsPeerAuthManager.hxx"
8 #include "resip/stack/Helper.hxx"
9 #include "rutil/Logger.hxx"
10 #include "rutil/WinLeakCheck.hxx"
11
12 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
13
14 using namespace resip;
15 using namespace std;
16
17 TlsPeerAuthManager::TlsPeerAuthManager(DialogUsageManager& dum, TargetCommand::Target& target, const std::set<Data>& trustedPeers, bool thirdPartyRequiresCertificate) :
18 DumFeature(dum, target),
19 mTrustedPeers(trustedPeers),
20 mThirdPartyRequiresCertificate(thirdPartyRequiresCertificate)
21 {
22 }
23
24 TlsPeerAuthManager::TlsPeerAuthManager(DialogUsageManager& dum, TargetCommand::Target& target, const std::set<Data>& trustedPeers, bool thirdPartyRequiresCertificate, CommonNameMappings& commonNameMappings) :
25 DumFeature(dum, target),
26 mTrustedPeers(trustedPeers),
27 mThirdPartyRequiresCertificate(thirdPartyRequiresCertificate),
28 mCommonNameMappings(commonNameMappings)
29 {
30 }
31
32 TlsPeerAuthManager::~TlsPeerAuthManager()
33 {
34 InfoLog(<< "~TlsPeerAuthManager");
35 }
36
37 // !bwc! We absolutely, positively, MUST NOT throw here. This is because in
38 // DialogUsageManager::process(), we do not know if a DumFeature has taken
39 // ownership of msg until we get a return. If we throw, the ownership of msg
40 // is unknown. This is unacceptable.
41 DumFeature::ProcessingResult
42 TlsPeerAuthManager::process(Message* msg)
43 {
44 SipMessage* sipMessage = dynamic_cast<SipMessage*>(msg);
45
46 if (sipMessage)
47 {
48 //!dcm! -- unecessary happens in handle
49 switch ( handle(sipMessage) )
50 {
51 case TlsPeerAuthManager::Rejected:
52 InfoLog(<< "TlsPeerAuth rejected request " << sipMessage->brief());
53 return DumFeature::ChainDoneAndEventDone;
54 default: // includes Authorized, Skipped
55 return DumFeature::FeatureDone;
56 }
57 }
58
59 // Catch-all (handles something that was not a SipMessage)
60 return FeatureDone;
61 }
62
63 bool
64 TlsPeerAuthManager::authorizedForThisIdentity(
65 const std::list<resip::Data> &peerNames,
66 resip::Uri &fromUri)
67 {
68 Data aor = fromUri.getAorNoPort();
69 Data domain = fromUri.host();
70
71 std::list<Data>::const_iterator it = peerNames.begin();
72 for(; it != peerNames.end(); ++it)
73 {
74 const Data& i = *it;
75 if(i == aor)
76 {
77 DebugLog(<< "Matched certificate name " << i << " against full AoR " << aor);
78 return true;
79 }
80 if(i == domain)
81 {
82 DebugLog(<< "Matched certificate name " << i << " against domain " << domain);
83 return true;
84 }
85 CommonNameMappings::iterator _mapping =
86 mCommonNameMappings.find(i);
87 if(_mapping != mCommonNameMappings.end())
88 {
89 DebugLog(<< "CN mapping(s) exist for the certificate " << i);
90 PermittedFromAddresses& permitted = _mapping->second;
91 if(permitted.find(aor) != permitted.end())
92 {
93 DebugLog(<< "Matched certificate name " << i << " against full AoR " << aor << " by common name mappings");
94 return true;
95 }
96 if(permitted.find(domain) != permitted.end())
97 {
98 DebugLog(<< "Matched certificate name " << i << " against domain " << domain << " by common name mappings");
99 return true;
100 }
101 }
102 DebugLog(<< "Certificate name " << i << " doesn't match AoR " << aor << " or domain " << domain);
103 }
104
105 // catch-all: access denied
106 return false;
107 }
108
109 // return true if request has been consumed
110 TlsPeerAuthManager::Result
111 TlsPeerAuthManager::handle(SipMessage* sipMessage)
112 {
113 //InfoLog( << "trying to do auth" );
114 if (!sipMessage->isRequest() ||
115 sipMessage->header(h_RequestLine).method() == ACK ||
116 sipMessage->header(h_RequestLine).method() == CANCEL)
117 {
118 // Do not inspect ACKs or CANCELs
119 return Skipped;
120 }
121
122 if(!sipMessage->header(h_From).isWellFormed() ||
123 sipMessage->header(h_From).isAllContacts() )
124 {
125 InfoLog(<<"Malformed From header: cannot verify against any certificate. Rejecting.");
126 SharedPtr<SipMessage> response(new SipMessage);
127 Helper::makeResponse(*response, *sipMessage, 400, "Malformed From header");
128 mDum.send(response);
129 return Rejected;
130 }
131
132 // We are only concerned with connections over TLS
133 if(!sipMessage->isExternal() || !isSecure(sipMessage->getSource().getType()))
134 {
135 DebugLog(<<"Can't validate certificate on non-TLS connection");
136 return Skipped;
137 }
138
139 if(isTrustedSource(*sipMessage))
140 {
141 return Authorized;
142 }
143
144 const std::list<resip::Data> &peerNames = sipMessage->getTlsPeerNames();
145 if (mDum.isMyDomain(sipMessage->header(h_From).uri().host()))
146 {
147 // peerNames is empty if client certificate mode is `optional'
148 // or if the message didn't come in on TLS transport
149 if (requiresAuthorization(*sipMessage) && !peerNames.empty())
150 {
151 if(authorizedForThisIdentity(peerNames, sipMessage->header(h_From).uri()))
152 return Authorized;
153 SharedPtr<SipMessage> response(new SipMessage);
154 Helper::makeResponse(*response, *sipMessage, 403, "Authorization Failed for peer cert");
155 mDum.send(response);
156 return Rejected;
157 }
158 else
159 return Skipped;
160 }
161 else
162 {
163 // peerNames is empty if client certificate mode is `optional'
164 // or if the message didn't come in on TLS transport
165 if(peerNames.empty())
166 {
167 if(mThirdPartyRequiresCertificate)
168 {
169 SharedPtr<SipMessage> response(new SipMessage);
170 Helper::makeResponse(*response, *sipMessage, 403, "Mutual TLS required to handle that message");
171 mDum.send(response);
172 return Rejected;
173 }
174 else
175 return Skipped;
176 }
177 if(authorizedForThisIdentity(peerNames, sipMessage->header(h_From).uri()))
178 return Authorized;
179 SharedPtr<SipMessage> response(new SipMessage);
180 Helper::makeResponse(*response, *sipMessage, 403, "Authorization Failed for peer cert");
181 mDum.send(response);
182 return Rejected;
183 }
184
185 InfoLog(<< "Skipping some message that we didn't explicitly handle");
186 return Skipped;
187 }
188
189 bool
190 TlsPeerAuthManager::requiresAuthorization(const SipMessage& msg)
191 {
192 // everything must be authorized, over-ride this method
193 // to implement some other policy
194 return true;
195 }
196
197 bool
198 TlsPeerAuthManager::isTrustedSource(const SipMessage& msg)
199 {
200 // over-ride this method to implement some other policy
201
202 const std::list<resip::Data> &peerNames = msg.getTlsPeerNames();
203 std::list<Data>::const_iterator it = peerNames.begin();
204 for(; it != peerNames.end(); ++it)
205 {
206 const Data& i = *it;
207 if(mTrustedPeers.find(i) != mTrustedPeers.end())
208 {
209 DebugLog(<< "Matched certificate name " << i << " is a trusted peer");
210 return true;
211 }
212 }
213
214 return false;
215 }
216
217 /* ====================================================================
218 *
219 * Copyright (c) 2012 Daniel Pocock All rights reserved.
220 *
221 * Redistribution and use in source and binary forms, with or without
222 * modification, are permitted provided that the following conditions
223 * are met:
224 *
225 * 1. Redistributions of source code must retain the above copyright
226 * notice, this list of conditions and the following disclaimer.
227 *
228 * 2. Redistributions in binary form must reproduce the above copyright
229 * notice, this list of conditions and the following disclaimer in
230 * the documentation and/or other materials provided with the
231 * distribution.
232 *
233 * 3. Neither the name of the author(s) nor the names of any contributors
234 * may be used to endorse or promote products derived from this software
235 * without specific prior written permission.
236 *
237 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
238 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
240 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
241 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
242 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
243 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
244 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
245 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
246 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
247 * SUCH DAMAGE.
248 *
249 * ====================================================================
250 *
251 */

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27