26RCSID(
"$Id: 2e4d15bf9609eea3229dbb0bb4769fc394e4e429 $")
29#include <freeradius-devel/server/base.h>
30#include <freeradius-devel/server/module_rlm.h>
31#include <freeradius-devel/server/password.h>
32#include <freeradius-devel/tls/base.h>
33#include <freeradius-devel/tls/log.h>
35#include <freeradius-devel/util/base64.h>
36#include <freeradius-devel/util/debug.h>
37#include <freeradius-devel/util/base16.h>
38#include <freeradius-devel/util/md5.h>
39#include <freeradius-devel/util/sha1.h>
41#include <freeradius-devel/unlang/action.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");
187 REDEBUG3(
"Password : %pV", password);
188 REDEBUG3(
"Expected : %pV", &known_good->data);
203 struct crypt_data crypt_data = { .initialized = 0 };
205 crypt_out = crypt_r(password->vb_strvalue, known_good->vp_strvalue, &crypt_data);
206 if (crypt_out) cmp = strcmp(known_good->vp_strvalue, crypt_out);
212 crypt_out = crypt(password->vb_strvalue, known_good->vp_strvalue);
219 if (crypt_out) cmp = strcmp(known_good->vp_strvalue, crypt_out);
226 if (!crypt_out || (cmp != 0)) {
227 REDEBUG(
"Crypt digest does not match \"known good\" digest");
242 REDEBUG(
"\"known-good\" MD5 password has incorrect length, expected 16 got %zu", known_good->vp_length);
246 fr_md5_calc(digest, password->vb_octets, password->vb_length);
248 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
249 REDEBUG(
"MD5 digest does not match \"known good\" digest");
251 REDEBUG3(
"Password : %pV", password);
269 REDEBUG(
"\"known-good\" Password.SMD5 has incorrect length, expected 16 got %zu", known_good->vp_length);
274 fr_md5_update(md5_ctx, password->vb_octets, password->vb_length);
283 REDEBUG(
"SMD5 digest does not match \"known good\" digest");
285 REDEBUG3(
"Password : %pV", password);
302 REDEBUG(
"\"known-good\" Password.SHA1 has incorrect length, expected 20 got %zu", known_good->vp_length);
307 fr_sha1_update(&sha1_context, password->vb_octets, password->vb_length);
310 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
311 REDEBUG(
"SHA1 digest does not match \"known good\" digest");
313 REDEBUG3(
"Password : %pV", password);
330 REDEBUG(
"\"known-good\" Password.SSHA has incorrect length, expected > 20 got %zu", known_good->vp_length);
335 fr_sha1_update(&sha1_context, password->vb_octets, password->vb_length);
341 REDEBUG(
"SSHA digest does not match \"known good\" digest");
343 REDEBUG3(
"Password : %pV", password);
354#ifdef HAVE_OPENSSL_EVP_H
358 char const *
name, EVP_MD
const *md)
361 uint8_t digest[EVP_MAX_MD_SIZE];
362 unsigned int digest_len;
364 ctx = EVP_MD_CTX_create();
365 EVP_DigestInit_ex(ctx, md, NULL);
366 EVP_DigestUpdate(ctx, password->vb_octets, password->vb_length);
367 EVP_DigestFinal_ex(ctx, digest, &digest_len);
368 EVP_MD_CTX_destroy(ctx);
370 fr_assert((
size_t) digest_len == known_good->vp_length);
372 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
373 REDEBUG(
"%s digest does not match \"known good\" digest",
name);
375 REDEBUG3(
"Password : %pV", password);
377 REDEBUG3(
"Expected : %pH", &known_good->data);
387 char const *
name, EVP_MD
const *md)
390 uint8_t digest[EVP_MAX_MD_SIZE];
391 unsigned int digest_len, min_len;
393 min_len = EVP_MD_size(md);
394 ctx = EVP_MD_CTX_create();
395 EVP_DigestInit_ex(ctx, md, NULL);
396 EVP_DigestUpdate(ctx, password->vb_octets, password->vb_length);
397 EVP_DigestUpdate(ctx, known_good->vp_octets + min_len, known_good->vp_length - min_len);
398 EVP_DigestFinal_ex(ctx, digest, &digest_len);
399 EVP_MD_CTX_destroy(ctx);
401 fr_assert((
size_t) digest_len == min_len);
406 if (
fr_digest_cmp(digest, known_good->vp_octets, (
size_t)digest_len) != 0) {
407 REDEBUG(
"%s digest does not match \"known good\" digest",
name);
409 REDEBUG3(
"Password : %pV", password);
411 fr_box_octets(known_good->vp_octets + digest_len, known_good->vp_length - digest_len));
423#define PAP_AUTH_EVP_MD(_func, _new_func, _name, _md) \
424static unlang_action_t CC_HINT(nonnull) _new_func(unlang_result_t *p_result, \
425 rlm_pap_t const *inst, request_t *request, \
426 fr_pair_t const *known_good, fr_value_box_t const *password) \
428 return _func(p_result, inst, request, known_good, password, _name, _md); \
431PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_224,
"SHA2-224", EVP_sha224())
432PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_256, "SHA2-256", EVP_sha256())
433PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_384, "SHA2-384", EVP_sha384())
434PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha2_512, "SHA2-512", EVP_sha512())
435PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_224, "SSHA2-224", EVP_sha224())
436PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_256, "SSHA2-256", EVP_sha256())
437PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_384, "SSHA2-384", EVP_sha384())
438PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha2_512, "SSHA2-512", EVP_sha512())
440PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_224, "SHA3-224", EVP_sha3_224())
441PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_256, "SHA3-256", EVP_sha3_256())
442PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_384, "SHA3-384", EVP_sha3_384())
443PAP_AUTH_EVP_MD(pap_auth_evp_md, pap_auth_sha3_512, "SHA3-512", EVP_sha3_512())
444PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_224, "SSHA3-224", EVP_sha3_224())
445PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_256, "SSHA3-256", EVP_sha3_256())
446PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_384, "SSHA3-384", EVP_sha3_384())
447PAP_AUTH_EVP_MD(pap_auth_evp_md_salted, pap_auth_ssha3_512, "SSHA3-512", EVP_sha3_512())
466 int digest_type,
char iter_sep,
char salt_sep,
474 EVP_MD
const *evp_md;
482 uint8_t digest[EVP_MAX_MD_SIZE];
490 switch (digest_type) {
497 evp_md = EVP_sha224();
498 digest_len = SHA224_DIGEST_LENGTH;
502 evp_md = EVP_sha256();
503 digest_len = SHA256_DIGEST_LENGTH;
507 evp_md = EVP_sha384();
508 digest_len = SHA384_DIGEST_LENGTH;
512 evp_md = EVP_sha512();
513 digest_len = SHA512_DIGEST_LENGTH;
517 evp_md = EVP_sha3_224();
518 digest_len = SHA224_DIGEST_LENGTH;
522 evp_md = EVP_sha3_256();
523 digest_len = SHA256_DIGEST_LENGTH;
527 evp_md = EVP_sha3_384();
528 digest_len = SHA384_DIGEST_LENGTH;
532 evp_md = EVP_sha3_512();
533 digest_len = SHA512_DIGEST_LENGTH;
537 REDEBUG(
"Unknown PBKDF2 digest type \"%d\"", digest_type);
541 if (((end - p) < 1) || !(q = memchr(p, iter_sep, end - p))) {
542 REDEBUG(
"Password.PBKDF2 missing iterations component");
547 REDEBUG(
"Password.PBKDF2 iterations component too short");
554 if (!iter_is_base64) {
555 char iterations_buff[
sizeof(
"4294967295") + 1];
561 if ((
size_t) (q - p) >=
sizeof(iterations_buff)) {
563 "Password.PBKDF2 iterations field is too large");
568 strlcpy(iterations_buff, (
char const *)p, (q - p) + 1);
570 iterations = strtoul(iterations_buff, &qq, 10);
572 REMARKER(iterations_buff, qq - iterations_buff,
573 "Password.PBKDF2 iterations field contains an invalid character");
584 &
FR_SBUFF_IN((
char const *)p, (
char const *)q),
false,
false);
586 RPEDEBUG(
"Failed decoding Password.PBKDF2 iterations component (%.*s)", (
int)(q - p), p);
589 if (slen !=
sizeof(iterations)) {
590 REDEBUG(
"Decoded Password.PBKDF2 iterations component is wrong size");
593 iterations = ntohl(iterations);
601 if (iterations == 0) iterations = 1;
603 if (((end - p) < 1) || !(q = memchr(p, salt_sep, end - p))) {
604 REDEBUG(
"Password.PBKDF2 missing salt component");
609 REDEBUG(
"Password.PBKDF2 salt component too short");
615 &
FR_SBUFF_IN((
char const *) p, (
char const *)q),
false,
false);
617 RPEDEBUG(
"Failed decoding Password.PBKDF2 salt component");
625 REDEBUG(
"Password.PBKDF2 hash component too short");
630 &
FR_SBUFF_IN((
char const *)p, (
char const *)end),
false,
false);
632 RPEDEBUG(
"Failed decoding Password.PBKDF2 hash component");
636 if ((
size_t)slen != digest_len) {
637 REDEBUG(
"Password.PBKDF2 hash component length is incorrect for hash type, expected %zu, got %zd",
645 RDEBUG2(
"PBKDF2 %s: Iterations %u, salt length %zu, hash length %zd",
647 iterations, salt_len, slen);
652 if (PKCS5_PBKDF2_HMAC((
char const *)password->vb_octets, (
int)password->vb_length,
653 (
unsigned char const *)salt, (
int)salt_len,
656 (
int)digest_len, (
unsigned char *)digest) == 0) {
657 fr_tls_log(request,
"PBKDF2 digest failure");
662 REDEBUG(
"PBKDF2 digest does not match \"known good\" digest");
698 char scheme_sep,
char iter_sep,
char salt_sep,
706 RDEBUG2(
"Comparing with \"known-good\" Password.PBKDF2");
709 REDEBUG(
"Password.PBKDF2 is too short");
719 q = memchr(p, scheme_sep, end - p);
721 REDEBUG(
"Password.PBKDF2 has no component separators");
729 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, digest_type, iter_sep, salt_sep, iter_is_base64, password);
740 uint8_t const *p = known_good->vp_octets, *q, *end = p + known_good->vp_length;
743 REDEBUG(
"Password.PBKDF2 too short");
758 if ((
size_t)(end - p) >=
sizeof(
"{PBKDF2-") && (memcmp(p,
"{PBKDF2-",
sizeof(
"{PBKDF2-") - 1) == 0)) {
759 p +=
sizeof(
"{PBKDF2-") - 1;
760 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
761 pbkdf2_passlib_names, pbkdf2_passlib_names_len,
762 '}',
'$',
'$',
false, password);
768 q = memchr(p,
'}', end - p);
771 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
772 pbkdf2_crypt_names, pbkdf2_crypt_names_len,
773 ':',
':',
':',
true, password);
782 if ((
size_t)(end - p) >=
sizeof(
"$PBKDF2$") && (memcmp(p,
"$PBKDF2$",
sizeof(
"$PBKDF2$") - 1) == 0)) {
783 p +=
sizeof(
"$PBKDF2$") - 1;
784 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
785 pbkdf2_crypt_names, pbkdf2_crypt_names_len,
786 ':',
':',
'$',
false, password);
796 if ((
size_t)(end - p) >=
sizeof(
"$pbkdf2-") && (memcmp(p,
"$pbkdf2-",
sizeof(
"$pbkdf2-") - 1) == 0)) {
797 p +=
sizeof(
"$pbkdf2-") - 1;
798 return pap_auth_pbkdf2_parse(p_result, request, p, end - p,
799 pbkdf2_passlib_names, pbkdf2_passlib_names_len,
800 '$',
'$',
'$',
false, password);
803 REDEBUG(
"Can't determine format of Password.PBKDF2");
818 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
821 REDEBUG(
"Password.With-Header {PBKDF2-SHA1} too short");
825 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA1,
'$',
'$',
false, password);
833 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
836 REDEBUG(
"Password.With-Header {PBKDF2-SHA256} too short");
840 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA2_256,
'$',
'$',
false, password);
848 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
851 REDEBUG(
"Password.With-Header {PBKDF2-SHA512} too short");
855 return pap_auth_pbkdf2_parse_digest(p_result, request, p, end - p, FR_SSHA2_512,
'$',
'$',
false, password);
874#define PBKDF2_SHA256_LEGACY_SALT_LENGTH 64
875#define PBKDF2_SHA256_LEGACY_ITERATIONS_LENGTH 4
876#define PBKDF2_SHA256_LEGACY_HASH_LENGTH 256
877#define PBKDF2_SHA256_LEGACY_TOTAL_LENGTH (PBKDF2_SHA256_LEGACY_ITERATIONS_LENGTH + PBKDF2_SHA256_LEGACY_SALT_LENGTH + PBKDF2_SHA256_LEGACY_HASH_LENGTH)
878#define PBKDF2_SHA256_LEGACY_ITERATIONS 8192
879#define PBKDF2_SHA256_LEGACY_B64_LENGTH (PBKDF2_SHA256_LEGACY_TOTAL_LENGTH * 4 / 3)
883 uint8_t salt[PBKDF2_SHA256_LEGACY_SALT_LENGTH];
886 struct pbkdf2_bufs pbkdf2_buf = { .iterations = PBKDF2_SHA256_LEGACY_ITERATIONS };
889 uint8_t const *p = known_good->vp_octets, *end = p + known_good->vp_length;
891 EVP_MD
const *evp_md = EVP_sha256();
892 size_t digest_len = SHA256_DIGEST_LENGTH;
893 uint8_t digest[SHA256_DIGEST_LENGTH];
895 if ((end - p) != PBKDF2_SHA256_LEGACY_B64_LENGTH) {
896 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has incorrect size %zd instead of %d.", known_good->vp_length, PBKDF2_SHA256_LEGACY_B64_LENGTH);
901 &
FR_SBUFF_IN((
char const *) p, (
char const *)end),
false,
false);
904 RPEDEBUG(
"Failed decoding Password.With-Header {PBKDF2_SHA256}: \"%.*s\"", (
int)(end -p), p);
908 if (slen != PBKDF2_SHA256_LEGACY_TOTAL_LENGTH) {
909 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has incorrect decoded size %zd instead of %d.", slen, PBKDF2_SHA256_LEGACY_TOTAL_LENGTH);
913 pbkdf2_buf.iterations = ntohl(pbkdf2_buf.iterations);
915 if (pbkdf2_buf.iterations != PBKDF2_SHA256_LEGACY_ITERATIONS) {
916 REDEBUG(
"Password.With-Header {PBKDF2_SHA256} has unexpected number of iterations %d instead of %d.", pbkdf2_buf.iterations, PBKDF2_SHA256_LEGACY_ITERATIONS);
920 if (PKCS5_PBKDF2_HMAC((
char const *)password->vb_octets, (
int)password->vb_length,
921 (
unsigned char const *)pbkdf2_buf.salt, (
int)PBKDF2_SHA256_LEGACY_SALT_LENGTH,
922 (
int)pbkdf2_buf.iterations,
924 (
int)digest_len, (
unsigned char *)digest) == 0) {
925 fr_tls_log(request,
"PBKDF2_SHA256 digest failure");
929 if (
fr_digest_cmp(digest, pbkdf2_buf.hash, (
size_t)digest_len) != 0) {
930 REDEBUG(
"PBKDF2_SHA256 digest does not match \"known good\" digest");
950 RDEBUG2(
"Comparing with \"known-good\" Password.NT");
953 REDEBUG(
"\"known good\" Password.NT has incorrect length, expected 16 got %zu", known_good->vp_length);
958 password->vb_strvalue, password->vb_length);
960 REDEBUG(
"User-Password is not in UCS2 format");
966 if (
fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
967 REDEBUG(
"NT digest does not match \"known good\" digest");
970 REDEBUG3(
"Expected : %pH", &known_good->data);
986 RDEBUG2(
"Using Password.NT-MTA-MD5");
988 if (known_good->vp_length != 64) {
989 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 has incorrect length, expected 64 got %zu",
990 known_good->vp_length);
998 &
FR_SBUFF_IN(known_good->vp_strvalue, known_good->vp_length),
false) != 16) {
999 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 has invalid value");
1008 if (password->vb_length >= (
sizeof(
buff) - 2 - 2 * 32)) {
1009 REDEBUG(
"\"known good\" Password.NS-MTA-MD5 is too long");
1019 memcpy(p, &known_good->vp_octets[32], 32);
1022 memcpy(p, password->vb_strvalue, password->vb_length);
1023 p += password->vb_length;
1025 memcpy(p, &known_good->vp_octets[32], 32);
1032 REDEBUG(
"NS-MTA-MD5 digest does not match \"known good\" digest");
1058 [FR_CRYPT] = pap_auth_crypt,
1066#ifdef HAVE_OPENSSL_EVP_H
1067 [FR_PBKDF2] = pap_auth_pbkdf2,
1068 [FR_PBKDF2_SHA1] = pap_auth_pbkdf2_sha1,
1069 [FR_PBKDF2_SHA256] = pap_auth_pbkdf2_sha256,
1070 [FR_PBKDF2_SHA512] = pap_auth_pbkdf2_sha512,
1071 [FR_PBKDF2_SHA256_LEGACY] = pap_auth_pbkdf2_sha256_legacy,
1073 [FR_SHA2_224] = pap_auth_sha2_224,
1074 [FR_SHA2_256] = pap_auth_sha2_256,
1075 [FR_SHA2_384] = pap_auth_sha2_384,
1076 [FR_SHA2_512] = pap_auth_sha2_512,
1077 [FR_SSHA2_224] = pap_auth_ssha2_224,
1078 [FR_SSHA2_256] = pap_auth_ssha2_256,
1079 [FR_SSHA2_384] = pap_auth_ssha2_384,
1080 [FR_SSHA2_512] = pap_auth_ssha2_512,
1082 [FR_SHA3_224] = pap_auth_sha3_224,
1083 [FR_SHA3_256] = pap_auth_sha3_256,
1084 [FR_SHA3_384] = pap_auth_sha3_384,
1085 [FR_SHA3_512] = pap_auth_sha3_512,
1086 [FR_SSHA3_224] = pap_auth_ssha3_224,
1087 [FR_SSHA3_256] = pap_auth_ssha3_256,
1088 [FR_SSHA3_384] = pap_auth_ssha3_384,
1089 [FR_SSHA3_512] = pap_auth_ssha3_512,
1107 REDEBUG(
"You set 'Auth-Type = PAP' for a request that does not contain a %s attribute!",
1115 if (env_data->
password.vb_length == 0) {
1116 REDEBUG(
"Password must not be empty");
1124 RDEBUG2(
"Login attempt with password");
1137 REDEBUG(
"No \"known good\" password found for user");
1147 RDEBUG3(
"Comparing with \"known good\" %pP (%zu)", known_good, known_good->vp_length);
1149 RDEBUG2(
"Comparing with \"known-good\" %s (%zu)", known_good->
da->name, known_good->vp_length);
1155 auth_func(p_result,
inst, request, known_good, &env_data->
password);
1156 if (ephemeral) TALLOC_FREE(known_good);
1157 switch (p_result->
rcode) {
1159 REDEBUG(
"Password incorrect");
1163 RDEBUG2(
"User authenticated successfully");
1178 if (!
inst->auth_type) {
1179 WARN(
"Failed to find 'authenticate %s {...}' section. PAP will likely not work",
1195 PERROR(
"%s", __FUNCTION__);
1199 PERROR(
"%s", __FUNCTION__);
1225 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_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 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
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)
#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)