2 * Password strength checking program for Heimdal.
4 * This is a wrapper around the krb5-strength-modified version of CrackLib
5 * that supports the Heimdal external password strength check program
6 * interface. It uses a krb5.conf parameter to determine the location of its
9 * Written by Russ Allbery <eagle@eyrie.org>
10 * Copyright 2020 Russ Allbery <eagle@eyrie.org>
11 * Copyright 2009, 2013
12 * The Board of Trustees of the Leland Stanford Junior University
14 * SPDX-License-Identifier: MIT
18 #include <portable/krb5.h>
19 #include <portable/system.h>
23 #include <plugin/internal.h>
24 #include <util/macros.h>
25 #include <util/messages-krb5.h>
26 #include <util/messages.h>
27 #include <util/xmalloc.h>
31 * Read a key/value pair from stdin, check that the key is the one expected,
32 * and if so, copy the value into the provided buffer. Exits with an
33 * appropriate error on failure.
36 read_key(const char *key, char *buffer, size_t length)
39 int size = (length < INT_MAX) ? (int) length : INT_MAX;
41 if (fgets(buffer, size, stdin) == NULL)
42 sysdie("Cannot read %s", key);
43 if (strlen(buffer) < 1 || buffer[strlen(buffer) - 1] != '\n')
44 die("Malformed or too long %s line", key);
45 buffer[strlen(buffer) - 1] = '\0';
46 if (strncmp(buffer, key, strlen(key)) != 0)
47 die("Malformed %s line", key);
48 p = buffer + strlen(key);
49 if (p[0] != ':' || p[1] != ' ')
50 die("Malformed %s line", key);
52 memmove(buffer, p, strlen(p) + 1);
57 * Read a principal and password from standard input and do strength checking
58 * on that principal and password, returning the results expected by the
59 * Heimdal external-check interface. Takes the password strength checking
63 check_password(krb5_context ctx, krb5_pwqual_moddata data)
65 char principal[BUFSIZ], password[BUFSIZ], end[BUFSIZ];
69 read_key("principal", principal, sizeof(principal));
70 read_key("new-password", password, sizeof(password));
71 if (fgets(end, sizeof(end), stdin) == NULL)
72 sysdie("Cannot read end of entry");
73 if (strcmp(end, "end\n") != 0)
74 die("Malformed end line");
75 code = strength_check(ctx, data, principal, password);
79 message = krb5_get_error_message(ctx, code);
80 fprintf(stderr, "%s\n", message);
81 krb5_free_error_message(ctx, message);
87 * Main routine. There will be one argument, the principal, but we ignore it
88 * (we get it again via the input data).
90 * Heimdal 1.3 appears to pass the principal as argv[0], where the name of the
91 * program would normally be, so allow for that behavior as well.
94 main(int argc, char *argv[] UNUSED)
98 krb5_pwqual_moddata data;
100 /* Check command-line arguments. */
101 if (argc != 1 && argc != 2)
102 die("Usage: heimdal-strength <principal>");
104 /* Initialize Kerberos and the module. */
105 code = krb5_init_context(&ctx);
107 die_krb5(ctx, code, "Cannot create Kerberos context");
108 code = strength_init(ctx, NULL, &data);
110 die_krb5(ctx, code, "Cannot initialize strength checking");
112 /* Check the password and report results. */
113 check_password(ctx, data);
115 /* Close and free resources. */
116 strength_close(ctx, data);
117 krb5_free_context(ctx);