reSIProcate/stack  9694
Auth.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include "resip/stack/Auth.hxx"
00006 #include "resip/stack/UnknownParameter.hxx"
00007 #include "rutil/Data.hxx"
00008 #include "rutil/DnsUtil.hxx"
00009 #include "rutil/Logger.hxx"
00010 #include "rutil/ParseBuffer.hxx"
00011 //#include "rutil/WinLeakCheck.hxx"  // not compatible with placement new used below
00012 
00013 using namespace resip;
00014 using namespace std;
00015 
00016 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00017 
00018 //====================
00019 // Auth:
00020 //====================
00021 Auth::Auth() : 
00022    ParserCategory() 
00023 {}
00024 
00025 Auth::Auth(const HeaderFieldValue& hfv, Headers::Type type, PoolBase* pool) 
00026    : ParserCategory(hfv, type, pool) 
00027 {}
00028 
00029 Auth::Auth(const Auth& rhs, PoolBase* pool)
00030    : ParserCategory(rhs, pool),
00031    mScheme(rhs.mScheme)
00032 {}
00033 
00034 Auth&
00035 Auth::operator=(const Auth& rhs)
00036 {
00037    if (this != &rhs)
00038    {
00039       ParserCategory::operator=(rhs);
00040       mScheme = rhs.mScheme;
00041    }
00042    return *this;
00043 }
00044 
00045 Data& 
00046 Auth::scheme()
00047 {
00048    checkParsed(); 
00049    return mScheme;
00050 }
00051 
00052 const Data& 
00053 Auth::scheme() const 
00054 {
00055    checkParsed(); 
00056    return mScheme;
00057 }
00058 
00059 void
00060 Auth::parse(ParseBuffer& pb)
00061 {
00062    const char* start;
00063    start = pb.skipWhitespace();
00064    static const std::bitset<256> schemeDelimiter(Data::toBitset("\r\n\t ="));
00065    pb.skipToOneOf(schemeDelimiter);
00066 
00067    if (!pb.eof() && *pb.position() == Symbols::EQUALS[0])
00068    {
00069       // Authentication-Info only
00070       // back up, and then parse
00071       pb.reset(start);
00072       parseAuthParameters(pb);
00073    }
00074    else
00075    {
00076       // everything else
00077       pb.data(mScheme, start);
00078 
00079       pb.skipWhitespace();
00080       parseAuthParameters(pb);
00081    }
00082 }
00083 
00084 EncodeStream& 
00085 Auth::encodeParsed(EncodeStream& str) const
00086 {
00087    if (!mScheme.empty())
00088    {
00089       str << mScheme << Symbols::SPACE;
00090    }
00091 
00092    encodeAuthParameters(str);
00093 
00094    return str;
00095 }
00096 
00097 ParserCategory* 
00098 Auth::clone() const
00099 {
00100    return new Auth(*this);
00101 }
00102 
00103 ParserCategory* 
00104 Auth::clone(void* location) const
00105 {
00106    return new (location) Auth(*this);
00107 }
00108 
00109 ParserCategory* 
00110 Auth::clone(PoolBase* pool) const
00111 {
00112    return new (pool) Auth(*this, pool);
00113 }
00114 
00115 void
00116 Auth::parseAuthParameters(ParseBuffer& pb)
00117 {
00118    while (!pb.eof())
00119    {
00120       const char* keyStart = pb.position();
00121       static std::bitset<256> paramBegin=Data::toBitset(" \t\r\n=");
00122       static std::bitset<256> terminators=Data::toBitset(" \t\r\n,");
00123       const char* keyEnd = pb.skipToOneOf(paramBegin);
00124       if((int)(keyEnd-keyStart) != 0)
00125       {
00126          ParameterTypes::Type type = ParameterTypes::getType(keyStart, (unsigned int)(keyEnd - keyStart));
00127          Parameter* p=createParam(type, pb, terminators, getPool());
00128          if (!p)
00129          {
00130             mUnknownParameters.push_back(new UnknownParameter(keyStart, 
00131                                                               int((keyEnd - keyStart)), pb, 
00132                                                               terminators));
00133          }
00134          else
00135          {
00136             // invoke the particular factory
00137             mParameters.push_back(p);
00138          }
00139          pb.skipWhitespace();
00140          if (pb.eof() || *pb.position() != Symbols::COMMA[0])
00141          {
00142             break;
00143          }
00144          pb.skipChar();
00145          pb.skipWhitespace();
00146       }
00147    }
00148 }
00149 
00150 EncodeStream&
00151 Auth::encodeAuthParameters(EncodeStream& str) const
00152 {
00153    bool first = true;
00154    for (ParameterList::const_iterator it = mParameters.begin();
00155         it != mParameters.end(); it++)
00156    {
00157       if (!first)
00158       {
00159          str << Symbols::COMMA;
00160       }
00161       first = false;
00162       (*it)->encode(str);
00163    }
00164 
00165    for (ParameterList::const_iterator it = mUnknownParameters.begin();
00166         it != mUnknownParameters.end(); it++)
00167    {
00168       if (!first)
00169       {
00170          str << Symbols::COMMA;
00171       }
00172       first = false;
00173       (*it)->encode(str);
00174    }
00175    return str;
00176 }
00177 
00178 ParameterTypes::Factory Auth::ParameterFactories[ParameterTypes::MAX_PARAMETER]={0};
00179 
00180 Parameter* 
00181 Auth::createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool)
00182 {
00183    if(type==ParameterTypes::qop)
00184    {
00185       DataParameter* qop = 0;
00186       switch(mHeaderType)
00187       {
00188          case Headers::ProxyAuthenticate:
00189          case Headers::WWWAuthenticate:
00190             qop = new (pool) DataParameter(ParameterTypes::qopOptions,pb,terminators);
00191             qop->setQuoted(true);
00192             break;
00193          case Headers::ProxyAuthorization:
00194          case Headers::Authorization:
00195          case Headers::AuthenticationInfo:
00196          default:
00197             qop = new (pool) DataParameter(ParameterTypes::qop,pb,terminators);
00198             qop->setQuoted(false);
00199       }
00200       return qop;
00201    }
00202 
00203    if(type > ParameterTypes::UNKNOWN && type < ParameterTypes::MAX_PARAMETER && ParameterFactories[type])
00204    {
00205       return ParameterFactories[type](type, pb, terminators, pool);
00206    }
00207    return 0;
00208 }
00209 
00210 bool 
00211 Auth::exists(const Param<Auth>& paramType) const
00212 {
00213     checkParsed();
00214     bool ret = getParameterByEnum(paramType.getTypeNum()) != NULL;
00215     return ret;
00216 }
00217 
00218 void 
00219 Auth::remove(const Param<Auth>& paramType)
00220 {
00221     checkParsed();
00222     removeParameterByEnum(paramType.getTypeNum());
00223 }
00224 
00225 #define defineParam(_enum, _name, _type, _RFC_ref_ignored)                                                      \
00226 _enum##_Param::DType&                                                                                           \
00227 Auth::param(const _enum##_Param& paramType)                                                                     \
00228 {                                                                                                               \
00229    checkParsed();                                                                                               \
00230    _enum##_Param::Type* p = static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));      \
00231    if (!p)                                                                                                      \
00232    {                                                                                                            \
00233       p = new _enum##_Param::Type(paramType.getTypeNum());                                                      \
00234       mParameters.push_back(p);                                                                                 \
00235    }                                                                                                            \
00236    return p->value();                                                                                           \
00237 }                                                                                                               \
00238 const _enum##_Param::DType&                                                                                     \
00239 Auth::param(const _enum##_Param& paramType) const                                                               \
00240 {                                                                                                               \
00241    checkParsed();                                                                                               \
00242    _enum##_Param::Type* p = static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum()));      \
00243    if (!p)                                                                                                      \
00244    {                                                                                                            \
00245       InfoLog(<< "Missing parameter " << ParameterTypes::ParameterNames[paramType.getTypeNum()]);               \
00246       DebugLog(<< *this);                                                                                       \
00247       throw Exception("Missing parameter", __FILE__, __LINE__);                                                 \
00248    }                                                                                                            \
00249    return p->value();                                                                                           \
00250 }
00251 
00252 defineParam(algorithm, "algorithm", DataParameter, "RFC 2617");
00253 defineParam(cnonce, "cnonce", QuotedDataParameter, "RFC 2617");
00254 defineParam(domain, "domain", QuotedDataParameter, "RFC 3261");
00255 defineParam(nc, "nc", DataParameter, "RFC 2617");
00256 defineParam(nonce, "nonce", QuotedDataParameter, "RFC 2617");
00257 defineParam(opaque, "opaque", QuotedDataParameter, "RFC 2617");
00258 defineParam(realm, "realm", QuotedDataParameter, "RFC 2617");
00259 defineParam(response, "response", QuotedDataParameter, "RFC 3261");
00260 defineParam(stale, "stale", DataParameter, "RFC 2617");
00261 defineParam(uri, "uri", QuotedDataParameter, "RFC 3261");
00262 defineParam(username, "username", QuotedDataParameter, "RFC 3261");
00263 
00264 DataParameter::Type&
00265 Auth::param(const qop_Param& paramType)
00266 {
00267    checkParsed();
00268    DataParameter* p = static_cast<DataParameter*>(getParameterByEnum(paramType.getTypeNum()));
00269    if (!p)
00270    {
00271       p = new DataParameter(ParameterTypes::qop);
00272       p->setQuoted(false);
00273       mParameters.push_back(p);
00274    }
00275    return p->value();
00276 }
00277 const DataParameter::Type&
00278 Auth::param(const qop_Param& paramType) const
00279 {
00280    checkParsed();
00281    DataParameter* p = static_cast<DataParameter*>(getParameterByEnum(paramType.getTypeNum()));
00282    if (!p)
00283    {
00284       InfoLog(<< "Missing parameter " << ParameterTypes::ParameterNames[paramType.getTypeNum()]);
00285       DebugLog(<< *this);
00286       throw Exception("Missing parameter", __FILE__, __LINE__);
00287    }
00288    return p->value();
00289 }
00290 
00291 DataParameter::Type&
00292 Auth::param(const qopOptions_Param& paramType)
00293 {
00294    checkParsed();
00295    DataParameter* p = static_cast<DataParameter*>(getParameterByEnum(paramType.getTypeNum()));
00296    if (!p)
00297    {
00298       p = new DataParameter(ParameterTypes::qopOptions);
00299       p->setQuoted(true);
00300       mParameters.push_back(p);
00301    }
00302    return p->value();
00303 }
00304 const DataParameter::Type&
00305 Auth::param(const qopOptions_Param& paramType) const
00306 {
00307    checkParsed();
00308    DataParameter* p = static_cast<DataParameter*>(getParameterByEnum(paramType.getTypeNum()));
00309    if (!p)
00310    {
00311       InfoLog(<< "Missing parameter " << ParameterTypes::ParameterNames[paramType.getTypeNum()]);
00312       DebugLog(<< *this);
00313       throw Exception("Missing parameter", __FILE__, __LINE__);
00314    }
00315    return p->value();
00316 }
00317 
00318 
00319 #undef defineParam
00320 
00321 /* ====================================================================
00322  * The Vovida Software License, Version 1.0 
00323  * 
00324  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00325  * 
00326  * Redistribution and use in source and binary forms, with or without
00327  * modification, are permitted provided that the following conditions
00328  * are met:
00329  * 
00330  * 1. Redistributions of source code must retain the above copyright
00331  *    notice, this list of conditions and the following disclaimer.
00332  * 
00333  * 2. Redistributions in binary form must reproduce the above copyright
00334  *    notice, this list of conditions and the following disclaimer in
00335  *    the documentation and/or other materials provided with the
00336  *    distribution.
00337  * 
00338  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00339  *    and "Vovida Open Communication Application Library (VOCAL)" must
00340  *    not be used to endorse or promote products derived from this
00341  *    software without prior written permission. For written
00342  *    permission, please contact vocal@vovida.org.
00343  *
00344  * 4. Products derived from this software may not be called "VOCAL", nor
00345  *    may "VOCAL" appear in their name, without prior written
00346  *    permission of Vovida Networks, Inc.
00347  * 
00348  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00349  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00350  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00351  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00352  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00353  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00354  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00355  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00356  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00357  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00358  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00359  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00360  * DAMAGE.
00361  * 
00362  * ====================================================================
00363  * 
00364  * This software consists of voluntary contributions made by Vovida
00365  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00366  * Inc.  For more information on Vovida Networks, Inc., please see
00367  * <http://www.vovida.org/>.
00368  *
00369  */