/********** This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. (See .) This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **********/ // "liveMedia" // Copyright (c) 1996-2026 Live Networks, Inc. All rights reserved. // A class used for digest authentication. // Implementation #include "DigestAuthentication.hh" #include "ourMD5.hh" #include #include // for gettimeofday() #include #include #include Authenticator::Authenticator() { assign(NULL, NULL, NULL, NULL, False); } Authenticator::Authenticator(char const* username, char const* password, Boolean passwordIsMD5) { assign(NULL, NULL, username, password, passwordIsMD5); } Authenticator::Authenticator(const Authenticator& orig) { assign(orig.realm(), orig.nonce(), orig.username(), orig.password(), orig.fPasswordIsMD5); } Authenticator& Authenticator::operator=(const Authenticator& rightSide) { if (&rightSide != this) { reset(); assign(rightSide.realm(), rightSide.nonce(), rightSide.username(), rightSide.password(), rightSide.fPasswordIsMD5); } return *this; } Boolean Authenticator::operator<(const Authenticator* rightSide) { // Returns True if "rightSide" is 'newer' than us: if (rightSide != NULL && rightSide != this && (rightSide->realm() != NULL || rightSide->nonce() != NULL || username() == NULL || password() == NULL || strcmp(rightSide->username(), username()) != 0 || strcmp(rightSide->password(), password()) != 0)) { return True; } return False; } Authenticator::~Authenticator() { reset(); } void Authenticator::reset() { resetRealmAndNonce(); resetUsernameAndPassword(); } void Authenticator::setRealmAndNonce(char const* realm, char const* nonce) { resetRealmAndNonce(); assignRealmAndNonce(realm, nonce); } void Authenticator::setRealmAndRandomNonce(char const* realm) { resetRealmAndNonce(); // Construct data to seed the random nonce: struct { struct timeval timestamp; unsigned counter; } seedData; gettimeofday(&seedData.timestamp, NULL); static unsigned counter = 0; seedData.counter = ++counter; // Use MD5 to compute a 'random' nonce from this seed data: char nonceBuf[33]; our_MD5Data((unsigned char*)(&seedData), sizeof seedData, nonceBuf); assignRealmAndNonce(realm, nonceBuf); } void Authenticator::setUsernameAndPassword(char const* username, char const* password, Boolean passwordIsMD5) { resetUsernameAndPassword(); assignUsernameAndPassword(username, password, passwordIsMD5); } char const* Authenticator::computeDigestResponse(char const* cmd, char const* url) const { // The "response" field is computed as: // md5(md5(::)::md5(:)) // or, if "fPasswordIsMD5" is True: // md5(::md5(:)) char ha1Buf[33]; if (fPasswordIsMD5) { strncpy(ha1Buf, password(), 32); ha1Buf[32] = '\0'; // just in case } else { unsigned const ha1DataLen = strlen(username()) + 1 + strlen(realm()) + 1 + strlen(password()); unsigned char* ha1Data = new unsigned char[ha1DataLen+1]; sprintf((char*)ha1Data, "%s:%s:%s", username(), realm(), password()); our_MD5Data(ha1Data, ha1DataLen, ha1Buf); delete[] ha1Data; } unsigned const ha2DataLen = strlen(cmd) + 1 + strlen(url); unsigned char* ha2Data = new unsigned char[ha2DataLen+1]; sprintf((char*)ha2Data, "%s:%s", cmd, url); char ha2Buf[33]; our_MD5Data(ha2Data, ha2DataLen, ha2Buf); delete[] ha2Data; unsigned const digestDataLen = 32 + 1 + strlen(nonce()) + 1 + 32; unsigned char* digestData = new unsigned char[digestDataLen+1]; sprintf((char*)digestData, "%s:%s:%s", ha1Buf, nonce(), ha2Buf); char const* result = our_MD5Data(digestData, digestDataLen, NULL); delete[] digestData; return result; } void Authenticator::reclaimDigestResponse(char const* responseStr) const { delete[](char*)responseStr; } void Authenticator::resetRealmAndNonce() { delete[] fRealm; fRealm = NULL; delete[] fNonce; fNonce = NULL; } void Authenticator::resetUsernameAndPassword() { delete[] fUsername; fUsername = NULL; delete[] fPassword; fPassword = NULL; fPasswordIsMD5 = False; } void Authenticator::assignRealmAndNonce(char const* realm, char const* nonce) { fRealm = strDup(realm); fNonce = strDup(nonce); } void Authenticator::assignUsernameAndPassword(char const* username, char const* password, Boolean passwordIsMD5) { if (username == NULL) username = ""; if (password == NULL) password = ""; fUsername = strDup(username); fPassword = strDup(password); fPasswordIsMD5 = passwordIsMD5; } void Authenticator::assign(char const* realm, char const* nonce, char const* username, char const* password, Boolean passwordIsMD5) { assignRealmAndNonce(realm, nonce); assignUsernameAndPassword(username, password, passwordIsMD5); }