25 RCSID(
"$Id: dfbb50bbb97289a16bf43d165357505cf370beba $")
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/server/module_rlm.h>
30 #include <freeradius-devel/util/base16.h>
31 #include <freeradius-devel/util/md5.h>
97 if (!
inst->auth_type) {
98 WARN(
"No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup Digest authentication",
116 size_t a1_len, a2_len, kd_len;
131 if (passwd->vp_length != 32) {
132 REDEBUG(
"Digest-Attributes.HA1 has invalid length, authentication failed");
139 REDEBUG(
"Password.Cleartext or Digest-Attributes.HA1 is required for authentication");
145 REDEBUG(
"Digest-Attributes is required for authentication");
148 list = &
vp->vp_group;
155 REDEBUG(
"No Digest-Attributes.Nonce: Cannot perform Digest authentication");
164 REDEBUG(
"No Digest-Attributes.User-Name: Cannot perform Digest authentication");
167 memcpy(&a1[0],
vp->vp_octets,
vp->vp_length);
168 a1_len =
vp->vp_length;
175 REDEBUG(
"No Digest-Attributes.Attributes.Realm: Cannot perform Digest authentication");
178 memcpy(&a1[a1_len],
vp->vp_octets,
vp->vp_length);
179 a1_len +=
vp->vp_length;
185 memcpy(&a1[a1_len], passwd->vp_octets, passwd->vp_length);
186 a1_len += passwd->vp_length;
191 RDEBUG2(
"A1 = %s (using Digest-Attributes.HA1)", a1);
201 (
strcasecmp(algo->vp_strvalue,
"MD5") == 0)) {
207 &
FR_SBUFF_IN(passwd->vp_strvalue, passwd->vp_length),
false) != 16) {
208 RDEBUG2(
"Invalid text in Digest-Attributes.HA1");
213 }
else if (
strcasecmp(algo->vp_strvalue,
"MD5-sess") == 0) {
224 memcpy(&a1[0], passwd->vp_strvalue, 32);
234 if ((nonce->vp_length & 1) != 0) {
235 REDEBUG(
"Received Digest-Attributes.Nonce hex string with invalid length: Cannot perform Digest authentication");
238 memcpy(&a1[a1_len], nonce->vp_octets, nonce->vp_length);
239 a1_len += nonce->vp_length;
246 REDEBUG(
"No Digest-Attributes.CNonce: Cannot perform Digest authentication");
253 if ((
vp->vp_length & 1) != 0) {
254 REDEBUG(
"Received Digest-Attributes.CNonce hex string with invalid length: Cannot perform Digest authentication");
257 memcpy(&a1[a1_len],
vp->vp_octets,
vp->vp_length);
258 a1_len +=
vp->vp_length;
260 }
else if (
strcasecmp(algo->vp_strvalue,
"MD5") != 0) {
265 REDEBUG(
"%pP - Unknown Digest-Attributes.Algorithm: Cannot perform Digest authentication",
vp);
274 REDEBUG(
"No Digest-Attributes.Method: Cannot perform Digest authentication");
277 memcpy(&a2[0],
vp->vp_octets,
vp->vp_length);
278 a2_len =
vp->vp_length;
285 REDEBUG(
"No Digest-Attributes.URI: Cannot perform Digest authentication");
288 memcpy(&a2[a2_len],
vp->vp_octets,
vp->vp_length);
289 a2_len +=
vp->vp_length;
296 if (
strcasecmp(qop->vp_strvalue,
"auth-int") == 0) {
310 REDEBUG(
"No Digest-Attributes.Body-Digest: Cannot perform Digest authentication");
314 if ((a2_len + body->vp_length) >
sizeof(a2)) {
315 REDEBUG(
"Digest-Attributes.Body-Digest is too long");
319 memcpy(a2 + a2_len, body->vp_octets, body->vp_length);
320 a2_len += body->vp_length;
322 }
else if (
strcasecmp(qop->vp_strvalue,
"auth") != 0) {
323 REDEBUG(
"%pP - Unknown value: Cannot perform Digest authentication", qop);
336 if (((algo != NULL) && (
strcasecmp(algo->vp_strvalue,
"MD5-Sess") == 0)) ||
341 memcpy(&
hash[0], &a1[0], a1_len);
352 memcpy(&kd[kd_len], nonce->vp_octets, nonce->vp_length);
353 kd_len += nonce->vp_length;
373 REDEBUG(
"No Digest-Attributes.Nonce-Count: Cannot perform Digest authentication");
376 memcpy(&kd[kd_len],
vp->vp_octets,
vp->vp_length);
377 kd_len +=
vp->vp_length;
384 REDEBUG(
"No Digest-Attributes.CNonce: Cannot perform Digest authentication");
387 memcpy(&kd[kd_len],
vp->vp_octets,
vp->vp_length);
388 kd_len +=
vp->vp_length;
393 memcpy(&kd[kd_len], qop->vp_octets, qop->vp_length);
394 kd_len += qop->vp_length;
419 memcpy(&kd[0], &
hash[0], 16);
427 REDEBUG(
"No Digest-Response attribute in the request. Cannot perform digest authentication");
433 RDEBUG2(
"Invalid text in Digest-Response");
444 REDEBUG(
"FAILED authentication");
458 if (!
inst->auth_type) {
459 WARN(
"Failed to find 'authenticate %s {...}' section. Digest authentication will likely not work",
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define fr_base16_encode(_out, _in)
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
Value of an enumerated attribute.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define RHEXDUMP_INLINE3(_data, _len, _fmt,...)
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Perform a single digest operation on a single input buffer.
int strcasecmp(char *s1, char *s2)
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
module_t common
Common fields presented by all modules.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
#define RETURN_MODULE_REJECT
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_INVALID
rlm_rcode_t
Return codes indicating the result of the module call.
static const fr_dict_attr_t * attr_digest_user_name
static const fr_dict_attr_t * attr_digest_body_digest
static const fr_dict_attr_t * attr_digest_ha1
static const fr_dict_attr_t * attr_digest_method
static const fr_dict_attr_t * attr_digest_qop
static const fr_dict_attr_t * attr_cleartext_password
static const fr_dict_attr_t * attr_digest_attributes
static fr_dict_t const * dict_freeradius
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
static const fr_dict_attr_t * attr_digest_cnonce
static fr_dict_t const * dict_radius
static const fr_dict_attr_t * attr_digest_algorithm
static const fr_dict_attr_t * attr_digest_response
static const fr_dict_attr_t * attr_digest_uri
static const fr_dict_attr_t * attr_digest_realm
static const fr_dict_attr_t * attr_digest_nonce_count
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static const fr_dict_attr_t * attr_auth_type
fr_dict_attr_autoload_t rlm_digest_dict_attr[]
fr_dict_enum_value_t * auth_type
static const fr_dict_attr_t * attr_digest_nonce
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_dict_autoload_t rlm_digest_dict[]
static unsigned int hash(char const *username, unsigned int tablesize)
static int instantiate(module_inst_ctx_t const *mctx)
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
char const * name
Instance name e.g. user_database.
void * data
Module's instance data.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#define FR_MAX_STRING_LEN
#define fr_box_octets(_val, _len)