diff options
Diffstat (limited to 'kio/misc/kntlm/kntlm.cpp')
-rw-r--r-- | kio/misc/kntlm/kntlm.cpp | 389 |
1 files changed, 0 insertions, 389 deletions
diff --git a/kio/misc/kntlm/kntlm.cpp b/kio/misc/kntlm/kntlm.cpp deleted file mode 100644 index dd9cd33ec..000000000 --- a/kio/misc/kntlm/kntlm.cpp +++ /dev/null @@ -1,389 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (c) 2004 Szombathelyi Gy�gy <gyurco@freemail.hu> - - The implementation is based on the documentation and sample code - at http://davenport.sourceforge.net/ntlm.html - The DES encryption functions are from libntlm - at http://josefsson.org/libntlm/ - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include <string.h> - -#include <tqdatetime.h> -#include <kapplication.h> -#include <kswap.h> -#include <kmdcodec.h> -#include <kdebug.h> - -#include "des.h" -#include "kntlm.h" - -TQString KNTLM::getString( const TQByteArray &buf, const SecBuf &secbuf, bool unicode ) -{ - //watch for buffer overflows - TQ_UINT32 offset; - TQ_UINT16 len; - offset = KFromToLittleEndian((TQ_UINT32)secbuf.offset); - len = KFromToLittleEndian(secbuf.len); - if ( offset > buf.size() || - offset + len > buf.size() ) return TQString::null; - - TQString str; - const char *c = buf.data() + offset; - - if ( unicode ) { - str = UnicodeLE2TQString( (TQChar*) c, len >> 1 ); - } else { - str = TQString::fromLatin1( c, len ); - } - return str; -} - -TQByteArray KNTLM::getBuf( const TQByteArray &buf, const SecBuf &secbuf ) -{ - TQByteArray ret; - TQ_UINT32 offset; - TQ_UINT16 len; - offset = KFromToLittleEndian((TQ_UINT32)secbuf.offset); - len = KFromToLittleEndian(secbuf.len); - //watch for buffer overflows - if ( offset > buf.size() || - offset + len > buf.size() ) return ret; - ret.duplicate( buf.data() + offset, buf.size() ); - return ret; -} - -void KNTLM::addString( TQByteArray &buf, SecBuf &secbuf, const TQString &str, bool unicode ) -{ - TQByteArray tmp; - - if ( unicode ) { - tmp = QString2UnicodeLE( str ); - addBuf( buf, secbuf, tmp ); - } else { - const char *c; - c = str.latin1(); - tmp.setRawData( c, str.length() ); - addBuf( buf, secbuf, tmp ); - tmp.resetRawData( c, str.length() ); - } -} - -void KNTLM::addBuf( TQByteArray &buf, SecBuf &secbuf, TQByteArray &data ) -{ - TQ_UINT32 offset; - TQ_UINT16 len, maxlen; - offset = (buf.size() + 1) & 0xfffffffe; - len = data.size(); - maxlen = data.size(); - - secbuf.offset = KFromToLittleEndian((TQ_UINT32)offset); - secbuf.len = KFromToLittleEndian(len); - secbuf.maxlen = KFromToLittleEndian(maxlen); - buf.resize( offset + len ); - memcpy( buf.data() + offset, data.data(), data.size() ); -} - -bool KNTLM::getNegotiate( TQByteArray &negotiate, const TQString &domain, const TQString &workstation, TQ_UINT32 flags ) -{ - TQByteArray rbuf( sizeof(Negotiate) ); - - rbuf.fill( 0 ); - memcpy( rbuf.data(), "NTLMSSP", 8 ); - ((Negotiate*) rbuf.data())->msgType = KFromToLittleEndian( (TQ_UINT32)1 ); - if ( !domain.isEmpty() ) { - flags |= Negotiate_Domain_Supplied; - addString( rbuf, ((Negotiate*) rbuf.data())->domain, domain ); - } - if ( !workstation.isEmpty() ) { - flags |= Negotiate_WS_Supplied; - addString( rbuf, ((Negotiate*) rbuf.data())->domain, workstation ); - } - ((Negotiate*) rbuf.data())->flags = KFromToLittleEndian( flags ); - negotiate = rbuf; - return true; -} - -bool KNTLM::getAuth( TQByteArray &auth, const TQByteArray &challenge, const TQString &user, - const TQString &password, const TQString &domain, const TQString &workstation, - bool forceNTLM, bool forceNTLMv2 ) -{ - TQByteArray rbuf( sizeof(Auth) ); - Challenge *ch = (Challenge *) challenge.data(); - TQByteArray response; - uint chsize = challenge.size(); - bool unicode = false; - TQString dom; - - //challenge structure too small - if ( chsize < 32 ) return false; - - unicode = KFromToLittleEndian(ch->flags) & Negotiate_Unicode; - if ( domain.isEmpty() ) - dom = getString( challenge, ch->targetName, unicode ); - else - dom = domain; - - rbuf.fill( 0 ); - memcpy( rbuf.data(), "NTLMSSP", 8 ); - ((Auth*) rbuf.data())->msgType = KFromToLittleEndian( (TQ_UINT32)3 ); - ((Auth*) rbuf.data())->flags = ch->flags; - TQByteArray targetInfo = getBuf( challenge, ch->targetInfo ); - -// if ( forceNTLMv2 || (!targetInfo.isEmpty() && (KFromToLittleEndian(ch->flags) & Negotiate_Target_Info)) /* may support NTLMv2 */ ) { -// if ( KFromToLittleEndian(ch->flags) & Negotiate_NTLM ) { -// if ( targetInfo.isEmpty() ) return false; -// response = getNTLMv2Response( dom, user, password, targetInfo, ch->challengeData ); -// addBuf( rbuf, ((Auth*) rbuf.data())->ntResponse, response ); -// } else { -// if ( !forceNTLM ) { -// response = getLMv2Response( dom, user, password, ch->challengeData ); -// addBuf( rbuf, ((Auth*) rbuf.data())->lmResponse, response ); -// } else -// return false; -// } -// } else { //if no targetinfo structure and NTLMv2 or LMv2 not forced, try the older methods - - response = getNTLMResponse( password, ch->challengeData ); - addBuf( rbuf, ((Auth*) rbuf.data())->ntResponse, response ); - response = getLMResponse( password, ch->challengeData ); - addBuf( rbuf, ((Auth*) rbuf.data())->lmResponse, response ); -// } - if ( !dom.isEmpty() ) - addString( rbuf, ((Auth*) rbuf.data())->domain, dom, unicode ); - addString( rbuf, ((Auth*) rbuf.data())->user, user, unicode ); - if ( !workstation.isEmpty() ) - addString( rbuf, ((Auth*) rbuf.data())->workstation, workstation, unicode ); - - auth = rbuf; - - return true; -} - -TQByteArray KNTLM::getLMResponse( const TQString &password, const unsigned char *challenge ) -{ - TQByteArray hash, answer; - - hash = lmHash( password ); - hash.resize( 21 ); - memset( hash.data() + 16, 0, 5 ); - answer = lmResponse( hash, challenge ); - hash.fill( 0 ); - return answer; -} - -TQByteArray KNTLM::lmHash( const TQString &password ) -{ - TQByteArray keyBytes( 14 ); - TQByteArray hash( 16 ); - DES_KEY ks; - const char *magic = "KGS!@#$%"; - - keyBytes.fill( 0 ); - strncpy( keyBytes.data(), password.upper().latin1(), 14 ); - - convertKey( (unsigned char*) keyBytes.data(), &ks ); - ntlm_des_ecb_encrypt( magic, 8, &ks, (unsigned char*) hash.data() ); - - convertKey( (unsigned char*) keyBytes.data() + 7, &ks ); - ntlm_des_ecb_encrypt( magic, 8, &ks, (unsigned char*) hash.data() + 8 ); - - keyBytes.fill( 0 ); - memset( &ks, 0, sizeof (ks) ); - - return hash; -} - -TQByteArray KNTLM::lmResponse( const TQByteArray &hash, const unsigned char *challenge ) -{ - DES_KEY ks; - TQByteArray answer( 24 ); - - convertKey( (unsigned char*) hash.data(), &ks ); - ntlm_des_ecb_encrypt( challenge, 8, &ks, (unsigned char*) answer.data() ); - - convertKey( (unsigned char*) hash.data() + 7, &ks ); - ntlm_des_ecb_encrypt( challenge, 8, &ks, (unsigned char*) answer.data() + 8 ); - - convertKey( (unsigned char*) hash.data() + 14, &ks ); - ntlm_des_ecb_encrypt( challenge, 8, &ks, (unsigned char*) answer.data() + 16 ); - - memset( &ks, 0, sizeof (ks) ); - return answer; -} - -TQByteArray KNTLM::getNTLMResponse( const TQString &password, const unsigned char *challenge ) -{ - TQByteArray hash, answer; - - hash = ntlmHash( password ); - hash.resize( 21 ); - memset( hash.data() + 16, 0, 5 ); - answer = lmResponse( hash, challenge ); - hash.fill( 0 ); - return answer; -} - -TQByteArray KNTLM::ntlmHash( const TQString &password ) -{ - KMD4::Digest digest; - TQByteArray ret, unicode; - unicode = QString2UnicodeLE( password ); - - KMD4 md4( unicode ); - md4.rawDigest( digest ); - ret.duplicate( (const char*) digest, sizeof( digest ) ); - return ret; -} - -TQByteArray KNTLM::getNTLMv2Response( const TQString &target, const TQString &user, - const TQString &password, const TQByteArray &targetInformation, - const unsigned char *challenge ) -{ - TQByteArray hash = ntlmv2Hash( target, user, password ); - TQByteArray blob = createBlob( targetInformation ); - return lmv2Response( hash, blob, challenge ); -} - -TQByteArray KNTLM::getLMv2Response( const TQString &target, const TQString &user, - const TQString &password, const unsigned char *challenge ) -{ - TQByteArray hash = ntlmv2Hash( target, user, password ); - TQByteArray clientChallenge( 8 ); - for ( uint i = 0; i<8; i++ ) { - clientChallenge.data()[i] = TDEApplication::random() % 0xff; - } - return lmv2Response( hash, clientChallenge, challenge ); -} - -TQByteArray KNTLM::ntlmv2Hash( const TQString &target, const TQString &user, const TQString &password ) -{ - TQByteArray hash1 = ntlmHash( password ); - TQByteArray key, ret; - TQString id = user.upper() + target.upper(); - key = QString2UnicodeLE( id ); - ret = hmacMD5( key, hash1 ); - return ret; -} - -TQByteArray KNTLM::lmv2Response( const TQByteArray &hash, - const TQByteArray &clientData, const unsigned char *challenge ) -{ - TQByteArray data( 8 + clientData.size() ); - memcpy( data.data(), challenge, 8 ); - memcpy( data.data() + 8, clientData.data(), clientData.size() ); - TQByteArray mac = hmacMD5( data, hash ); - mac.resize( 16 + clientData.size() ); - memcpy( mac.data() + 16, clientData.data(), clientData.size() ); - return mac; -} - -TQByteArray KNTLM::createBlob( const TQByteArray &targetinfo ) -{ - TQByteArray blob( sizeof(Blob) + 4 + targetinfo.size() ); - blob.fill( 0 ); - - Blob *bl = (Blob *) blob.data(); - bl->signature = KFromToBigEndian( (TQ_UINT32) 0x01010000 ); - TQ_UINT64 now = TQDateTime::currentDateTime().toTime_t(); - now += (TQ_UINT64)3600*(TQ_UINT64)24*(TQ_UINT64)134774; - now *= (TQ_UINT64)10000000; - bl->timestamp = KFromToLittleEndian( now ); - for ( uint i = 0; i<8; i++ ) { - bl->challenge[i] = TDEApplication::random() % 0xff; - } - memcpy( blob.data() + sizeof(Blob), targetinfo.data(), targetinfo.size() ); - return blob; -} - -TQByteArray KNTLM::hmacMD5( const TQByteArray &data, const TQByteArray &key ) -{ - TQ_UINT8 ipad[64], opad[64]; - KMD5::Digest digest; - TQByteArray ret; - - memset( ipad, 0x36, sizeof(ipad) ); - memset( opad, 0x5c, sizeof(opad) ); - for ( int i = key.size()-1; i >= 0; i-- ) { - ipad[i] ^= key[i]; - opad[i] ^= key[i]; - } - - TQByteArray content( data.size()+64 ); - memcpy( content.data(), ipad, 64 ); - memcpy( content.data() + 64, data.data(), data.size() ); - KMD5 md5( content ); - md5.rawDigest( digest ); - content.resize( sizeof(digest) + 64 ); - memcpy( content.data(), opad, 64 ); - memcpy( content.data() + 64, digest, sizeof(digest) ); - md5.reset(); - md5.update( content ); - md5.rawDigest( digest ); - - ret.duplicate( (const char*) digest, sizeof( digest ) ); - return ret; -} - -/* -* turns a 56 bit key into the 64 bit, odd parity key and sets the key. -* The key schedule ks is also set. -*/ -void KNTLM::convertKey( unsigned char *key_56, void* ks ) -{ - unsigned char key[8]; - - key[0] = key_56[0]; - key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); - key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); - key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); - key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); - key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); - key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); - key[7] = (key_56[6] << 1) & 0xFF; - - for ( uint i=0; i<8; i++ ) { - unsigned char b = key[i]; - bool needsParity = (((b>>7) ^ (b>>6) ^ (b>>5) ^ (b>>4) ^ (b>>3) ^ (b>>2) ^ (b>>1)) & 0x01) == 0; - if ( needsParity ) - key[i] |= 0x01; - else - key[i] &= 0xfe; - } - - ntlm_des_set_key ( (DES_KEY*) ks, (char*) &key, sizeof (key)); - - memset (&key, 0, sizeof (key)); -} - -TQByteArray KNTLM::QString2UnicodeLE( const TQString &target ) -{ - TQByteArray unicode( target.length() * 2 ); - for ( uint i = 0; i < target.length(); i++ ) { - ((TQ_UINT16*)unicode.data())[ i ] = KFromToLittleEndian( target[i].unicode() ); - } - return unicode; -} - -TQString KNTLM::UnicodeLE2TQString( const TQChar* data, uint len ) -{ - TQString ret; - for ( uint i = 0; i < len; i++ ) { - ret += KFromToLittleEndian( data[ i ].unicode() ); - } - return ret; -} |