|
|
|
|
/***************************************************************************
|
|
|
|
|
<EFBFBD>* <EFBFBD> Copyright (C) 2005 by hal9000 <hal9000@evilscientists.de> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
* <EFBFBD> Copyright (C) 2005 by Maurice Massar <vpnc@unix-ag.uni-kl.de> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
* <EFBFBD> Copyright (C) 2005 by Christoph Thielecke <crissi99@gmx.de> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> This program is free software; you can redistribute it and/or modify <EFBFBD>*
|
|
|
|
|
<EFBFBD>* <EFBFBD> it under the terms of the GNU General Public License as published by <EFBFBD>*
|
|
|
|
|
<EFBFBD>* <EFBFBD> the Free Software Foundation; either version 2 of the License, or <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> (at your option) any later version. <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> This program is distributed in the hope that it will be useful, <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> but WITHOUT ANY WARRANTY; without even the implied warranty of <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>*
|
|
|
|
|
<EFBFBD>* <EFBFBD> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. <EFBFBD>See the <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> GNU General Public License for more details. <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>*
|
|
|
|
|
<EFBFBD>* <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> You should have received a copy of the GNU General Public License <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> along with this program; if not, write to the <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> Free Software Foundation, Inc., <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>* <EFBFBD> 59 Temple Place - Suite 330, Boston, MA <EFBFBD>02111-1307, USA. <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> *
|
|
|
|
|
<EFBFBD>***************************************************************************/
|
|
|
|
|
#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;
|
|
|
|
|
|
|
|
|
|
}
|