|
reSIProcate/stack
9694
|
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 */
1.7.5.1