reSIProcate/stack  9694
Helper.cxx
Go to the documentation of this file.
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  */