summaryrefslogtreecommitdiffstats
path: root/src/ciscopasswddecoder.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-12-06 12:36:58 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-12-06 12:36:58 -0600
commitd08a0ede1d2cb15bb14b0ff75eacf5c682b1fa0a (patch)
treee5ce4701bac540038a279b4e208c86390a24ba11 /src/ciscopasswddecoder.cpp
downloadkvpnc-d08a0ede1d2cb15bb14b0ff75eacf5c682b1fa0a.tar.gz
kvpnc-d08a0ede1d2cb15bb14b0ff75eacf5c682b1fa0a.zip
Initial import of year-and-a-half-old upstream version 0.9.6a
Diffstat (limited to 'src/ciscopasswddecoder.cpp')
-rw-r--r--src/ciscopasswddecoder.cpp227
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;
+
+}