summaryrefslogtreecommitdiff
path: root/lib/Config/ClawsMail/Password.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Config/ClawsMail/Password.pm')
-rw-r--r--lib/Config/ClawsMail/Password.pm110
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/Config/ClawsMail/Password.pm b/lib/Config/ClawsMail/Password.pm
new file mode 100644
index 0000000..c3e1b19
--- /dev/null
+++ b/lib/Config/ClawsMail/Password.pm
@@ -0,0 +1,110 @@
+package Config::ClawsMail::Password;
+use strict;
+use warnings;
+use Inline 'C';
+use MIME::Base64;
+use namespace::clean -except => [qw(decrypt_password)];
+
+sub cleartext_password {
+ my ($password) = @_;
+ return decrypt_password(decode_base64($password));
+}
+
+1;
+
+__DATA__
+__C__
+#include <memory.h>
+
+#define PASSCRYPT_KEY "passkey0"
+unsigned char crypt_cfb_iv[64];
+int crypt_cfb_blocksize = 8; /* 8 for DES */
+
+static void crypt_unpack(unsigned char *a) {
+ int i, j;
+
+ for (i = 7; i >= 0; --i)
+ for (j = 7; j >= 0; --j)
+ a[(i << 3) + j] = (a[i] & (0x80 >> j)) != 0;
+}
+
+static void crypt_cfb_xor(
+ unsigned char *to,
+ const unsigned char *from,
+ unsigned len) {
+ unsigned i;
+ unsigned j;
+ unsigned char c;
+
+ for (i = 0; i < len; i++) {
+ c = 0;
+ for (j = 0; j < 8; j++)
+ c = (c << 1) | *from++;
+ *to++ ^= c;
+ }
+}
+
+static void crypt_cfb_shift(
+ unsigned char *to,
+ const unsigned char *from,
+ unsigned len) {
+ unsigned i;
+ unsigned j;
+ unsigned k;
+
+ if (len < crypt_cfb_blocksize) {
+ i = len * 8;
+ j = crypt_cfb_blocksize * 8;
+ for (k = i; k < j; k++) {
+ to[0] = to[i];
+ ++to;
+ }
+ }
+
+ for (i = 0; i < len; i++) {
+ j = *from++;
+ for (k = 0x80; k; k >>= 1)
+ *to++ = ((j & k) != 0);
+ }
+}
+
+static void crypt_cfb_buf(
+ const char key[8],
+ unsigned char *buf,
+ unsigned len,
+ unsigned chunksize,
+ int decrypt) {
+ unsigned char temp[64];
+
+ memcpy(temp, key, 8);
+ crypt_unpack(temp);
+ setkey((const char *) temp);
+ memset(temp, 0, sizeof(temp));
+
+ memset(crypt_cfb_iv, 0, sizeof(crypt_cfb_iv));
+
+ if (chunksize > crypt_cfb_blocksize)
+ chunksize = crypt_cfb_blocksize;
+
+ while (len) {
+ memcpy(temp, crypt_cfb_iv, sizeof(temp));
+ encrypt((char *) temp, 0);
+ if (chunksize > len)
+ chunksize = len;
+ if (decrypt)
+ crypt_cfb_shift(crypt_cfb_iv, buf, chunksize);
+ crypt_cfb_xor((unsigned char *) buf, temp, chunksize);
+ if (!decrypt)
+ crypt_cfb_shift(crypt_cfb_iv, buf, chunksize);
+ len -= chunksize;
+ buf += chunksize;
+ }
+}
+
+SV* decrypt_password(SV* password) {
+ size_t len = sv_len(password);
+ char *tmp = (char*)malloc(len);
+ memcpy(tmp,SvPVbyte(password,len),len);
+ crypt_cfb_buf(PASSCRYPT_KEY, tmp, len, 1, 1 );
+ return newSVpvn(tmp,len);
+}