26RCSID(
"$Id: a5883672a7884147069189082cfbe63afc0a4348 $")
29#include <freeradius-devel/server/base.h>
30#include <freeradius-devel/server/module_rlm.h>
31#include <freeradius-devel/tls/base.h>
32#include <freeradius-devel/tls/log.h>
34#include <freeradius-devel/util/base64.h>
35#include <freeradius-devel/util/base16.h>
36#include <freeradius-devel/util/md5.h>
37#include <freeradius-devel/util/sha1.h>
40#include <freeradius-devel/protocol/freeradius/freeradius.internal.password.h>
47#ifdef HAVE_OPENSSL_EVP_H
48# include <openssl/evp.h>
86 .inst_type =
"pap_call_env_t",
112#ifdef HAVE_OPENSSL_EVP_H
114 {
L(
"HMACSHA1"), FR_SSHA1 },
115 {
L(
"HMACSHA2+224"), FR_SSHA2_224 },
116 {
L(
"HMACSHA2+256"), FR_SSHA2_256 },
117 {
L(
"HMACSHA2+384"), FR_SSHA2_384 },
118 {
L(
"HMACSHA2+512"), FR_SSHA2_512 },
119 {
L(
"HMACSHA3+224"), FR_SSHA3_224 },
120 {
L(
"HMACSHA3+256"), FR_SSHA3_256 },
121 {
L(
"HMACSHA3+384"), FR_SSHA3_384 },
122 {
L(
"HMACSHA3+512"), FR_SSHA3_512 },
124static size_t pbkdf2_crypt_names_len =
NUM_ELEMENTS(pbkdf2_crypt_names);
127 {
L(
"sha1"), FR_SSHA1 },
128 {
L(
"sha256"), FR_SSHA2_256 },
129 {
L(
"sha512"), FR_SSHA2_512 }
131static size_t pbkdf2_passlib_names_len =
NUM_ELEMENTS(pbkdf2_passlib_names);
148 RDEBUG3(
"Auth-Type is already set. Not setting 'Auth-Type := %s'", mctx->
mi->
name);
157 if (!
inst->auth_type) {
158 WARN(
"No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup PAP authentication.",
176 if ((known_good->vp_length != password->vb_length) ||
177 (
fr_digest_cmp(known_good->vp_octets, password->vb_octets, known_good->vp_length) != 0)) {
178 REDEBUG(
"Cleartext password does not match \"known good\" password");
180 REDEBUG3(
"Password : %pV", password);
181 REDEBUG3(
"Expected : %pV", &known_good->data);
196 struct crypt_data crypt_data = { .initialized = 0 };
198 crypt_out = crypt_r(password->vb_strvalue, known_good->vp_strvalue, &crypt_data);
199 if (crypt_out) cmp = strcmp(known_good->vp_strvalue, crypt_out);
205 crypt_out = crypt(password->vb_strvalue, known_good->vp_strvalue);
212 if (crypt_out) cmp = strcmp(known_good->vp_strvalue, crypt_out);
219 if (!crypt_out || (cmp != 0)) {
220 REDEBUG(
"Crypt digest does not match \"known good\" digest");
235 REDEBUG(
"\"known-good\" MD5 password has incorrect length, expected 16 got %zu", known_good->vp_length);
239 fr_md5_calc(digest, password->vb_octets, password->vb_length);
241 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
242 REDEBUG(
"MD5 digest does not match \"known good\" digest");
244 REDEBUG3(
"Password : %pV", password);
262 REDEBUG(
"\"known-good\" Password.SMD5 has incorrect length, expected 16 got %zu", known_good->vp_length);
267 fr_md5_update(md5_ctx, password->vb_octets, password->vb_length);
276 REDEBUG(
"SMD5 digest does not match \"known good\" digest");
278 REDEBUG3(
"Password : %pV", password);
295 REDEBUG(
"\"known-good\" Password.SHA1 has incorrect length, expected 20 got %zu", known_good->vp_length);
300 fr_sha1_update(&sha1_context, password->vb_octets, password->vb_length);
303 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
304 REDEBUG(
"SHA1 digest does not match \"known good\" digest");
306 REDEBUG3(
"Password : %pV", password);
323 REDEBUG(
"\"known-good\" Password.SSHA has incorrect length, expected > 20 got %zu", known_good->vp_length);
328 fr_sha1_update(&sha1_context, password->vb_octets, password->vb_length);
334 REDEBUG(
"SSHA digest does not match \"known good\" digest");
336 REDEBUG3(
"Password : %pV", password);
347#ifdef HAVE_OPENSSL_EVP_H
351 char const *
name, EVP_MD
const *md)
354 uint8_t digest[EVP_MAX_MD_SIZE];
355 unsigned int digest_len;
357 ctx = EVP_MD_CTX_create();
360 EVP_DigestInit_ex(ctx, md, NULL);
361 EVP_DigestUpdate(ctx, password->vb_octets, password->vb_length);
362 EVP_DigestFinal_ex(ctx, digest, &digest_len);
363 EVP_MD_CTX_destroy(ctx);
367 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
368 REDEBUG(
"%s digest does not match \"known good\" digest",
name);
370 REDEBUG3(
"Password : %pV", password);
372 REDEBUG3(
"Expected : %pH", &known_good->data);
382 char const *
name, EVP_MD
const *md)
385 uint8_t digest[EVP_MAX_MD_SIZE];
386 unsigned int digest_len, min_len;
388 min_len = EVP_MD_size(md);
389 ctx = EVP_MD_CTX_create();
392 EVP_DigestInit_ex(ctx, md, NULL);
393 EVP_DigestUpdate(ctx, password->vb_octets, password->vb_length);
394 EVP_DigestUpdate(ctx, known_good->vp_octets + min_len, known_good->vp_length - min_len);
395 EVP_DigestFinal_ex(ctx, digest, &digest_len);
396 EVP_MD_CTX_destroy(ctx);
403 if (
fr_digest_cmp(digest, known_good->vp_octets, (
size_t)digest_len) != 0) {
404 REDEBUG(
"%s digest does not match \"known good\" digest",
name);
406 REDEBUG3(
"Password : %pV", password);
408 fr_box_octets(known_good->vp_octets + digest_len, known_good->vp_length - digest_len));
420#define PAP_AUTH_EVP_MD(_func, _new_func, _name, _md) \
421static unlang_action_t CC_HINT(nonnull) _new_func(unlang_result_t *p_result, \
422 rlm_pap_t const *inst, request_t *request, \
423 fr_pair_t const *known_good, fr_value_box_t const *password) \
425 return _func(p_result, inst, request, known_good, password, _name, _md); \
428PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_224,
"SHA2-224", EVP_sha224())
429PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_256, "SHA2-256", EVP_sha256())
430PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_384, "SHA2-384", EVP_sha384())
431PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_512, "SHA2-512", EVP_sha512())
432PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_224, "SSHA2-224", EVP_sha224())
433PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_256, "SSHA2-256", EVP_sha256())
434PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_384, "SSHA2-384", EVP_sha384())
435PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_512, "SSHA2-512", EVP_sha512())
437PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_224, "SHA3-224", EVP_sha3_224())
438PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_256, "SHA3-256", EVP_sha3_256())
439PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_384, "SHA3-384", EVP_sha3_384())
440PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_512, "SHA3-512", EVP_sha3_512())
441PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_224, "SSHA3-224", EVP_sha3_224())
442PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_256, "SSHA3-256", EVP_sha3_256())
443PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_384, "SSHA3-384", EVP_sha3_384())
444PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_512, "SSHA3-512", EVP_sha3_512())
463 int digest_type,
char iter_sep,
char salt_sep,
471 EVP_MD
const *evp_md;
479 uint8_t digest[EVP_MAX_MD_SIZE];
487 switch (digest_type) {
494 evp_md = EVP_sha224();
495 digest_len = SHA224_DIGEST_LENGTH;
499 evp_md = EVP_sha256();
500 digest_len = SHA256_DIGEST_LENGTH;
504 evp_md = EVP_sha384();
505 digest_len = SHA384_DIGEST_LENGTH;
509 evp_md = EVP_sha512();
510 digest_len = SHA512_DIGEST_LENGTH;
514 evp_md = EVP_sha3_224();
515 digest_len = SHA224_DIGEST_LENGTH;
519 evp_md = EVP_sha3_256();
520 digest_len = SHA256_DIGEST_LENGTH;
524 evp_md = EVP_sha3_384();
525 digest_len = SHA384_DIGEST_LENGTH;
529 evp_md = EVP_sha3_512();
530 digest_len = SHA512_DIGEST_LENGTH;
534 REDEBUG(
"Unknown PBKDF2 digest type \"%d\"", digest_type);
538 if (((end - p) < 1) || !(q = memchr(p, iter_sep, end - p))) {
539 REDEBUG(
"Password.PBKDF2 missing iterations component");
544 REDEBUG(
"Password.PBKDF2 iterations component too short");
551 if (!iter_is_base64) {
552 unsigned long iterations_long;
554 char iterations_buff[
sizeof(
"4294967295")];
559 if ((
size_t) (q - p) >=
sizeof(iterations_buff)) {
561 "Password.PBKDF2 iterations field is too large");
565 strlcpy(iterations_buff, (
char const *)p, (q - p) + 1);
567 iterations_long = strtoul(iterations_buff, &qq, 10);
569 REMARKER(iterations_buff, qq - iterations_buff,
570 "Password.PBKDF2 iterations field contains an invalid character");
573 if (iterations_long > UINT32_MAX) {
574 REMARKER(iterations_buff, qq - iterations_buff,
575 "Password.PBKDF2 iterations field contains too large iteration count");
578 iterations = iterations_long;
587 &
FR_SBUFF_IN((
char const *)p, (
char const *)q),
false,
false);
589 RPEDEBUG(
"Failed decoding Password.PBKDF2 iterations component (%.*s)", (
int)(q - p), p);
592 if (slen !=
sizeof(iterations)) {
593 REDEBUG(
"Decoded Password.PBKDF2 iterations component is wrong size");
597 iterations = ntohl(iterations);
605 if (iterations == 0) iterations = 1;
607 if (((end - p) < 1) || !(q = memchr(p, salt_sep, end - p))) {
608 REDEBUG(
"Password.PBKDF2 missing salt component");
613 REDEBUG(
"Password.PBKDF2 salt component too short");
619 &
FR_SBUFF_IN((
char const *) p, (
char const *)q),
false,
false);
621 RPEDEBUG(
"Failed decoding Password.PBKDF2 salt component");
628 if ((end - p) == 0) {
629 REDEBUG(
"Password.PBKDF2 hash component too short");
634 &
FR_SBUFF_IN((
char const *)p, (
char const *)end),
false,
false);
636 RPEDEBUG(
"Failed decoding Password.PBKDF2 hash component");
640 if ((
size_t)slen != digest_len) {
641 REDEBUG(
"Password.PBKDF2 hash component length is incorrect for hash type, expected %zu, got %zd",
649 RDEBUG2(
"PBKDF2 %s: Iterations %u, salt length %zu, hash length %zd",
651 iterations, salt_len, slen);
656 if ((password->vb_length > INT_MAX) || (salt_len > INT_MAX) ||
657 (iterations > INT_MAX) || (digest_len > INT_MAX)) {
664 if (PKCS5_PBKDF2_HMAC((
char const *)password->vb_octets, (
int)password->vb_length,
665 (
unsigned char const *)salt, (
int)salt_len,
668 (
int)digest_len, (
unsigned char *)digest) == 0) {
669 fr_tls_log(request,
"PBKDF2 digest failure");
674 REDEBUG(
"PBKDF2 digest does not match \"known good\" digest");
710 char scheme_sep,
char iter_sep,
char salt_sep,
718 RDEBUG2(
"Comparing with \"known-good\" Password.PBKDF2");
721 REDEBUG(
"Password.PBKDF2 is too short");
731 q = memchr(p, scheme_sep, end - p);
733 REDEBUG(
"Password.PBKDF2 has no component separators");
741 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, digest_type, iter_sep, salt_sep, iter_is_base64, password);
752 uint8_t const *p = known_good->vp_octets, *q, *end = p + known_good->vp_length;
755 REDEBUG(
"Password.PBKDF2 too short");
770 if ((
size_t)(end - p) >=
sizeof(
"{PBKDF2-") && (memcmp(p,
"{PBKDF2-",
sizeof(
"{PBKDF2-") - 1) == 0)) {
771 p +=
sizeof(
"{PBKDF2-") - 1;
772 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
773 pbkdf2_passlib_names, pbkdf2_passlib_names_len,
774 '}',
'$',
'$',
false, password);
780 q = memchr(p,
'}', end - p);
782 REDEBUG(
"Password.PBKDF2 is missing '}");
787 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
788 pbkdf2_crypt_names, pbkdf2_crypt_names_len,
789 ':',
':',
':',
true, password);
798 if ((
size_t)(end - p) >=
sizeof(
"$PBKDF2$") && (memcmp(p,
"$PBKDF2$",
sizeof(
"$PBKDF2$") - 1) == 0)) {
799 p +=
sizeof(
"$PBKDF2$") - 1;
800 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
801 pbkdf2_crypt_names, pbkdf2_crypt_names_len,
802 ':',
':',
'$',
false, password);
812 if ((
size_t)(end - p) >=
sizeof(
"$pbkdf2-") && (memcmp(p,
"$pbkdf2-",
sizeof(
"$pbkdf2-") - 1) == 0)) {
813 p +=
sizeof(
"$pbkdf2-") - 1;
814 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
815 pbkdf2_passlib_names, pbkdf2_passlib_names_len,
816 '$',
'$',
'$',
false, password);
819 REDEBUG(
"Can't determine format of Password.PBKDF2");
834 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
837 REDEBUG(
"Password.With-Header {PBKDF2-SHA1} too short");
841 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA1,
'$',
'$',
false, password);
849 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
852 REDEBUG(
"Password.With-Header {PBKDF2-SHA256} too short");
856 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA2_256,
'$',
'$',
false, password);
864 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
867 REDEBUG(
"Password.With-Header {PBKDF2-SHA512} too short");
871 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA2_512,
'$',
'$',
false, password);
890#define PBKDF2_SHA256_LEGACY_SALT_LENGTH 64
891#define PBKDF2_SHA256_LEGACY_ITERATIONS_LENGTH 4
892#define PBKDF2_SHA256_LEGACY_HASH_LENGTH 256
893#define PBKDF2_SHA256_LEGACY_TOTAL_LENGTH (PBKDF2_SHA256_LEGACY_ITERATIONS_LENGTH + PBKDF2_SHA256_LEGACY_SALT_LENGTH + PBKDF2_SHA256_LEGACY_HASH_LENGTH)
894#define PBKDF2_SHA256_LEGACY_ITERATIONS 8192
895#define PBKDF2_SHA256_LEGACY_B64_LENGTH (PBKDF2_SHA256_LEGACY_TOTAL_LENGTH * 4 / 3)
899 uint8_t salt[PBKDF2_SHA256_LEGACY_SALT_LENGTH];
902 struct pbkdf2_bufs pbkdf2_buf = { .iterations = PBKDF2_SHA256_LEGACY_ITERATIONS };
905 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
907 EVP_MD
const *evp_md = EVP_sha256();
908 size_t digest_len = SHA256_DIGEST_LENGTH;
909 uint8_t digest[SHA256_DIGEST_LENGTH];
911 if ((end - p) != PBKDF2_SHA256_LEGACY_B64_LENGTH) {
912 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has incorrect size %zd instead of %d.", known_good->vp_length, PBKDF2_SHA256_LEGACY_B64_LENGTH);
917 &
FR_SBUFF_IN((
char const *) p, (
char const *)end),
false,
false);
920 RPEDEBUG(
"Failed decoding Password.With-Header {PBKDF2_SHA256}: \"%.*s\"", (
int)(end -p), p);
924 if (slen != PBKDF2_SHA256_LEGACY_TOTAL_LENGTH) {
925 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has incorrect decoded size %zd instead of %d.", slen, PBKDF2_SHA256_LEGACY_TOTAL_LENGTH);
929 pbkdf2_buf.iterations = ntohl(pbkdf2_buf.iterations);
931 if (pbkdf2_buf.iterations < 1) {
932 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has invalid number of iterations %d.", pbkdf2_buf.iterations);
936 if (PKCS5_PBKDF2_HMAC((
char const *)password->vb_octets, (
int)password->vb_length,
937 (
unsigned char const *)pbkdf2_buf.salt, (
int)PBKDF2_SHA256_LEGACY_SALT_LENGTH,
938 (
int)pbkdf2_buf.iterations,
940 (
int)digest_len, (
unsigned char *)digest) == 0) {
941 fr_tls_log(request,
"PBKDF2_SHA256 digest failure");
945 if (
fr_digest_cmp(digest, pbkdf2_buf.hash, (
size_t)digest_len) != 0) {
946 REDEBUG(
"PBKDF2_SHA256 digest does not match \"known good\" digest");
966 RDEBUG2(
"Comparing with \"known-good\" Password.NT");
969 REDEBUG(
"\"known good\" Password.NT has incorrect length, expected 16 got %zu", known_good->vp_length);
974 password->vb_strvalue, password->vb_length);
976 REDEBUG(
"User-Password is not in UCS2 format");
982 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
983 REDEBUG(
"NT digest does not match \"known good\" digest");
986 REDEBUG3(
"Expected : %pH", &known_good->data);
1002 RDEBUG2(
"Using Password.NT-MTA-MD5");
1004 if (known_good->vp_length != 64) {
1005 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 has incorrect length, expected 64 got %zu",
1006 known_good->vp_length);
1014 &
FR_SBUFF_IN(known_good->vp_strvalue, known_good->vp_length),
false) != 16) {
1015 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 has invalid value");
1024 if (password->vb_length >= (
sizeof(
buff) - 2 - 2 * 32)) {
1025 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 is too long");
1035 memcpy(p, &known_good->vp_octets[32], 32);
1038 memcpy(p, password->vb_strvalue, password->vb_length);
1039 p += password->vb_length;
1041 memcpy(p, &known_good->vp_octets[32], 32);
1048 REDEBUG(
"NS-MTA-MD5 digest does not match \"known good\" digest");
1074 [FR_CRYPT] = pap_auth_crypt,
1082#ifdef HAVE_OPENSSL_EVP_H
1083 [FR_PBKDF2] = pap_auth_pbkdf2,
1084 [FR_PBKDF2_SHA1] = pap_auth_pbkdf2_sha1,
1085 [FR_PBKDF2_SHA256] = pap_auth_pbkdf2_sha256,
1086 [FR_PBKDF2_SHA512] = pap_auth_pbkdf2_sha512,
1087 [FR_PBKDF2_SHA256_LEGACY] = pap_auth_pbkdf2_sha256_legacy,
1089 [FR_SHA2_224] = pap_auth_sha2_224,
1090 [FR_SHA2_256] = pap_auth_sha2_256,
1091 [FR_SHA2_384] = pap_auth_sha2_384,
1092 [FR_SHA2_512] = pap_auth_sha2_512,
1093 [FR_SSHA2_224] = pap_auth_ssha2_224,
1094 [FR_SSHA2_256] = pap_auth_ssha2_256,
1095 [FR_SSHA2_384] = pap_auth_ssha2_384,
1096 [FR_SSHA2_512] = pap_auth_ssha2_512,
1098 [FR_SHA3_224] = pap_auth_sha3_224,
1099 [FR_SHA3_256] = pap_auth_sha3_256,
1100 [FR_SHA3_384] = pap_auth_sha3_384,
1101 [FR_SHA3_512] = pap_auth_sha3_512,
1102 [FR_SSHA3_224] = pap_auth_ssha3_224,
1103 [FR_SSHA3_256] = pap_auth_ssha3_256,
1104 [FR_SSHA3_384] = pap_auth_ssha3_384,
1105 [FR_SSHA3_512] = pap_auth_ssha3_512,
1123 REDEBUG(
"You set 'Auth-Type = PAP' for a request that does not contain a %s attribute!",
1131 if (env_data->
password.vb_length == 0) {
1132 REDEBUG(
"Password must not be empty");
1140 RDEBUG2(
"Login attempt with password");
1153 REDEBUG(
"No \"known good\" password found for user");
1163 RDEBUG3(
"Comparing with \"known good\" %pP (%zu)", known_good, known_good->vp_length);
1165 RDEBUG2(
"Comparing with \"known-good\" %s (%zu)", known_good->
da->name, known_good->vp_length);
1171 auth_func(p_result,
inst, request, known_good, &env_data->
password);
1172 if (ephemeral) TALLOC_FREE(known_good);
1173 switch (p_result->
rcode) {
1175 REDEBUG(
"Password incorrect");
1179 RDEBUG2(
"User authenticated successfully");
1194 if (!
inst->auth_type) {
1195 WARN(
"Failed to find 'authenticate %s {...}' section. PAP will likely not work",
1211 PERROR(
"%s", __FUNCTION__);
1215 PERROR(
"%s", __FUNCTION__);
1241 ERROR(
"Could not resolve password attribute %zu", i);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define fr_base64_decode(_out, _in, _expect_padding, _no_trailing)
#define FR_BASE64_DEC_LENGTH(_inlen)
#define USES_APPLE_DEPRECATED_API
#define L(_str)
Helper for initialising arrays of string literals.
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_PARSE_OFFSET(_name, _cast_type, _flags, _struct, _field, _parse_field)
Specify a call_env_parser_t which writes out runtime results and the result of the parsing phase to t...
size_t inst_size
Size of per call env.
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl MUST contain an attribute reference.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_dict_autofree(_to_free)
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.
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
#define fr_dict_autoload(_to_load)
#define DICT_AUTOLOAD_TERMINATOR
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
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.
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define REDEBUG3(fmt,...)
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
#define RPEDEBUG(fmt,...)
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
#define RHEXDUMP2(_data, _len, _fmt,...)
void fr_md4_calc(uint8_t out[static MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD4 hash of the contents of a buffer.
#define MD4_DIGEST_LENGTH
void fr_md5_ctx_free_from_list(fr_md5_ctx_t **ctx)
Free function for MD5 digest ctx.
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
Allocation function for MD5 digest context.
#define fr_md5_final(_out, _ctx)
Finalise the ctx, producing the digest.
#define fr_md5_update(_ctx, _in, _inlen)
Ingest plaintext into the digest.
#define MD5_DIGEST_LENGTH
@ 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.
ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
Convert UTF8 string to UCS2 encoding.
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
void * env_data
Per call environment data.
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.
static ssize_t normify(normalise_t *action, uint8_t *buffer, size_t bufflen, char const *known_good, size_t len, size_t min_len)
fr_pair_t * password_find(bool *ephemeral, TALLOC_CTX *ctx, request_t *request, fr_dict_attr_t const *allowed_attrs[], size_t allowed_attrs_len, bool normify)
Find a "known good" password in the control list of a request.
static const conf_parser_t config[]
#define RETURN_UNLANG_UPDATED
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_REJECT
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_REJECT
Immediately reject the request.
#define RETURN_UNLANG_NOOP
static const pap_auth_func_t auth_func_table[]
Table of password types we can process.
static int mod_load(void)
unlang_action_t(* pap_auth_func_t)(unlang_result_t *p_result, rlm_pap_t const *inst, request_t *request, fr_pair_t const *, fr_value_box_t const *)
static fr_dict_attr_autoload_t rlm_pap_dict_attr[]
static unlang_action_t pap_auth_md5(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, request_t *request, fr_pair_t const *known_good, fr_value_box_t const *password)
static fr_dict_t const * dict_freeradius
static const call_env_method_t pap_method_env
fr_dict_enum_value_t const * auth_type
static fr_dict_autoload_t rlm_pap_dict[]
static unlang_action_t pap_auth_nt(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, request_t *request, fr_pair_t const *known_good, fr_value_box_t const *password)
static fr_dict_attr_t const * attr_auth_type
static unlang_action_t mod_authorize(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static void mod_unload(void)
static unlang_action_t pap_auth_sha1(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, request_t *request, fr_pair_t const *known_good, fr_value_box_t const *password)
static unlang_action_t pap_auth_clear(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, request_t *request, fr_pair_t const *known_good, fr_value_box_t const *password)
static unlang_action_t mod_authenticate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_attr_t const * attr_root
static unlang_action_t pap_auth_dummy(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, UNUSED request_t *request, UNUSED fr_pair_t const *known_good, UNUSED fr_value_box_t const *password)
Auth func for password types that should have been normalised away.
static unlang_action_t pap_auth_ns_mta_md5(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, request_t *request, fr_pair_t const *known_good, fr_value_box_t const *password)
static unlang_action_t pap_auth_ssha1(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, request_t *request, fr_pair_t const *known_good, fr_value_box_t const *password)
static fr_dict_attr_t const ** pap_alloweds
static USES_APPLE_DEPRECATED_API pthread_mutex_t fr_crypt_mutex
static const conf_parser_t module_config[]
static int mod_instantiate(module_inst_ctx_t const *mctx)
static unlang_action_t pap_auth_smd5(unlang_result_t *p_result, UNUSED rlm_pap_t const *inst, request_t *request, fr_pair_t const *known_good, fr_value_box_t const *password)
static unsigned int hash(char const *username, unsigned int tablesize)
#define FR_SBUFF_IN(_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.
void fr_sha1_init(fr_sha1_ctx *context)
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
#define SHA1_DIGEST_LENGTH
static char buff[sizeof("18446744073709551615")+3]
eap_aka_sim_process_conf_t * inst
size_t strlcpy(char *dst, char const *src, size_t siz)
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_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
#define fr_table_value_by_substr(_table, _name, _name_len, _def)
Convert a partial string to a value using an ordered or sorted table.
An element in a lexicographically sorted array of name to num mappings.
#define talloc_get_type_abort_const
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define FR_MAX_STRING_LEN
#define fr_box_octets(_val, _len)