liveMedia/DigestAuthentication.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2008 Live Networks, Inc.  All rights reserved.
00018 // A class used for digest authentication.
00019 // Implementation
00020 
00021 #include "DigestAuthentication.hh"
00022 #include "our_md5.h"
00023 #include <strDup.hh>
00024 #include <GroupsockHelper.hh> // for gettimeofday()
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 Authenticator::Authenticator() {
00030   assign(NULL, NULL, NULL, NULL, False);
00031 }
00032 
00033 Authenticator::Authenticator(const Authenticator& orig) {
00034   assign(orig.realm(), orig.nonce(), orig.username(), orig.password(),
00035          orig.fPasswordIsMD5);
00036 }
00037 
00038 Authenticator& Authenticator::operator=(const Authenticator& rightSide) {
00039   if (&rightSide != this) {
00040     reset();
00041     assign(rightSide.realm(), rightSide.nonce(),
00042            rightSide.username(), rightSide.password(), rightSide.fPasswordIsMD5);
00043   }
00044 
00045   return *this;
00046 }
00047 
00048 Authenticator::~Authenticator() {
00049   reset();
00050 }
00051 
00052 void Authenticator::reset() {
00053   resetRealmAndNonce();
00054   resetUsernameAndPassword();
00055 }
00056 
00057 void Authenticator::setRealmAndNonce(char const* realm, char const* nonce) {
00058   resetRealmAndNonce();
00059   assignRealmAndNonce(realm, nonce);
00060 }
00061 
00062 void Authenticator::setRealmAndRandomNonce(char const* realm) {
00063   resetRealmAndNonce();
00064 
00065   // Construct data to seed the random nonce:
00066   struct {
00067     struct timeval timestamp;
00068     unsigned counter;
00069   } seedData;
00070   gettimeofday(&seedData.timestamp, NULL);
00071   static unsigned counter = 0;
00072   seedData.counter = ++counter;
00073 
00074   // Use MD5 to compute a 'random' nonce from this seed data:
00075   char nonceBuf[33];
00076   our_MD5Data((unsigned char*)(&seedData), sizeof seedData, nonceBuf);
00077 
00078   assignRealmAndNonce(realm, nonceBuf);
00079 }
00080 
00081 void Authenticator::setUsernameAndPassword(char const* username,
00082                                            char const* password,
00083                                            Boolean passwordIsMD5) {
00084   resetUsernameAndPassword();
00085   assignUsernameAndPassword(username, password, passwordIsMD5);
00086 }
00087 
00088 char const* Authenticator::computeDigestResponse(char const* cmd,
00089                                                  char const* url) const {
00090   // The "response" field is computed as:
00091   //    md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>))
00092   // or, if "fPasswordIsMD5" is True:
00093   //    md5(<password>:<nonce>:md5(<cmd>:<url>))
00094   char ha1Buf[33];
00095   if (fPasswordIsMD5) {
00096     strncpy(ha1Buf, password(), 32);
00097     ha1Buf[32] = '\0'; // just in case
00098   } else {
00099     unsigned const ha1DataLen = strlen(username()) + 1
00100       + strlen(realm()) + 1 + strlen(password());
00101     unsigned char* ha1Data = new unsigned char[ha1DataLen+1];
00102     sprintf((char*)ha1Data, "%s:%s:%s", username(), realm(), password());
00103     our_MD5Data(ha1Data, ha1DataLen, ha1Buf);
00104     delete[] ha1Data;
00105   }
00106 
00107   unsigned const ha2DataLen = strlen(cmd) + 1 + strlen(url);
00108   unsigned char* ha2Data = new unsigned char[ha2DataLen+1];
00109   sprintf((char*)ha2Data, "%s:%s", cmd, url);
00110   char ha2Buf[33];
00111   our_MD5Data(ha2Data, ha2DataLen, ha2Buf);
00112   delete[] ha2Data;
00113 
00114   unsigned const digestDataLen
00115     = 32 + 1 + strlen(nonce()) + 1 + 32;
00116   unsigned char* digestData = new unsigned char[digestDataLen+1];
00117   sprintf((char*)digestData, "%s:%s:%s",
00118           ha1Buf, nonce(), ha2Buf);
00119   char const* result = our_MD5Data(digestData, digestDataLen, NULL);
00120   delete[] digestData;
00121   return result;
00122 }
00123 
00124 void Authenticator::reclaimDigestResponse(char const* responseStr) const {
00125   free((char*)responseStr); // NOT delete, because it was malloc-allocated
00126 }
00127 
00128 void Authenticator::resetRealmAndNonce() {
00129   delete[] fRealm; fRealm = NULL;
00130   delete[] fNonce; fNonce = NULL;
00131 }
00132 
00133 void Authenticator::resetUsernameAndPassword() {
00134   delete[] fUsername; fUsername = NULL;
00135   delete[] fPassword; fPassword = NULL;
00136   fPasswordIsMD5 = False;
00137 }
00138 
00139 void Authenticator::assignRealmAndNonce(char const* realm, char const* nonce) {
00140   fRealm = strDup(realm);
00141   fNonce = strDup(nonce);
00142 }
00143 
00144 void Authenticator
00145 ::assignUsernameAndPassword(char const* username, char const* password,
00146                             Boolean passwordIsMD5) {
00147   fUsername = strDup(username);
00148   fPassword = strDup(password);
00149   fPasswordIsMD5 = passwordIsMD5;
00150 }
00151 
00152 void Authenticator::assign(char const* realm, char const* nonce,
00153                            char const* username, char const* password,
00154                            Boolean passwordIsMD5) {
00155   assignRealmAndNonce(realm, nonce);
00156   assignUsernameAndPassword(username, password, passwordIsMD5);
00157 }

Generated on Tue Oct 7 15:38:08 2008 for live by  doxygen 1.5.2