Remove DH-AES/DH-BLOWFISH mechanisms and misc cleanup
- AES and Blowfish mechanisms are deemed insecure and servers have removed support for them - Remove attempts to retry since we only support one mech - Handle SASL 3.2's new syntax for supported mechs
This commit is contained in:
parent
6b62c4738d
commit
4362085847
|
@ -422,9 +422,7 @@ typedef struct session
|
||||||
|
|
||||||
/* SASL Mechanisms */
|
/* SASL Mechanisms */
|
||||||
#define MECH_PLAIN 0
|
#define MECH_PLAIN 0
|
||||||
#define MECH_BLOWFISH 1
|
#define MECH_EXTERNAL 1
|
||||||
#define MECH_AES 2
|
|
||||||
#define MECH_EXTERNAL 3
|
|
||||||
|
|
||||||
typedef struct server
|
typedef struct server
|
||||||
{
|
{
|
||||||
|
@ -546,7 +544,6 @@ typedef struct server
|
||||||
unsigned int skip_next_whois:1; /* hide whois output */
|
unsigned int skip_next_whois:1; /* hide whois output */
|
||||||
unsigned int inside_whois:1;
|
unsigned int inside_whois:1;
|
||||||
unsigned int doing_dns:1; /* /dns has been done */
|
unsigned int doing_dns:1; /* /dns has been done */
|
||||||
unsigned int retry_sasl:1; /* retrying another sasl mech */
|
|
||||||
unsigned int end_of_motd:1; /* end of motd reached (logged in) */
|
unsigned int end_of_motd:1; /* end of motd reached (logged in) */
|
||||||
unsigned int sent_quit:1; /* sent a QUIT already? */
|
unsigned int sent_quit:1; /* sent a QUIT already? */
|
||||||
unsigned int use_listargs:1; /* undernet and dalnet need /list >0,<10000 */
|
unsigned int use_listargs:1; /* undernet and dalnet need /list >0,<10000 */
|
||||||
|
@ -570,7 +567,6 @@ typedef struct server
|
||||||
unsigned int have_cert:1; /* have loaded a cert */
|
unsigned int have_cert:1; /* have loaded a cert */
|
||||||
unsigned int use_who:1; /* whether to use WHO command to get dcc_ip */
|
unsigned int use_who:1; /* whether to use WHO command to get dcc_ip */
|
||||||
unsigned int sasl_mech; /* mechanism for sasl auth */
|
unsigned int sasl_mech; /* mechanism for sasl auth */
|
||||||
unsigned int sent_saslauth:1; /* have sent AUTHENICATE yet */
|
|
||||||
unsigned int sent_capend:1; /* have sent CAP END yet */
|
unsigned int sent_capend:1; /* have sent CAP END yet */
|
||||||
unsigned int waiting_on_cap:1; /* waiting on another line of CAP LS */
|
unsigned int waiting_on_cap:1; /* waiting on another line of CAP LS */
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
|
|
|
@ -1633,6 +1633,12 @@ inbound_identified (server *serv) /* 'MODE +e MYSELF' on freenode */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *sasl_mechanisms[] =
|
||||||
|
{
|
||||||
|
"PLAIN",
|
||||||
|
"EXTERNAL"
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable)
|
inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable)
|
||||||
{
|
{
|
||||||
|
@ -1666,24 +1672,12 @@ inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable)
|
||||||
serv->have_sasl = enable;
|
serv->have_sasl = enable;
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
serv->sent_saslauth = FALSE;
|
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
if (serv->loginmethod == LOGIN_SASLEXTERNAL)
|
if (serv->loginmethod == LOGIN_SASLEXTERNAL)
|
||||||
{
|
|
||||||
serv->sasl_mech = MECH_EXTERNAL;
|
serv->sasl_mech = MECH_EXTERNAL;
|
||||||
tcp_send_len (serv, "AUTHENTICATE EXTERNAL\r\n", 23);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* default to most secure, it will fallback if not supported */
|
|
||||||
serv->sasl_mech = MECH_AES;
|
|
||||||
tcp_send_len (serv, "AUTHENTICATE DH-AES\r\n", 21);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
serv->sasl_mech = MECH_PLAIN;
|
|
||||||
tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20);
|
|
||||||
#endif
|
#endif
|
||||||
|
/* Mechanism either defaulted to PLAIN or server gave us list */
|
||||||
|
tcp_sendf (serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[serv->sasl_mech]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1735,6 +1729,37 @@ static const char * const supported_caps[] = {
|
||||||
"twitch.tv/membership",
|
"twitch.tv/membership",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_supported_mech (server *serv, const char *list)
|
||||||
|
{
|
||||||
|
char **mechs = g_strsplit (list, ",", 0);
|
||||||
|
gsize i;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
for (i = 0; mechs[i]; ++i)
|
||||||
|
{
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
if (serv->loginmethod == LOGIN_SASLEXTERNAL)
|
||||||
|
{
|
||||||
|
if (!strcmp (mechs[i], "EXTERNAL"))
|
||||||
|
{
|
||||||
|
ret = MECH_EXTERNAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (!strcmp (mechs[i], "PLAIN"))
|
||||||
|
{
|
||||||
|
ret = MECH_PLAIN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (mechs);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
inbound_cap_ls (server *serv, char *nick, char *extensions_str,
|
inbound_cap_ls (server *serv, char *nick, char *extensions_str,
|
||||||
const message_tags_data *tags_data)
|
const message_tags_data *tags_data)
|
||||||
|
@ -1781,6 +1806,13 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
|
||||||
((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0)
|
((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0)
|
||||||
|| (serv->loginmethod == LOGIN_SASLEXTERNAL && serv->have_cert)))
|
|| (serv->loginmethod == LOGIN_SASLEXTERNAL && serv->have_cert)))
|
||||||
{
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
int sasl_mech = get_supported_mech (serv, value);
|
||||||
|
if (sasl_mech == -1) /* No supported mech */
|
||||||
|
continue;
|
||||||
|
serv->sasl_mech = sasl_mech;
|
||||||
|
}
|
||||||
want_cap = TRUE;
|
want_cap = TRUE;
|
||||||
want_sasl = TRUE;
|
want_sasl = TRUE;
|
||||||
g_strlcat (buffer, "sasl ", sizeof(buffer));
|
g_strlcat (buffer, "sasl ", sizeof(buffer));
|
||||||
|
@ -1839,40 +1871,6 @@ inbound_cap_list (server *serv, char *nick, char *extensions,
|
||||||
NULL, NULL, 0, tags_data->timestamp);
|
NULL, NULL, 0, tags_data->timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sasl_mechanisms[] =
|
|
||||||
{
|
|
||||||
"PLAIN",
|
|
||||||
"DH-BLOWFISH",
|
|
||||||
"DH-AES",
|
|
||||||
"EXTERNAL"
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
inbound_sasl_supportedmechs (server *serv, char *list)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (serv->sasl_mech != MECH_EXTERNAL)
|
|
||||||
{
|
|
||||||
/* Use most secure one supported */
|
|
||||||
for (i = MECH_AES; i >= MECH_PLAIN; i--)
|
|
||||||
{
|
|
||||||
if (strstr (list, sasl_mechanisms[i]) != NULL)
|
|
||||||
{
|
|
||||||
serv->sasl_mech = i;
|
|
||||||
serv->retry_sasl = TRUE;
|
|
||||||
tcp_sendf (serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[i]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Abort, none supported */
|
|
||||||
serv->sent_saslauth = TRUE;
|
|
||||||
tcp_sendf (serv, "AUTHENTICATE *\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
inbound_sasl_authenticate (server *serv, char *data)
|
inbound_sasl_authenticate (server *serv, char *data)
|
||||||
{
|
{
|
||||||
|
@ -1880,12 +1878,10 @@ inbound_sasl_authenticate (server *serv, char *data)
|
||||||
char *user, *pass = NULL;
|
char *user, *pass = NULL;
|
||||||
const char *mech = sasl_mechanisms[serv->sasl_mech];
|
const char *mech = sasl_mechanisms[serv->sasl_mech];
|
||||||
|
|
||||||
/* Got a list of supported mechanisms from inspircd */
|
/* Got a list of supported mechanisms from outdated inspircd
|
||||||
|
* just ignore it as it goes against spec */
|
||||||
if (strchr (data, ',') != NULL)
|
if (strchr (data, ',') != NULL)
|
||||||
{
|
|
||||||
inbound_sasl_supportedmechs (serv, data);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (net->user && !(net->flags & FLAG_USE_GLOBAL))
|
if (net->user && !(net->flags & FLAG_USE_GLOBAL))
|
||||||
user = net->user;
|
user = net->user;
|
||||||
|
@ -1898,12 +1894,6 @@ inbound_sasl_authenticate (server *serv, char *data)
|
||||||
pass = encode_sasl_pass_plain (user, serv->password);
|
pass = encode_sasl_pass_plain (user, serv->password);
|
||||||
break;
|
break;
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
case MECH_BLOWFISH:
|
|
||||||
pass = encode_sasl_pass_blowfish (user, serv->password, data);
|
|
||||||
break;
|
|
||||||
case MECH_AES:
|
|
||||||
pass = encode_sasl_pass_aes (user, serv->password, data);
|
|
||||||
break;
|
|
||||||
case MECH_EXTERNAL:
|
case MECH_EXTERNAL:
|
||||||
pass = g_strdup ("+");
|
pass = g_strdup ("+");
|
||||||
break;
|
break;
|
||||||
|
@ -1913,12 +1903,10 @@ inbound_sasl_authenticate (server *serv, char *data)
|
||||||
if (pass == NULL)
|
if (pass == NULL)
|
||||||
{
|
{
|
||||||
/* something went wrong abort */
|
/* something went wrong abort */
|
||||||
serv->sent_saslauth = TRUE; /* prevent trying PLAIN */
|
|
||||||
tcp_sendf (serv, "AUTHENTICATE *\r\n");
|
tcp_sendf (serv, "AUTHENTICATE *\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
serv->sent_saslauth = TRUE;
|
|
||||||
tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass);
|
tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass);
|
||||||
g_free (pass);
|
g_free (pass);
|
||||||
|
|
||||||
|
@ -1927,19 +1915,9 @@ inbound_sasl_authenticate (server *serv, char *data)
|
||||||
NULL, NULL, 0, 0);
|
NULL, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
inbound_sasl_error (server *serv)
|
inbound_sasl_error (server *serv)
|
||||||
{
|
{
|
||||||
if (serv->retry_sasl && !serv->sent_saslauth)
|
/* Just abort, not much we can do */
|
||||||
return 1;
|
tcp_sendf (serv, "AUTHENTICATE *\r\n");
|
||||||
|
|
||||||
/* If server sent 904 before we sent password,
|
|
||||||
* mech not support so fallback to next mech */
|
|
||||||
if (!serv->sent_saslauth && serv->sasl_mech != MECH_EXTERNAL && serv->sasl_mech != MECH_PLAIN)
|
|
||||||
{
|
|
||||||
serv->sasl_mech -= 1;
|
|
||||||
tcp_sendf (serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[serv->sasl_mech]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,8 +98,7 @@ void inbound_cap_list (server *serv, char *nick, char *extensions,
|
||||||
void inbound_cap_del (server *serv, char *nick, char *extensions,
|
void inbound_cap_del (server *serv, char *nick, char *extensions,
|
||||||
const message_tags_data *tags_data);
|
const message_tags_data *tags_data);
|
||||||
void inbound_sasl_authenticate (server *serv, char *data);
|
void inbound_sasl_authenticate (server *serv, char *data);
|
||||||
int inbound_sasl_error (server *serv);
|
void inbound_sasl_error (server *serv);
|
||||||
void inbound_sasl_supportedmechs (server *serv, char *list);
|
|
||||||
void do_dns (session *sess, char *nick, char *host,
|
void do_dns (session *sess, char *nick, char *host,
|
||||||
const message_tags_data *tags_data);
|
const message_tags_data *tags_data);
|
||||||
gboolean alert_match_word (char *word, char *masks);
|
gboolean alert_match_word (char *word, char *masks);
|
||||||
|
|
|
@ -946,10 +946,9 @@ process_numeric (session * sess, int n,
|
||||||
word_eol[6]+1, word[1], word[2], NULL, 0,
|
word_eol[6]+1, word[1], word[2], NULL, 0,
|
||||||
tags_data->timestamp);
|
tags_data->timestamp);
|
||||||
break;
|
break;
|
||||||
case 903: /* successful SASL auth */
|
|
||||||
case 904: /* failed SASL auth */
|
case 904: /* failed SASL auth */
|
||||||
if (inbound_sasl_error (serv))
|
inbound_sasl_error (serv);
|
||||||
break; /* might retry */
|
case 903: /* successful SASL auth */
|
||||||
case 905: /* failed SASL auth */
|
case 905: /* failed SASL auth */
|
||||||
case 906: /* aborted */
|
case 906: /* aborted */
|
||||||
case 907: /* attempting to re-auth after a successful auth */
|
case 907: /* attempting to re-auth after a successful auth */
|
||||||
|
@ -963,7 +962,7 @@ process_numeric (session * sess, int n,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 908: /* Supported SASL Mechs */
|
case 908: /* Supported SASL Mechs */
|
||||||
inbound_sasl_supportedmechs (serv, word[4]);
|
/* ignored for now, SASL 3.2 is a better solution and we only do PLAIN atm */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1727,6 +1727,7 @@ server_set_defaults (server *serv)
|
||||||
serv->chanmodes = g_strdup ("beI,k,l");
|
serv->chanmodes = g_strdup ("beI,k,l");
|
||||||
serv->nick_prefixes = g_strdup ("@%+");
|
serv->nick_prefixes = g_strdup ("@%+");
|
||||||
serv->nick_modes = g_strdup ("ohv");
|
serv->nick_modes = g_strdup ("ohv");
|
||||||
|
serv->sasl_mech = MECH_PLAIN;
|
||||||
|
|
||||||
server_set_encoding (serv, "UTF-8");
|
server_set_encoding (serv, "UTF-8");
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,6 @@
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/blowfish.h>
|
|
||||||
#include <openssl/aes.h>
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1393,227 +1391,6 @@ encode_sasl_pass_plain (char *user, char *pass)
|
||||||
return encoded;
|
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 = NULL;
|
|
||||||
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 = g_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:
|
|
||||||
g_free (secret);
|
|
||||||
g_free (decoded_data);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
encode_sasl_pass_blowfish (char *user, char *pass, char *data)
|
|
||||||
{
|
|
||||||
DH *dh;
|
|
||||||
char *response, *ret = NULL;
|
|
||||||
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 = g_malloc0 (pass_len);
|
|
||||||
plain_pass = g_malloc0 (pass_len);
|
|
||||||
memcpy (plain_pass, pass, strlen(pass));
|
|
||||||
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 = g_malloc0 (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);
|
|
||||||
|
|
||||||
g_free (response);
|
|
||||||
|
|
||||||
DH_free(dh);
|
|
||||||
g_free (plain_pass);
|
|
||||||
g_free (encrypted_pass);
|
|
||||||
g_free (secret);
|
|
||||||
|
|
||||||
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 = g_malloc0 (userpass_len);
|
|
||||||
plain_userpass = g_malloc0 (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 = g_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);
|
|
||||||
g_free (plain_userpass);
|
|
||||||
g_free (encrypted_userpass);
|
|
||||||
g_free (secret);
|
|
||||||
g_free (response);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
static char *
|
static char *
|
||||||
str_sha256hash (char *string)
|
str_sha256hash (char *string)
|
||||||
|
|
|
@ -76,8 +76,6 @@ void canonalize_key (char *key);
|
||||||
int portable_mode (void);
|
int portable_mode (void);
|
||||||
int unity_mode (void);
|
int unity_mode (void);
|
||||||
char *encode_sasl_pass_plain (char *user, char *pass);
|
char *encode_sasl_pass_plain (char *user, char *pass);
|
||||||
char *encode_sasl_pass_blowfish (char *user, char *pass, char *data);
|
|
||||||
char *encode_sasl_pass_aes (char *user, char *pass, char *data);
|
|
||||||
char *challengeauth_response (char *username, char *password, char *challenge);
|
char *challengeauth_response (char *username, char *password, char *challenge);
|
||||||
size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time);
|
size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time);
|
||||||
gsize strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time);
|
gsize strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time);
|
||||||
|
|
Loading…
Reference in New Issue