25RCSID(
"$Id: 2fa2a57479e11bdac0fdd7106e7a1d10f7c89407 $")
 
   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.
#define DICT_AUTOLOAD_TERMINATOR
fr_dict_enum_value_t const * 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_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.
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.
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_REJECT
#define RETURN_UNLANG_NOOP
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 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 unlang_action_t mod_authorize(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
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
fr_dict_enum_value_t const  * auth_type
static const fr_dict_attr_t * attr_auth_type
fr_dict_attr_autoload_t rlm_digest_dict_attr[]
static const fr_dict_attr_t * attr_digest_nonce
static unlang_action_t mod_authenticate(unlang_result_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
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)
#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.
size_t inst_size
Size of the module's instance data.
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)