*
* 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 "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
static int digest_authorize(void *instance, REQUEST *request)
{
/*
* We require access to the plain-text password.
*/
- passwd = pairfind(request->config_items, PW_PASSWORD);
- if (!passwd) passwd = pairfind(request->config_items, PW_DIGEST_HA1);
+ passwd = pairfind(request->config_items, PW_DIGEST_HA1);
+ if (passwd) {
+ if (passwd->length != 32) {
+ radlog(L_AUTH, "rlm_digest: Digest-HA1 has invalid length, authentication failed.");
+ return RLM_MODULE_INVALID;
+ }
+ } else {
+ passwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
+ }
if (!passwd) {
- radlog(L_AUTH, "rlm_digest: Configuration item \"User-Password\" or MD5-Password is required for authentication.");
+ radlog(L_AUTH, "rlm_digest: Cleartext-Password or Digest-HA1 is required for authentication.");
return RLM_MODULE_INVALID;
}
while (vp) {
int length = vp->length;
int attrlen;
- uint8_t *p = &vp->strvalue[0];
+ uint8_t *p = &vp->vp_octets[0];
VALUE_PAIR *sub;
/*
if (!sub) {
return RLM_MODULE_FAIL; /* out of memory */
}
- memcpy(&sub->strvalue[0], &p[2], attrlen - 2);
- sub->strvalue[attrlen - 2] = '\0';
+ memcpy(&sub->vp_octets[0], &p[2], attrlen - 2);
+ sub->vp_octets[attrlen - 2] = '\0';
sub->length = attrlen - 2;
if (debug_flag) {
DEBUG("ERROR: No Digest-User-Name: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a1[0], &vp->strvalue[0], vp->length);
+ memcpy(&a1[0], &vp->vp_octets[0], vp->length);
a1_len = vp->length;
a1[a1_len] = ':';
DEBUG("ERROR: No Digest-Realm: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a1[a1_len], &vp->strvalue[0], vp->length);
+ memcpy(&a1[a1_len], &vp->vp_octets[0], vp->length);
a1_len += vp->length;
a1[a1_len] = ':';
a1_len++;
- if (passwd->attribute == PW_USER_PASSWORD) {
- memcpy(&a1[a1_len], &passwd->strvalue[0], passwd->length);
+ if (passwd->attribute == PW_CLEARTEXT_PASSWORD) {
+ memcpy(&a1[a1_len], &passwd->vp_octets[0], passwd->length);
a1_len += passwd->length;
a1[a1_len] = '\0';
DEBUG2("A1 = %s", a1);
*/
algo = pairfind(request->packet->vps, PW_DIGEST_ALGORITHM);
if ((algo == NULL) ||
- (strcasecmp(algo->strvalue, "MD5") == 0)) {
+ (strcasecmp(algo->vp_strvalue, "MD5") == 0)) {
/*
* Set A1 to Digest-HA1 if no User-Password found
*/
- if (passwd->attribute != PW_USER_PASSWORD) {
- memcpy(&a1[0], passwd->strvalue, 16);
+ if (passwd->attribute == PW_DIGEST_HA1) {
+ if (lrad_hex2bin(passwd->vp_strvalue, &a1[0], 16) != 16) {
+ DEBUG2("rlm_digest: Invalid text in Digest-HA1");
+ return RLM_MODULE_INVALID;
+ }
}
- } else if (strcasecmp(algo->strvalue, "MD5-sess") == 0) {
+ } 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_USER_PASSWORD) {
+ if (passwd->attribute == PW_CLEARTEXT_PASSWORD) {
librad_md5_calc(hash, &a1[0], a1_len);
lrad_bin2hex(hash, &a1[0], 16);
- } else {
- lrad_bin2hex(passwd->strvalue, &a1[0], 16);
+ } else { /* MUST be Digest-HA1 */
+ memcpy(&a1[0], passwd->vp_strvalue, 32);
}
a1_len = 32;
DEBUG("ERROR: Received Digest-Nonce hex string with invalid length: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a1[a1_len], &nonce->strvalue[0], nonce->length);
+ memcpy(&a1[a1_len], &nonce->vp_octets[0], nonce->length);
a1_len += nonce->length;
a1[a1_len] = ':';
DEBUG("ERROR: Received Digest-CNonce hex string with invalid length: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a1[a1_len], &vp->strvalue[0], vp->length);
+ memcpy(&a1[a1_len], &vp->vp_octets[0], vp->length);
a1_len += vp->length;
} else if ((algo != NULL) &&
- (strcasecmp(algo->strvalue, "MD5") != 0)) {
+ (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->strvalue);
+ DEBUG("ERROR: Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", vp->vp_strvalue);
return RLM_MODULE_INVALID;
}
DEBUG("ERROR: No Digest-Method: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a2[0], &vp->strvalue[0], vp->length);
+ memcpy(&a2[0], &vp->vp_octets[0], vp->length);
a2_len = vp->length;
a2[a2_len] = ':';
DEBUG("ERROR: No Digest-URI: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&a2[a2_len], &vp->strvalue[0], vp->length);
+ memcpy(&a2[a2_len], &vp->vp_octets[0], vp->length);
a2_len += vp->length;
/*
*/
qop = pairfind(request->packet->vps, PW_DIGEST_QOP);
if ((qop != NULL) &&
- (strcasecmp(qop->strvalue, "auth-int") == 0)) {
+ (strcasecmp(qop->vp_strvalue, "auth-int") == 0)) {
VALUE_PAIR *body;
/*
return RLM_MODULE_INVALID;
}
- memcpy(a2 + a2_len, body->strvalue, body->length);
+ memcpy(a2 + a2_len, body->vp_octets, body->length);
a2_len += body->length;
} else if ((qop != NULL) &&
- (strcasecmp(qop->strvalue, "auth") != 0)) {
- DEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->strvalue);
+ (strcasecmp(qop->vp_strvalue, "auth") != 0)) {
+ DEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->vp_strvalue);
return RLM_MODULE_INVALID;
}
* or if we found a User-Password.
*/
if (((algo != NULL) &&
- (strcasecmp(algo->strvalue, "MD5-Sess") == 0)) ||
- (passwd->attribute == PW_USER_PASSWORD)) {
- a1[a1_len] = '\0';
+ (strcasecmp(algo->vp_strvalue, "MD5-Sess") == 0)) ||
+ (passwd->attribute == PW_CLEARTEXT_PASSWORD)) {
+ a1[a1_len] = '\0';
librad_md5_calc(&hash[0], &a1[0], a1_len);
} else {
memcpy(&hash[0], &a1[0], a1_len);
kd[kd_len] = ':';
kd_len++;
- memcpy(&kd[kd_len], nonce->strvalue, nonce->length);
+ memcpy(&kd[kd_len], nonce->vp_octets, nonce->length);
kd_len += nonce->length;
/*
DEBUG("ERROR: No Digest-Nonce-Count: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&kd[kd_len], &vp->strvalue[0], vp->length);
+ memcpy(&kd[kd_len], &vp->vp_octets[0], vp->length);
kd_len += vp->length;
kd[kd_len] = ':';
DEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
return RLM_MODULE_INVALID;
}
- memcpy(&kd[kd_len], &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->strvalue[0], qop->length);
+ memcpy(&kd[kd_len], &qop->vp_octets[0], qop->length);
kd_len += qop->length;
}
return RLM_MODULE_INVALID;
}
- lrad_hex2bin(&vp->strvalue[0], &hash[0], vp->length >> 1);
+ if (lrad_hex2bin(&vp->vp_octets[0], &hash[0], vp->length >> 1) != (vp->length >> 1)) {
+ DEBUG2("rlm_digest: Invalid text in Digest-Response");
+ return RLM_MODULE_INVALID;
+ }
#ifndef NDEBUG
if (debug_flag) {
* is single-threaded.
*/
module_t rlm_digest = {
- "DIGEST",
+ RLM_MODULE_INIT,
+ "digest",
0, /* type */
- NULL, /* initialization */
NULL, /* instantiation */
+ NULL, /* detach */
{
digest_authenticate, /* authentication */
digest_authorize, /* authorization */
NULL, /* post-proxy */
NULL /* post-auth */
},
- NULL, /* detach */
- NULL, /* destroy */
};