24 RCSID(
"$Id: 27b879af3a69211a15e11db0148b0bae7ac093e1 $")
26 #include <freeradius-devel/server/password.h>
28 #include <freeradius-devel/util/base64.h>
29 #include <freeradius-devel/util/base16.h>
30 #include <freeradius-devel/util/md4.h>
31 #include <freeradius-devel/util/md5.h>
32 #include <freeradius-devel/util/misc.h>
33 #include <freeradius-devel/util/sha1.h>
34 #include <freeradius-devel/util/value.h>
36 #include <freeradius-devel/protocol/freeradius/freeradius.internal.password.h>
38 #ifdef HAVE_OPENSSL_EVP_H
39 # include <freeradius-devel/tls/openssl_user_macros.h>
40 # include <openssl/evp.h>
41 # include <openssl/sha.h>
198 {
L(
"{base64_md5}"), FR_MD5 },
199 {
L(
"{clear}"), FR_CLEARTEXT },
200 {
L(
"{cleartext}"), FR_CLEARTEXT },
201 {
L(
"{crypt}"), FR_CRYPT },
202 {
L(
"{md4}"), FR_NT },
203 {
L(
"{md5}"), FR_MD5 },
204 {
L(
"{ns-mta-md5}"), FR_NS_MTA_MD5 },
205 {
L(
"{nt}"), FR_NT },
206 {
L(
"{nthash}"), FR_NT },
208 #ifdef HAVE_OPENSSL_EVP_H
209 {
L(
"{sha224}"), FR_SHA2 },
210 {
L(
"{sha256}"), FR_SHA2 },
211 {
L(
"{sha2}"), FR_SHA2 },
212 {
L(
"{sha384}"), FR_SHA2_384 },
213 {
L(
"{sha512}"), FR_SHA2_512 },
215 {
L(
"{sha}"), FR_SHA1 },
216 {
L(
"{smd5}"), FR_SMD5 },
217 #ifdef HAVE_OPENSSL_EVP_H
218 {
L(
"{ssha224}"), FR_SSHA2_224 },
219 {
L(
"{ssha256}"), FR_SSHA2_256 },
220 # if OPENSSL_VERSION_NUMBER >= 0x10101000L
221 {
L(
"{ssha3-224}"), FR_SSHA3_224 },
222 {
L(
"{ssha3-256}"), FR_SSHA3_256 },
223 {
L(
"{ssha3-384}"), FR_SSHA3_384 },
224 {
L(
"{ssha3-512}"), FR_SSHA3_512 },
226 {
L(
"{ssha384}"), FR_SSHA2_384 },
227 {
L(
"{ssha512}"), FR_SSHA2_512 },
229 {
L(
"{ssha}"), FR_SSHA1 },
230 {
L(
"{x- orcllmv}"), FR_LM },
231 {
L(
"{x- orclntv}"), FR_NT },
232 {
L(
"{x-nthash}"), FR_NT },
233 {
L(
"{x-pbkdf2}"), FR_PBKDF2 },
237 #ifdef HAVE_OPENSSL_EVP_H
239 # if OPENSSL_VERSION_NUMBER >= 0x10101000L
292 #ifdef HAVE_OPENSSL_EVP_H
296 .func = password_process_sha2,
297 .min_hash_len = SHA224_DIGEST_LENGTH,
298 .max_hash_len = SHA512_DIGEST_LENGTH
303 .min_hash_len = SHA224_DIGEST_LENGTH,
308 .min_hash_len = SHA256_DIGEST_LENGTH,
313 .min_hash_len = SHA384_DIGEST_LENGTH,
318 .min_hash_len = SHA512_DIGEST_LENGTH,
320 # if OPENSSL_VERSION_NUMBER >= 0x10101000L
324 .func = password_process_sha3,
325 .min_hash_len = SHA224_DIGEST_LENGTH,
330 .min_hash_len = SHA224_DIGEST_LENGTH,
335 .min_hash_len = SHA256_DIGEST_LENGTH,
340 .min_hash_len = SHA384_DIGEST_LENGTH,
345 .min_hash_len = SHA512_DIGEST_LENGTH
359 #ifdef HAVE_OPENSSL_EVP_H
363 .min_hash_len = SHA224_DIGEST_LENGTH
368 .min_hash_len = SHA256_DIGEST_LENGTH
373 .min_hash_len = SHA384_DIGEST_LENGTH
378 .min_hash_len = SHA512_DIGEST_LENGTH
380 # if OPENSSL_VERSION_NUMBER >= 0x10101000L
384 .min_hash_len = SHA224_DIGEST_LENGTH,
389 .min_hash_len = SHA256_DIGEST_LENGTH
394 .min_hash_len = SHA384_DIGEST_LENGTH
399 .min_hash_len = SHA512_DIGEST_LENGTH
405 #define MIN_LEN(_info) (info->type == PASSWORD_HASH_SALTED ? (info->min_hash_len + 1) : info->min_hash_len)
408 char const *known_good,
size_t len,
size_t min_len)
415 if (min_len >= bufflen)
return 0;
421 if (!(len & 0x01) && len >= (2 * min_len)) {
427 if (decoded == (
ssize_t)(len >> 1)) {
437 if ((len * 3) >= ((min_len * 4))) {
441 if (decoded <= 0)
return 0;
442 if (decoded >= (
ssize_t) min_len) {
483 if (min_len >=
sizeof(
buffer))
return NULL;
485 switch (known_good->vp_type) {
488 (
char const *)known_good->vp_octets, known_good->vp_length, min_len);
493 known_good->vp_strvalue, known_good->vp_length, min_len);
501 RDEBUG2(
"Normalizing %s %s encoding, %zu bytes -> %zu bytes",
503 known_good->vp_length, decoded);
515 #ifdef HAVE_OPENSSL_EVP_H
529 switch (known_good->vp_length) {
530 case SHA224_DIGEST_LENGTH:
535 case SHA256_DIGEST_LENGTH:
540 case SHA384_DIGEST_LENGTH:
545 case SHA512_DIGEST_LENGTH:
552 if (!
out)
return NULL;
554 normalised = password_process_sha2(ctx, request,
out);
561 # if OPENSSL_VERSION_NUMBER >= 0x10101000L
575 switch (known_good->vp_length) {
576 case SHA224_DIGEST_LENGTH:
581 case SHA256_DIGEST_LENGTH:
586 case SHA384_DIGEST_LENGTH:
591 case SHA512_DIGEST_LENGTH:
598 if (!
out)
return NULL;
600 normalised = password_process_sha3(ctx, request,
out);
626 char const *p, *q, *end;
645 p = known_good->vp_strvalue;
646 end = p + known_good->vp_length;
652 if ((*p ==
'{') && (q = memchr(p,
'}', end - p))) {
658 if (hlen >=
sizeof(header)) {
659 REDEBUG(
"Password header too long. Got %zu bytes must be less than %zu bytes",
660 hlen,
sizeof(header));
664 memcpy(header, p, hlen);
673 RDEBUG3(
"Unknown header %s in %pP, re-writing to %s",
674 header, known_good, def->name);
676 RDEBUG2(
"Unknown header %s in %s, re-writing to %s",
677 header, known_good->
da->name, def->name);
689 switch ((*(info->
da))->type) {
705 #ifdef STATIC_ANALYZER
709 memset(n1, 0,
sizeof(n1));
722 decoded =
normify(&normalised, n1,
sizeof(n1), p, end - p, 4);
724 if ((n1[0] ==
'{') && (memchr(n1,
'}', decoded) != NULL)) {
725 RDEBUG2(
"Normalizing %s %s encoding, %zu bytes -> %zu bytes",
727 known_good->vp_length, decoded);
734 memcpy(n2, n1, decoded);
735 p = (
char const *)n2;
749 RDEBUG3(
"No {...} in &control.%pP, re-writing to %s", known_good, def->name);
751 RDEBUG2(
"No {...} in &control.%s, re-writing to %s", known_good->
da->name, def->name);
777 from_func = info->
func(ctx, request, known_good);
778 if (!from_func)
return NULL;
792 if (from_func != known_good) TALLOC_FREE(from_func);
795 if ((from_func != known_good) && (from_recurse != from_func)) TALLOC_FREE(from_func);
808 out = from_normify ? from_normify : known_good;
818 RWDEBUG3(
"&control.%pP too short, expected %zu bytes, got %zu bytes",
821 RWDEBUG2(
"&control.%s too short, expected %zu bytes, got %zu bytes",
825 if (
out != known_good) TALLOC_FREE(
out);
834 RWDEBUG3(
"&control.%pP too long, expected %zu bytes, got %zu bytes",
837 RWDEBUG2(
"&control.%s too long, expected %zu bytes, got %zu bytes",
849 RWDEBUG3(
"&control.%pP incorrect length, expected %zu bytes, got %zu bytes",
852 RWDEBUG2(
"&control.%s incorrect length, expected %zu bytes, got %zu bytes",
885 RDEBUG3(
"Replacing &control.%pP with &control.%pP",
889 RDEBUG2(
"Replacing &control.%s with &control.%s",
890 known_good->
da->name, new->da->name);
913 if (!
new)
return NULL;
920 if (new->da != known_good->
da) {
921 for (j = 0; j < allowed_attrs_len; j++)
if (allowed_attrs[j] == new->da)
return new;
970 RWDEBUG(
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
971 RWDEBUG(
"!!! Ignoring control.User-Password. Update your !!!");
972 RWDEBUG(
"!!! configuration so that the \"known good\" clear text !!!");
973 RWDEBUG(
"!!! password is in Password.Cleartext and NOT in !!!");
974 RWDEBUG(
"!!! User-Password. !!!");
975 RWDEBUG(
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
995 allowed_attrs, allowed_attrs_len,
1000 RDEBUG3(
"Using \"known good\" %s password %pP",
1005 RDEBUG2(
"Using \"known good\" %s password %s",
1008 "<INVALID>"),
out->da->name);
1010 if (ephemeral) *ephemeral = (known_good !=
out);
1014 for (i = 0; i < allowed_attrs_len; i++) {
1015 if (allowed_attrs[i] != known_good->
da)
continue;
1018 allowed_attrs, allowed_attrs_len,
1034 PERROR(
"%s", __FUNCTION__);
1038 PERROR(
"%s", __FUNCTION__);
static int const char char buffer[256]
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define fr_base64_decode(_out, _in, _expect_padding, _no_trailing)
#define L(_str)
Helper for initialising arrays of string literals.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static void fr_dcursor_free_item(fr_dcursor_t *cursor)
talloc_free the current item
static int fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
Insert a single item at the start of the list.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
#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)
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.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define RWDEBUG2(fmt,...)
#define RWDEBUG3(fmt,...)
#define MD4_DIGEST_LENGTH
#define MD5_DIGEST_LENGTH
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_OCTETS
Raw octets.
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_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
int fr_pair_value_copy(fr_pair_t *dst, fr_pair_t *src)
Copy the value from one pair to another.
static fr_dict_attr_t const * attr_lm
@ PASSWORD_HASH
Fixed length.
@ PASSWORD_HASH_VARIABLE
Variable length everything.
@ PASSWORD_HASH_SALTED
Fixed length hash, variable length salt.
@ PASSWORD_CLEARTEXT
Variable length.
static fr_dict_attr_t const * attr_ssha2_512
static fr_table_num_sorted_t const password_type_table[]
size_t max_hash_len
Maximum length of the decoded string if normifying.
password_preprocess_t func
Preprocessing function.
static fr_dict_attr_t const * attr_sha2_256
password_type_t type
What type of password value this is.
static fr_dict_attr_t const * attr_nt
static fr_dict_attr_t const * attr_ssha2_384
static fr_dict_attr_t const * attr_pbkdf2
static fr_dict_attr_t const * attr_crypt
static fr_dict_attr_t const * attr_sha3_256
static fr_dict_t const * dict_freeradius
static ssize_t normify(normalise_t *action, uint8_t *buffer, size_t bufflen, char const *known_good, size_t len, size_t min_len)
static fr_dict_attr_t const * attr_sha2_512
static fr_dict_attr_t const * attr_ns_mta_md5
int password_init(void)
Load our dictionaries.
static size_t password_header_table_len
static fr_dict_t const * dict_radius
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 fr_dict_attr_t const * attr_user
fr_pair_t *(* password_preprocess_t)(TALLOC_CTX *ctx, request_t *request, fr_pair_t *in)
Apply preprocessing logic to a password value.
static password_info_t password_info[]
Metadata for various password attributes.
static fr_dict_attr_t const * attr_sha2_224
size_t min_hash_len
Minimum length of the decoded string if normifying.
bool always_allow
Always allow processing of this attribute, irrespective of what the caller says.
static fr_pair_t * password_process(TALLOC_CTX *ctx, request_t *request, fr_pair_t *known_good, bool normify)
Apply any processing and normification.
static fr_dict_attr_t const * attr_ssha3_224
static fr_pair_t * password_process_header(TALLOC_CTX *ctx, request_t *request, fr_pair_t *known_good)
Convert a Password.With-Header attribute to the correct type.
static fr_dict_attr_t const * attr_md5
static fr_dict_attr_t const * attr_sha3_224
static fr_dict_attr_t const * attr_ssha2_256
bool no_normify
Don't attempt to normalise the contents of this attribute using the hex/base64 decoders.
static fr_pair_t * password_normalise_and_recheck(TALLOC_CTX *ctx, request_t *request, fr_dict_attr_t const *allowed_attrs[], size_t allowed_attrs_len, bool normify, fr_pair_t *const known_good)
static fr_dict_attr_t const * attr_root
static fr_dict_attr_t const * attr_sha3_384
static fr_dict_attr_t const * attr_ssha3_256
static fr_dict_attr_t const * attr_sha2
static fr_pair_t * password_normify(TALLOC_CTX *ctx, request_t *request, fr_pair_t const *known_good)
Hex or base64 or bin auto-discovery.
int password_normalise_and_replace(request_t *request, bool normify)
Find all password attributes in the control list of a request and normalise them.
fr_dict_autoload_t password_dict[]
static fr_table_num_sorted_t const password_header_table[]
static fr_dict_attr_t const * attr_ssha3_512
static fr_dict_attr_t const * attr_sha3
static fr_dict_attr_t const * attr_ssha2_224
static size_t normalise_table_len
static fr_dict_attr_t const * attr_sha2_384
static fr_dict_attr_t const * attr_ssha1
static size_t password_type_table_len
static fr_dict_attr_t const * attr_cleartext
static fr_dict_attr_t const * attr_ssha3_384
fr_dict_attr_autoload_t password_dict_attr[]
static fr_dict_attr_t const * attr_smd5
static fr_dict_attr_t const * attr_sha1
static fr_dict_attr_t const * attr_sha3_512
fr_dict_attr_t const ** da
Dictionary attribute representing this type of password.
static fr_table_num_sorted_t const normalise_table[]
static fr_dict_attr_t const * attr_with_header
#define FR_SBUFF_IN(_start, _len_or_end)
#define SHA1_DIGEST_LENGTH
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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 fr_pair_dcursor_by_ancestor_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes descended from the specified fr_dict_attr_t.
static size_t char ** out