|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include <string.h> 00006 #include <iomanip> 00007 #include <algorithm> 00008 #include <memory> 00009 00010 #include "resip/stack/Auth.hxx" 00011 #include "resip/stack/BasicNonceHelper.hxx" 00012 #include "resip/stack/Helper.hxx" 00013 #include "resip/stack/NonceHelper.hxx" 00014 #include "rutil/Coders.hxx" 00015 #include "resip/stack/Uri.hxx" 00016 #include "rutil/Logger.hxx" 00017 #include "rutil/Random.hxx" 00018 #include "rutil/Timer.hxx" 00019 #include "rutil/DataStream.hxx" 00020 #include "rutil/MD5Stream.hxx" 00021 #include "rutil/DnsUtil.hxx" 00022 #include "rutil/compat.hxx" 00023 #include "rutil/ParseBuffer.hxx" 00024 #include "resip/stack/SipMessage.hxx" 00025 #include "resip/stack/Pkcs7Contents.hxx" 00026 #include "resip/stack/MultipartSignedContents.hxx" 00027 #include "resip/stack/MultipartMixedContents.hxx" 00028 #include "resip/stack/MultipartAlternativeContents.hxx" 00029 #include "rutil/WinLeakCheck.hxx" 00030 00031 #ifdef USE_SSL 00032 #include "resip/stack/ssl/Security.hxx" 00033 #endif 00034 00035 using namespace resip; 00036 using namespace std; 00037 00038 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP 00039 00040 const int Helper::tagSize = 4; 00041 00042 // !jf! this should be settable by the application in case a group of apps 00043 // (e.g. proxies) want to share the same secret 00044 Helper::NonceHelperPtr Helper::mNonceHelperPtr; 00045 00046 void Helper::integer2hex(char* _d, unsigned int _s, bool _l) 00047 { 00048 int i; 00049 unsigned char j; 00050 int k = 0; 00051 char* s; 00052 00053 _s = htonl(_s); 00054 s = (char*)&_s; 00055 00056 for (i = 0; i < 4; i++) 00057 { 00058 j = (s[i] >> 4) & 0xf; 00059 if (j <= 9) 00060 { 00061 if(_l || j != 0 || k != 0) 00062 { 00063 _d[k++] = (j + '0'); 00064 } 00065 } 00066 else 00067 { 00068 _d[k++] = (j + 'a' - 10); 00069 } 00070 00071 j = s[i] & 0xf; 00072 if (j <= 9) 00073 { 00074 if(_l || j != 0 || k != 0) 00075 { 00076 _d[k++] = (j + '0'); 00077 } 00078 } 00079 else 00080 { 00081 _d[k++] = (j + 'a' - 10); 00082 } 00083 } 00084 } 00085 00086 unsigned int Helper::hex2integer(const char* _s) 00087 { 00088 unsigned int i, res = 0; 00089 00090 for(i = 0; i < 8; i++) 00091 { 00092 if ((_s[i] >= '0') && (_s[i] <= '9')) 00093 { 00094 res *= 16; 00095 res += _s[i] - '0'; 00096 } 00097 else if ((_s[i] >= 'a') && (_s[i] <= 'f')) 00098 { 00099 res *= 16; 00100 res += _s[i] - 'a' + 10; 00101 } 00102 else if ((_s[i] >= 'A') && (_s[i] <= 'F')) 00103 { 00104 res *= 16; 00105 res += _s[i] - 'A' + 10; 00106 } 00107 else 00108 { 00109 return res; 00110 } 00111 } 00112 00113 return res; 00114 } 00115 00116 SipMessage* 00117 Helper::makeRequest(const NameAddr& target, const NameAddr& from, const NameAddr& contact, MethodTypes method) 00118 { 00119 std::auto_ptr<SipMessage> request(new SipMessage); 00120 RequestLine rLine(method); 00121 rLine.uri() = target.uri(); 00122 request->header(h_To) = target; 00123 request->header(h_RequestLine) = rLine; 00124 request->header(h_MaxForwards).value() = 70; 00125 request->header(h_CSeq).method() = method; 00126 request->header(h_CSeq).sequence() = 1; 00127 request->header(h_From) = from; 00128 request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize); 00129 request->header(h_Contacts).push_back(contact); 00130 request->header(h_CallId).value() = Helper::computeCallId(); 00131 //request->header(h_ContentLength).value() = 0; 00132 00133 Via via; 00134 request->header(h_Vias).push_back(via); 00135 00136 return request.release(); 00137 } 00138 00139 SipMessage* 00140 Helper::makeRequest(const NameAddr& target, const NameAddr& from, MethodTypes method) 00141 { 00142 NameAddr contact; 00143 return makeRequest(target, from, contact, method); 00144 } 00145 00146 SipMessage* 00147 Helper::makeRegister(const NameAddr& to, const NameAddr& from) 00148 { 00149 NameAddr contact; 00150 return makeRegister(to, from, contact); 00151 } 00152 00153 SipMessage* 00154 Helper::makeRegister(const NameAddr& to, const NameAddr& from, const NameAddr& contact) 00155 { 00156 std::auto_ptr<SipMessage> request(new SipMessage); 00157 RequestLine rLine(REGISTER); 00158 00159 rLine.uri().scheme() = to.uri().scheme(); 00160 rLine.uri().host() = to.uri().host(); 00161 rLine.uri().port() = to.uri().port(); 00162 if (to.uri().exists(p_transport)) 00163 { 00164 rLine.uri().param(p_transport) = to.uri().param(p_transport); 00165 } 00166 00167 request->header(h_To) = to; 00168 request->header(h_RequestLine) = rLine; 00169 request->header(h_MaxForwards).value() = 70; 00170 request->header(h_CSeq).method() = REGISTER; 00171 request->header(h_CSeq).sequence() = 1; 00172 request->header(h_From) = from; 00173 request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize); 00174 request->header(h_CallId).value() = Helper::computeCallId(); 00175 assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty()); 00176 request->header(h_Contacts).push_back( contact ); 00177 00178 Via via; 00179 request->header(h_Vias).push_back(via); 00180 00181 return request.release(); 00182 } 00183 00184 SipMessage* 00185 Helper::makeRegister(const NameAddr& to,const Data& transport) 00186 { 00187 NameAddr contact; 00188 return makeRegister(to, transport, contact); 00189 00190 } 00191 00192 SipMessage* 00193 Helper::makeRegister(const NameAddr& to, const Data& transport, const NameAddr& contact) 00194 { 00195 std::auto_ptr<SipMessage> request(new SipMessage); 00196 RequestLine rLine(REGISTER); 00197 00198 rLine.uri().scheme() = to.uri().scheme(); 00199 rLine.uri().host() = to.uri().host(); 00200 rLine.uri().port() = to.uri().port(); 00201 if (!transport.empty()) 00202 { 00203 rLine.uri().param(p_transport) = transport; 00204 } 00205 00206 request->header(h_To) = to; 00207 request->header(h_RequestLine) = rLine; 00208 request->header(h_MaxForwards).value() = 70; 00209 request->header(h_CSeq).method() = REGISTER; 00210 request->header(h_CSeq).sequence() = 1; 00211 request->header(h_From) = to; 00212 request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize); 00213 request->header(h_CallId).value() = Helper::computeCallId(); 00214 assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty()); 00215 request->header(h_Contacts).push_back( contact ); 00216 00217 Via via; 00218 request->header(h_Vias).push_back(via); 00219 00220 return request.release(); 00221 } 00222 00223 00224 SipMessage* 00225 Helper::makePublish(const NameAddr& target, const NameAddr& from) 00226 { 00227 NameAddr contact; 00228 return makePublish(target, from, contact); 00229 } 00230 00231 SipMessage* 00232 Helper::makePublish(const NameAddr& target, const NameAddr& from, const NameAddr& contact) 00233 { 00234 std::auto_ptr<SipMessage> request(new SipMessage); 00235 RequestLine rLine(PUBLISH); 00236 rLine.uri() = target.uri(); 00237 00238 request->header(h_To) = target; 00239 request->header(h_RequestLine) = rLine; 00240 request->header(h_MaxForwards).value() = 70; 00241 request->header(h_CSeq).method() = PUBLISH; 00242 request->header(h_CSeq).sequence() = 1; 00243 request->header(h_From) = from; 00244 request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize); 00245 request->header(h_CallId).value() = Helper::computeCallId(); 00246 assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty()); 00247 request->header(h_Contacts).push_back( contact ); 00248 Via via; 00249 request->header(h_Vias).push_back(via); 00250 00251 return request.release(); 00252 } 00253 00254 SipMessage* 00255 Helper::makeMessage(const NameAddr& target, const NameAddr& from) 00256 { 00257 NameAddr contact; 00258 return makeMessage(target, from, contact); 00259 } 00260 00261 SipMessage* 00262 Helper::makeMessage(const NameAddr& target, const NameAddr& from, const NameAddr& contact) 00263 { 00264 std::auto_ptr<SipMessage> request(new SipMessage); 00265 RequestLine rLine(MESSAGE); 00266 rLine.uri() = target.uri(); 00267 00268 request->header(h_To) = target; 00269 request->header(h_RequestLine) = rLine; 00270 request->header(h_MaxForwards).value() = 70; 00271 request->header(h_CSeq).method() = MESSAGE; 00272 request->header(h_CSeq).sequence() = 1; 00273 request->header(h_From) = from; 00274 request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize); 00275 request->header(h_CallId).value() = Helper::computeCallId(); 00276 assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty()); 00277 request->header(h_Contacts).push_back( contact ); 00278 Via via; 00279 request->header(h_Vias).push_back(via); 00280 00281 return request.release(); 00282 } 00283 00284 00285 SipMessage* 00286 Helper::makeSubscribe(const NameAddr& target, const NameAddr& from) 00287 { 00288 NameAddr contact; 00289 return makeSubscribe(target, from, contact); 00290 } 00291 00292 SipMessage* 00293 Helper::makeSubscribe(const NameAddr& target, const NameAddr& from, const NameAddr& contact) 00294 { 00295 std::auto_ptr<SipMessage> request(new SipMessage); 00296 RequestLine rLine(SUBSCRIBE); 00297 rLine.uri() = target.uri(); 00298 00299 request->header(h_To) = target; 00300 request->header(h_RequestLine) = rLine; 00301 request->header(h_MaxForwards).value() = 70; 00302 request->header(h_CSeq).method() = SUBSCRIBE; 00303 request->header(h_CSeq).sequence() = 1; 00304 request->header(h_From) = from; 00305 request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize); 00306 request->header(h_CallId).value() = Helper::computeCallId(); 00307 assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty()); 00308 request->header(h_Contacts).push_front( contact ); 00309 Via via; 00310 request->header(h_Vias).push_front(via); 00311 00312 return request.release(); 00313 } 00314 00315 int 00316 Helper::jitterValue(int input, int lowerPercentage, int upperPercentage, int minimum) 00317 { 00318 assert(upperPercentage >= lowerPercentage); 00319 if (input < minimum) 00320 { 00321 return input; 00322 } 00323 else if (lowerPercentage == 100 && upperPercentage == 100) 00324 { 00325 return input; 00326 } 00327 else 00328 { 00329 const int rnd = Random::getRandom() % (upperPercentage-lowerPercentage) + lowerPercentage; 00330 return (input * rnd) / 100; 00331 } 00332 } 00333 00334 SipMessage* 00335 Helper::makeInvite(const NameAddr& target, const NameAddr& from) 00336 { 00337 return Helper::makeRequest(target, from, INVITE); 00338 } 00339 00340 SipMessage* 00341 Helper::makeInvite(const NameAddr& target, const NameAddr& from, const NameAddr& contact) 00342 { 00343 return Helper::makeRequest(target, from, contact, INVITE); 00344 } 00345 00346 00347 void 00348 Helper::makeResponse(SipMessage& response, 00349 const SipMessage& request, 00350 int responseCode, 00351 const NameAddr& myContact, 00352 const Data& reason, 00353 const Data& hostname, 00354 const Data& warning) 00355 { 00356 makeResponse(response,request, responseCode, reason,hostname, warning); 00357 // in general, this should not create a Contact header since only requests 00358 // that create a dialog (or REGISTER requests) should produce a response with 00359 // a contact(s). 00360 response.header(h_Contacts).clear(); 00361 response.header(h_Contacts).push_back(myContact); 00362 } 00363 00364 00365 void 00366 Helper::makeResponse(SipMessage& response, 00367 const SipMessage& request, 00368 int responseCode, 00369 const Data& reason, 00370 const Data& hostname, 00371 const Data& warning) 00372 { 00373 DebugLog(<< "Helper::makeResponse(" << request.brief() << " code=" << responseCode << " reason=" << reason); 00374 response.header(h_StatusLine).responseCode() = responseCode; 00375 response.header(h_From) = request.header(h_From); 00376 response.header(h_To) = request.header(h_To); 00377 response.header(h_CallId) = request.header(h_CallId); 00378 response.header(h_CSeq) = request.header(h_CSeq); 00379 response.header(h_Vias) = request.header(h_Vias); 00380 00381 if (!warning.empty()) 00382 { 00383 WarningCategory warn; 00384 warn.code() = 399; 00385 warn.hostname() = hostname; 00386 warn.text() = warning; 00387 response.header(h_Warnings).push_back(warn); 00388 } 00389 00390 if(responseCode > 100 && 00391 response.const_header(h_To).isWellFormed() && 00392 !response.const_header(h_To).exists(p_tag)) 00393 { 00394 // Only generate a To: tag if one doesn't exist. Think Re-INVITE. 00395 // No totag for failure responses or 100s 00396 // ?bwc? Should we be generating to-tags for failure responses or not? 00397 // The comments say no, but the code says yes. Which is it? 00398 response.header(h_To).param(p_tag) = Helper::computeTag(Helper::tagSize); 00399 } 00400 00401 // .bwc. This will only throw if the topmost Via is malformed, and that 00402 // should have been caught at the transport level. 00403 response.setRFC2543TransactionId(request.getRFC2543TransactionId()); 00404 00405 //response.header(h_ContentLength).value() = 0; 00406 00407 if (responseCode >= 180 && responseCode < 300 && request.exists(h_RecordRoutes)) 00408 { 00409 response.header(h_RecordRoutes) = request.header(h_RecordRoutes); 00410 } 00411 00412 // .bwc. If CSeq is malformed, basicCheck would have already attempted to 00413 // parse it, meaning we won't throw here (we never try to parse the same 00414 // thing twice, see LazyParser::checkParsed()) 00415 if (responseCode/100 == 2 && 00416 !response.exists(h_Contacts) && 00417 !(response.const_header(h_CSeq).method()==CANCEL) ) 00418 { 00419 // in general, this should not create a Contact header since only requests 00420 // that create a dialog (or REGISTER requests) should produce a response with 00421 // a contact(s). 00422 00423 NameAddr contact; 00424 response.header(h_Contacts).push_back(contact); 00425 } 00426 00427 if (request.isExternal()) 00428 { 00429 response.setFromTU(); 00430 } 00431 else 00432 { 00433 response.setFromExternal(); 00434 } 00435 00436 if (reason.size()) 00437 { 00438 response.header(h_StatusLine).reason() = reason; 00439 } 00440 else 00441 { 00442 getResponseCodeReason(responseCode, response.header(h_StatusLine).reason()); 00443 } 00444 } 00445 00446 SipMessage* 00447 Helper::makeResponse(const SipMessage& request, 00448 int responseCode, 00449 const NameAddr& myContact, 00450 const Data& reason, 00451 const Data& hostname, 00452 const Data& warning) 00453 { 00454 // .bwc. Exception safety. Catch/rethrow is dicey because we can't rethrow 00455 // resip::BaseException, since it is abstract. 00456 std::auto_ptr<SipMessage> response(new SipMessage); 00457 00458 makeResponse(*response, request, responseCode, reason, hostname, warning); 00459 00460 // in general, this should not create a Contact header since only requests 00461 // that create a dialog (or REGISTER requests) should produce a response with 00462 // a contact(s). 00463 response->header(h_Contacts).clear(); 00464 response->header(h_Contacts).push_back(myContact); 00465 return response.release(); 00466 } 00467 00468 00469 SipMessage* 00470 Helper::makeResponse(const SipMessage& request, 00471 int responseCode, 00472 const Data& reason, 00473 const Data& hostname, 00474 const Data& warning) 00475 { 00476 // .bwc. Exception safety. Catch/rethrow is dicey because we can't rethrow 00477 // resip::BaseException, since it is abstract. 00478 std::auto_ptr<SipMessage> response(new SipMessage); 00479 00480 makeResponse(*response, request, responseCode, reason, hostname, warning); 00481 return response.release(); 00482 } 00483 00484 void 00485 Helper::makeRawResponse(Data& raw, 00486 const SipMessage& msg, 00487 int responseCode, 00488 const Data& additionalHeaders, 00489 const Data& body) 00490 { 00491 raw.reserve(256); 00492 { 00493 DataStream encodeStream(raw); 00494 encodeStream << "SIP/2.0 " << responseCode << " "; 00495 Data reason; 00496 getResponseCodeReason(responseCode, reason); 00497 encodeStream << reason; 00498 msg.encodeSingleHeader(Headers::Via,encodeStream); 00499 msg.encodeSingleHeader(Headers::To,encodeStream); 00500 msg.encodeSingleHeader(Headers::From,encodeStream); 00501 msg.encodeSingleHeader(Headers::CallID,encodeStream); 00502 msg.encodeSingleHeader(Headers::CSeq,encodeStream); 00503 encodeStream << additionalHeaders; 00504 encodeStream << "Content-Length: " << body.size() << "\r\n\r\n"; 00505 } 00506 } 00507 00508 void 00509 Helper::getResponseCodeReason(int responseCode, Data& reason) 00510 { 00511 switch (responseCode) 00512 { 00513 case 100: reason = "Trying"; break; 00514 case 180: reason = "Ringing"; break; 00515 case 181: reason = "Call Is Being Forwarded"; break; 00516 case 182: reason = "Queued"; break; 00517 case 183: reason = "Session Progress"; break; 00518 case 200: reason = "OK"; break; 00519 case 202: reason = "Accepted"; break; 00520 case 300: reason = "Multiple Choices"; break; 00521 case 301: reason = "Moved Permanently"; break; 00522 case 302: reason = "Moved Temporarily"; break; 00523 case 305: reason = "Use Proxy"; break; 00524 case 380: reason = "Alternative Service"; break; 00525 case 400: reason = "Bad Request"; break; 00526 case 401: reason = "Unauthorized"; break; 00527 case 402: reason = "Payment Required"; break; 00528 case 403: reason = "Forbidden"; break; 00529 case 404: reason = "Not Found"; break; 00530 case 405: reason = "Method Not Allowed"; break; 00531 case 406: reason = "Not Acceptable"; break; 00532 case 407: reason = "Proxy Authentication Required"; break; 00533 case 408: reason = "Request Timeout"; break; 00534 case 410: reason = "Gone"; break; 00535 case 412: reason = "Precondition Failed"; break; 00536 case 413: reason = "Request Entity Too Large"; break; 00537 case 414: reason = "Request-URI Too Long"; break; 00538 case 415: reason = "Unsupported Media Type"; break; 00539 case 416: reason = "Unsupported URI Scheme"; break; 00540 case 420: reason = "Bad Extension"; break; 00541 case 421: reason = "Extension Required"; break; 00542 case 422: reason = "Session Interval Too Small"; break; 00543 case 423: reason = "Interval Too Brief"; break; 00544 case 430: reason = "Flow failed"; break; 00545 case 439: reason = "First Hop Lacks Outbound Support"; break; 00546 case 480: reason = "Temporarily Unavailable"; break; 00547 case 481: reason = "Call/Transaction Does Not Exist"; break; 00548 case 482: reason = "Loop Detected"; break; 00549 case 483: reason = "Too Many Hops"; break; 00550 case 484: reason = "Address Incomplete"; break; 00551 case 485: reason = "Ambiguous"; break; 00552 case 486: reason = "Busy Here"; break; 00553 case 487: reason = "Request Terminated"; break; 00554 case 488: reason = "Not Acceptable Here"; break; 00555 case 489: reason = "Event Package Not Supported"; break; 00556 case 491: reason = "Request Pending"; break; 00557 case 493: reason = "Undecipherable"; break; 00558 case 500: reason = "Server Internal Error"; break; 00559 case 501: reason = "Not Implemented"; break; 00560 case 502: reason = "Bad Gateway"; break; 00561 case 503: reason = "Service Unavailable"; break; 00562 case 504: reason = "Server Time-out"; break; 00563 case 505: reason = "Version Not Supported"; break; 00564 case 513: reason = "Message Too Large"; break; 00565 case 600: reason = "Busy Everywhere"; break; 00566 case 603: reason = "Decline"; break; 00567 case 604: reason = "Does Not Exist Anywhere"; break; 00568 case 606: reason = "Not Acceptable"; break; 00569 } 00570 } 00571 00572 SipMessage* 00573 Helper::makeCancel(const SipMessage& request) 00574 { 00575 assert(request.isRequest()); 00576 assert(request.header(h_RequestLine).getMethod() == INVITE); 00577 std::auto_ptr<SipMessage> cancel(new SipMessage); 00578 00579 RequestLine rLine(CANCEL, request.header(h_RequestLine).getSipVersion()); 00580 rLine.uri() = request.header(h_RequestLine).uri(); 00581 cancel->header(h_RequestLine) = rLine; 00582 cancel->header(h_MaxForwards).value() = 70; 00583 cancel->header(h_To) = request.header(h_To); 00584 cancel->header(h_From) = request.header(h_From); 00585 cancel->header(h_CallId) = request.header(h_CallId); 00586 if (request.exists(h_ProxyAuthorizations)) 00587 { 00588 cancel->header(h_ProxyAuthorizations) = request.header(h_ProxyAuthorizations); 00589 } 00590 if (request.exists(h_Authorizations)) 00591 { 00592 cancel->header(h_Authorizations) = request.header(h_Authorizations); 00593 } 00594 00595 if (request.exists(h_Routes)) 00596 { 00597 cancel->header(h_Routes) = request.header(h_Routes); 00598 } 00599 00600 cancel->header(h_CSeq) = request.header(h_CSeq); 00601 cancel->header(h_CSeq).method() = CANCEL; 00602 cancel->header(h_Vias).push_back(request.header(h_Vias).front()); 00603 00604 return cancel.release(); 00605 } 00606 00607 00608 SipMessage* 00609 Helper::makeFailureAck(const SipMessage& request, const SipMessage& response) 00610 { 00611 assert (request.header(h_Vias).size() >= 1); 00612 assert (request.header(h_RequestLine).getMethod() == INVITE); 00613 00614 std::auto_ptr<SipMessage> ack(new SipMessage); 00615 00616 RequestLine rLine(ACK, request.header(h_RequestLine).getSipVersion()); 00617 rLine.uri() = request.header(h_RequestLine).uri(); 00618 ack->header(h_RequestLine) = rLine; 00619 ack->header(h_MaxForwards).value() = 70; 00620 ack->header(h_CallId) = request.header(h_CallId); 00621 ack->header(h_From) = request.header(h_From); 00622 ack->header(h_To) = response.header(h_To); // to get to-tag 00623 ack->header(h_Vias).push_back(request.header(h_Vias).front()); 00624 ack->header(h_CSeq) = request.header(h_CSeq); 00625 ack->header(h_CSeq).method() = ACK; 00626 if (request.exists(h_Routes)) 00627 { 00628 ack->header(h_Routes) = request.header(h_Routes); 00629 } 00630 00631 return ack.release(); 00632 } 00633 00634 00635 static const Data cookie("z9hG4bK"); // magic cookie per rfc3261 00636 Data 00637 Helper::computeUniqueBranch() 00638 { 00639 Data result(16, Data::Preallocate); 00640 result += cookie; 00641 result += Random::getRandomHex(4); 00642 result += "C1"; 00643 result += Random::getRandomHex(2); 00644 return result; 00645 } 00646 00647 00648 static Data localhostname = DnsUtil::getLocalHostName(); 00649 Data 00650 Helper::computeCallId() 00651 { 00652 Data hostAndSalt(localhostname + Random::getRandomHex(16)); 00653 #ifndef USE_SSL // .bwc. None of this is neccessary if we're using openssl 00654 #if defined(__linux__) || defined(__APPLE__) 00655 pid_t pid = getpid(); 00656 hostAndSalt.append((char*)&pid,sizeof(pid)); 00657 #endif 00658 #ifdef __APPLE__ 00659 pthread_t thread = pthread_self(); 00660 hostAndSalt.append((char*)&thread,sizeof(thread)); 00661 #endif 00662 #ifdef WIN32 00663 DWORD proccessId = ::GetCurrentProcessId(); 00664 DWORD threadId = ::GetCurrentThreadId(); 00665 hostAndSalt.append((char*)&proccessId,sizeof(proccessId)); 00666 hostAndSalt.append((char*)&threadId,sizeof(threadId)); 00667 #endif 00668 #endif // of USE_SSL 00669 return hostAndSalt.md5(Data::BASE64); 00670 } 00671 00672 Data 00673 Helper::computeTag(int numBytes) 00674 { 00675 return Random::getRandomHex(numBytes); 00676 } 00677 00678 void 00679 Helper::setNonceHelper(NonceHelper *nonceHelper) 00680 { 00681 mNonceHelperPtr.mNonceHelper = nonceHelper; 00682 } 00683 00684 NonceHelper* 00685 Helper::getNonceHelper() 00686 { 00687 if (mNonceHelperPtr.mNonceHelper == 0) 00688 { 00689 mNonceHelperPtr.mNonceHelper = new BasicNonceHelper(); 00690 } 00691 return mNonceHelperPtr.mNonceHelper; 00692 } 00693 00694 00695 Data 00696 Helper::makeNonce(const SipMessage& request, const Data& timestamp) 00697 { 00698 return getNonceHelper()->makeNonce(request, timestamp); 00699 } 00700 00701 static Data noBody = MD5Stream().getHex(); 00702 Data 00703 Helper::makeResponseMD5WithA1(const Data& a1, 00704 const Data& method, const Data& digestUri, const Data& nonce, 00705 const Data& qop, const Data& cnonce, const Data& cnonceCount, 00706 const Contents* entityBody) 00707 { 00708 MD5Stream a2; 00709 a2 << method 00710 << Symbols::COLON 00711 << digestUri; 00712 00713 if (qop == Symbols::authInt) 00714 { 00715 if (entityBody) 00716 { 00717 MD5Stream eStream; 00718 eStream << *entityBody; 00719 a2 << Symbols::COLON << eStream.getHex(); 00720 } 00721 else 00722 { 00723 a2 << Symbols::COLON << noBody; 00724 } 00725 } 00726 00727 MD5Stream r; 00728 r << a1 00729 << Symbols::COLON 00730 << nonce 00731 << Symbols::COLON; 00732 00733 if (!qop.empty()) 00734 { 00735 r << cnonceCount 00736 << Symbols::COLON 00737 << cnonce 00738 << Symbols::COLON 00739 << qop 00740 << Symbols::COLON; 00741 } 00742 r << a2.getHex(); 00743 00744 return r.getHex(); 00745 } 00746 00747 //RFC 2617 3.2.2.1 00748 Data 00749 Helper::makeResponseMD5(const Data& username, const Data& password, const Data& realm, 00750 const Data& method, const Data& digestUri, const Data& nonce, 00751 const Data& qop, const Data& cnonce, const Data& cnonceCount, 00752 const Contents *entity) 00753 { 00754 MD5Stream a1; 00755 a1 << username 00756 << Symbols::COLON 00757 << realm 00758 << Symbols::COLON 00759 << password; 00760 00761 return makeResponseMD5WithA1(a1.getHex(), method, digestUri, nonce, qop, 00762 cnonce, cnonceCount, entity); 00763 } 00764 00765 static Data digest("digest"); 00766 std::pair<Helper::AuthResult,Data> 00767 Helper::advancedAuthenticateRequest(const SipMessage& request, 00768 const Data& realm, 00769 const Data& a1, 00770 int expiresDelta, 00771 bool proxyAuthorization) 00772 { 00773 Data username; 00774 DebugLog(<< "Authenticating: realm=" << realm << " expires=" << expiresDelta); 00775 //DebugLog(<< request); 00776 00777 const ParserContainer<Auth>* auths = 0; 00778 if(proxyAuthorization) 00779 { 00780 if(request.exists(h_ProxyAuthorizations)) 00781 { 00782 auths = &request.header(h_ProxyAuthorizations); 00783 } 00784 } 00785 else 00786 { 00787 if(request.exists(h_Authorizations)) 00788 { 00789 auths = &request.header(h_Authorizations); 00790 } 00791 } 00792 00793 if (auths) 00794 { 00795 for (ParserContainer<Auth>::const_iterator i = auths->begin(); i != auths->end(); i++) 00796 { 00797 if (i->exists(p_realm) && 00798 i->exists(p_nonce) && 00799 i->exists(p_response) && 00800 i->param(p_realm) == realm) 00801 { 00802 if(!isEqualNoCase(i->scheme(),digest)) 00803 { 00804 DebugLog(<< "Scheme must be Digest"); 00805 continue; 00806 } 00807 /* ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size()); 00808 if (!pb.eof() && !isdigit(*pb.position())) 00809 { 00810 DebugLog(<< "Invalid nonce; expected timestamp."); 00811 return make_pair(BadlyFormed,username); 00812 } 00813 const char* anchor = pb.position(); 00814 pb.skipToChar(Symbols::COLON[0]); 00815 00816 if (pb.eof()) 00817 { 00818 DebugLog(<< "Invalid nonce; expected timestamp terminator."); 00819 return make_pair(BadlyFormed,username); 00820 } 00821 00822 Data then; 00823 pb.data(then, anchor); 00824 if (expiresDelta > 0) 00825 { 00826 unsigned int now = (unsigned int)(Timer::getTimeMs()/1000); 00827 if ((unsigned int)then.convertUInt64() + expiresDelta < now) 00828 { 00829 DebugLog(<< "Nonce has expired."); 00830 return make_pair(Expired,username); 00831 } 00832 } */ 00833 00834 NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce)); 00835 if(x_nonce.getCreationTime() == 0) 00836 return make_pair(BadlyFormed,username); 00837 00838 if (expiresDelta > 0) 00839 { 00840 UInt64 now = Timer::getTimeSecs(); 00841 if (x_nonce.getCreationTime() + expiresDelta < now) 00842 { 00843 DebugLog(<< "Nonce has expired."); 00844 return make_pair(Expired,username); 00845 } 00846 } 00847 00848 Data then(x_nonce.getCreationTime()); 00849 if (i->param(p_nonce) != makeNonce(request, then)) 00850 { 00851 InfoLog(<< "Not my nonce. expected=" << makeNonce(request, then) 00852 << " received=" << i->param(p_nonce) 00853 << " then=" << then); 00854 00855 return make_pair(BadlyFormed,username); 00856 } 00857 00858 if (i->exists(p_qop)) 00859 { 00860 if (i->param(p_qop) == Symbols::auth || i->param(p_qop) == Symbols::authInt) 00861 { 00862 if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc)) 00863 { 00864 if (i->param(p_response) == makeResponseMD5WithA1(a1, 00865 getMethodName(request.header(h_RequestLine).getMethod()), 00866 i->param(p_uri), 00867 i->param(p_nonce), 00868 i->param(p_qop), 00869 i->param(p_cnonce), 00870 i->param(p_nc), 00871 request.getContents())) 00872 { 00873 if(i->exists(p_username)) 00874 { 00875 username = i->param(p_username); 00876 } 00877 return make_pair(Authenticated,username); 00878 } 00879 else 00880 { 00881 return make_pair(Failed,username); 00882 } 00883 } 00884 } 00885 else 00886 { 00887 InfoLog (<< "Unsupported qop=" << i->param(p_qop)); 00888 return make_pair(Failed,username); 00889 } 00890 } 00891 else if(i->exists(p_uri)) 00892 { 00893 if (i->param(p_response) == makeResponseMD5WithA1(a1, 00894 getMethodName(request.header(h_RequestLine).getMethod()), 00895 i->param(p_uri), 00896 i->param(p_nonce))) 00897 { 00898 if(i->exists(p_username)) 00899 { 00900 username = i->param(p_username); 00901 } 00902 return make_pair(Authenticated,username); 00903 } 00904 else 00905 { 00906 return make_pair(Failed,username); 00907 } 00908 } 00909 } 00910 else 00911 { 00912 return make_pair(BadlyFormed,username); 00913 } 00914 } 00915 return make_pair(BadlyFormed,username); 00916 } 00917 DebugLog (<< "No authentication headers. Failing request."); 00918 return make_pair(Failed,username); 00919 } 00920 00921 Helper::AuthResult 00922 Helper::authenticateRequest(const SipMessage& request, 00923 const Data& realm, 00924 const Data& password, 00925 int expiresDelta) 00926 { 00927 DebugLog(<< "Authenticating: realm=" << realm << " expires=" << expiresDelta); 00928 //DebugLog(<< request); 00929 00930 // !bwc! Somewhat inefficient. Maybe optimize later. 00931 ParserContainer<Auth> auths; 00932 00933 if(request.exists(h_ProxyAuthorizations)) 00934 { 00935 auths.append(request.header(h_ProxyAuthorizations)); 00936 } 00937 00938 if(request.exists(h_Authorizations)) 00939 { 00940 auths.append(request.header(h_Authorizations)); 00941 } 00942 00943 if(auths.empty()) 00944 { 00945 DebugLog (<< "No authentication headers. Failing request."); 00946 return Failed; 00947 } 00948 00949 // ?bwc? Why is const_iterator& operator=(const iterator& rhs) 00950 // not working properly? 00951 //ParserContainer<Auth>::const_iterator i = auths.begin(); 00952 00953 ParserContainer<Auth>::iterator i = auths.begin(); 00954 00955 for (; i != auths.end(); i++) 00956 { 00957 if (i->exists(p_realm) && 00958 i->exists(p_nonce) && 00959 i->exists(p_response) && 00960 i->param(p_realm) == realm) 00961 { 00962 if(!isEqualNoCase(i->scheme(),digest)) 00963 { 00964 DebugLog(<< "Scheme must be Digest"); 00965 continue; 00966 } 00967 /* 00968 ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size()); 00969 if (!pb.eof() && !isdigit(*pb.position())) 00970 { 00971 DebugLog(<< "Invalid nonce; expected timestamp."); 00972 return BadlyFormed; 00973 } 00974 const char* anchor = pb.position(); 00975 pb.skipToChar(Symbols::COLON[0]); 00976 00977 if (pb.eof()) 00978 { 00979 DebugLog(<< "Invalid nonce; expected timestamp terminator."); 00980 return BadlyFormed; 00981 } 00982 00983 Data then; 00984 pb.data(then, anchor); 00985 */ 00986 NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce)); 00987 if(x_nonce.getCreationTime() == 0) 00988 return BadlyFormed; 00989 00990 00991 00992 00993 00994 if (expiresDelta > 0) 00995 { 00996 UInt64 now = Timer::getTimeSecs(); 00997 if (x_nonce.getCreationTime() + expiresDelta < now) 00998 { 00999 DebugLog(<< "Nonce has expired."); 01000 return Expired; 01001 } 01002 } 01003 01004 Data then(x_nonce.getCreationTime()); 01005 if (i->param(p_nonce) != makeNonce(request, then)) 01006 { 01007 InfoLog(<< "Not my nonce."); 01008 return Failed; 01009 } 01010 01011 InfoLog (<< " username=" << (i->param(p_username)) 01012 << " password=" << password 01013 << " realm=" << realm 01014 << " method=" << getMethodName(request.header(h_RequestLine).getMethod()) 01015 << " uri=" << i->param(p_uri) 01016 << " nonce=" << i->param(p_nonce)); 01017 01018 if (i->exists(p_qop)) 01019 { 01020 if (i->param(p_qop) == Symbols::auth || i->param(p_qop) == Symbols::authInt) 01021 { 01022 if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc)) 01023 { 01024 if (i->param(p_response) == makeResponseMD5(i->param(p_username), 01025 password, 01026 realm, 01027 getMethodName(request.header(h_RequestLine).getMethod()), 01028 i->param(p_uri), 01029 i->param(p_nonce), 01030 i->param(p_qop), 01031 i->param(p_cnonce), 01032 i->param(p_nc)), 01033 request.getContents()) 01034 { 01035 return Authenticated; 01036 } 01037 else 01038 { 01039 return Failed; 01040 } 01041 } 01042 } 01043 else 01044 { 01045 InfoLog (<< "Unsupported qop=" << i->param(p_qop)); 01046 return Failed; 01047 } 01048 } 01049 else if(i->exists(p_uri)) 01050 { 01051 01052 if (i->param(p_response) == makeResponseMD5(i->param(p_username), 01053 password, 01054 realm, 01055 getMethodName(request.header(h_RequestLine).getMethod()), 01056 i->param(p_uri), 01057 i->param(p_nonce))) 01058 { 01059 return Authenticated; 01060 } 01061 else 01062 { 01063 return Failed; 01064 } 01065 } 01066 } 01067 else 01068 { 01069 return BadlyFormed; 01070 } 01071 } 01072 01073 return BadlyFormed; 01074 01075 } 01076 01077 Helper::AuthResult 01078 Helper::authenticateRequestWithA1(const SipMessage& request, 01079 const Data& realm, 01080 const Data& hA1, 01081 int expiresDelta) 01082 { 01083 DebugLog(<< "Authenticating with HA1: realm=" << realm << " expires=" << expiresDelta); 01084 //DebugLog(<< request); 01085 01086 // !bwc! Somewhat inefficient. Maybe optimize later. 01087 ParserContainer<Auth> auths; 01088 01089 if(request.exists(h_ProxyAuthorizations)) 01090 { 01091 auths.append(request.header(h_ProxyAuthorizations)); 01092 } 01093 01094 if(request.exists(h_Authorizations)) 01095 { 01096 auths.append(request.header(h_Authorizations)); 01097 } 01098 01099 if(auths.empty()) 01100 { 01101 DebugLog (<< "No authentication headers. Failing request."); 01102 return Failed; 01103 } 01104 01105 // ?bwc? Why is const_iterator& operator=(const iterator& rhs) 01106 // not working properly? 01107 //ParserContainer<Auth>::const_iterator i = auths.begin(); 01108 01109 ParserContainer<Auth>::iterator i = auths.begin(); 01110 01111 for (;i != auths.end(); i++) 01112 { 01113 if (i->exists(p_realm) && 01114 i->exists(p_nonce) && 01115 i->exists(p_response) && 01116 i->param(p_realm) == realm) 01117 { 01118 if(!isEqualNoCase(i->scheme(),digest)) 01119 { 01120 DebugLog(<< "Scheme must be Digest"); 01121 continue; 01122 } 01123 /* 01124 ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size()); 01125 if (!pb.eof() && !isdigit(*pb.position())) 01126 { 01127 DebugLog(<< "Invalid nonce; expected timestamp."); 01128 return BadlyFormed; 01129 } 01130 const char* anchor = pb.position(); 01131 pb.skipToChar(Symbols::COLON[0]); 01132 01133 if (pb.eof()) 01134 { 01135 DebugLog(<< "Invalid nonce; expected timestamp terminator."); 01136 return BadlyFormed; 01137 } 01138 01139 Data then; 01140 pb.data(then, anchor); 01141 */ 01142 01143 NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce)); 01144 if(x_nonce.getCreationTime() == 0) 01145 return BadlyFormed; 01146 01147 01148 01149 if (expiresDelta > 0) 01150 { 01151 UInt64 now = Timer::getTimeSecs(); 01152 if (x_nonce.getCreationTime() + expiresDelta < now) 01153 { 01154 DebugLog(<< "Nonce has expired."); 01155 return Expired; 01156 } 01157 } 01158 01159 Data then(x_nonce.getCreationTime()); 01160 01161 if (i->param(p_nonce) != makeNonce(request, then)) 01162 { 01163 InfoLog(<< "Not my nonce."); 01164 return Failed; 01165 } 01166 01167 InfoLog (<< " username=" << (i->param(p_username)) 01168 << " H(A1)=" << hA1 01169 << " realm=" << realm 01170 << " method=" << getMethodName(request.header(h_RequestLine).getMethod()) 01171 << " uri=" << i->param(p_uri) 01172 << " nonce=" << i->param(p_nonce)); 01173 01174 if (i->exists(p_qop)) 01175 { 01176 if (i->param(p_qop) == Symbols::auth || i->param(p_qop) == Symbols::authInt) 01177 { 01178 if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc)) 01179 { 01180 if (i->param(p_response) == makeResponseMD5WithA1(hA1, 01181 getMethodName(request.header(h_RequestLine).getMethod()), 01182 i->param(p_uri), 01183 i->param(p_nonce), 01184 i->param(p_qop), 01185 i->param(p_cnonce), 01186 i->param(p_nc), 01187 request.getContents())) 01188 { 01189 return Authenticated; 01190 } 01191 else 01192 { 01193 return Failed; 01194 } 01195 } 01196 } 01197 else 01198 { 01199 InfoLog (<< "Unsupported qop=" << i->param(p_qop)); 01200 return Failed; 01201 } 01202 } 01203 else if(i->exists(p_uri)) 01204 { 01205 if (i->param(p_response) == makeResponseMD5WithA1(hA1, 01206 getMethodName(request.header(h_RequestLine).getMethod()), 01207 i->param(p_uri), 01208 i->param(p_nonce))) 01209 { 01210 return Authenticated; 01211 } 01212 else 01213 { 01214 return Failed; 01215 } 01216 } 01217 } 01218 else 01219 { 01220 return BadlyFormed; 01221 } 01222 } 01223 01224 return BadlyFormed; 01225 01226 } 01227 01228 SipMessage* 01229 Helper::make405(const SipMessage& request, 01230 const int* allowedMethods, 01231 int len ) 01232 { 01233 SipMessage* resp = Helper::makeResponse(request, 405); 01234 01235 if (len < 0) 01236 { 01237 int upperBound = static_cast<int>(MAX_METHODS); 01238 01239 // The UNKNOWN method name is the first in the enum 01240 for (int i = 1 ; i < upperBound; i ++) 01241 { 01242 int last = 0; 01243 01244 // ENUMS must be contiguous in order for this to work. 01245 assert( i - last <= 1); 01246 Token t; 01247 t.value() = getMethodName(static_cast<resip::MethodTypes>(i)); 01248 resp->header(h_Allows).push_back(t); 01249 last = i; 01250 } 01251 } 01252 else 01253 { 01254 // use user's list 01255 for ( int i = 0 ; i < len ; i++) 01256 { 01257 Token t; 01258 t.value() = getMethodName(static_cast<resip::MethodTypes>(allowedMethods[i])); 01259 resp->header(h_Allows).push_back(t); 01260 } 01261 } 01262 return resp; 01263 } 01264 01265 01266 SipMessage* 01267 Helper::makeProxyChallenge(const SipMessage& request, const Data& realm, bool useAuth, bool stale) 01268 { 01269 return makeChallenge(request,realm,useAuth,stale,true); 01270 } 01271 01272 SipMessage* 01273 Helper::makeWWWChallenge(const SipMessage& request, const Data& realm, bool useAuth, bool stale) 01274 { 01275 return makeChallenge(request,realm,useAuth,stale,false); 01276 } 01277 01278 SipMessage* 01279 Helper::makeChallenge(const SipMessage& request, const Data& realm, bool useAuth, bool stale, bool proxy) 01280 { 01281 Auth auth; 01282 auth.scheme() = Symbols::Digest; 01283 Data timestamp(Timer::getTimeSecs()); 01284 auth.param(p_nonce) = makeNonce(request, timestamp); 01285 auth.param(p_algorithm) = "MD5"; 01286 auth.param(p_realm) = realm; 01287 if (useAuth) 01288 { 01289 auth.param(p_qopOptions) = "auth,auth-int"; 01290 } 01291 if (stale) 01292 { 01293 auth.param(p_stale) = "true"; 01294 } 01295 SipMessage *response; 01296 if(proxy) 01297 { 01298 response = Helper::makeResponse(request, 407); 01299 response->header(h_ProxyAuthenticates).push_back(auth); 01300 } 01301 else 01302 { 01303 response = Helper::makeResponse(request, 401); 01304 response->header(h_WWWAuthenticates).push_back(auth); 01305 } 01306 return response; 01307 } 01308 01309 void 01310 Helper::updateNonceCount(unsigned int& nonceCount, Data& nonceCountString) 01311 { 01312 if (!nonceCountString.empty()) 01313 { 01314 return; 01315 } 01316 nonceCount++; 01317 { 01318 //DataStream s(nonceCountString); 01319 01320 //s << std::setw(8) << std::setfill('0') << std::hex << nonceCount; 01321 char buf[128]; 01322 *buf = 0; 01323 01324 #if (defined(_MSC_VER) && _MSC_VER >= 1400) 01325 sprintf_s(buf,128,"%08x",nonceCount); 01326 #else 01327 sprintf(buf,"%08x",nonceCount); 01328 #endif 01329 nonceCountString = buf; 01330 } 01331 DebugLog(<< "nonceCount is now: [" << nonceCountString << "]"); 01332 } 01333 01334 01335 Auth 01336 Helper::makeChallengeResponseAuth(const SipMessage& request, 01337 const Data& username, 01338 const Data& password, 01339 const Auth& challenge, 01340 const Data& cnonce, 01341 unsigned int& nonceCount, 01342 Data& nonceCountString) 01343 { 01344 Auth auth; 01345 Data authQop = qopOption(challenge); 01346 if(!authQop.empty()) 01347 { 01348 updateNonceCount(nonceCount, nonceCountString); 01349 } 01350 makeChallengeResponseAuth(request, username, password, challenge, cnonce, authQop, nonceCountString, auth); 01351 return auth; 01352 } 01353 01354 void 01355 Helper::makeChallengeResponseAuth(const SipMessage& request, 01356 const Data& username, 01357 const Data& password, 01358 const Auth& challenge, 01359 const Data& cnonce, 01360 const Data& authQop, 01361 const Data& nonceCountString, 01362 Auth& auth) 01363 { 01364 auth.scheme() = Symbols::Digest; 01365 auth.param(p_username) = username; 01366 assert(challenge.exists(p_realm)); 01367 auth.param(p_realm) = challenge.param(p_realm); 01368 assert(challenge.exists(p_nonce)); 01369 auth.param(p_nonce) = challenge.param(p_nonce); 01370 Data digestUri; 01371 { 01372 DataStream s(digestUri); 01373 //s << request.header(h_RequestLine).uri().host(); // wrong 01374 s << request.header(h_RequestLine).uri(); // right 01375 } 01376 auth.param(p_uri) = digestUri; 01377 01378 if (!authQop.empty()) 01379 { 01380 auth.param(p_response) = Helper::makeResponseMD5(username, 01381 password, 01382 challenge.param(p_realm), 01383 getMethodName(request.header(h_RequestLine).getMethod()), 01384 digestUri, 01385 challenge.param(p_nonce), 01386 authQop, 01387 cnonce, 01388 nonceCountString, 01389 request.getContents()); 01390 auth.param(p_cnonce) = cnonce; 01391 auth.param(p_nc) = nonceCountString; 01392 auth.param(p_qop) = authQop; 01393 } 01394 else 01395 { 01396 assert(challenge.exists(p_realm)); 01397 auth.param(p_response) = Helper::makeResponseMD5(username, 01398 password, 01399 challenge.param(p_realm), 01400 getMethodName(request.header(h_RequestLine).getMethod()), 01401 digestUri, 01402 challenge.param(p_nonce)); 01403 } 01404 01405 if (challenge.exists(p_algorithm)) 01406 { 01407 auth.param(p_algorithm) = challenge.param(p_algorithm); 01408 } 01409 else 01410 { 01411 auth.param(p_algorithm) = "MD5"; 01412 } 01413 01414 if (challenge.exists(p_opaque) && challenge.param(p_opaque).size() > 0) 01415 { 01416 auth.param(p_opaque) = challenge.param(p_opaque); 01417 } 01418 } 01419 01420 // priority-order list of preferred qop tokens 01421 static Data preferredTokens[] = 01422 { 01423 "auth-int", 01424 "auth" 01425 }; 01426 static size_t pTokenSize=sizeof(preferredTokens)/sizeof(*preferredTokens); 01427 Data 01428 Helper::qopOption(const Auth& challenge) 01429 { 01430 bool found = false; 01431 size_t index = pTokenSize; 01432 if (challenge.exists(p_qopOptions) && !challenge.param(p_qopOptions).empty()) 01433 { 01434 ParseBuffer pb(challenge.param(p_qopOptions).data(), challenge.param(p_qopOptions).size()); 01435 do 01436 { 01437 const char* anchor = pb.skipWhitespace(); 01438 pb.skipToChar(Symbols::COMMA[0]); 01439 Data q; 01440 pb.data(q, anchor); 01441 if (!pb.eof()) 01442 pb.skipChar(); 01443 for (size_t i=0; i < pTokenSize; i++) 01444 { 01445 if (q == preferredTokens[i]) 01446 { 01447 // found a preferred token; is it higher priority? 01448 if (i < index) 01449 { 01450 found = true; 01451 index = i; 01452 } 01453 } 01454 } 01455 } 01456 while(!pb.eof()); 01457 } 01458 01459 if (found) 01460 return preferredTokens[index]; 01461 01462 return Data::Empty; 01463 01464 } 01465 01466 01467 Auth 01468 Helper::makeChallengeResponseAuthWithA1(const SipMessage& request, 01469 const Data& username, 01470 const Data& passwordHashA1, 01471 const Auth& challenge, 01472 const Data& cnonce, 01473 unsigned int& nonceCount, 01474 Data& nonceCountString) 01475 { 01476 Auth auth; 01477 Data authQop = qopOption(challenge); 01478 if(!authQop.empty()) 01479 { 01480 updateNonceCount(nonceCount, nonceCountString); 01481 } 01482 makeChallengeResponseAuthWithA1(request, username, passwordHashA1, challenge, cnonce, authQop, nonceCountString, auth); 01483 return auth; 01484 } 01485 01486 void 01487 Helper::makeChallengeResponseAuthWithA1(const SipMessage& request, 01488 const Data& username, 01489 const Data& passwordHashA1, 01490 const Auth& challenge, 01491 const Data& cnonce, 01492 const Data& authQop, 01493 const Data& nonceCountString, 01494 Auth& auth) 01495 { 01496 auth.scheme() = Symbols::Digest; 01497 auth.param(p_username) = username; 01498 assert(challenge.exists(p_realm)); 01499 auth.param(p_realm) = challenge.param(p_realm); 01500 assert(challenge.exists(p_nonce)); 01501 auth.param(p_nonce) = challenge.param(p_nonce); 01502 Data digestUri; 01503 { 01504 DataStream s(digestUri); 01505 //s << request.const_header(h_RequestLine).uri().host(); // wrong 01506 s << request.const_header(h_RequestLine).uri(); // right 01507 } 01508 auth.param(p_uri) = digestUri; 01509 01510 if (!authQop.empty()) 01511 { 01512 auth.param(p_response) = Helper::makeResponseMD5WithA1(passwordHashA1, 01513 getMethodName(request.header(h_RequestLine).getMethod()), 01514 digestUri, 01515 challenge.param(p_nonce), 01516 authQop, 01517 cnonce, 01518 nonceCountString, 01519 request.getContents()); 01520 auth.param(p_cnonce) = cnonce; 01521 auth.param(p_nc) = nonceCountString; 01522 auth.param(p_qop) = authQop; 01523 } 01524 else 01525 { 01526 assert(challenge.exists(p_realm)); 01527 auth.param(p_response) = Helper::makeResponseMD5WithA1(passwordHashA1, 01528 getMethodName(request.header(h_RequestLine).getMethod()), 01529 digestUri, 01530 challenge.param(p_nonce)); 01531 } 01532 01533 if (challenge.exists(p_algorithm)) 01534 { 01535 auth.param(p_algorithm) = challenge.param(p_algorithm); 01536 } 01537 else 01538 { 01539 auth.param(p_algorithm) = "MD5"; 01540 } 01541 01542 if (challenge.exists(p_opaque) && challenge.param(p_opaque).size() > 0) 01543 { 01544 auth.param(p_opaque) = challenge.param(p_opaque); 01545 } 01546 } 01547 01548 //.dcm. all the auth stuff should be yanked out of helper and 01549 //architected for algorithm independance 01550 bool 01551 Helper::algorithmAndQopSupported(const Auth& challenge) 01552 { 01553 if ( !(challenge.exists(p_nonce) && challenge.exists(p_realm))) 01554 { 01555 return false; 01556 } 01557 return ((!challenge.exists(p_algorithm) 01558 || isEqualNoCase(challenge.param(p_algorithm), "MD5")) 01559 && (!challenge.exists(p_qop) 01560 || isEqualNoCase(challenge.param(p_qop), Symbols::auth) 01561 || isEqualNoCase(challenge.param(p_qop), Symbols::authInt))); 01562 } 01563 01564 SipMessage& 01565 Helper::addAuthorization(SipMessage& request, 01566 const SipMessage& challenge, 01567 const Data& username, 01568 const Data& password, 01569 const Data& cnonce, 01570 unsigned int& nonceCount) 01571 { 01572 Data nonceCountString = Data::Empty; 01573 01574 assert(challenge.isResponse()); 01575 assert(challenge.header(h_StatusLine).responseCode() == 401 || 01576 challenge.header(h_StatusLine).responseCode() == 407); 01577 01578 if (challenge.exists(h_ProxyAuthenticates)) 01579 { 01580 const ParserContainer<Auth>& auths = challenge.header(h_ProxyAuthenticates); 01581 for (ParserContainer<Auth>::const_iterator i = auths.begin(); 01582 i != auths.end(); i++) 01583 { 01584 request.header(h_ProxyAuthorizations).push_back(makeChallengeResponseAuth(request, username, password, *i, 01585 cnonce, nonceCount, nonceCountString)); 01586 } 01587 } 01588 if (challenge.exists(h_WWWAuthenticates)) 01589 { 01590 const ParserContainer<Auth>& auths = challenge.header(h_WWWAuthenticates); 01591 for (ParserContainer<Auth>::const_iterator i = auths.begin(); 01592 i != auths.end(); i++) 01593 { 01594 request.header(h_Authorizations).push_back(makeChallengeResponseAuth(request, username, password, *i, 01595 cnonce, nonceCount, nonceCountString)); 01596 } 01597 } 01598 return request; 01599 } 01600 01601 Uri 01602 Helper::makeUri(const Data& aor, const Data& scheme) 01603 { 01604 assert(!aor.prefix("sip:")); 01605 assert(!aor.prefix("sips:")); 01606 01607 Data tmp(aor.size() + scheme.size() + 1, Data::Preallocate); 01608 tmp += scheme; 01609 tmp += Symbols::COLON; 01610 tmp += aor; 01611 Uri uri(tmp); 01612 return uri; 01613 } 01614 01615 void 01616 Helper::processStrictRoute(SipMessage& request) 01617 { 01618 if (request.exists(h_Routes) && 01619 !request.const_header(h_Routes).empty() && 01620 !request.const_header(h_Routes).front().uri().exists(p_lr)) 01621 { 01622 // The next hop is a strict router. Move the next hop into the 01623 // Request-URI and move the ultimate destination to the end of the 01624 // route list. Force the message target to be the next hop router. 01625 request.header(h_Routes).push_back(NameAddr(request.const_header(h_RequestLine).uri())); 01626 request.header(h_RequestLine).uri() = request.const_header(h_Routes).front().uri(); 01627 request.header(h_Routes).pop_front(); // !jf! 01628 assert(!request.hasForceTarget()); 01629 request.setForceTarget(request.const_header(h_RequestLine).uri()); 01630 } 01631 } 01632 01633 void 01634 Helper::massageRoute(const SipMessage& request, NameAddr& rt) 01635 { 01636 assert(request.isRequest()); 01637 // .bwc. Let's not record-route with a tel uri or something, shall we? 01638 // If the topmost route header is malformed, we can get along without. 01639 if (!request.empty(h_Routes) && 01640 request.header(h_Routes).front().isWellFormed() && 01641 (request.header(h_Routes).front().uri().scheme() == "sip" || 01642 request.header(h_Routes).front().uri().scheme() == "sips" )) 01643 { 01644 rt.uri().scheme() = request.header(h_Routes).front().uri().scheme(); 01645 } 01646 else if(request.header(h_RequestLine).uri().scheme() == "sip" || 01647 request.header(h_RequestLine).uri().scheme() == "sips") 01648 { 01649 rt.uri().scheme() = request.header(h_RequestLine).uri().scheme(); 01650 } 01651 01652 rt.uri().param(p_lr); 01653 } 01654 01655 int 01656 Helper::getPortForReply(SipMessage& request) 01657 { 01658 assert(request.isRequest()); 01659 int port = 0; 01660 if(request.const_header(h_Vias).front().transport() == Symbols::TCP || 01661 request.const_header(h_Vias).front().transport() == Symbols::TLS) 01662 { 01663 // 18.2.2 - bullet 1 and 2 01664 port = request.getSource().getPort(); 01665 if(port == 0) // .slg. not sure if it makes sense for sourcePort to be 0 01666 { 01667 port = request.const_header(h_Vias).front().sentPort(); 01668 } 01669 } 01670 else // unreliable transport 18.2.2 bullets 3 and 4 01671 { 01672 if (request.const_header(h_Vias).front().exists(p_rport)) 01673 { 01674 port = request.getSource().getPort(); 01675 } 01676 else 01677 { 01678 port = request.const_header(h_Vias).front().sentPort(); 01679 } 01680 } 01681 01682 // If we haven't got a valid port yet, then use the default 01683 if (port <= 0 || port > 65535) 01684 { 01685 if(request.const_header(h_Vias).front().transport() == Symbols::TLS || 01686 request.const_header(h_Vias).front().transport() == Symbols::DTLS) 01687 { 01688 port = Symbols::DefaultSipsPort; 01689 } 01690 else 01691 { 01692 port = Symbols::DefaultSipPort; 01693 } 01694 } 01695 return port; 01696 } 01697 01698 Uri 01699 Helper::fromAor(const Data& aor, const Data& scheme) 01700 { 01701 return makeUri(aor, scheme); 01702 } 01703 01704 bool 01705 Helper::validateMessage(const SipMessage& message,resip::Data* reason) 01706 { 01707 if (message.empty(h_To) || 01708 message.empty(h_From) || 01709 message.empty(h_CSeq) || 01710 message.empty(h_CallId) || 01711 message.empty(h_Vias) || 01712 message.empty(h_Vias)) 01713 { 01714 InfoLog(<< "Missing mandatory header fields (To, From, CSeq, Call-Id or Via)"); 01715 DebugLog(<< message); 01716 if(reason) *reason="Missing mandatory header field"; 01717 return false; 01718 } 01719 else 01720 { 01721 if(!message.header(h_CSeq).isWellFormed()) 01722 { 01723 InfoLog(<<"Malformed CSeq header"); 01724 if(reason) *reason="Malformed CSeq header"; 01725 return false; 01726 } 01727 01728 if(!message.header(h_Vias).front().isWellFormed()) 01729 { 01730 InfoLog(<<"Malformed topmost Via header"); 01731 if(reason) *reason="Malformed topmost Via header"; 01732 return false; 01733 } 01734 01735 if (message.isRequest()) 01736 { 01737 if(!message.header(h_RequestLine).isWellFormed()) 01738 { 01739 InfoLog(<< "Illegal request line"); 01740 if(reason) *reason="Malformed Request Line"; 01741 return false; 01742 } 01743 01744 if(message.header(h_RequestLine).method()!=message.header(h_CSeq).method()) 01745 { 01746 InfoLog(<< "Method mismatch btw Request Line and CSeq"); 01747 if(reason) *reason="Method mismatch btw Request Line and CSeq"; 01748 return false; 01749 } 01750 } 01751 else 01752 { 01753 if(!message.header(h_StatusLine).isWellFormed()) 01754 { 01755 InfoLog(<< "Malformed status line"); 01756 if(reason) *reason="Malformed status line"; 01757 return false; 01758 } 01759 } 01760 01761 return true; 01762 } 01763 } 01764 01765 #if defined(USE_SSL) 01766 #include <openssl/blowfish.h> 01767 01768 static const Data sep("[]"); 01769 static const Data pad("\0\0\0\0\0\0\0", 7); 01770 static const Data GRUU("_GRUU"); 01771 static const int saltBytes(16); 01772 01773 Data 01774 Helper::gruuUserPart(const Data& instanceId, 01775 const Data& aor, 01776 const Data& key) 01777 { 01778 unsigned char ivec[8]; 01779 01780 ivec[0] = '\x6E'; 01781 ivec[1] = '\xE7'; 01782 ivec[2] = '\xB0'; 01783 ivec[3] = '\x4A'; 01784 ivec[4] = '\x45'; 01785 ivec[5] = '\x93'; 01786 ivec[6] = '\x7D'; 01787 ivec[7] = '\x51'; 01788 01789 BF_KEY fish; 01790 BF_set_key(&fish, (int)key.size(), (const unsigned char*)key.data()); 01791 01792 const Data salt(resip::Random::getRandomHex(saltBytes)); 01793 01794 const Data token(salt + instanceId + sep + aor + '\0' + 01795 pad.substr(0, (8 - ((salt.size() + 01796 instanceId.size() + 01797 sep.size() + 1 01798 + aor.size() ) % 8)) 01799 % 8)); 01800 auto_ptr <unsigned char> out(new unsigned char[token.size()]); 01801 BF_cbc_encrypt((const unsigned char*)token.data(), 01802 out.get(), 01803 (long)token.size(), 01804 &fish, 01805 ivec, 01806 BF_ENCRYPT); 01807 01808 return GRUU + Data(out.get(),token.size()).base64encode(true/*safe URL*/); 01809 } 01810 01811 std::pair<Data,Data> 01812 Helper::fromGruuUserPart(const Data& gruuUserPart, 01813 const Data& key) 01814 { 01815 unsigned char ivec[8]; 01816 01817 ivec[0] = '\x6E'; 01818 ivec[1] = '\xE7'; 01819 ivec[2] = '\xB0'; 01820 ivec[3] = '\x4A'; 01821 ivec[4] = '\x45'; 01822 ivec[5] = '\x93'; 01823 ivec[6] = '\x7D'; 01824 ivec[7] = '\x51'; 01825 01826 static const std::pair<Data, Data> empty; 01827 01828 if (gruuUserPart.size() < GRUU.size()) 01829 { 01830 return empty; 01831 } 01832 01833 const Data gruu = gruuUserPart.substr(GRUU.size()); 01834 01835 BF_KEY fish; 01836 BF_set_key(&fish, (int)key.size(), (const unsigned char*)key.data()); 01837 01838 const Data decoded = gruu.base64decode(); 01839 01840 auto_ptr <unsigned char> out(new unsigned char[gruuUserPart.size()+1]); 01841 BF_cbc_encrypt((const unsigned char*)decoded.data(), 01842 out.get(), 01843 (long)decoded.size(), 01844 &fish, 01845 ivec, 01846 BF_DECRYPT); 01847 const Data pair(out.get(), decoded.size()); 01848 01849 Data::size_type pos = pair.find(sep); 01850 if (pos == Data::npos) 01851 { 01852 return empty; 01853 } 01854 01855 return std::make_pair(pair.substr(2*saltBytes, pos), // strip out the salt 01856 pair.substr(pos+sep.size())); 01857 } 01858 #endif 01859 Helper::ContentsSecAttrs::ContentsSecAttrs() 01860 : mContents(0), 01861 mAttributes(0) 01862 {} 01863 01864 Helper::ContentsSecAttrs::ContentsSecAttrs(std::auto_ptr<Contents> contents, 01865 std::auto_ptr<SecurityAttributes> attributes) 01866 : mContents(contents), 01867 mAttributes(attributes) 01868 {} 01869 01870 // !!bwc!! Yikes! Destructive copy c'tor! Are we _sure_ this is the 01871 // intended behavior? 01872 Helper::ContentsSecAttrs::ContentsSecAttrs(const ContentsSecAttrs& rhs) 01873 : mContents(rhs.mContents), 01874 mAttributes(rhs.mAttributes) 01875 {} 01876 01877 Helper::ContentsSecAttrs& 01878 Helper::ContentsSecAttrs::operator=(const ContentsSecAttrs& rhs) 01879 { 01880 if (&rhs != this) 01881 { 01882 // !!bwc!! Yikes! Destructive assignment operator! Are we _sure_ this is 01883 // the intended behavior? 01884 mContents = rhs.mContents; 01885 mAttributes = rhs.mAttributes; 01886 } 01887 return *this; 01888 } 01889 01890 01891 Contents* 01892 extractFromPkcs7Recurse(Contents* tree, 01893 const Data& signerAor, 01894 const Data& receiverAor, 01895 SecurityAttributes* attributes, 01896 Security& security) 01897 { 01898 Pkcs7Contents* pk; 01899 if ((pk = dynamic_cast<Pkcs7Contents*>(tree))) 01900 { 01901 InfoLog( << "GREG1: " << *pk ); 01902 #if defined(USE_SSL) 01903 Contents* contents = security.decrypt(receiverAor, pk); 01904 if (contents) 01905 { 01906 attributes->setEncrypted(); 01907 } 01908 return contents; 01909 #else 01910 return 0; 01911 #endif 01912 } 01913 MultipartSignedContents* mps; 01914 if ((mps = dynamic_cast<MultipartSignedContents*>(tree))) 01915 { 01916 InfoLog( << "GREG2: " << *mps ); 01917 #if defined(USE_SSL) 01918 Data signer; 01919 SignatureStatus sigStatus; 01920 Contents* b = extractFromPkcs7Recurse(security.checkSignature(mps, 01921 &signer, 01922 &sigStatus), 01923 signerAor, 01924 receiverAor, attributes, security); 01925 attributes->setSigner(signer); 01926 attributes->setSignatureStatus(sigStatus); 01927 return b->clone(); 01928 #else 01929 return mps->parts().front()->clone(); 01930 #endif 01931 } 01932 MultipartAlternativeContents* alt; 01933 if ((alt = dynamic_cast<MultipartAlternativeContents*>(tree))) 01934 { 01935 InfoLog( << "GREG3: " << *alt ); 01936 for (MultipartAlternativeContents::Parts::reverse_iterator i = alt->parts().rbegin(); 01937 i != alt->parts().rend(); ++i) 01938 { 01939 Contents* b = extractFromPkcs7Recurse(*i, signerAor, receiverAor, attributes, security); 01940 if (b) 01941 { 01942 return b; 01943 } 01944 } 01945 } 01946 01947 MultipartMixedContents* mult; 01948 if ((mult = dynamic_cast<MultipartMixedContents*>(tree))) 01949 { 01950 InfoLog( << "GREG4: " << *mult ); 01951 for (MultipartMixedContents::Parts::iterator i = mult->parts().begin(); 01952 i != mult->parts().end(); ++i) 01953 { 01954 Contents* b = extractFromPkcs7Recurse(*i, signerAor, receiverAor, 01955 attributes, security); 01956 if (b) 01957 { 01958 return b; 01959 } 01960 }; 01961 01962 return 0; 01963 } 01964 01965 return tree->clone(); 01966 } 01967 01968 Helper::ContentsSecAttrs 01969 Helper::extractFromPkcs7(const SipMessage& message, 01970 Security& security) 01971 { 01972 SecurityAttributes* attr = new SecurityAttributes; 01973 // .dlb. currently flattening SecurityAttributes? 01974 //attr->setIdentity(message.getIdentity()); 01975 attr->setIdentity(message.header(h_From).uri().getAor()); 01976 Contents *b = message.getContents(); 01977 if (b) 01978 { 01979 Data fromAor(message.header(h_From).uri().getAor()); 01980 Data toAor(message.header(h_To).uri().getAor()); 01981 if (message.isRequest()) 01982 { 01983 b = extractFromPkcs7Recurse(b, fromAor, toAor, attr, security); 01984 } 01985 else // its a response 01986 { 01987 b = extractFromPkcs7Recurse(b, toAor, fromAor, attr, security); 01988 } 01989 } 01990 std::auto_ptr<Contents> c(b); 01991 std::auto_ptr<SecurityAttributes> a(attr); 01992 return ContentsSecAttrs(c, a); 01993 } 01994 01995 Helper::FailureMessageEffect 01996 Helper::determineFailureMessageEffect(const SipMessage& response) 01997 { 01998 assert(response.isResponse()); 01999 int code = response.header(h_StatusLine).statusCode(); 02000 assert(code >= 400); 02001 02002 switch(code) 02003 { 02004 case 404: 02005 case 410: 02006 case 416: 02007 case 480: // but maybe not, still not quite decided: 02008 case 481: 02009 case 482: // but maybe not, still not quite decided: 02010 case 484: 02011 case 485: 02012 case 502: 02013 case 604: 02014 return DialogTermination; 02015 case 403: 02016 case 489: //only for only subscription 02017 case 408: //again, maybe not. This seems best. 02018 return UsageTermination; 02019 case 400: 02020 case 401: 02021 case 402: 02022 case 405: //doesn't agree w/ -00 of dialogusage 02023 case 406: 02024 case 412: 02025 case 413: 02026 case 414: 02027 case 415: 02028 case 420: 02029 case 421: 02030 case 423: 02031 02032 case 429: // but if this the refer creating the Subscription, no sub will be created. 02033 case 486: 02034 case 487: 02035 case 488: 02036 case 491: 02037 case 493: 02038 case 494: 02039 case 500: 02040 case 505: 02041 case 513: 02042 case 603: 02043 case 606: 02044 return TransactionTermination; 02045 case 483: // who knows, gravefully terminate or just destroy dialog 02046 case 501: 02047 return ApplicationDependant; 02048 default: 02049 if (code < 600) 02050 { 02051 if (response.exists(h_RetryAfter)) 02052 02053 { 02054 return RetryAfter; 02055 } 02056 else 02057 { 02058 return OptionalRetryAfter; 02059 } 02060 } 02061 else 02062 { 02063 if (response.exists(h_RetryAfter)) 02064 { 02065 return RetryAfter; 02066 } 02067 else 02068 { 02069 return ApplicationDependant; 02070 } 02071 } 02072 } 02073 } 02074 02075 SdpContents* getSdpRecurse(Contents* tree) 02076 { 02077 if (dynamic_cast<SdpContents*>(tree)) 02078 { 02079 return static_cast<SdpContents*>(tree); 02080 } 02081 02082 MultipartSignedContents* mps; 02083 if ((mps = dynamic_cast<MultipartSignedContents*>(tree))) 02084 { 02085 try 02086 { 02087 MultipartSignedContents::Parts::const_iterator it = mps->parts().begin(); 02088 Contents* contents = getSdpRecurse(*it); 02089 return static_cast<SdpContents*>(contents); 02090 } 02091 catch (ParseException& e) 02092 { 02093 ErrLog(<< e.name() << endl << e.getMessage()); 02094 } 02095 catch (BaseException& e) 02096 { 02097 ErrLog(<< e.name() << endl << e.getMessage()); 02098 } 02099 02100 return 0; 02101 } 02102 02103 MultipartAlternativeContents* alt; 02104 if ((alt = dynamic_cast<MultipartAlternativeContents*>(tree))) 02105 { 02106 try 02107 { 02108 for (MultipartAlternativeContents::Parts::reverse_iterator i = alt->parts().rbegin(); 02109 i != alt->parts().rend(); ++i) 02110 { 02111 Contents* contents = getSdpRecurse(*i); 02112 if (contents) 02113 { 02114 return static_cast<SdpContents*>(contents); 02115 } 02116 } 02117 } 02118 catch (ParseException& e) 02119 { 02120 ErrLog(<< e.name() << endl << e.getMessage()); 02121 } 02122 catch (BaseException& e) 02123 { 02124 ErrLog(<< e.name() << endl << e.getMessage()); 02125 } 02126 02127 return 0; 02128 } 02129 02130 MultipartMixedContents* mult; 02131 if ((mult = dynamic_cast<MultipartMixedContents*>(tree))) 02132 { 02133 02134 try 02135 { 02136 for (MultipartMixedContents::Parts::iterator i = mult->parts().begin(); 02137 i != mult->parts().end(); ++i) 02138 { 02139 Contents* contents = getSdpRecurse(*i); 02140 if (contents) 02141 { 02142 return static_cast<SdpContents*>(contents); 02143 } 02144 } 02145 } 02146 catch (ParseException& e) 02147 { 02148 ErrLog(<< e.name() << endl << e.getMessage()); 02149 } 02150 catch (BaseException& e) 02151 { 02152 ErrLog(<< e.name() << endl << e.getMessage()); 02153 } 02154 02155 return 0; 02156 } 02157 02158 return 0; 02159 } 02160 02161 static std::auto_ptr<SdpContents> emptysdp; 02162 auto_ptr<SdpContents> Helper::getSdp(Contents* tree) 02163 { 02164 if (tree) 02165 { 02166 SdpContents* sdp = getSdpRecurse(tree); 02167 02168 if (sdp) 02169 { 02170 DebugLog(<< "Got sdp" << endl); 02171 return auto_ptr<SdpContents>(static_cast<SdpContents*>(sdp->clone())); 02172 } 02173 } 02174 02175 //DebugLog(<< "No sdp" << endl); 02176 return emptysdp; 02177 } 02178 02179 bool 02180 Helper::isClientBehindNAT(const SipMessage& request, bool privateToPublicOnly) 02181 { 02182 assert(request.isRequest()); 02183 assert(!request.header(h_Vias).empty()); 02184 02185 // If received parameter is on top Via, then the source of the message doesn't match 02186 // the address provided in the via. Assume this is because the sender is behind a NAT. 02187 // The assumption here is that this SipStack instance is the first hop in a public SIP server 02188 // architecture, and that clients are directly connected to this instance. 02189 if(request.header(h_Vias).front().exists(p_received)) 02190 { 02191 if(privateToPublicOnly) 02192 { 02193 if(Tuple(request.header(h_Vias).front().sentHost(), 0, UNKNOWN_TRANSPORT).isPrivateAddress() && 02194 !Tuple(request.header(h_Vias).front().param(p_received), 0, UNKNOWN_TRANSPORT).isPrivateAddress()) 02195 { 02196 return true; 02197 } 02198 else 02199 { 02200 return false; 02201 } 02202 } 02203 return true; 02204 } 02205 return false; 02206 } 02207 02208 02209 Tuple 02210 Helper::getClientPublicAddress(const SipMessage& request) 02211 { 02212 assert(request.isRequest()); 02213 assert(!request.header(h_Vias).empty()); 02214 02215 // Iterate through Via's starting at the bottom (closest to the client). Return the first 02216 // public address found from received parameter if present, or Via host. 02217 Vias::const_iterator it = request.header(h_Vias).end(); 02218 while(true) 02219 { 02220 it--; 02221 if(it->exists(p_received)) 02222 { 02223 // Check IP from received parameter 02224 Tuple address(it->param(p_received), 0, UNKNOWN_TRANSPORT); 02225 if(!address.isPrivateAddress()) 02226 { 02227 address.setPort(it->exists(p_rport) ? it->param(p_rport).port() : it->sentPort()); 02228 address.setType(Tuple::toTransport(it->transport())); 02229 return address; 02230 } 02231 } 02232 02233 // Check IP from Via sentHost 02234 Tuple address(it->sentHost(), 0, UNKNOWN_TRANSPORT); 02235 if(!address.isPrivateAddress()) 02236 { 02237 address.setPort(it->exists(p_rport) ? it->param(p_rport).port() : it->sentPort()); 02238 address.setType(Tuple::toTransport(it->transport())); 02239 return address; 02240 } 02241 02242 if(it == request.header(h_Vias).begin()) break; 02243 } 02244 return Tuple(); 02245 } 02246 02247 02248 /* ==================================================================== 02249 * The Vovida Software License, Version 1.0 02250 * 02251 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 02252 * 02253 * Redistribution and use in source and binary forms, with or without 02254 * modification, are permitted provided that the following conditions 02255 * are met: 02256 * 02257 * 1. Redistributions of source code must retain the above copyright 02258 * notice, this list of conditions and the following disclaimer. 02259 * 02260 * 2. Redistributions in binary form must reproduce the above copyright 02261 * notice, this list of conditions and the following disclaimer in 02262 * the documentation and/or other materials provided with the 02263 * distribution. 02264 * 02265 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 02266 * and "Vovida Open Communication Application Library (VOCAL)" must 02267 * not be used to endorse or promote products derived from this 02268 * software without prior written permission. For written 02269 * permission, please contact vocal@vovida.org. 02270 * 02271 * 4. Products derived from this software may not be called "VOCAL", nor 02272 * may "VOCAL" appear in their name, without prior written 02273 * permission of Vovida Networks, Inc. 02274 * 02275 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 02276 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 02277 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 02278 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 02279 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 02280 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 02281 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 02282 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 02283 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 02284 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 02285 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 02286 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 02287 * DAMAGE. 02288 * 02289 * ==================================================================== 02290 * 02291 * This software consists of voluntary contributions made by Vovida 02292 * Networks, Inc. and many individuals on behalf of Vovida Networks, 02293 * Inc. For more information on Vovida Networks, Inc., please see 02294 * <http://www.vovida.org/>. 02295 * 02296 */
1.7.5.1