struct sockaddr_storage *sa, socklen_t *salen);
int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
fr_ipaddr_t *ipaddr, int * port);
+ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen);
#ifdef WITH_ASCEND_BINARY
#include <fcntl.h>
#include <signal.h>
-int fr_dns_lookups = 0;
-int fr_debug_flag = 0;
-
+#define FR_PUT_LE16(a, val)\
+ do {\
+ a[1] = ((uint16_t) (val)) >> 8;\
+ a[0] = ((uint16_t) (val)) & 0xff;\
+ } while (0)
static int fr_debugger_present = -1;
-/** Stub callback to see if the SIGTRAP handler is overriden
+int fr_dns_lookups = 0;
+int fr_debug_flag = 0;
+
+fr_thread_local_setup(char *, fr_inet_ntop_buffer); /* macro */
+
+/** Allocates a new talloc context from the root autofree context
*
* @param signum signal raised.
*/
return 1;
}
+
+/** Convert UTF8 string to UCS2 encoding
+ *
+ * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
+ *
+ * @param[out] out Where to write the ucs2 string.
+ * @param[in] outlen Size of output buffer.
+ * @param[in] in UTF8 string to convert.
+ * @param[in] inlen length of UTF8 string.
+ * @return the size of the UCS2 string written to the output buffer (in bytes).
+ */
+ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
+{
+ size_t i;
+ uint8_t *start = out;
+
+ for (i = 0; i < inlen; i++) {
+ uint8_t c, c2, c3;
+
+ c = in[i];
+ if ((size_t)(out - start) >= outlen) {
+ /* input too long */
+ return -1;
+ }
+
+ /* One-byte encoding */
+ if (c <= 0x7f) {
+ FR_PUT_LE16(out, c);
+ out += 2;
+ continue;
+ } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
+ /* Incomplete surrogate */
+ return -1;
+ }
+
+ c2 = in[++i];
+ /* Two-byte encoding */
+ if ((c & 0xe0) == 0xc0) {
+ FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
+ out += 2;
+ continue;
+ }
+ if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
+ /* Incomplete surrogate */
+ return -1;
+ }
+
+ /* Three-byte encoding */
+ c3 = in[++i];
+ FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
+ out += 2;
+ }
+
+ return out - start;
+}
+
p[1] = 0x01; /* NT hash */
- mschap_ntpwdhash(nthash, password);
+ if (mschap_ntpwdhash(nthash, password) < 0) {
+ return 0;
+ }
- smbdes_mschap(nthash, challenge->vp_octets,
- p + 26);
+ smbdes_mschap(nthash, challenge->vp_octets, p + 26);
return 1;
}
/*
* Get the NT-Password hash.
*/
-static int eapleap_ntpwdhash(unsigned char *ntpwdhash, VALUE_PAIR *password)
+static int eapleap_ntpwdhash(uint8_t *out, VALUE_PAIR *password)
{
if ((password->da->attr == PW_USER_PASSWORD) ||
(password->da->attr == PW_CLEARTEXT_PASSWORD)) {
- size_t i;
- unsigned char unicode[512];
+ ssize_t len;
+ uint8_t ucs2_password[512];
/*
* Convert the password to NT's weird Unicode format.
*/
- memset(unicode, 0, sizeof(unicode));
- for (i = 0; i < password->length; i++) {
- /*
- * Yes, the *even* bytes have the values,
- * and the *odd* bytes are zero.
- */
- unicode[(i << 1)] = password->vp_strvalue[i];
+ len = fr_utf8_to_ucs2(ucs2_password, sizeof(ucs2_password), password->vp_strvalue, password->length);
+ if (len < 0) {
+ ERROR("rlm_eap_leap: Error converting password to UCS2");
+ return 0;
}
/*
* Get the NT Password hash.
*/
- fr_md4_calc(ntpwdhash, unicode, password->length * 2);
-
+ fr_md4_calc(out, ucs2_password, len);
} else { /* MUST be NT-Password */
uint8_t *p = NULL;
talloc_free(p);
}
- memcpy(ntpwdhash, password->vp_octets, 16);
+ memcpy(out, password->vp_octets, 16);
}
return 1;
}
int eapleap_stage4(leap_packet_t *packet, VALUE_PAIR* password,
leap_session_t *session)
{
- unsigned char ntpwdhash[16];
+ unsigned char out[16];
unsigned char response[24];
return 0;
}
- if (!eapleap_ntpwdhash(ntpwdhash, password)) {
+ if (!eapleap_ntpwdhash(out, password)) {
return 0;
}
/*
* Calculate and verify the CHAP challenge.
*/
- eapleap_mschap(ntpwdhash, session->peer_challenge, response);
+ eapleap_mschap(out, session->peer_challenge, response);
if (memcmp(response, packet->challenge, 24) == 0) {
DEBUG2(" rlm_eap_leap: NtChallengeResponse from AP is valid");
memcpy(session->peer_response, response, sizeof(response));
/*
* Verify ourselves to the AP
*/
-leap_packet_t *eapleap_stage6(leap_packet_t *packet, REQUEST *request,
- VALUE_PAIR *user_name, VALUE_PAIR* password,
- leap_session_t *session)
+leap_packet_t *eapleap_stage6(leap_packet_t *packet, REQUEST *request, VALUE_PAIR *user_name, VALUE_PAIR *password,
+ leap_session_t *session)
{
size_t i;
- uint8_t ntpwdhash[16], ntpwdhashhash[16];
+ uint8_t out[16], outhash[16];
uint8_t *p, buffer[256];
leap_packet_t *reply;
char *q;
/*
* MPPE hash = ntpwdhash(ntpwdhash(unicode(pw)))
*/
- if (!eapleap_ntpwdhash(ntpwdhash, password)) {
+ if (!eapleap_ntpwdhash(out, password)) {
talloc_free(reply);
return NULL;
}
- fr_md4_calc(ntpwdhashhash, ntpwdhash, 16);
+ fr_md4_calc(outhash, out, 16);
/*
- * Calculate our response, to authenticate ourselves
- * to the AP.
+ * Calculate our response, to authenticate ourselves to the AP.
*/
- eapleap_mschap(ntpwdhashhash, packet->challenge, reply->challenge);
+ eapleap_mschap(outhash, packet->challenge, reply->challenge);
/*
- * Calculate the leap:session-key attribute
+ * Calculate the leap:session-key attribute
*/
vp = pairmake_reply("Cisco-AVPair", NULL, T_OP_ADD);
if (!vp) {
* And calculate the MPPE session key.
*/
p = buffer;
- memcpy(p, ntpwdhashhash, 16); /* MPPEHASH */
+ memcpy(p, outhash, 16); /* MPPEHASH */
p += 16;
memcpy(p, packet->challenge, 8); /* APC */
p += 8;
/*
* These 16 bytes are the session key to use.
*/
- fr_md5_calc(ntpwdhash, buffer, 16 + 8 + 24 + 8 + 24);
+ fr_md5_calc(out, buffer, 16 + 8 + 24 + 8 + 24);
q = talloc_array(vp, char, 16 + sizeof("leap:session-key="));
strcpy(q, "leap:session-key=");
- memcpy(q + 17, ntpwdhash, 16);
+ memcpy(q + 17, out, 16);
i = 16;
rad_tunnel_pwencode(q + 17, &i,
#include "smbdes.h"
#include "mschap.h"
-/*
- * ntpwdhash converts Unicode password to 16-byte NT hash
- * with MD4
+/** Converts Unicode password to 16-byte NT hash with MD4
+ *
+ * @param[out] out Pointer to 16 byte output buffer.
+ * @param[in] password to encode.
+ * @return 0 on success else -1 on failure.
*/
-void mschap_ntpwdhash (uint8_t *szHash, char const *szPassword)
+int mschap_ntpwdhash(uint8_t *out, char const *password)
{
- char szUnicodePass[513];
- int nPasswordLen;
- int i;
+ ssize_t len;
+ uint8_t ucs2_password[512];
- /*
- * NT passwords are unicode. Convert plain text password
- * to unicode by inserting a zero every other byte
- */
- nPasswordLen = strlen(szPassword);
- for (i = 0; i < nPasswordLen; i++) {
- szUnicodePass[i << 1] = szPassword[i];
- szUnicodePass[(i << 1) + 1] = 0;
+ len = fr_utf8_to_ucs2(ucs2_password, sizeof(ucs2_password), password, strlen(password));
+ if (len < 0) {
+ *out = '\0';
+ return -1;
}
+ fr_md4_calc(out, (uint8_t *) ucs2_password, len);
- /* Encrypt Unicode password to a 16-byte MD4 hash */
- fr_md4_calc(szHash, (uint8_t *) szUnicodePass, (nPasswordLen<<1) );
+ return 0;
}
-
/*
* challenge_hash() is used by mschap2() and auth_response()
* implements RFC2759 ChallengeHash()
RCSIDH(mschap_h, "$Id$")
-void mschap_ntpwdhash (uint8_t *szHash, char const *szPassword);
+int mschap_ntpwdhash(uint8_t *out, char const *password);
void mschap_challenge_hash(uint8_t const *peer_challenge,
uint8_t const *auth_challenge,
char const *user_name, uint8_t *challenge );
return 0;
}
- mschap_ntpwdhash(buffer,buf2);
+ if (mschap_ntpwdhash(buffer, buf2) < 0) {
+ RERROR("Failed generating NT-Password");
+ *buffer = '\0';
+ return 0;
+ }
fr_bin2hex(out, buffer, 16);
out[32] = '\0';
} else {
nt_password->length = 16;
nt_password->vp_octets = p = talloc_array(nt_password, uint8_t, nt_password->length);
- mschap_ntpwdhash(p, password->vp_strvalue);
+
+ if (mschap_ntpwdhash(p, password->vp_strvalue) < 0) {
+ RERROR("Failed generating NT-Password");
+ return RLM_MODULE_FAIL;
+ }
}
}
dst[(i*2)] = 0;
}
-static void ntpwdhash (uint8_t *szHash, char const *szPassword)
+static void ntpwdhash(uint8_t *out, char const *password)
{
- char szUnicodePass[513];
- char nPasswordLen;
- int i;
+ ssize_t len;
+ uint8_t ucs2_password[512];
- /*
- * NT passwords are unicode. Convert plain text password
- * to unicode by inserting a zero every other byte
- */
- nPasswordLen = strlen(szPassword);
- for (i = 0; i < nPasswordLen; i++) {
- szUnicodePass[i << 1] = szPassword[i];
- szUnicodePass[(i << 1) + 1] = 0;
+ len = fr_utf8_to_ucs2(ucs2_password, sizeof(ucs2_password), password, strlen(password));
+ if (len < 0) {
+ *out = '\0';
+ return;
}
-
- /* Encrypt Unicode password to a 16-byte MD4 hash */
- fr_md4_calc(szHash, (uint8_t *) szUnicodePass, (nPasswordLen<<1) );
+ fr_md4_calc(out, (uint8_t *) ucs2_password, len);
}
-
-
int main (int argc, char *argv[])
{
int i, l;