* krb5_appdefaults_* functions.
*
* Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2016 Russ Allbery <eagle@eyrie.org>
* Copyright 2013
* The Board of Trustees of the Leland Stanford Junior University
*
- * See LICENSE for licensing terms.
+ * SPDX-License-Identifier: MIT
*/
#include <config.h>
typedef krb5_data *realm_type;
#endif
+/* Maximum number of character classes. */
+#define MAX_CLASSES 4
+
/*
* Obtain the default realm and translate it into the format required by
return NULL;
code = krb5_get_default_realm(ctx, &realm);
if (code != 0) {
- free(realm);
+ free(realm_data);
return NULL;
}
realm_data->magic = KV5M_DATA;
krb5_free_default_realm(ctx, realm);
return NULL;
}
- realm_data->length = strlen(realm);
+ realm_data->length = (unsigned int) strlen(realm);
krb5_free_default_realm(ctx, realm);
return realm_data;
}
struct vector *classes = NULL;
size_t i;
krb5_error_code code;
- const char *end;
+ const char *class, *end;
bool okay;
/* Create the basic rule structure. */
*rule = calloc(1, sizeof(struct class_rule));
+ if (*rule == NULL)
+ return strength_error_system(ctx, "cannot allocate memory");
/*
- * If the rule starts with a digit, it starts with a range of affected
- * password lengths. Parse that range.
+ * If the rule starts with a digit and contains a '-', it starts
+ * with a range of affected password lengths. Parse that range.
*/
- if (isdigit((unsigned char) *spec)) {
+ if (isdigit((unsigned char) *spec) && strchr(spec, '-') != NULL) {
okay = parse_number(spec, &(*rule)->min, &end);
if (okay)
okay = (*end == '-');
if (okay)
spec = end + 1;
else {
- code = strength_error_config(ctx, "bad character class requirement"
- " in configuration: %s", spec);
+ code = strength_error_config(ctx,
+ "bad character class requirement in"
+ " configuration: %s",
+ spec);
goto fail;
}
}
* unknown character class.
*/
for (i = 0; i < classes->count; i++) {
- if (strcmp(classes->strings[i], "upper") == 0)
+ class = classes->strings[i];
+ if (strcmp(class, "upper") == 0)
(*rule)->upper = true;
- else if (strcmp(classes->strings[i], "lower") == 0)
+ else if (strcmp(class, "lower") == 0)
(*rule)->lower = true;
- else if (strcmp(classes->strings[i], "digit") == 0)
+ else if (strcmp(class, "digit") == 0)
(*rule)->digit = true;
- else if (strcmp(classes->strings[i], "symbol") == 0)
+ else if (strcmp(class, "symbol") == 0)
(*rule)->symbol = true;
- else {
+ else if (isdigit((unsigned char) *class)) {
+ okay = parse_number(class, &(*rule)->num_classes, &end);
+ if (!okay || *end != '\0' || (*rule)->num_classes > MAX_CLASSES) {
+ code = strength_error_config(ctx,
+ "bad character class minimum in"
+ " configuration: %s",
+ class);
+ goto fail;
+ }
+ } else {
code = strength_error_config(ctx, "unknown character class %s",
- classes->strings[i]);
+ class);
goto fail;
}
}
/* Each word in the list will be a class rule. */
code = parse_class(ctx, config->strings[0], &rules);
- if (code != 0)
+ if (code != 0 || rules == NULL)
goto fail;
last = rules;
for (i = 1; i < config->count; i++) {
code = parse_class(ctx, config->strings[i], &last->next);
- if (code != 0)
+ if (code != 0 || last->next == NULL)
goto fail;
last = last->next;
}
* allocation failed while parsing or while setting the default value.
*/
krb5_error_code
-strength_config_list(krb5_context ctx, const char *opt,
- struct vector **result)
+strength_config_list(krb5_context ctx, const char *opt, struct vector **result)
{
realm_type realm;
char *value = NULL;