27RCSID(
"$Id: dd98c0b278d2942cb570a3e995cb3dec9cd704b7 $")
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/server/module_rlm.h>
32#include <freeradius-devel/server/password.h>
33#include <freeradius-devel/tls/base.h>
34#include <freeradius-devel/tls/log.h>
36#include <freeradius-devel/util/base64.h>
37#include <freeradius-devel/util/debug.h>
38#include <freeradius-devel/util/base16.h>
39#include <freeradius-devel/util/md5.h>
40#include <freeradius-devel/util/sha1.h>
42#include <freeradius-devel/unlang/call_env.h>
44#include <freeradius-devel/protocol/freeradius/freeradius.internal.password.h>
53#ifdef HAVE_OPENSSL_EVP_H
54# include <freeradius-devel/tls/openssl_user_macros.h>
55# include <openssl/evp.h>
93 .inst_type =
"pap_call_env_t",
119#ifdef HAVE_OPENSSL_EVP_H
121 {
L(
"HMACSHA1"), FR_SSHA1 },
122 {
L(
"HMACSHA2+224"), FR_SSHA2_224 },
123 {
L(
"HMACSHA2+256"), FR_SSHA2_256 },
124 {
L(
"HMACSHA2+384"), FR_SSHA2_384 },
125 {
L(
"HMACSHA2+512"), FR_SSHA2_512 },
126 {
L(
"HMACSHA3+224"), FR_SSHA3_224 },
127 {
L(
"HMACSHA3+256"), FR_SSHA3_256 },
128 {
L(
"HMACSHA3+384"), FR_SSHA3_384 },
129 {
L(
"HMACSHA3+512"), FR_SSHA3_512 },
131static size_t pbkdf2_crypt_names_len =
NUM_ELEMENTS(pbkdf2_crypt_names);
134 {
L(
"sha1"), FR_SSHA1 },
135 {
L(
"sha256"), FR_SSHA2_256 },
136 {
L(
"sha512"), FR_SSHA2_512 }
138static size_t pbkdf2_passlib_names_len =
NUM_ELEMENTS(pbkdf2_passlib_names);
155 RDEBUG3(
"Auth-Type is already set. Not setting 'Auth-Type := %s'", mctx->
mi->
name);
164 if (!
inst->auth_type) {
165 WARN(
"No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup PAP authentication.",
183 if ((known_good->vp_length != password->vb_length) ||
184 (
fr_digest_cmp(known_good->vp_octets, password->vb_octets, known_good->vp_length) != 0)) {
185 REDEBUG(
"Cleartext password does not match \"known good\" password");
186 REDEBUG3(
"Password : %pV", password);
187 REDEBUG3(
"Expected : %pV", &known_good->data);
202 struct crypt_data crypt_data = { .initialized = 0 };
204 crypt_out = crypt_r(password->vb_strvalue, known_good->vp_strvalue, &crypt_data);
205 if (crypt_out) cmp = strcmp(known_good->vp_strvalue, crypt_out);
211 crypt_out = crypt(password->vb_strvalue, known_good->vp_strvalue);
218 if (crypt_out) cmp = strcmp(known_good->vp_strvalue, crypt_out);
225 if (!crypt_out || (cmp != 0)) {
226 REDEBUG(
"Crypt digest does not match \"known good\" digest");
241 REDEBUG(
"\"known-good\" MD5 password has incorrect length, expected 16 got %zu", known_good->vp_length);
245 fr_md5_calc(digest, password->vb_octets, password->vb_length);
247 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
248 REDEBUG(
"MD5 digest does not match \"known good\" digest");
249 REDEBUG3(
"Password : %pV", password);
267 REDEBUG(
"\"known-good\" Password.SMD5 has incorrect length, expected 16 got %zu", known_good->vp_length);
272 fr_md5_update(md5_ctx, password->vb_octets, password->vb_length);
281 REDEBUG(
"SMD5 digest does not match \"known good\" digest");
282 REDEBUG3(
"Password : %pV", password);
299 REDEBUG(
"\"known-good\" Password.SHA1 has incorrect length, expected 20 got %zu", known_good->vp_length);
304 fr_sha1_update(&sha1_context, password->vb_octets, password->vb_length);
307 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
308 REDEBUG(
"SHA1 digest does not match \"known good\" digest");
309 REDEBUG3(
"Password : %pV", password);
326 REDEBUG(
"\"known-good\" Password.SSHA has incorrect length, expected > 20 got %zu", known_good->vp_length);
331 fr_sha1_update(&sha1_context, password->vb_octets, password->vb_length);
337 REDEBUG(
"SSHA digest does not match \"known good\" digest");
338 REDEBUG3(
"Password : %pV", password);
349#ifdef HAVE_OPENSSL_EVP_H
353 char const *
name, EVP_MD
const *md)
356 uint8_t digest[EVP_MAX_MD_SIZE];
357 unsigned int digest_len;
359 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);
365 fr_assert((
size_t) digest_len == known_good->vp_length);
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);
369 REDEBUG3(
"Password : %pV", password);
371 REDEBUG3(
"Expected : %pH", &known_good->data);
381 char const *
name, EVP_MD
const *md)
384 uint8_t digest[EVP_MAX_MD_SIZE];
385 unsigned int digest_len, min_len;
387 min_len = EVP_MD_size(md);
388 ctx = EVP_MD_CTX_create();
389 EVP_DigestInit_ex(ctx, md, NULL);
390 EVP_DigestUpdate(ctx, password->vb_octets, password->vb_length);
391 EVP_DigestUpdate(ctx, known_good->vp_octets + min_len, known_good->vp_length - min_len);
392 EVP_DigestFinal_ex(ctx, digest, &digest_len);
393 EVP_MD_CTX_destroy(ctx);
395 fr_assert((
size_t) digest_len == min_len);
400 if (
fr_digest_cmp(digest, known_good->vp_octets, (
size_t)digest_len) != 0) {
401 REDEBUG(
"%s digest does not match \"known good\" digest",
name);
402 REDEBUG3(
"Password : %pV", password);
404 fr_box_octets(known_good->vp_octets + digest_len, known_good->vp_length - digest_len));
416#define PAP_AUTH_EVP_MD(_func, _new_func, _name, _md) \
417static unlang_action_t CC_HINT(nonnull) _new_func(unlang_result_t *p_result, \
418 rlm_pap_t const *inst, request_t *request, \
419 fr_pair_t const *known_good, fr_value_box_t const *password) \
421 return _func(p_result, inst, request, known_good, password, _name, _md); \
424PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_224,
"SHA2-224", EVP_sha224())
425PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_256, "SHA2-256", EVP_sha256())
426PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_384, "SHA2-384", EVP_sha384())
427PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_512, "SHA2-512", EVP_sha512())
428PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_224, "SSHA2-224", EVP_sha224())
429PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_256, "SSHA2-256", EVP_sha256())
430PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_384, "SSHA2-384", EVP_sha384())
431PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_512, "SSHA2-512", EVP_sha512())
433PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_224, "SHA3-224", EVP_sha3_224())
434PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_256, "SHA3-256", EVP_sha3_256())
435PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_384, "SHA3-384", EVP_sha3_384())
436PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_512, "SHA3-512", EVP_sha3_512())
437PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_224, "SSHA3-224", EVP_sha3_224())
438PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_256, "SSHA3-256", EVP_sha3_256())
439PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_384, "SSHA3-384", EVP_sha3_384())
440PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_512, "SSHA3-512", EVP_sha3_512())
459 int digest_type,
char iter_sep,
char salt_sep,
467 EVP_MD
const *evp_md;
475 uint8_t digest[EVP_MAX_MD_SIZE];
483 switch (digest_type) {
490 evp_md = EVP_sha224();
491 digest_len = SHA224_DIGEST_LENGTH;
495 evp_md = EVP_sha256();
496 digest_len = SHA256_DIGEST_LENGTH;
500 evp_md = EVP_sha384();
501 digest_len = SHA384_DIGEST_LENGTH;
505 evp_md = EVP_sha512();
506 digest_len = SHA512_DIGEST_LENGTH;
510 evp_md = EVP_sha3_224();
511 digest_len = SHA224_DIGEST_LENGTH;
515 evp_md = EVP_sha3_256();
516 digest_len = SHA256_DIGEST_LENGTH;
520 evp_md = EVP_sha3_384();
521 digest_len = SHA384_DIGEST_LENGTH;
525 evp_md = EVP_sha3_512();
526 digest_len = SHA512_DIGEST_LENGTH;
530 REDEBUG(
"Unknown PBKDF2 digest type \"%d\"", digest_type);
534 if (((end - p) < 1) || !(q = memchr(p, iter_sep, end - p))) {
535 REDEBUG(
"Password.PBKDF2 missing iterations component");
540 REDEBUG(
"Password.PBKDF2 iterations component too short");
547 if (!iter_is_base64) {
548 char iterations_buff[
sizeof(
"4294967295") + 1];
554 if ((
size_t) (q - p) >=
sizeof(iterations_buff)) {
556 "Password.PBKDF2 iterations field is too large");
561 strlcpy(iterations_buff, (
char const *)p, (q - p) + 1);
563 iterations = strtoul(iterations_buff, &qq, 10);
565 REMARKER(iterations_buff, qq - iterations_buff,
566 "Password.PBKDF2 iterations field contains an invalid character");
577 &
FR_SBUFF_IN((
char const *)p, (
char const *)q),
false,
false);
579 RPEDEBUG(
"Failed decoding Password.PBKDF2 iterations component (%.*s)", (
int)(q - p), p);
582 if (slen !=
sizeof(iterations)) {
583 REDEBUG(
"Decoded Password.PBKDF2 iterations component is wrong size");
586 iterations = ntohl(iterations);
594 if (iterations == 0) iterations = 1;
596 if (((end - p) < 1) || !(q = memchr(p, salt_sep, end - p))) {
597 REDEBUG(
"Password.PBKDF2 missing salt component");
602 REDEBUG(
"Password.PBKDF2 salt component too short");
608 &
FR_SBUFF_IN((
char const *) p, (
char const *)q),
false,
false);
610 RPEDEBUG(
"Failed decoding Password.PBKDF2 salt component");
618 REDEBUG(
"Password.PBKDF2 hash component too short");
623 &
FR_SBUFF_IN((
char const *)p, (
char const *)end),
false,
false);
625 RPEDEBUG(
"Failed decoding Password.PBKDF2 hash component");
629 if ((
size_t)slen != digest_len) {
630 REDEBUG(
"Password.PBKDF2 hash component length is incorrect for hash type, expected %zu, got %zd",
638 RDEBUG2(
"PBKDF2 %s: Iterations %u, salt length %zu, hash length %zd",
640 iterations, salt_len, slen);
645 if (PKCS5_PBKDF2_HMAC((
char const *)password->vb_octets, (
int)password->vb_length,
646 (
unsigned char const *)salt, (
int)salt_len,
649 (
int)digest_len, (
unsigned char *)digest) == 0) {
650 fr_tls_log(request,
"PBKDF2 digest failure");
655 REDEBUG(
"PBKDF2 digest does not match \"known good\" digest");
690 char scheme_sep,
char iter_sep,
char salt_sep,
698 RDEBUG2(
"Comparing with \"known-good\" Password.PBKDF2");
701 REDEBUG(
"Password.PBKDF2 is too short");
711 q = memchr(p, scheme_sep, end - p);
713 REDEBUG(
"Password.PBKDF2 has no component separators");
721 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, digest_type, iter_sep, salt_sep, iter_is_base64, password);
732 uint8_t const *p = known_good->vp_octets, *q, *end = p + known_good->vp_length;
735 REDEBUG(
"Password.PBKDF2 too short");
750 if ((
size_t)(end - p) >=
sizeof(
"{PBKDF2-") && (memcmp(p,
"{PBKDF2-",
sizeof(
"{PBKDF2-") - 1) == 0)) {
751 p +=
sizeof(
"{PBKDF2-") - 1;
752 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
753 pbkdf2_passlib_names, pbkdf2_passlib_names_len,
754 '}',
'$',
'$',
false, password);
760 q = memchr(p,
'}', end - p);
763 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
764 pbkdf2_crypt_names, pbkdf2_crypt_names_len,
765 ':',
':',
':',
true, password);
774 if ((
size_t)(end - p) >=
sizeof(
"$PBKDF2$") && (memcmp(p,
"$PBKDF2$",
sizeof(
"$PBKDF2$") - 1) == 0)) {
775 p +=
sizeof(
"$PBKDF2$") - 1;
776 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
777 pbkdf2_crypt_names, pbkdf2_crypt_names_len,
778 ':',
':',
'$',
false, password);
788 if ((
size_t)(end - p) >=
sizeof(
"$pbkdf2-") && (memcmp(p,
"$pbkdf2-",
sizeof(
"$pbkdf2-") - 1) == 0)) {
789 p +=
sizeof(
"$pbkdf2-") - 1;
790 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
791 pbkdf2_passlib_names, pbkdf2_passlib_names_len,
792 '$',
'$',
'$',
false, password);
795 REDEBUG(
"Can't determine format of Password.PBKDF2");
810 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
813 REDEBUG(
"Password.With-Header {PBKDF2-SHA1} too short");
817 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA1,
'$',
'$',
false, password);
825 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
828 REDEBUG(
"Password.With-Header {PBKDF2-SHA256} too short");
832 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA2_256,
'$',
'$',
false, password);
840 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
843 REDEBUG(
"Password.With-Header {PBKDF2-SHA512} too short");
847 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA2_512,
'$',
'$',
false, password);
866#define PBKDF2_SHA256_LEGACY_SALT_LENGTH 64
867#define PBKDF2_SHA256_LEGACY_ITERATIONS_LENGTH 4
868#define PBKDF2_SHA256_LEGACY_HASH_LENGTH 256
869#define PBKDF2_SHA256_LEGACY_TOTAL_LENGTH (PBKDF2_SHA256_LEGACY_ITERATIONS_LENGTH + PBKDF2_SHA256_LEGACY_SALT_LENGTH + PBKDF2_SHA256_LEGACY_HASH_LENGTH)
870#define PBKDF2_SHA256_LEGACY_ITERATIONS 8192
871#define PBKDF2_SHA256_LEGACY_B64_LENGTH (PBKDF2_SHA256_LEGACY_TOTAL_LENGTH * 4 / 3)
875 uint8_t salt[PBKDF2_SHA256_LEGACY_SALT_LENGTH];
878 struct pbkdf2_bufs pbkdf2_buf = { .iterations = PBKDF2_SHA256_LEGACY_ITERATIONS };
881 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
883 EVP_MD
const *evp_md = EVP_sha256();
884 size_t digest_len = SHA256_DIGEST_LENGTH;
885 uint8_t digest[SHA256_DIGEST_LENGTH];
887 if ((end - p) != PBKDF2_SHA256_LEGACY_B64_LENGTH) {
888 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has incorrect size %zd instead of %d.", known_good->vp_length, PBKDF2_SHA256_LEGACY_B64_LENGTH);
893 &
FR_SBUFF_IN((
char const *) p, (
char const *)end),
false,
false);
896 RPEDEBUG(
"Failed decoding Password.With-Header {PBKDF2_SHA256}: \"%.*s\"", (
int)(end -p), p);
900 if (slen != PBKDF2_SHA256_LEGACY_TOTAL_LENGTH) {
901 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has incorrect decoded size %zd instead of %d.", slen, PBKDF2_SHA256_LEGACY_TOTAL_LENGTH);
905 pbkdf2_buf.iterations = ntohl(pbkdf2_buf.iterations);
907 if (pbkdf2_buf.iterations != PBKDF2_SHA256_LEGACY_ITERATIONS) {
908 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has unexpected number of iterations %d instead of %d.", pbkdf2_buf.iterations, PBKDF2_SHA256_LEGACY_ITERATIONS);
912 if (PKCS5_PBKDF2_HMAC((
char const *)password->vb_octets, (
int)password->vb_length,
913 (
unsigned char const *)pbkdf2_buf.salt, (
int)PBKDF2_SHA256_LEGACY_SALT_LENGTH,
914 (
int)pbkdf2_buf.iterations,
916 (
int)digest_len, (
unsigned char *)digest) == 0) {
917 fr_tls_log(request,
"PBKDF2_SHA256 digest failure");
921 if (
fr_digest_cmp(digest, pbkdf2_buf.hash, (
size_t)digest_len) != 0) {
922 REDEBUG(
"PBKDF2_SHA256 digest does not match \"known good\" digest");
941 RDEBUG2(
"Comparing with \"known-good\" Password.NT");
944 REDEBUG(
"\"known good\" Password.NT has incorrect length, expected 16 got %zu", known_good->vp_length);
949 password->vb_strvalue, password->vb_length);
951 REDEBUG(
"User-Password is not in UCS2 format");
957 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
958 REDEBUG(
"NT digest does not match \"known good\" digest");
960 REDEBUG3(
"Expected : %pH", &known_good->data);
976 RDEBUG2(
"Using Password.NT-MTA-MD5");
978 if (known_good->vp_length != 64) {
979 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 has incorrect length, expected 64 got %zu",
980 known_good->vp_length);
988 &
FR_SBUFF_IN(known_good->vp_strvalue, known_good->vp_length),
false) != 16) {
989 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 has invalid value");
998 if (password->vb_length >= (
sizeof(
buff) - 2 - 2 * 32)) {
999 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 is too long");
1009 memcpy(p, &known_good->vp_octets[32], 32);
1012 memcpy(p, password->vb_strvalue, password->vb_length);
1013 p += password->vb_length;
1015 memcpy(p, &known_good->vp_octets[32], 32);
1022 REDEBUG(
"NS-MTA-MD5 digest does not match \"known good\" digest");
1048 [FR_CRYPT] = pap_auth_crypt,
1056#ifdef HAVE_OPENSSL_EVP_H
1057 [FR_PBKDF2] = pap_auth_pbkdf2,
1058 [FR_PBKDF2_SHA1] = pap_auth_pbkdf2_sha1,
1059 [FR_PBKDF2_SHA256] = pap_auth_pbkdf2_sha256,
1060 [FR_PBKDF2_SHA512] = pap_auth_pbkdf2_sha512,
1061 [FR_PBKDF2_SHA256_LEGACY] = pap_auth_pbkdf2_sha256_legacy,
1063 [FR_SHA2_224] = pap_auth_sha2_224,
1064 [FR_SHA2_256] = pap_auth_sha2_256,
1065 [FR_SHA2_384] = pap_auth_sha2_384,
1066 [FR_SHA2_512] = pap_auth_sha2_512,
1067 [FR_SSHA2_224] = pap_auth_ssha2_224,
1068 [FR_SSHA2_256] = pap_auth_ssha2_256,
1069 [FR_SSHA2_384] = pap_auth_ssha2_384,
1070 [FR_SSHA2_512] = pap_auth_ssha2_512,
1072 [FR_SHA3_224] = pap_auth_sha3_224,
1073 [FR_SHA3_256] = pap_auth_sha3_256,
1074 [FR_SHA3_384] = pap_auth_sha3_384,
1075 [FR_SHA3_512] = pap_auth_sha3_512,
1076 [FR_SSHA3_224] = pap_auth_ssha3_224,
1077 [FR_SSHA3_256] = pap_auth_ssha3_256,
1078 [FR_SSHA3_384] = pap_auth_ssha3_384,
1079 [FR_SSHA3_512] = pap_auth_ssha3_512,
1097 REDEBUG(
"You set 'Auth-Type = PAP' for a request that does not contain a %s attribute!",
1105 if (env_data->
password.vb_length == 0) {
1106 REDEBUG(
"Password must not be empty");
1114 RDEBUG2(
"Login attempt with password");
1127 REDEBUG(
"No \"known good\" password found for user");
1137 RDEBUG3(
"Comparing with \"known good\" %pP (%zu)", known_good, known_good->vp_length);
1139 RDEBUG2(
"Comparing with \"known-good\" %s (%zu)", known_good->
da->name, known_good->vp_length);
1145 auth_func(p_result,
inst, request, known_good, &env_data->
password);
1146 if (ephemeral) TALLOC_FREE(known_good);
1147 switch (p_result->
rcode) {
1149 REDEBUG(
"Password incorrect");
1153 RDEBUG2(
"User authenticated successfully");
1168 if (!
inst->auth_type) {
1169 WARN(
"Failed to find 'authenticate %s {...}' section. PAP will likely not work",
1185 PERROR(
"%s", __FUNCTION__);
1189 PERROR(
"%s", __FUNCTION__);
1215 ERROR(
"Could not resolve password attribute %zu", i);
Unlang interpreter actions.
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ 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)
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 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
fr_md5_update_t fr_md5_update
fr_md5_final_t fr_md5_final
void fr_md5_ctx_free_from_list(fr_md5_ctx_t **ctx)
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
#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)
static int instantiate(module_inst_ctx_t const *mctx)
#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)