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-2013 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(char const* username, char const* password, Boolean passwordIsMD5) {
00034   assign(NULL, NULL, username, password, passwordIsMD5);
00035 }
00036 
00037 Authenticator::Authenticator(const Authenticator& orig) {
00038   assign(orig.realm(), orig.nonce(), orig.username(), orig.password(), orig.fPasswordIsMD5);
00039 }
00040 
00041 Authenticator& Authenticator::operator=(const Authenticator& rightSide) {
00042   if (&rightSide != this) {
00043     reset();
00044     assign(rightSide.realm(), rightSide.nonce(),
00045            rightSide.username(), rightSide.password(), rightSide.fPasswordIsMD5);
00046   }
00047 
00048   return *this;
00049 }
00050 
00051 Authenticator::~Authenticator() {
00052   reset();
00053 }
00054 
00055 void Authenticator::reset() {
00056   resetRealmAndNonce();
00057   resetUsernameAndPassword();
00058 }
00059 
00060 void Authenticator::setRealmAndNonce(char const* realm, char const* nonce) {
00061   resetRealmAndNonce();
00062   assignRealmAndNonce(realm, nonce);
00063 }
00064 
00065 void Authenticator::setRealmAndRandomNonce(char const* realm) {
00066   resetRealmAndNonce();
00067 
00068   // Construct data to seed the random nonce:
00069   struct {
00070     struct timeval timestamp;
00071     unsigned counter;
00072   } seedData;
00073   gettimeofday(&seedData.timestamp, NULL);
00074   static unsigned counter = 0;
00075   seedData.counter = ++counter;
00076 
00077   // Use MD5 to compute a 'random' nonce from this seed data:
00078   char nonceBuf[33];
00079   our_MD5Data((unsigned char*)(&seedData), sizeof seedData, nonceBuf);
00080 
00081   assignRealmAndNonce(realm, nonceBuf);
00082 }
00083 
00084 void Authenticator::setUsernameAndPassword(char const* username,
00085                                            char const* password,
00086                                            Boolean passwordIsMD5) {
00087   resetUsernameAndPassword();
00088   assignUsernameAndPassword(username, password, passwordIsMD5);
00089 }
00090 
00091 char const* Authenticator::computeDigestResponse(char const* cmd,
00092                                                  char const* url) const {
00093   // The "response" field is computed as:
00094   //    md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>))
00095   // or, if "fPasswordIsMD5" is True:
00096   //    md5(<password>:<nonce>:md5(<cmd>:<url>))
00097   char ha1Buf[33];
00098   if (fPasswordIsMD5) {
00099     strncpy(ha1Buf, password(), 32);
00100     ha1Buf[32] = '\0'; // just in case
00101   } else {
00102     unsigned const ha1DataLen = strlen(username()) + 1
00103       + strlen(realm()) + 1 + strlen(password());
00104     unsigned char* ha1Data = new unsigned char[ha1DataLen+1];
00105     sprintf((char*)ha1Data, "%s:%s:%s", username(), realm(), password());
00106     our_MD5Data(ha1Data, ha1DataLen, ha1Buf);
00107     delete[] ha1Data;
00108   }
00109 
00110   unsigned const ha2DataLen = strlen(cmd) + 1 + strlen(url);
00111   unsigned char* ha2Data = new unsigned char[ha2DataLen+1];
00112   sprintf((char*)ha2Data, "%s:%s", cmd, url);
00113   char ha2Buf[33];
00114   our_MD5Data(ha2Data, ha2DataLen, ha2Buf);
00115   delete[] ha2Data;
00116 
00117   unsigned const digestDataLen
00118     = 32 + 1 + strlen(nonce()) + 1 + 32;
00119   unsigned char* digestData = new unsigned char[digestDataLen+1];
00120   sprintf((char*)digestData, "%s:%s:%s",
00121           ha1Buf, nonce(), ha2Buf);
00122   char const* result = our_MD5Data(digestData, digestDataLen, NULL);
00123   delete[] digestData;
00124   return result;
00125 }
00126 
00127 void Authenticator::reclaimDigestResponse(char const* responseStr) const {
00128   free((char*)responseStr); // NOT delete, because it was malloc-allocated
00129 }
00130 
00131 void Authenticator::resetRealmAndNonce() {
00132   delete[] fRealm; fRealm = NULL;
00133   delete[] fNonce; fNonce = NULL;
00134 }
00135 
00136 void Authenticator::resetUsernameAndPassword() {
00137   delete[] fUsername; fUsername = NULL;
00138   delete[] fPassword; fPassword = NULL;
00139   fPasswordIsMD5 = False;
00140 }
00141 
00142 void Authenticator::assignRealmAndNonce(char const* realm, char const* nonce) {
00143   fRealm = strDup(realm);
00144   fNonce = strDup(nonce);
00145 }
00146 
00147 void Authenticator::assignUsernameAndPassword(char const* username, char const* password, Boolean passwordIsMD5) {
00148   fUsername = strDup(username);
00149   fPassword = strDup(password);
00150   fPasswordIsMD5 = passwordIsMD5;
00151 }
00152 
00153 void Authenticator::assign(char const* realm, char const* nonce,
00154                            char const* username, char const* password, Boolean passwordIsMD5) {
00155   assignRealmAndNonce(realm, nonce);
00156   assignUsernameAndPassword(username, password, passwordIsMD5);
00157 }

Generated on Mon Apr 29 13:28:01 2013 for live by  doxygen 1.5.2