*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * Copyright 2002 The FreeRADIUS server project
+ * Copyright 2002,2006 The FreeRADIUS server project
* Copyright 2002 Alan DeKok <aland@ox.org>
*/
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-#include "rad_assert.h"
-
-static const char rcsid[] = "$Id$";
-
-static int digest_authorize(void *instance, REQUEST *request)
+static int digest_fix(REQUEST *request)
{
VALUE_PAIR *vp;
- /* quiet the compiler */
- instance = instance;
-
/*
* We need both of these attributes to do the authentication.
*/
- vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE);
+ vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE, 0);
if (vp == NULL) {
return RLM_MODULE_NOOP;
}
* Check the sanity of the attribute.
*/
if (vp->length != 32) {
- DEBUG("ERROR: Received invalid Digest-Response attribute (length %d should be 32)", vp->length);
- return RLM_MODULE_INVALID;
+ return RLM_MODULE_NOOP;
}
/*
* We need these, too.
*/
- vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES);
+ vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES, 0);
if (vp == NULL) {
- DEBUG("ERROR: Received Digest-Response without Digest-Attributes");
- return RLM_MODULE_INVALID;
+ return RLM_MODULE_NOOP;
+ }
+
+ /*
+ * Check for proper format of the Digest-Attributes
+ */
+ RDEBUG("Checking for correctly formatted Digest-Attributes");
+ while (vp) {
+ int length = vp->length;
+ int attrlen;
+ uint8_t *p = &vp->vp_octets[0];
+
+ /*
+ * Until this stupidly encoded attribute is exhausted.
+ */
+ while (length > 0) {
+ /*
+ * The attribute type must be valid
+ */
+ if ((p[0] == 0) || (p[0] > 10)) {
+ RDEBUG("Not formatted as Digest-Attributes");
+ return RLM_MODULE_NOOP;
+ }
+
+ attrlen = p[1]; /* stupid VSA format */
+
+ /*
+ * Too short.
+ */
+ if (attrlen < 3) {
+ RDEBUG("Not formatted as Digest-Attributes");
+ return RLM_MODULE_NOOP;
+ }
+
+ /*
+ * Too long.
+ */
+ if (attrlen > length) {
+ RDEBUG("Not formatted as Digest-Attributes");
+ return RLM_MODULE_NOOP;
+ }
+
+ length -= attrlen;
+ p += attrlen;
+ } /* loop over this one attribute */
+
+ /*
+ * Find the next one, if it exists.
+ */
+ vp = pairfind(vp->next, PW_DIGEST_ATTRIBUTES, 0);
}
/*
- * Loop through the Digest-Attributes, sanity checking them.
+ * Convert them to something sane.
*/
- DEBUG(" rlm_digest: Converting Digest-Attributes to something sane...");
+ RDEBUG("Digest-Attributes look OK. Converting them to something more usful.");
+ vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES, 0);
while (vp) {
int length = vp->length;
int attrlen;
- uint8_t *p = &vp->vp_strvalue[0];
+ uint8_t *p = &vp->vp_octets[0];
VALUE_PAIR *sub;
/*
- * Until this stupidly encoded attribure is exhausted.
+ * Until this stupidly encoded attribute is exhausted.
*/
while (length > 0) {
/*
* The attribute type must be valid
*/
if ((p[0] == 0) || (p[0] > 10)) {
- DEBUG("ERROR: Received Digest-Attributes with invalid sub-attribute %d", p[0]);
+ RDEBUG("ERROR: Received Digest-Attributes with invalid sub-attribute %d", p[0]);
return RLM_MODULE_INVALID;
}
* Too short.
*/
if (attrlen < 3) {
- DEBUG("ERROR: Received Digest-Attributes with short sub-attribute %d, of length %d", p[0], attrlen);
+ RDEBUG("ERROR: Received Digest-Attributes with short sub-attribute %d, of length %d", p[0], attrlen);
return RLM_MODULE_INVALID;
}
* Too long.
*/
if (attrlen > length) {
- DEBUG("ERROR: Received Digest-Attributes with long sub-attribute %d, of length %d", p[0], attrlen);
+ RDEBUG("ERROR: Received Digest-Attributes with long sub-attribute %d, of length %d", p[0], attrlen);
return RLM_MODULE_INVALID;
}
*
* Didn't they know that VSA's exist?
*/
- sub = paircreate(PW_DIGEST_REALM - 1 + p[0],
- PW_TYPE_STRING);
- if (!sub) {
- return RLM_MODULE_FAIL; /* out of memory */
- }
- memcpy(&sub->vp_strvalue[0], &p[2], attrlen - 2);
- sub->vp_strvalue[attrlen - 2] = '\0';
+ sub = radius_paircreate(request, &request->packet->vps,
+ PW_DIGEST_REALM - 1 + p[0], 0,
+ PW_TYPE_STRING);
+ memcpy(&sub->vp_octets[0], &p[2], attrlen - 2);
+ sub->vp_octets[attrlen - 2] = '\0';
sub->length = attrlen - 2;
- if (debug_flag) {
- putchar('\t');
- vp_print(stdout, sub);
- putchar('\n');
+ if ((debug_flag > 1) && fr_log_fp) {
+ fputc('\t', fr_log_fp);
+ vp_print(fr_log_fp, sub);
+ fputc('\n', fr_log_fp);
}
/*
- * And add it to the request pairs.
- */
- pairadd(&request->packet->vps, sub);
-
- /*
* FIXME: Check for the existence
* of the necessary attributes!
*/
/*
* Find the next one, if it exists.
*/
- vp = pairfind(vp->next, PW_DIGEST_ATTRIBUTES);
+ vp = pairfind(vp->next, PW_DIGEST_ATTRIBUTES, 0);
}
+ return RLM_MODULE_OK;
+}
+
+static int digest_authorize(void *instance, REQUEST *request)
+{
+ int rcode;
+
+ /* quiet the compiler */
+ instance = instance;
+
+ /*
+ * Double-check and fix the attributes.
+ */
+ rcode = digest_fix(request);
+ if (rcode != RLM_MODULE_OK) return rcode;
+
/*
* Everything's OK, add a digest authentication type.
*/
- if (pairfind(request->config_items, PW_AUTHTYPE) == NULL) {
- DEBUG("rlm_digest: Adding Auth-Type = DIGEST");
+ if (pairfind(request->config_items, PW_AUTHTYPE, 0) == NULL) {
+ RDEBUG("Adding Auth-Type = DIGEST");
pairadd(&request->config_items,
pairmake("Auth-Type", "DIGEST", T_OP_EQ));
}
}
/*
- * Convert a string in hex to one in binary
- */
-static void hex2bin(uint8_t *out, const uint8_t *in)
-{
- unsigned int tmp;
-
- while (*in) {
- sscanf(in, "%02x", &tmp);
- *out = tmp;
- out++;
- in += 2;
- }
-}
-
-/*
* Perform all of the wondrous variants of digest authentication.
*/
static int digest_authenticate(void *instance, REQUEST *request)
{
int i;
- int a1_len, a2_len, kd_len;
+ size_t a1_len, a2_len, kd_len;
uint8_t a1[(MAX_STRING_LEN + 1) * 5]; /* can be 5 attributes */
uint8_t a2[(MAX_STRING_LEN + 1) * 3]; /* can be 3 attributes */
uint8_t kd[(MAX_STRING_LEN + 1) * 5];
uint8_t hash[16]; /* MD5 output */
- VALUE_PAIR *vp;
+ VALUE_PAIR *vp, *passwd, *algo;
VALUE_PAIR *qop, *nonce;
instance = instance; /* -Wunused */
/*
- * We require access to the plain-text password.
+ * We require access to the plain-text password, or to the
+ * Digest-HA1 parameter.
*/
- vp = pairfind(request->config_items, PW_PASSWORD);
- if (!vp) {
- radlog(L_AUTH, "rlm_digest: Configuration item \"User-Password\" is required for authentication.");
+ passwd = pairfind(request->config_items, PW_DIGEST_HA1, 0);
+ if (passwd) {
+ if (passwd->length != 32) {
+ radlog_request(L_AUTH, 0, request, "Digest-HA1 has invalid length, authentication failed.");
+ return RLM_MODULE_INVALID;
+ }
+ } else {
+ passwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0);
+ }
+ if (!passwd) {
+ radlog_request(L_AUTH, 0, request, "Cleartext-Password or Digest-HA1 is required for authentication.");
return RLM_MODULE_INVALID;
}
/*
+ * We need these, too.
+ */
+ vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES, 0);
+ if (vp == NULL) {
+ error:
+ RDEBUG("ERROR: You set 'Auth-Type = Digest' for a request that did not contain any digest attributes!w");
+ return RLM_MODULE_INVALID;
+ }
+
+ /*
+ * Look for the "internal" FreeRADIUS Digest attributes.
+ * If they don't exist, it means that someone forced
+ * Auth-Type = digest, without putting "digest" into the
+ * "authorize" section. In that case, try to decode the
+ * attributes here.
+ */
+ if (!pairfind(request->packet->vps, PW_DIGEST_NONCE, 0)) {
+ int rcode;
+
+ rcode = digest_fix(request);
+
+ /*
+ * NOOP means "couldn't find the attributes".
+ * That's bad.
+ */
+ if (rcode == RLM_MODULE_NOOP) goto error;
+
+ if (rcode != RLM_MODULE_OK) return rcode;
+ }
+
+ /*
* We require access to the Digest-Nonce-Value
*/
- nonce = pairfind(request->packet->vps, PW_DIGEST_NONCE);
+ nonce = pairfind(request->packet->vps, PW_DIGEST_NONCE, 0);
if (!nonce) {
- DEBUG("ERROR: No Digest-Nonce: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-Nonce: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
/*
* A1 = Digest-User-Name ":" Realm ":" Password
*/
- vp = pairfind(request->packet->vps, PW_DIGEST_USER_NAME);
+ vp = pairfind(request->packet->vps, PW_DIGEST_USER_NAME, 0);
if (!vp) {
- DEBUG("ERROR: No Digest-User-Name: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-User-Name: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a1[0], &vp->vp_strvalue[0], vp->length);
+ memcpy(&a1[0], &vp->vp_octets[0], vp->length);
a1_len = vp->length;
a1[a1_len] = ':';
a1_len++;
- vp = pairfind(request->packet->vps, PW_DIGEST_REALM);
+ vp = pairfind(request->packet->vps, PW_DIGEST_REALM, 0);
if (!vp) {
- DEBUG("ERROR: No Digest-Realm: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-Realm: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a1[a1_len], &vp->vp_strvalue[0], vp->length);
+ memcpy(&a1[a1_len], &vp->vp_octets[0], vp->length);
a1_len += vp->length;
a1[a1_len] = ':';
a1_len++;
- vp = pairfind(request->config_items, PW_PASSWORD);
- if (!vp) {
- DEBUG("ERROR: No User-Password: Cannot perform Digest authentication");
- return RLM_MODULE_INVALID;
+ if (passwd->attribute == PW_CLEARTEXT_PASSWORD) {
+ memcpy(&a1[a1_len], &passwd->vp_octets[0], passwd->length);
+ a1_len += passwd->length;
+ a1[a1_len] = '\0';
+ RDEBUG2("A1 = %s", a1);
+ } else {
+ a1[a1_len] = '\0';
+ RDEBUG2("A1 = %s (using Digest-HA1)", a1);
+ a1_len = 16;
}
- memcpy(&a1[a1_len], &vp->vp_strvalue[0], vp->length);
- a1_len += vp->length;
-
- a1[a1_len] = '\0';
- DEBUG2("A1 = %s", a1);
/*
* See which variant we calculate.
+ * Assume MD5 if no Digest-Algorithm attribute received
*/
- vp = pairfind(request->packet->vps, PW_DIGEST_ALGORITHM);
- if ((vp != NULL) &&
- (strcasecmp(vp->vp_strvalue, "MD5-sess") == 0)) {
- librad_md5_calc(hash, &a1[0], a1_len);
- memcpy(&a1[0], hash, 16);
- a1_len = 16;
+ algo = pairfind(request->packet->vps, PW_DIGEST_ALGORITHM, 0);
+ if ((algo == NULL) ||
+ (strcasecmp(algo->vp_strvalue, "MD5") == 0)) {
+ /*
+ * Set A1 to Digest-HA1 if no User-Password found
+ */
+ if (passwd->attribute == PW_DIGEST_HA1) {
+ if (fr_hex2bin(passwd->vp_strvalue, &a1[0], 16) != 16) {
+ RDEBUG2("Invalid text in Digest-HA1");
+ return RLM_MODULE_INVALID;
+ }
+ }
+
+ } else if (strcasecmp(algo->vp_strvalue, "MD5-sess") == 0) {
+ /*
+ * K1 = H(A1) : Digest-Nonce ... : H(A2)
+ *
+ * If we find Digest-HA1, we assume it contains
+ * H(A1).
+ */
+ if (passwd->attribute == PW_CLEARTEXT_PASSWORD) {
+ fr_md5_calc(hash, &a1[0], a1_len);
+ fr_bin2hex(hash, (char *) &a1[0], 16);
+ } else { /* MUST be Digest-HA1 */
+ memcpy(&a1[0], passwd->vp_strvalue, 32);
+ }
+ a1_len = 32;
a1[a1_len] = ':';
a1_len++;
/*
- * Tack on the Digest-Nonce
+ * Tack on the Digest-Nonce. Length must be even
*/
- hex2bin(&a1[a1_len], &nonce->vp_strvalue[0]);
- a1_len += (nonce->length >> 1); /* FIXME: CHECK LENGTH */
+ if ((nonce->length & 1) != 0) {
+ RDEBUG("ERROR: Received Digest-Nonce hex string with invalid length: Cannot perform Digest authentication");
+ return RLM_MODULE_INVALID;
+ }
+ memcpy(&a1[a1_len], &nonce->vp_octets[0], nonce->length);
+ a1_len += nonce->length;
a1[a1_len] = ':';
a1_len++;
- vp = pairfind(request->packet->vps, PW_DIGEST_CNONCE);
+ vp = pairfind(request->packet->vps, PW_DIGEST_CNONCE, 0);
if (!vp) {
- DEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
- return RLM_MODULE_INVALID;
+ RDEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
+ return RLM_MODULE_INVALID;
}
- hex2bin(&a1[a1_len], &vp->vp_strvalue[0]);
- a1_len += (vp->length >> 1); /* FIXME: CHECK LENGTH */
+ /*
+ * Digest-CNonce length must be even
+ */
+ if ((vp->length & 1) != 0) {
+ RDEBUG("ERROR: Received Digest-CNonce hex string with invalid length: Cannot perform Digest authentication");
+ return RLM_MODULE_INVALID;
+ }
+ memcpy(&a1[a1_len], &vp->vp_octets[0], vp->length);
+ a1_len += vp->length;
- } else if ((vp != NULL) &&
- (strcasecmp(vp->vp_strvalue, "MD5") != 0)) {
+ } else if ((algo != NULL) &&
+ (strcasecmp(algo->vp_strvalue, "MD5") != 0)) {
/*
* We check for "MD5-sess" and "MD5".
* Anything else is an error.
*/
- DEBUG("ERROR: Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", vp->vp_strvalue);
+ RDEBUG("ERROR: Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", vp->vp_strvalue);
return RLM_MODULE_INVALID;
}
/*
* A2 = Digest-Method ":" Digest-URI
*/
- vp = pairfind(request->packet->vps, PW_DIGEST_METHOD);
+ vp = pairfind(request->packet->vps, PW_DIGEST_METHOD, 0);
if (!vp) {
- DEBUG("ERROR: No Digest-Method: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-Method: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a2[0], &vp->vp_strvalue[0], vp->length);
+ memcpy(&a2[0], &vp->vp_octets[0], vp->length);
a2_len = vp->length;
a2[a2_len] = ':';
a2_len++;
- vp = pairfind(request->packet->vps, PW_DIGEST_URI);
+ vp = pairfind(request->packet->vps, PW_DIGEST_URI, 0);
if (!vp) {
- DEBUG("ERROR: No Digest-URI: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-URI: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a2[a2_len], &vp->vp_strvalue[0], vp->length);
+ memcpy(&a2[a2_len], &vp->vp_octets[0], vp->length);
a2_len += vp->length;
/*
* QOP is "auth-int", tack on ": Digest-Body-Digest"
*/
- qop = pairfind(request->packet->vps, PW_DIGEST_QOP);
+ qop = pairfind(request->packet->vps, PW_DIGEST_QOP, 0);
if ((qop != NULL) &&
(strcasecmp(qop->vp_strvalue, "auth-int") == 0)) {
VALUE_PAIR *body;
/*
* Must be a hex representation of an MD5 digest.
*/
- body = pairfind(request->packet->vps, PW_DIGEST_BODY_DIGEST);
+ body = pairfind(request->packet->vps, PW_DIGEST_BODY_DIGEST, 0);
if (!body) {
- DEBUG("ERROR: No Digest-Body-Digest: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-Body-Digest: Cannot perform Digest authentication");
+ return RLM_MODULE_INVALID;
+ }
+
+ if ((a2_len + body->length) > sizeof(a2)) {
+ RDEBUG("ERROR: Digest-Body-Digest is too long");
return RLM_MODULE_INVALID;
}
- rad_assert(body->length == 32); /* FIXME: check in 'auth' */
- hex2bin(&a2[a2_len], &body->vp_strvalue[0]);
- a2_len += (body->length >> 1);
+ memcpy(a2 + a2_len, body->vp_octets, body->length);
+ a2_len += body->length;
} else if ((qop != NULL) &&
(strcasecmp(qop->vp_strvalue, "auth") != 0)) {
- DEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->vp_strvalue);
+ RDEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->vp_strvalue);
return RLM_MODULE_INVALID;
}
a2[a2_len] = '\0';
- DEBUG2("A2 = %s", a2);
+ RDEBUG2("A2 = %s", a2);
/*
- * KD = H(A1) : Digest-Nonce ... : H(A2)
+ * KD = H(A1) : Digest-Nonce ... : H(A2).
+ * Compute MD5 if Digest-Algorithm == "MD5-Sess",
+ * or if we found a User-Password.
*/
- librad_md5_calc(&hash[0], &a1[0], a1_len);
-
- for (i = 0; i < 16; i++) {
- sprintf(&kd[i * 2], "%02x", hash[i]);
+ if (((algo != NULL) &&
+ (strcasecmp(algo->vp_strvalue, "MD5-Sess") == 0)) ||
+ (passwd->attribute == PW_CLEARTEXT_PASSWORD)) {
+ a1[a1_len] = '\0';
+ fr_md5_calc(&hash[0], &a1[0], a1_len);
+ } else {
+ memcpy(&hash[0], &a1[0], a1_len);
}
+ fr_bin2hex(hash, (char *) kd, sizeof(hash));
-#ifndef NDEBUG
- if (debug_flag) {
- printf("H(A1) = ");
+#ifndef NRDEBUG
+ if (debug_flag > 1) {
+ fr_printf_log("H(A1) = ");
for (i = 0; i < 16; i++) {
- printf("%02x", hash[i]);
+ fr_printf_log("%02x", hash[i]);
}
- printf("\n");
+ fr_printf_log("\n");
}
#endif
kd_len = 32;
kd[kd_len] = ':';
kd_len++;
- memcpy(&kd[kd_len], nonce->vp_strvalue, nonce->length);
+ memcpy(&kd[kd_len], nonce->vp_octets, nonce->length);
kd_len += nonce->length;
/*
kd[kd_len] = ':';
kd_len++;
- vp = pairfind(request->packet->vps, PW_DIGEST_NONCE_COUNT);
+ vp = pairfind(request->packet->vps, PW_DIGEST_NONCE_COUNT, 0);
if (!vp) {
- DEBUG("ERROR: No Digest-Nonce-Count: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-Nonce-Count: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&kd[kd_len], &vp->vp_strvalue[0], vp->length);
+ memcpy(&kd[kd_len], &vp->vp_octets[0], vp->length);
kd_len += vp->length;
kd[kd_len] = ':';
kd_len++;
- vp = pairfind(request->packet->vps, PW_DIGEST_CNONCE);
+ vp = pairfind(request->packet->vps, PW_DIGEST_CNONCE, 0);
if (!vp) {
- DEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
+ RDEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&kd[kd_len], &vp->vp_strvalue[0], vp->length);
+ memcpy(&kd[kd_len], &vp->vp_octets[0], vp->length);
kd_len += vp->length;
kd[kd_len] = ':';
kd_len++;
- memcpy(&kd[kd_len], &qop->vp_strvalue[0], qop->length);
+ memcpy(&kd[kd_len], &qop->vp_octets[0], qop->length);
kd_len += qop->length;
}
kd[kd_len] = ':';
kd_len++;
- librad_md5_calc(&hash[0], &a2[0], a2_len);
+ fr_md5_calc(&hash[0], &a2[0], a2_len);
- for (i = 0; i < 16; i++) {
- sprintf(&kd[kd_len + (i * 2)], "%02x", hash[i]);
- }
+ fr_bin2hex(hash, (char *) kd + kd_len, sizeof(hash));
-#ifndef NDEBUG
- if (debug_flag) {
- printf("H(A2) = ");
+#ifndef NRDEBUG
+ if (debug_flag > 1) {
+ fr_printf_log("H(A2) = ");
for (i = 0; i < 16; i++) {
- printf("%02x", hash[i]);
+ fr_printf_log("%02x", hash[i]);
}
- printf("\n");
+ fr_printf_log("\n");
}
#endif
kd_len += 32;
kd[kd_len] = 0;
- DEBUG2("KD = %s\n", &kd[0]);
+ RDEBUG2("KD = %s\n", &kd[0]);
/*
* Take the hash of KD.
*/
- librad_md5_calc(&hash[0], &kd[0], kd_len);
+ fr_md5_calc(&hash[0], &kd[0], kd_len);
memcpy(&kd[0], &hash[0], 16);
/*
* Get the binary value of Digest-Response
*/
- vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE);
- rad_assert(vp != NULL);
+ vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE, 0);
+ if (!vp) {
+ RDEBUG("ERROR: No Digest-Response attribute in the request. Cannot perform digest authentication");
+ return RLM_MODULE_INVALID;
+ }
- hex2bin(&hash[0], &vp->vp_strvalue[0]);
+ if (fr_hex2bin(&vp->vp_strvalue[0], &hash[0], vp->length >> 1) != (vp->length >> 1)) {
+ RDEBUG2("Invalid text in Digest-Response");
+ return RLM_MODULE_INVALID;
+ }
-#ifndef NDEBUG
- if (debug_flag) {
- printf("EXPECTED ");
+#ifndef NRDEBUG
+ if (debug_flag > 1) {
+ fr_printf_log("EXPECTED ");
for (i = 0; i < 16; i++) {
- printf("%02x", kd[i]);
+ fr_printf_log("%02x", kd[i]);
}
- printf("\n");
+ fr_printf_log("\n");
- printf("RECEIVED ");
+ fr_printf_log("RECEIVED ");
for (i = 0; i < 16; i++) {
- printf("%02x", hash[i]);
+ fr_printf_log("%02x", hash[i]);
}
- printf("\n");
+ fr_printf_log("\n");
}
#endif
return RLM_MODULE_OK;
}
- DEBUG("rlm_digest: FAILED authentication");
+ RDEBUG("FAILED authentication");
return RLM_MODULE_REJECT;
}
module_t rlm_digest = {
RLM_MODULE_INIT,
"digest",
- 0, /* type */
+ RLM_TYPE_CHECK_CONFIG_SAFE, /* type */
NULL, /* instantiation */
NULL, /* detach */
{