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 #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); }