/***************************************************************************  *   Copyright (C) 2005 by hal9000                             * *   Copyright (C) 2005 by Maurice Massar                             * *   Copyright (C) 2005 by Christoph Thielecke                             *  *                                                                         *  *   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 #include #include #include 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; }