diff options
Diffstat (limited to 'src/ciscopasswddecoder.cpp')
-rw-r--r-- | src/ciscopasswddecoder.cpp | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/ciscopasswddecoder.cpp b/src/ciscopasswddecoder.cpp new file mode 100644 index 0000000..f4d98bb --- /dev/null +++ b/src/ciscopasswddecoder.cpp @@ -0,0 +1,227 @@ +/*************************************************************************** + * Copyright (C) 2005 by hal9000 <hal9000@evilscientists.de> * + * Copyright (C) 2005 by Maurice Massar <vpnc@unix-ag.uni-kl.de> * + * Copyright (C) 2005 by Christoph Thielecke <crissi99@gmx.de> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "ciscopasswddecoder.h" + +#include <qfile.h> +#include <qtextstream.h> +#include <kmessagebox.h> +#include <klocale.h> + +CiscoPasswdDecoder::CiscoPasswdDecoder(QString& profileFile) +{ + profile = profileFile; +} + +CiscoPasswdDecoder::~CiscoPasswdDecoder() +{} + +/* read hex strings for "enc_GroupPwd" and "enc_UserPassword" from profile file */ +void CiscoPasswdDecoder::readProfileData(QString& profile, QString& userData, QString& groupData) +{ + QFile PcfFile(profile); + QTextStream stream ( &PcfFile ); + + if ( PcfFile.open(IO_ReadOnly)) + { + QString line = ""; + while ( !stream.atEnd() ) + { + line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank + if ( !line.startsWith("#") ) + { + if (line.startsWith("enc_GroupPwd") || line.startsWith("enc_GroupPwd") ) + groupData=line.section('=',1,1).stripWhiteSpace(); + if (line.startsWith("enc_UserPassword") || line.startsWith("enc_GroupPwd") ) + userData=line.section('=',1,1).stripWhiteSpace(); + } + } + PcfFile.close(); + } + else + { + KMessageBox::error ( 0, i18n ( "Reading of \"%1\" has been failed!" ).arg ( PcfFile.name() ) ); + } +} + +int CiscoPasswdDecoder::hex2bin_c(unsigned int c) +{ + if ((c >= '0')&&(c <= '9')) + return c - '0'; + if ((c >= 'A')&&(c <= 'F')) + return c - 'A' + 10; + if ((c >= 'a')&&(c <= 'f')) + return c - 'a' + 10; + return -1; +} + +int CiscoPasswdDecoder::hex2bin(QString str, QString& bin, int& len) +{ +QString p; + int i, l; + + for (i = 0; str[i] != '\0'; i++) + if (hex2bin_c(QChar(str[i]).unicode()) == -1) + return EINVAL; + + l = i; + if ((l & 1) != 0) + return EINVAL; + l /= 2; + + for (i = 0; i < l; i++) + p+= hex2bin_c(QChar(str[i*2]).unicode()) << 4 | hex2bin_c(QChar(str[i*2+1]).unicode()); + + bin = p; + if (len) + len = l; + + return 0; +} + +int CiscoPasswdDecoder::c_decrypt(QString ct, int len, char **resp, int reslenp) +{ + QString h1 = ct; + const char *h4 = ct.ascii() + 20; + const char *enc = ct.ascii() + 40; + + char ht[20], h2[20], h3[20], key[24]; + const char *iv = h1.ascii(); + char *res; + gcry_cipher_hd_t ctx; + int reslen; + + if (len < 48) + return 0; + len -= 40; + + memcpy(ht, h1.ascii(), 20); + + ht[19]++; + gcry_md_hash_buffer(GCRY_MD_SHA1, h2, ht, 20); + + ht[19] += 2; + gcry_md_hash_buffer(GCRY_MD_SHA1, h3, ht, 20); + + memcpy(key, h2, 20); + memcpy(key+20, h3, 4); + /* who cares about parity anyway? */ + + gcry_md_hash_buffer(GCRY_MD_SHA1, ht, enc, len); + + if (memcmp(h4, ht, 20) != 0) + return -1; + + res = (char *)malloc(len); + if (res == NULL) + return -1; + + gcry_cipher_open(&ctx, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); + gcry_cipher_setkey(ctx, key, 24); + gcry_cipher_setiv(ctx, iv, 8); + gcry_cipher_decrypt(ctx, (unsigned char *)res, len, (unsigned char *)enc, len); + gcry_cipher_close(ctx); + + reslen = len - res[len-1]; + res[reslen] = '\0'; + + if (resp) + *resp = res; + + reslenp = reslen; + return 0; +} + +bool CiscoPasswdDecoder::decodePasswords(QString& userPasswd, QString& groupPasswd) +{ + QString encUserPasswd=""; + QString encGroupPasswd=""; + int i, len, ret = 0; + char *pw, *pw2; + QString bin,bin2; + int len2=0; + bool success=true; + + readProfileData(profile, encUserPasswd, encGroupPasswd); + + + if (!encGroupPasswd.isEmpty()) + { + ret = hex2bin( encGroupPasswd, bin, len); + + + if (ret != 0) + { + perror("error: groupPasswd: decoding input"); + success=false; + } + ret = c_decrypt(bin, len, &pw, 0); + + if (ret != 0) + { + perror("error: groupPasswd: decrypting input"); + success=false; + } + else + { +// printf("groupPasswd: %s\n", pw); +// std::cout << "groupPasswd: " << QString::fromLocal8Bit(pw) << std::endl; + + + groupPasswd = QString::fromLocal8Bit(pw); + //free(pw); + } + } + if (!encUserPasswd.isEmpty() ) + { + i=0; + len2=0; + ret = 0; + ret = hex2bin( encUserPasswd, bin2, len2); + + if (ret != 0) + { + perror("error: userPasswd: decoding input"); + success=false; + } + ret = c_decrypt(bin2, len2, &pw2, 0); + //free(bin2); + if (ret != 0) + { + perror("error: userPasswd: decrypting input"); + success=false; + } + else + { + +// // printf("userPasswd: %s\n", pw2); +// std::cout << "userPasswd " << QString::fromLocal8Bit(pw2) << std::endl; + userPasswd = QString::fromLocal8Bit(pw2); + + + //free(pw); + } + } + + + + return success; + +} |