File: heimdal.c

package info (click to toggle)
krb5-strength 3.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,112 kB
  • sloc: ansic: 8,236; sh: 4,977; perl: 1,528; makefile: 181
file content (126 lines) | stat: -rw-r--r-- 3,671 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * Heimdal shared module API.
 *
 * This is the glue required for a Heimdal password quality check via a
 * dynamically loaded module.  Heimdal's shared module API doesn't have
 * separate initialization and shutdown functions, so provide a self-contained
 * function that looks up the dictionary path from krb5.conf and does all the
 * work.  This means that it does memory allocations on every call, which
 * isn't ideal, but it's probably not that slow.
 *
 * Of course, the external Heimdal strength checking program can be used
 * instead.
 *
 * Written by Russ Allbery <eagle@eyrie.org>
 * Copyright 2020, 2023 Russ Allbery <eagle@eyrie.org>
 * Copyright 2009, 2013
 *     The Board of Trustees of the Leland Stanford Junior University
 *
 * SPDX-License-Identifier: MIT
 */

#include <config.h>
#include <portable/krb5.h>
#include <portable/system.h>

#include <errno.h>
#ifdef HAVE_KADM5_KADM5_PWCHECK_H
#    include <kadm5/kadm5-pwcheck.h>
#endif

#include <plugin/internal.h>
#include <util/macros.h>

/* Skip this entire file if not building with Heimdal. */
#ifdef HAVE_KRB5_REALM


/*
 * Write a Kerberos error string to a message buffer, with an optional
 * prefix.
 */
static void
convert_error(krb5_context ctx, krb5_error_code code, const char *prefix,
              char *message, size_t length)
{
    const char *error;

    error = krb5_get_error_message(ctx, code);
    if (prefix == NULL)
        snprintf(message, length, "%s", error);
    else
        snprintf(message, length, "%s: %s", prefix, error);
    krb5_free_error_message(ctx, error);
}


/*
 * This is the single check function that we provide.  It does the glue
 * required to initialize our checks, convert the Heimdal arguments to the
 * strings we expect, and return the result.
 */
static int
heimdal_pwcheck(krb5_context ctx, krb5_principal principal,
                krb5_data *password, const char *tuning UNUSED, char *message,
                size_t length)
{
    krb5_pwqual_moddata data = NULL;
    char *pastring;
    char *name = NULL;
    krb5_error_code code;

    /* Convert the password to a C string. */
    pastring = malloc(password->length + 1);
    if (pastring == NULL) {
        snprintf(message, length, "cannot allocate memory: %s",
                 strerror(errno));
        return 1;
    }
    memcpy(pastring, password->data, password->length);
    pastring[password->length] = '\0';

    /* Initialize strength checking. */
    code = strength_init(ctx, NULL, &data);
    if (code != 0) {
        convert_error(ctx, code, NULL, message, length);
        goto done;
    }

    /* Convert the principal to a string. */
    code = krb5_unparse_name(ctx, principal, &name);
    if (code != 0) {
        convert_error(ctx, code, "cannot unparse principal", message, length);
        goto done;
    }

    /* Do the password strength check. */
    code = strength_check(ctx, data, name, pastring);
    if (code != 0)
        convert_error(ctx, code, NULL, message, length);

done:
    explicit_bzero(pastring, password->length);
    free(pastring);
    if (name != NULL)
        krb5_free_unparsed_name(ctx, name);
    if (data != NULL)
        strength_close(ctx, data);
    return (code == 0) ? 0 : 1;
}

/* The public symbol that Heimdal looks for. */
/* clang-format off */
static struct kadm5_pw_policy_check_func functions[] = {
    {"krb5-strength", heimdal_pwcheck},
    {NULL, NULL}
};
extern struct kadm5_pw_policy_verifier kadm5_password_verifier;
struct kadm5_pw_policy_verifier kadm5_password_verifier = {
    "krb5-strength",
    KADM5_PASSWD_VERSION_V1,
    "Russ Allbery",
    functions
};
/* clang-format on */

#endif /* HAVE_KRB5_REALM */