reSIProcate/stack  9694
Helper.hxx
Go to the documentation of this file.
00001 #if !defined(RESIP_HELPER_HXX)
00002 #define RESIP_HELPER_HXX 
00003 
00004 #include <time.h>
00005 
00006 #include "resip/stack/NonceHelper.hxx"
00007 #include "resip/stack/Symbols.hxx"
00008 #include "resip/stack/Uri.hxx"
00009 #include "resip/stack/MethodTypes.hxx"
00010 #include "rutil/BaseException.hxx"
00011 #include "rutil/Data.hxx"
00012 #include "resip/stack/Contents.hxx"
00013 #include "resip/stack/SecurityAttributes.hxx"
00014 #include "resip/stack/SdpContents.hxx"
00015 
00016 namespace resip
00017 {
00018 
00019 class SipMessage;
00020 class NameAddr;
00021 class SecurityAttributes;
00022 class Security;
00023 
00024 class UnsupportedAuthenticationScheme : public BaseException
00025 {
00026    public:
00027       UnsupportedAuthenticationScheme(const Data& msg, const Data& file, const int line)
00028          : BaseException(msg, file, line) {}
00029       
00030       const char* name() const { return "UnsupportedAuthenticationScheme"; }
00031 };
00032 
00033 
00043 class Helper
00044 {
00045    public:
00046 
00048       const static int tagSize;  
00049 
00058       template<typename T>
00059       static T aBitSmallerThan(T secs)
00060       {
00061          return resipMax(T(0), resipMin(T(secs-5), T(9*secs/10)));
00062       }
00063 
00078       static void integer2hex(char* _d, unsigned int _s, bool _l = true);
00079 
00089       static unsigned int hex2integer(const char* _s);
00090 
00105       static int jitterValue(int input, int lowerPercentage, int upperPercentage, int minimum=0);
00106 
00115       static SipMessage* makeInvite(const NameAddr& target, const NameAddr& from);
00116       
00128       static SipMessage* makeInvite(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
00129       
00150       static void makeResponse(SipMessage& response, 
00151                                const SipMessage& request, 
00152                                int responseCode, 
00153                                const Data& reason = Data::Empty,
00154                                const Data& hostname = Data::Empty,
00155                                const Data& warning=Data::Empty);
00156 
00179       static void makeResponse(SipMessage& response, 
00180                                const SipMessage& request, 
00181                                int responseCode, 
00182                                const NameAddr& myContact, 
00183                                const Data& reason = Data::Empty,
00184                                const Data& hostname = Data::Empty,
00185                                const Data& warning=Data::Empty);
00186 
00209       static SipMessage* makeResponse(const SipMessage& request,
00210                                       int responseCode,
00211                                       const Data& reason = Data::Empty, 
00212                                       const Data& hostname = Data::Empty,
00213                                       const Data& warning=Data::Empty);
00214 
00239       static SipMessage* makeResponse(const SipMessage& request, 
00240                                       int responseCode, 
00241                                       const NameAddr& myContact, 
00242                                       const Data& reason = Data::Empty,
00243                                       const Data& hostname = Data::Empty,
00244                                       const Data& warning=Data::Empty);
00245 
00246       static void makeRawResponse(Data& rawBuffer,
00247                                     const SipMessage& request, 
00248                                     int responseCode,
00249                                     const Data& additionalHeaders=Data::Empty,
00250                                     const Data& body=Data::Empty);
00251 
00271       static SipMessage* make405(const SipMessage& request,
00272                                  const int* allowedMethods = 0,
00273                                  int nMethods = -1);
00274 
00283       static void getResponseCodeReason(int responseCode, Data& reason);
00284 
00307       static SipMessage* makeRequest(const NameAddr& target, const NameAddr& from, const NameAddr& contact, MethodTypes method);
00308 
00326       static SipMessage* makeRequest(const NameAddr& target, const NameAddr& from, MethodTypes method);
00327 
00336       static SipMessage* makeCancel(const SipMessage& request);
00337       
00339       static SipMessage* makeRegister(const NameAddr& to, const NameAddr& from, const NameAddr& contact);
00340 
00342       static SipMessage* makeRegister(const NameAddr& to, const NameAddr& from);
00343 
00345       static SipMessage* makeRegister(const NameAddr& to, const Data& transport, const NameAddr& contact);
00346 
00348       static SipMessage* makeRegister(const NameAddr& to, const Data& transport);
00349 
00351       static SipMessage* makeSubscribe(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
00352 
00354       static SipMessage* makeSubscribe(const NameAddr& target, const NameAddr& from);
00355 
00357       static SipMessage* makeMessage(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
00358 
00360       static SipMessage* makeMessage(const NameAddr& target, const NameAddr& from);
00361 
00363       static SipMessage* makePublish(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
00364 
00366       static SipMessage* makePublish(const NameAddr& target, const NameAddr& from);
00367 
00383       static SipMessage* makeFailureAck(const SipMessage& request, const SipMessage& response);
00384 
00391       static Data computeUniqueBranch();
00392       static Data computeProxyBranch(const SipMessage& request);
00393 
00394       static Data computeCallId();
00395       static Data computeTag(int numBytes);
00396 
00397       enum AuthResult {Failed = 1, Authenticated, Expired, BadlyFormed};
00398 
00399       static AuthResult authenticateRequest(const SipMessage& request, 
00400                                             const Data& realm,
00401                                             const Data& password,
00402                                             int expiresDelta = 0);
00403 
00404       static AuthResult authenticateRequestWithA1(const SipMessage& request, 
00405                                                   const Data& realm,
00406                                                   const Data& hA1,
00407                                                   int expiresDelta = 0);
00408       
00409       static std::pair<AuthResult,Data> 
00410                 advancedAuthenticateRequest(const SipMessage& request, 
00411                                             const Data& realm,
00412                                             const Data& a1,
00413                                             int expiresDelta = 0,
00414                                             bool proxyAuthorization = true);
00415       
00416       // create a 407 response with Proxy-Authenticate header filled in
00417       static SipMessage* makeProxyChallenge(const SipMessage& request, 
00418                                             const Data& realm,
00419                                             bool useAuth = true,
00420                                             bool stale = false);
00421 
00422       //create a 401 response with WWW-Authenticate header filled in
00423       static SipMessage* makeWWWChallenge(const SipMessage& request, 
00424                                             const Data& realm,
00425                                             bool useAuth = true,
00426                                             bool stale = false);
00427 
00428       // create a 401 or 407 response with Proxy-Authenticate or Authenticate header 
00429       // filled in
00430       static SipMessage* makeChallenge(const SipMessage& request, 
00431                                        const Data& realm,
00432                                        bool useAuth = true,
00433                                        bool stale = false,
00434                                        bool proxy = false);
00435 
00436       static Data qopOption(const Auth& challenge);
00437       static void updateNonceCount(unsigned int& nonceCount, Data& nonceCountString);
00438       static bool algorithmAndQopSupported(const Auth& challenge);
00439       
00440 
00441       // adds authorization headers in reponse to the 401 or 407--currently
00442       // only supports md5.
00443       static SipMessage& addAuthorization(SipMessage& request,
00444                                           const SipMessage& challenge,
00445                                           const Data& username,
00446                                           const Data& password,
00447                                           const Data& cnonce,
00448                                           unsigned int& nonceCount);
00449 
00450       static Auth makeChallengeResponseAuth(const SipMessage& request,
00451                                             const Data& username,
00452                                             const Data& password,
00453                                             const Auth& challenge,
00454                                             const Data& cnonce,
00455                                             unsigned int& nonceCount,
00456                                             Data& nonceCountString);      
00457 
00458       static void makeChallengeResponseAuth(const SipMessage& request,
00459                                             const Data& username,
00460                                             const Data& password,
00461                                             const Auth& challenge,
00462                                             const Data& cnonce,
00463                                             const Data& authQop,
00464                                             const Data& nonceCountString,
00465                                             Auth& auth);
00466 
00467       static Auth makeChallengeResponseAuthWithA1(const SipMessage& request,
00468                                                   const Data& username,
00469                                                   const Data& passwordHashA1,
00470                                                   const Auth& challenge,
00471                                                   const Data& cnonce,
00472                                                   unsigned int& nonceCount,
00473                                                   Data& nonceCountString);      
00474 
00475       static void makeChallengeResponseAuthWithA1(const SipMessage& request,
00476                                                   const Data& username,
00477                                                   const Data& passwordHashA1,
00478                                                   const Auth& challenge,
00479                                                   const Data& cnonce,
00480                                                   const Data& authQop,
00481                                                   const Data& nonceCountString,
00482                                                   Auth& auth);
00483 
00484       static Data makeResponseMD5WithA1(const Data& a1,
00485                                         const Data& method, const Data& digestUri, const Data& nonce,
00486                                         const Data& qop = Data::Empty, const Data& cnonce = Data::Empty, 
00487                                         const Data& cnonceCount = Data::Empty, const Contents *entityBody = 0);
00488 
00489       static Data makeResponseMD5(const Data& username, const Data& password, const Data& realm, 
00490                                   const Data& method, const Data& digestUri, const Data& nonce,
00491                                   const Data& qop = Data::Empty, const Data& cnonce = Data::Empty, 
00492                                   const Data& cnonceCount = Data::Empty, const Contents *entityBody = 0);
00493       
00495       static void setNonceHelper(NonceHelper *nonceHelper);
00496       static NonceHelper* getNonceHelper();
00497       static Data makeNonce(const SipMessage& request, const Data& timestamp);
00498 
00499       static Uri makeUri(const Data& aor, const Data& scheme=Symbols::DefaultSipScheme);
00500 
00501       static void processStrictRoute(SipMessage& request);
00502 
00503       // return the port that the response should be sent to using rules from 
00504       // RFC 3261 - 18.2.2
00505       static int getPortForReply(SipMessage& request);
00506 
00507       static void massageRoute(const SipMessage& request, NameAddr& route);
00508 
00509       static Uri fromAor(const Data& aor, const Data& scheme=Symbols::DefaultSipScheme);
00510 
00511       // Do basic checks to validate a received message off the wire
00512       // If the basic check fails, and reason is non-null, reason will be set
00513       // to the reason the check failed. This function does not take ownership
00514       // of reason.
00515       static bool validateMessage(const SipMessage& message,resip::Data* reason=0);
00516 
00517       // GRUU support -- reversibly and opaquely combine instance id and aor
00518       static Data gruuUserPart(const Data& instanceId,
00519                                const Data& aor,
00520                                const Data& key);
00521 
00522       // GRUU support -- extract instance id and aor from user portion
00523       static std::pair<Data,Data> fromGruuUserPart(const Data& gruuUserPart,
00524                                                    const Data& key);
00525 
00526       struct ContentsSecAttrs
00527       {
00528             ContentsSecAttrs();
00529             ContentsSecAttrs(std::auto_ptr<Contents> contents,
00530                              std::auto_ptr<SecurityAttributes> attributes);
00531             ContentsSecAttrs(const ContentsSecAttrs& rhs);
00532             ContentsSecAttrs& operator=(const ContentsSecAttrs& rhs);
00533             mutable std::auto_ptr<Contents> mContents;
00534             mutable std::auto_ptr<SecurityAttributes> mAttributes;
00535       };
00536 
00537       static ContentsSecAttrs extractFromPkcs7(const SipMessage& message, Security& security);
00538 
00539       
00540       enum FailureMessageEffect{ DialogTermination, TransactionTermination, UsageTermination, 
00541                                  RetryAfter, OptionalRetryAfter, ApplicationDependant };
00542       
00543       static FailureMessageEffect determineFailureMessageEffect(const SipMessage& response);      
00544 
00545       // Just simply walk the contents tree and return the first SdpContents in
00546       // the tree.
00547       static std::auto_ptr<SdpContents> getSdp(Contents* tree);
00548 
00561       static bool isClientBehindNAT(const SipMessage& request, bool privateToPublicOnly=true);
00562 
00571       static Tuple getClientPublicAddress(const SipMessage& request);
00572 
00573    private:
00574       class NonceHelperPtr
00575       {
00576          public:
00577             NonceHelperPtr() : mNonceHelper(0) {}
00578             ~NonceHelperPtr() { delete mNonceHelper; }
00579             NonceHelper *mNonceHelper;
00580       };
00581       static NonceHelperPtr mNonceHelperPtr;
00582 };
00583 
00584 }
00585 
00586 #endif
00587 
00588 /* ====================================================================
00589  * The Vovida Software License, Version 1.0 
00590  * 
00591  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00592  * 
00593  * Redistribution and use in source and binary forms, with or without
00594  * modification, are permitted provided that the following conditions
00595  * are met:
00596  * 
00597  * 1. Redistributions of source code must retain the above copyright
00598  *    notice, this list of conditions and the following disclaimer.
00599  * 
00600  * 2. Redistributions in binary form must reproduce the above copyright
00601  *    notice, this list of conditions and the following disclaimer in
00602  *    the documentation and/or other materials provided with the
00603  *    distribution.
00604  * 
00605  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00606  *    and "Vovida Open Communication Application Library (VOCAL)" must
00607  *    not be used to endorse or promote products derived from this
00608  *    software without prior written permission. For written
00609  *    permission, please contact vocal@vovida.org.
00610  *
00611  * 4. Products derived from this software may not be called "VOCAL", nor
00612  *    may "VOCAL" appear in their name, without prior written
00613  *    permission of Vovida Networks, Inc.
00614  * 
00615  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00616  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00617  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00618  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00619  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00620  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00621  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00622  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00623  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00624  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00625  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00626  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00627  * DAMAGE.
00628  * 
00629  * ====================================================================
00630  * 
00631  * This software consists of voluntary contributions made by Vovida
00632  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00633  * Inc.  For more information on Vovida Networks, Inc., please see
00634  * <http://www.vovida.org/>.
00635  *
00636  */