mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-12 08:40:19 +00:00
@@ -58,6 +58,17 @@
|
||||
#include <socks.h>
|
||||
#endif
|
||||
|
||||
/* SASL mechanisms */
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/blowfish.h>
|
||||
#include <openssl/aes.h>
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SNPRINTF
|
||||
#define snprintf g_snprintf
|
||||
#endif
|
||||
@@ -1929,7 +1940,7 @@ get_subdirs (const char *path)
|
||||
}
|
||||
|
||||
char *
|
||||
encode_sasl_pass (char *user, char *pass)
|
||||
encode_sasl_pass_plain (char *user, char *pass)
|
||||
{
|
||||
int authlen;
|
||||
char *buffer;
|
||||
@@ -1944,6 +1955,230 @@ encode_sasl_pass (char *user, char *pass)
|
||||
return encoded;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
/* Adapted from ZNC's SASL module */
|
||||
|
||||
static int
|
||||
parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out)
|
||||
{
|
||||
DH *dh;
|
||||
guchar *data, *decoded_data;
|
||||
guchar *secret;
|
||||
gsize data_len;
|
||||
guint size;
|
||||
guint16 size16;
|
||||
BIGNUM *pubkey;
|
||||
gint key_size;
|
||||
|
||||
dh = DH_new();
|
||||
data = decoded_data = g_base64_decode (str, &data_len);
|
||||
if (data_len < 2)
|
||||
goto fail;
|
||||
|
||||
/* prime number */
|
||||
memcpy (&size16, data, sizeof(size16));
|
||||
size = ntohs (size16);
|
||||
data += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (size > data_len)
|
||||
goto fail;
|
||||
|
||||
dh->p = BN_bin2bn (data, size, NULL);
|
||||
data += size;
|
||||
|
||||
/* Generator */
|
||||
if (data_len < 2)
|
||||
goto fail;
|
||||
|
||||
memcpy (&size16, data, sizeof(size16));
|
||||
size = ntohs (size16);
|
||||
data += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (size > data_len)
|
||||
goto fail;
|
||||
|
||||
dh->g = BN_bin2bn (data, size, NULL);
|
||||
data += size;
|
||||
|
||||
/* pub key */
|
||||
if (data_len < 2)
|
||||
goto fail;
|
||||
|
||||
memcpy (&size16, data, sizeof(size16));
|
||||
size = ntohs(size16);
|
||||
data += 2;
|
||||
data_len -= 2;
|
||||
|
||||
pubkey = BN_bin2bn (data, size, NULL);
|
||||
if (!(DH_generate_key (dh)))
|
||||
goto fail;
|
||||
|
||||
secret = (unsigned char*)malloc (DH_size(dh));
|
||||
key_size = DH_compute_key (secret, pubkey, dh);
|
||||
if (key_size == -1)
|
||||
goto fail;
|
||||
|
||||
g_free (decoded_data);
|
||||
|
||||
*dh_out = dh;
|
||||
*secret_out = secret;
|
||||
*keysize_out = key_size;
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
if (decoded_data)
|
||||
g_free (decoded_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
encode_sasl_pass_blowfish (char *user, char *pass, char *data)
|
||||
{
|
||||
DH *dh;
|
||||
char *response, *ret;
|
||||
unsigned char *secret;
|
||||
unsigned char *encrypted_pass;
|
||||
char *plain_pass;
|
||||
BF_KEY key;
|
||||
int key_size, length;
|
||||
int pass_len = strlen (pass) + (8 - (strlen (pass) % 8));
|
||||
int user_len = strlen (user);
|
||||
guint16 size16;
|
||||
char *in_ptr, *out_ptr;
|
||||
|
||||
if (!parse_dh (data, &dh, &secret, &key_size))
|
||||
return NULL;
|
||||
BF_set_key (&key, key_size, secret);
|
||||
|
||||
encrypted_pass = (guchar*)malloc (pass_len);
|
||||
memset (encrypted_pass, 0, pass_len);
|
||||
plain_pass = (char*)malloc (pass_len);
|
||||
memset (plain_pass, 0, pass_len);
|
||||
memcpy (plain_pass, pass, pass_len);
|
||||
out_ptr = (char*)encrypted_pass;
|
||||
in_ptr = (char*)plain_pass;
|
||||
|
||||
for (length = pass_len; length; length -= 8, in_ptr += 8, out_ptr += 8)
|
||||
BF_ecb_encrypt ((unsigned char*)in_ptr, (unsigned char*)out_ptr, &key, BF_ENCRYPT);
|
||||
|
||||
/* Create response */
|
||||
length = 2 + BN_num_bytes (dh->pub_key) + pass_len + user_len + 1;
|
||||
response = (char*)malloc (length);
|
||||
out_ptr = response;
|
||||
|
||||
/* our key */
|
||||
size16 = htons ((guint16)BN_num_bytes (dh->pub_key));
|
||||
memcpy (out_ptr, &size16, sizeof(size16));
|
||||
out_ptr += 2;
|
||||
BN_bn2bin (dh->pub_key, (guchar*)out_ptr);
|
||||
out_ptr += BN_num_bytes (dh->pub_key);
|
||||
|
||||
/* username */
|
||||
memcpy (out_ptr, user, user_len + 1);
|
||||
out_ptr += user_len + 1;
|
||||
|
||||
/* pass */
|
||||
memcpy (out_ptr, encrypted_pass, pass_len);
|
||||
|
||||
ret = g_base64_encode ((const guchar*)response, length);
|
||||
|
||||
DH_free (dh);
|
||||
free (plain_pass);
|
||||
free (encrypted_pass);
|
||||
free (secret);
|
||||
free (response);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
encode_sasl_pass_aes (char *user, char *pass, char *data)
|
||||
{
|
||||
DH *dh;
|
||||
AES_KEY key;
|
||||
char *response = NULL;
|
||||
char *out_ptr, *ret = NULL;
|
||||
unsigned char *secret, *ptr;
|
||||
unsigned char *encrypted_userpass, *plain_userpass;
|
||||
int key_size, length;
|
||||
guint16 size16;
|
||||
unsigned char iv[16], iv_copy[16];
|
||||
int user_len = strlen (user) + 1;
|
||||
int pass_len = strlen (pass) + 1;
|
||||
int len = user_len + pass_len;
|
||||
int padlen = 16 - (len % 16);
|
||||
int userpass_len = len + padlen;
|
||||
|
||||
if (!parse_dh (data, &dh, &secret, &key_size))
|
||||
return NULL;
|
||||
|
||||
encrypted_userpass = (guchar*)malloc (userpass_len);
|
||||
memset (encrypted_userpass, 0, userpass_len);
|
||||
plain_userpass = (guchar*)malloc (userpass_len);
|
||||
memset (plain_userpass, 0, userpass_len);
|
||||
|
||||
/* create message */
|
||||
/* format of: <username>\0<password>\0<padding> */
|
||||
ptr = plain_userpass;
|
||||
memcpy (ptr, user, user_len);
|
||||
ptr += user_len;
|
||||
memcpy (ptr, pass, pass_len);
|
||||
ptr += pass_len;
|
||||
if (padlen)
|
||||
{
|
||||
/* Padding */
|
||||
unsigned char randbytes[16];
|
||||
if (!RAND_bytes (randbytes, padlen))
|
||||
goto end;
|
||||
|
||||
memcpy (ptr, randbytes, padlen);
|
||||
}
|
||||
|
||||
if (!RAND_bytes (iv, sizeof (iv)))
|
||||
goto end;
|
||||
|
||||
memcpy (iv_copy, iv, sizeof(iv));
|
||||
|
||||
/* Encrypt */
|
||||
AES_set_encrypt_key (secret, key_size * 8, &key);
|
||||
AES_cbc_encrypt(plain_userpass, encrypted_userpass, userpass_len, &key, iv_copy, AES_ENCRYPT);
|
||||
|
||||
/* Create response */
|
||||
/* format of: <size pubkey><pubkey><iv (always 16 bytes)><ciphertext> */
|
||||
length = 2 + key_size + sizeof(iv) + userpass_len;
|
||||
response = (char*)malloc (length);
|
||||
out_ptr = response;
|
||||
|
||||
/* our key */
|
||||
size16 = htons ((guint16)key_size);
|
||||
memcpy (out_ptr, &size16, sizeof(size16));
|
||||
out_ptr += 2;
|
||||
BN_bn2bin (dh->pub_key, (guchar*)out_ptr);
|
||||
out_ptr += key_size;
|
||||
|
||||
/* iv */
|
||||
memcpy (out_ptr, iv, sizeof(iv));
|
||||
out_ptr += sizeof(iv);
|
||||
|
||||
/* userpass */
|
||||
memcpy (out_ptr, encrypted_userpass, userpass_len);
|
||||
|
||||
ret = g_base64_encode ((const guchar*)response, length);
|
||||
|
||||
end:
|
||||
DH_free (dh);
|
||||
free (plain_userpass);
|
||||
free (encrypted_userpass);
|
||||
free (secret);
|
||||
if (response)
|
||||
free (response);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
int
|
||||
find_font (const char *fontname)
|
||||
|
||||
Reference in New Issue
Block a user