|
reSIProcate/stack
9694
|
00001 #include <assert.h> 00002 #include <iostream> 00003 #include <string.h> 00004 #ifdef WIN32 00005 #include <io.h> 00006 #else 00007 #include <unistd.h> 00008 #endif 00009 #include <memory> 00010 00011 #ifdef WIN32 00012 #define usleep(x) Sleep(x/1000) 00013 #define sleep(x) Sleep(x*1000) 00014 #endif 00015 00016 #include "resip/stack/HeaderFieldValue.hxx" 00017 #include "resip/stack/HeaderTypes.hxx" 00018 #include "resip/stack/ParserCategories.hxx" 00019 #include "resip/stack/Uri.hxx" 00020 #include "resip/stack/Helper.hxx" 00021 #include "resip/stack/test/TestSupport.hxx" 00022 #include "rutil/Timer.hxx" 00023 #include "rutil/DataStream.hxx" 00024 #include "rutil/MD5Stream.hxx" 00025 #include "digcalc.hxx" 00026 00027 using namespace std; 00028 using namespace resip; 00029 00030 int 00031 main(int arc, char** argv) 00032 { 00033 { 00034 Auth auth; 00035 auth.scheme() = "Digest"; 00036 Data timestamp((unsigned int)(Timer::getTimeMs()/1000)); 00037 auth.param(p_nonce) = "askdfjhaslkjhf498hw98hw98hfsf"; 00038 auth.param(p_algorithm) = "MD5"; 00039 auth.param(p_realm) = "example.com"; 00040 00041 assert(Helper::algorithmAndQopSupported(auth)); 00042 auth.param(p_algorithm) = "MD5-sess"; 00043 assert(!Helper::algorithmAndQopSupported(auth)); 00044 auth.param(p_algorithm) = "monkey"; 00045 assert(!Helper::algorithmAndQopSupported(auth)); 00046 00047 auth.param(p_algorithm) = "MD5"; 00048 auth.param(p_qop) = Symbols::auth; 00049 assert(Helper::algorithmAndQopSupported(auth)); 00050 00051 auth.param(p_qop) = Symbols::authInt; 00052 assert(Helper::algorithmAndQopSupported(auth)); 00053 00054 auth.param(p_qop) = "monkey"; 00055 assert(!Helper::algorithmAndQopSupported(auth)); 00056 00057 cerr << "algorithmAndQopSupported passed" << endl; 00058 } 00059 00060 { 00061 assert(Data("").md5() == "d41d8cd98f00b204e9800998ecf8427e"); 00062 assert(Data("a").md5() == "0cc175b9c0f1b6a831c399e269772661"); 00063 assert(Data("abc").md5() == "900150983cd24fb0d6963f7d28e17f72"); 00064 assert(Data("message digest").md5() == "f96b697d7cb7938d525a2f31aaf161d0"); 00065 assert(Data("abcdefghijklmnopqrstuvwxyz").md5() == "c3fcd3d76192e4007dfb496cca67e13b"); 00066 assert(Data("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").md5() == "d174ab98d277d9f5a5611c2c9f419d9f"); 00067 assert(Data("12345678901234567890123456789012345678901234567890123456789012345678901234567890").md5() == "57edf4a22be3c955ac49da2e2107b67a"); 00068 } 00069 00070 { 00071 { 00072 MD5Stream s; 00073 assert(s.getHex() == Data("").md5()); 00074 } 00075 { 00076 MD5Stream s; 00077 s << "a"; 00078 assert(s.getHex() == Data("a").md5()); 00079 } 00080 { 00081 MD5Stream s; 00082 s << "abc"; 00083 assert(s.getHex() == Data("abc").md5()); 00084 } 00085 { 00086 MD5Stream s; 00087 s << "message digest"; 00088 assert(s.getHex() == Data("message digest").md5()); 00089 } 00090 { 00091 MD5Stream s; 00092 s << "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; 00093 assert(s.getHex() == Data("12345678901234567890123456789012345678901234567890123456789012345678901234567890").md5()); 00094 } 00095 { 00096 Data d; 00097 DataStream ds(d); 00098 MD5Stream s; 00099 00100 s << "this involves" << 7.8 << "foo" << 34653453 << -6 << "hike"; 00101 ds << "this involves" << 7.8 << "foo" << 34653453 << -6 << "hike"; 00102 ds.flush(); 00103 00104 assert(d.md5() == s.getHex()); 00105 } 00106 } 00107 00108 { 00109 const char* alg = "MD5"; 00110 const char* username = "user"; 00111 const char* password = "secret"; 00112 const char* realm = "localhost"; 00113 const char* method = "REGISTER"; 00114 const char* uri = "user@host.com"; 00115 const char* nonce = "92347fea23"; 00116 00117 Data responseMD5 = Helper::makeResponseMD5(username, 00118 password, 00119 realm, 00120 method, 00121 uri, 00122 nonce); 00123 00124 HASHHEX a1Hash; 00125 HASHHEX response; 00126 00127 DigestCalcHA1(alg, 00128 username, 00129 realm, 00130 password, 00131 nonce, 00132 (char*)"", 00133 a1Hash); 00134 00135 DigestCalcResponse(a1Hash, 00136 nonce, 00137 (char*)"", 00138 (char*)"", 00139 (char*)"", 00140 method, 00141 uri, 00142 (char*)"", 00143 response); 00144 00145 assert(responseMD5 == response); 00146 } 00147 00148 { 00149 const char* alg = "MD5"; 00150 const char* username = "user"; 00151 const char* password = "secret"; 00152 const char* realm = "localhost"; 00153 const char* method = "REGISTER"; 00154 const char* uri = "user@host.com"; 00155 const char* nonce = "92347fea23"; 00156 const char* cnonce = "72345hef"; 00157 const char* cnonceCount = "00000001"; 00158 const char* qop = "auth"; 00159 00160 Data responseMD5 = Helper::makeResponseMD5(username, 00161 password, 00162 realm, 00163 method, 00164 uri, 00165 nonce, 00166 qop, 00167 cnonce, 00168 cnonceCount); 00169 00170 HASHHEX a1Hash; 00171 HASHHEX response; 00172 00173 DigestCalcHA1(alg, 00174 username, 00175 realm, 00176 password, 00177 nonce, 00178 cnonce, 00179 a1Hash); 00180 00181 DigestCalcResponse(a1Hash, 00182 nonce, 00183 cnonceCount, 00184 cnonce, 00185 qop, 00186 method, 00187 uri, 00188 (char*)"", 00189 response); 00190 00191 assert(responseMD5 == response); 00192 } 00193 00194 { 00195 const char* alg = "MD5"; 00196 const char* username = "user"; 00197 const char* password = "secret"; 00198 const char* realm = "localhost"; 00199 const char* method = "REGISTER"; 00200 const char* uri = "user@host.com"; 00201 const char* nonce = "92347fea23"; 00202 00203 Data responseMD5 = Helper::makeResponseMD5(username, 00204 password, 00205 realm, 00206 method, 00207 uri, 00208 nonce); 00209 00210 HASHHEX a1Hash; 00211 HASHHEX response; 00212 00213 DigestCalcHA1(alg, 00214 username, 00215 realm, 00216 password, 00217 nonce, 00218 (char*)"", 00219 a1Hash); 00220 00221 DigestCalcResponse(a1Hash, 00222 nonce, 00223 (char*)"", 00224 (char*)"", 00225 (char*)"", 00226 method, 00227 uri, 00228 (char*)"", 00229 response); 00230 00231 assert(responseMD5 == response); 00232 } 00233 00234 /* 00235 REGISTER sip:kelowna.gloo.net SIP/2.0 00236 To: sip:100@kelowna.gloo.net 00237 From: <sip:100@kelowna.gloo.net> 00238 Call-ID: 000532ff-828108c2-79016ad7-69ac4815@192.168.2.233 00239 CSeq: 102 REGISTER 00240 Contact: sip:100@192.168.2.233:5060 00241 Via: SIP/2.0/UDP 192.168.2.233:5060;received=192.168.2.233;rport=5060 00242 Expires: 3600 00243 Date: Sat, 07 Dec 2002 02:21:59 GMT 00244 Proxy-Authorization: Digest username="sip:100@kelowna.gloo.net:5060",realm="kelowna.gloo.net",uri="sip:kelowna.gloo.net",response="8485db84088e6be6c55717d2eb891eca",nonce="1039227719:9e17fc5e10c30f162e7a21c9f6a4d2a7",algorithm=MD5 00245 User-Agent: CSCO/4 00246 Content-Length: 0 00247 */ 00248 00249 /* 00250 Proxy-Authorization: Digest username="sip:100@kelowna.gloo.net:5060",realm="kelowna.gloo.net",uri="sip:kelowna.gloo.net",response="8485db84088e6be6c55717d2eb891eca",nonce="1039227719:9e17fc5e10c30f162e7a21c9f6a4d2a7",algorithm=MD5 00251 */ 00252 { 00253 const char* alg = "MD5"; 00254 const char* username = "sip:100@kelowna.gloo.net:5060"; 00255 const char* password = "secret"; 00256 const char* realm = "kelowna.gloo.net"; 00257 const char* method = "REGISTER"; 00258 const char* uri = "sip:kelowna.gloo.net"; 00259 const char* nonce = "1039227719:9e17fc5e10c30f162e7a21c9f6a4d2a7"; 00260 const char* cnonce = ""; 00261 const char* cnonceCount = ""; 00262 const char* qop = ""; 00263 00264 Data responseMD5 = Helper::makeResponseMD5(username, 00265 password, 00266 realm, 00267 method, 00268 uri, 00269 nonce, 00270 qop, 00271 cnonce, 00272 cnonceCount); 00273 00274 HASHHEX a1Hash; 00275 HASHHEX response; 00276 00277 DigestCalcHA1(alg, 00278 username, 00279 realm, 00280 password, 00281 nonce, 00282 cnonce, 00283 a1Hash); 00284 00285 DigestCalcResponse(a1Hash, 00286 nonce, 00287 cnonceCount, 00288 cnonce, 00289 qop, 00290 method, 00291 uri, 00292 (char*)"", 00293 response); 00294 00295 assert(responseMD5 == response); 00296 } 00297 00298 00299 /* 00300 Calling form_SIPdigest with: 00301 nonce = 1039063045 00302 user = sip:100@kelowna.gloo.net:5060 00303 pswd = secret 00304 method = REGISTER 00305 uri = sip:kelowna.gloo.net 00306 realm = kelowna.gloo.net 00307 algorithm= MD5 00308 Message digest == 575a9ecd3a6f1989a978748217b24a25 00309 Calculated digest == 575a9ecd3a6f1989a978748217b24a25 00310 */ 00311 { 00312 const char* alg = "MD5"; 00313 const char* username = "sip:100@kelowna.gloo.net:5060"; 00314 const char* password = "secret"; 00315 const char* realm = "kelowna.gloo.net"; 00316 const char* method = "REGISTER"; 00317 const char* uri = "sip:kelowna.gloo.net"; 00318 const char* nonce = "1039063045"; 00319 00320 Data responseMD5 = Helper::makeResponseMD5(username, 00321 password, 00322 realm, 00323 method, 00324 uri, 00325 nonce); 00326 00327 HASHHEX a1Hash; 00328 HASHHEX response; 00329 00330 DigestCalcHA1(alg, 00331 username, 00332 realm, 00333 password, 00334 nonce, 00335 (char*)"", 00336 a1Hash); 00337 00338 DigestCalcResponse(a1Hash, 00339 nonce, 00340 (char*)"", 00341 (char*)"", 00342 (char*)"", 00343 method, 00344 uri, 00345 (char*)"", 00346 response); 00347 00348 assert(responseMD5 == response); 00349 assert(responseMD5 == "575a9ecd3a6f1989a978748217b24a25"); 00350 } 00351 00352 { 00353 Data txt("INVITE sip:bob@biloxi.com SIP/2.0\r\n" 00354 "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\r\n" 00355 "To: Bob <sip:bob@biloxi.com>\r\n" 00356 "From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n" 00357 "Call-ID: a84b4c76e66710\r\n" 00358 "CSeq: 314159 INVITE\r\n" 00359 "Max-Forwards: 70\r\n" 00360 "Contact: <sip:alice@pc33.atlanta.com>\r\n" 00361 "Content-Type: application/sdp\r\n" 00362 "Content-Length: 150\r\n" 00363 "\r\n" 00364 "v=0\r\n" 00365 "o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n" 00366 "s=-\r\n" 00367 "c=IN IP4 pc33.atlanta.com\r\n" 00368 "t=0 0\r\n" 00369 "m=audio 3456 RTP/AVP 0 1 3 99\r\n" 00370 "a=rtpmap:0 PCMU/8000\r\n"); 00371 00372 auto_ptr<SipMessage> request(TestSupport::makeMessage(txt.c_str())); 00373 00374 Data realm = "localhost"; 00375 auto_ptr<SipMessage> challenge(Helper::makeProxyChallenge(*request, realm, false)); 00376 00377 assert(challenge->exists(h_ProxyAuthenticates)); 00378 assert(challenge->header(h_ProxyAuthenticates).size() == 1); 00379 00380 Data username = "bob"; 00381 Data password = "secret"; 00382 Data cnonce = "366fead6"; 00383 unsigned int nc = 0; 00384 00385 Data encodedPassword = password.md5(); 00386 00387 Helper::addAuthorization(*request, 00388 *challenge, 00389 username, 00390 encodedPassword, 00391 cnonce, 00392 nc); 00393 00394 assert(request->exists(h_ProxyAuthorizations)); 00395 assert(request->header(h_ProxyAuthorizations).size() == 1); 00396 assert(!request->header(h_ProxyAuthorizations).front().exists(p_qop)); 00397 00398 const Auth& auth = request->header(h_ProxyAuthorizations).front(); 00399 00400 assert(auth.param(p_username) == "bob"); 00401 assert(auth.param(p_uri) == "sip:bob@biloxi.com"); 00402 assert(auth.param(p_algorithm) == "MD5"); 00403 00404 Helper::AuthResult res = Helper::authenticateRequest(*request, 00405 realm, 00406 encodedPassword); 00407 assert(res == Helper::Authenticated); 00408 00409 res = Helper::authenticateRequest(*request, 00410 realm, 00411 encodedPassword, 00412 5); 00413 00414 assert(res == Helper::Authenticated); 00415 00416 sleep(2); 00417 res = Helper::authenticateRequest(*request, 00418 realm, 00419 encodedPassword, 00420 1); 00421 00422 assert(res == Helper::Expired); 00423 00424 } 00425 00426 { 00427 Data txt("INVITE sip:bob@biloxi.com SIP/2.0\r\n" 00428 "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\r\n" 00429 "To: Bob <sip:bob@biloxi.com>\r\n" 00430 "From: Alice <sip:alice@atlanta.com>;tag=1928301774\r\n" 00431 "Call-ID: a84b4c76e66710\r\n" 00432 "CSeq: 314159 INVITE\r\n" 00433 "Max-Forwards: 70\r\n" 00434 "Contact: <sip:alice@pc33.atlanta.com>\r\n" 00435 "Content-Type: application/sdp\r\n" 00436 "Content-Length: 150\r\n" 00437 "\r\n" 00438 "v=0\r\n" 00439 "o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n" 00440 "s=-\r\n" 00441 "c=IN IP4 pc33.atlanta.com\r\n" 00442 "t=0 0\r\n" 00443 "m=audio 3456 RTP/AVP 0 1 3 99\r\n" 00444 "a=rtpmap:0 PCMU/8000\r\n"); 00445 00446 auto_ptr<SipMessage> request(TestSupport::makeMessage(txt.c_str())); 00447 00448 Data realm = "localhost"; 00449 auto_ptr<SipMessage> challenge(Helper::makeProxyChallenge(*request, realm, true)); 00450 00451 cerr << *challenge << endl; 00452 00453 assert(challenge->exists(h_ProxyAuthenticates)); 00454 assert(challenge->header(h_ProxyAuthenticates).size() == 1); 00455 assert(challenge->header(h_ProxyAuthenticates).front().exists(p_qopOptions)); 00456 assert(challenge->header(h_ProxyAuthenticates).front().param(p_algorithm) == "MD5"); 00457 assert(challenge->header(h_ProxyAuthenticates).front().scheme() == "Digest"); 00458 00459 Data username = "bob"; 00460 Data password = "secret"; 00461 Data cnonce = "366fead6"; 00462 unsigned int nc = 9; 00463 00464 Data encodedPassword = password.md5(); 00465 00466 Helper::addAuthorization(*request, 00467 *challenge, 00468 username, 00469 encodedPassword, 00470 cnonce, 00471 nc); 00472 00473 assert(nc == 10); 00474 00475 cerr << *request << endl; 00476 00477 assert(request->exists(h_ProxyAuthorizations)); 00478 assert(request->header(h_ProxyAuthorizations).size() == 1); 00479 assert(request->header(h_ProxyAuthorizations).front().exists(p_qop)); 00480 assert(request->header(h_ProxyAuthorizations).front().param(p_nc) == "0000000a"); 00481 00482 const Auth& auth = request->header(h_ProxyAuthorizations).front(); 00483 00484 assert(auth.param(p_username) == "bob"); 00485 assert(auth.param(p_uri) == "sip:bob@biloxi.com"); 00486 assert(auth.param(p_algorithm) == "MD5"); 00487 00488 Helper::AuthResult res = Helper::authenticateRequest(*request, 00489 realm, 00490 encodedPassword); 00491 assert(res == Helper::Authenticated); 00492 00493 res = Helper::authenticateRequest(*request, 00494 realm, 00495 encodedPassword, 00496 5); 00497 00498 assert(res == Helper::Authenticated); 00499 00500 sleep(2); 00501 res = Helper::authenticateRequest(*request, 00502 realm, 00503 encodedPassword, 00504 1); 00505 00506 assert(res == Helper::Expired); 00507 00508 } 00509 cerr << "ALL OK" << endl; 00510 return 0; 00511 } 00512 /* ==================================================================== 00513 * The Vovida Software License, Version 1.0 00514 * 00515 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00516 * 00517 * Redistribution and use in source and binary forms, with or without 00518 * modification, are permitted provided that the following conditions 00519 * are met: 00520 * 00521 * 1. Redistributions of source code must retain the above copyright 00522 * notice, this list of conditions and the following disclaimer. 00523 * 00524 * 2. Redistributions in binary form must reproduce the above copyright 00525 * notice, this list of conditions and the following disclaimer in 00526 * the documentation and/or other materials provided with the 00527 * distribution. 00528 * 00529 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00530 * and "Vovida Open Communication Application Library (VOCAL)" must 00531 * not be used to endorse or promote products derived from this 00532 * software without prior written permission. For written 00533 * permission, please contact vocal@vovida.org. 00534 * 00535 * 4. Products derived from this software may not be called "VOCAL", nor 00536 * may "VOCAL" appear in their name, without prior written 00537 * permission of Vovida Networks, Inc. 00538 * 00539 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00540 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00541 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00542 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00543 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00544 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00545 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00546 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00547 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00548 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00549 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00550 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00551 * DAMAGE. 00552 * 00553 * ==================================================================== 00554 * 00555 * This software consists of voluntary contributions made by Vovida 00556 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00557 * Inc. For more information on Vovida Networks, Inc., please see 00558 * <http://www.vovida.org/>. 00559 * 00560 */
1.7.5.1