24 RCSID(
"$Id: be2e3c363037e3c9ecd522e9d219ddd2accf09b7 $")
26 #include <freeradius-devel/server/password.h>
28 #include <freeradius-devel/util/atexit.h>
29 #include <freeradius-devel/util/base64.h>
30 #include <freeradius-devel/util/base16.h>
31 #include <freeradius-devel/util/md4.h>
32 #include <freeradius-devel/util/md5.h>
33 #include <freeradius-devel/util/misc.h>
34 #include <freeradius-devel/util/sha1.h>
35 #include <freeradius-devel/util/value.h>
37 #include <freeradius-devel/protocol/freeradius/freeradius.internal.password.h>
39 #ifdef HAVE_OPENSSL_EVP_H
40 # include <freeradius-devel/tls/openssl_user_macros.h>
41 # include <openssl/evp.h>
42 # include <openssl/sha.h>
199 {
L(
"{base64_md5}"), FR_MD5 },
200 {
L(
"{clear}"), FR_CLEARTEXT },
201 {
L(
"{cleartext}"), FR_CLEARTEXT },
202 {
L(
"{crypt}"), FR_CRYPT },
203 {
L(
"{md4}"), FR_NT },
204 {
L(
"{md5}"), FR_MD5 },
205 {
L(
"{ns-mta-md5}"), FR_NS_MTA_MD5 },
206 {
L(
"{nt}"), FR_NT },
207 {
L(
"{nthash}"), FR_NT },
209 #ifdef HAVE_OPENSSL_EVP_H
210 {
L(
"{sha224}"), FR_SHA2 },
211 {
L(
"{sha256}"), FR_SHA2 },
212 {
L(
"{sha2}"), FR_SHA2 },
213 {
L(
"{sha384}"), FR_SHA2_384 },
214 {
L(
"{sha512}"), FR_SHA2_512 },
216 {
L(
"{sha}"), FR_SHA1 },
217 {
L(
"{smd5}"), FR_SMD5 },
218 #ifdef HAVE_OPENSSL_EVP_H
219 {
L(
"{ssha224}"), FR_SSHA2_224 },
220 {
L(
"{ssha256}"), FR_SSHA2_256 },
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 },
225 {
L(
"{ssha384}"), FR_SSHA2_384 },
226 {
L(
"{ssha512}"), FR_SSHA2_512 },
228 {
L(
"{ssha}"), FR_SSHA1 },
229 {
L(
"{x- orcllmv}"), FR_LM },
230 {
L(
"{x- orclntv}"), FR_NT },
231 {
L(
"{x-nthash}"), FR_NT },
232 {
L(
"{x-pbkdf2}"), FR_PBKDF2 },
236 #ifdef HAVE_OPENSSL_EVP_H
289 #ifdef HAVE_OPENSSL_EVP_H
293 .func = password_process_sha2,
294 .min_hash_len = SHA224_DIGEST_LENGTH,
295 .max_hash_len = SHA512_DIGEST_LENGTH
300 .min_hash_len = SHA224_DIGEST_LENGTH,
305 .min_hash_len = SHA256_DIGEST_LENGTH,
310 .min_hash_len = SHA384_DIGEST_LENGTH,
315 .min_hash_len = SHA512_DIGEST_LENGTH,
320 .func = password_process_sha3,
321 .min_hash_len = SHA224_DIGEST_LENGTH,
326 .min_hash_len = SHA224_DIGEST_LENGTH,
331 .min_hash_len = SHA256_DIGEST_LENGTH,
336 .min_hash_len = SHA384_DIGEST_LENGTH,
341 .min_hash_len = SHA512_DIGEST_LENGTH
354 #ifdef HAVE_OPENSSL_EVP_H
358 .min_hash_len = SHA224_DIGEST_LENGTH
363 .min_hash_len = SHA256_DIGEST_LENGTH
368 .min_hash_len = SHA384_DIGEST_LENGTH
373 .min_hash_len = SHA512_DIGEST_LENGTH
378 .min_hash_len = SHA224_DIGEST_LENGTH,
383 .min_hash_len = SHA256_DIGEST_LENGTH
388 .min_hash_len = SHA384_DIGEST_LENGTH
393 .min_hash_len = SHA512_DIGEST_LENGTH
398 #define MIN_LEN(_info) (info->type == PASSWORD_HASH_SALTED ? (info->min_hash_len + 1) : info->min_hash_len)
401 char const *known_good,
size_t len,
size_t min_len)
408 if (min_len >= bufflen)
return 0;
414 if (!(len & 0x01) && len >= (2 * min_len)) {
420 if (decoded == (
ssize_t)(len >> 1)) {
430 if ((len * 3) >= ((min_len * 4))) {
434 if (decoded <= 0)
return 0;
435 if (decoded >= (
ssize_t) min_len) {
476 if (min_len >=
sizeof(
buffer))
return NULL;
478 switch (known_good->vp_type) {
481 (
char const *)known_good->vp_octets, known_good->vp_length, min_len);
486 known_good->vp_strvalue, known_good->vp_length, min_len);
494 RDEBUG2(
"Normalizing %s %s encoding, %zu bytes -> %zu bytes",
496 known_good->vp_length, decoded);
508 #ifdef HAVE_OPENSSL_EVP_H
522 switch (known_good->vp_length) {
523 case SHA224_DIGEST_LENGTH:
528 case SHA256_DIGEST_LENGTH:
533 case SHA384_DIGEST_LENGTH:
538 case SHA512_DIGEST_LENGTH:
545 if (!
out)
return NULL;
547 normalised = password_process_sha2(ctx, request,
out);
567 switch (known_good->vp_length) {
568 case SHA224_DIGEST_LENGTH:
573 case SHA256_DIGEST_LENGTH:
578 case SHA384_DIGEST_LENGTH:
583 case SHA512_DIGEST_LENGTH:
590 if (!
out)
return NULL;
592 normalised = password_process_sha3(ctx, request,
out);
617 char const *p, *q, *end;
636 p = known_good->vp_strvalue;
637 end = p + known_good->vp_length;
643 if ((*p ==
'{') && (q = memchr(p,
'}', end - p))) {
649 if (hlen >=
sizeof(header)) {
650 REDEBUG(
"Password header too long. Got %zu bytes must be less than %zu bytes",
651 hlen,
sizeof(header));
655 memcpy(header, p, hlen);
664 RDEBUG3(
"Unknown header %s in %pP, re-writing to %s",
665 header, known_good, def->name);
667 RDEBUG2(
"Unknown header %s in %s, re-writing to %s",
668 header, known_good->
da->name, def->name);
680 switch ((*(info->
da))->type) {
696 #ifdef STATIC_ANALYZER
700 memset(n1, 0,
sizeof(n1));
713 decoded =
normify(&normalised, n1,
sizeof(n1), p, end - p, 4);
715 if ((n1[0] ==
'{') && (memchr(n1,
'}', decoded) != NULL)) {
716 RDEBUG2(
"Normalizing %s %s encoding, %zu bytes -> %zu bytes",
718 known_good->vp_length, decoded);
725 memcpy(n2, n1, decoded);
726 p = (
char const *)n2;
740 RDEBUG3(
"No {...} in &control.%pP, re-writing to %s", known_good, def->name);
742 RDEBUG2(
"No {...} in &control.%s, re-writing to %s", known_good->
da->name, def->name);
768 from_func = info->
func(ctx, request, known_good);
769 if (!from_func)
return NULL;
783 if (from_func != known_good) TALLOC_FREE(from_func);
786 if ((from_func != known_good) && (from_recurse != from_func)) TALLOC_FREE(from_func);
799 out = from_normify ? from_normify : known_good;
809 RWDEBUG3(
"&control.%pP too short, expected %zu bytes, got %zu bytes",
812 RWDEBUG2(
"&control.%s too short, expected %zu bytes, got %zu bytes",
816 if (
out != known_good) TALLOC_FREE(
out);
825 RWDEBUG3(
"&control.%pP too long, expected %zu bytes, got %zu bytes",
828 RWDEBUG2(
"&control.%s too long, expected %zu bytes, got %zu bytes",
840 RWDEBUG3(
"&control.%pP incorrect length, expected %zu bytes, got %zu bytes",
843 RWDEBUG2(
"&control.%s incorrect length, expected %zu bytes, got %zu bytes",
876 RDEBUG3(
"Replacing &control.%pP with &control.%pP",
880 RDEBUG2(
"Replacing &control.%s with &control.%s",
881 known_good->
da->name, new->da->name);
904 if (!
new)
return NULL;
911 if (new->da != known_good->
da) {
912 for (j = 0; j < allowed_attrs_len; j++)
if (allowed_attrs[j] == new->da)
return new;
961 RWDEBUG(
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
962 RWDEBUG(
"!!! Ignoring control.User-Password. Update your !!!");
963 RWDEBUG(
"!!! configuration so that the \"known good\" clear text !!!");
964 RWDEBUG(
"!!! password is in Password.Cleartext and NOT in !!!");
965 RWDEBUG(
"!!! User-Password. !!!");
966 RWDEBUG(
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
986 allowed_attrs, allowed_attrs_len,
991 RDEBUG3(
"Using \"known good\" %s password %pP",
996 RDEBUG2(
"Using \"known good\" %s password %s",
999 "<INVALID>"),
out->da->name);
1001 if (ephemeral) *ephemeral = (known_good !=
out);
1005 for (i = 0; i < allowed_attrs_len; i++) {
1006 if (allowed_attrs[i] != known_good->
da)
continue;
1009 allowed_attrs, allowed_attrs_len,
1022 PERROR(
"%s", __FUNCTION__);
1026 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
fr_dcursor_eval_t void const * uctx
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 int _password_init(UNUSED void *uctx)
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.
static int _password_free(UNUSED void *uctx)
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