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 2009, 2013
11 * The Board of Trustees of the Leland Stanford Junior University
13 * See LICENSE for licensing terms.
17 #include <portable/krb5.h>
18 #include <portable/system.h>
22 #include <plugin/internal.h>
23 #include <util/macros.h>
24 #include <util/messages.h>
25 #include <util/messages-krb5.h>
26 #include <util/xmalloc.h>
30 * Read a key/value pair from stdin, check that the key is the one expected,
31 * and if so, copy the value into the provided buffer. Exits with an
32 * appropriate error on failure.
35 read_key(const char *key, char *buffer, size_t length)
39 if (fgets(buffer, length, stdin) == NULL)
40 sysdie("Cannot read %s", key);
41 if (strlen(buffer) < 1 || buffer[strlen(buffer) - 1] != '\n')
42 die("Malformed or too long %s line", key);
43 buffer[strlen(buffer) - 1] = '\0';
44 if (strncmp(buffer, key, strlen(key)) != 0)
45 die("Malformed %s line", key);
46 p = buffer + strlen(key);
47 if (p[0] != ':' || p[1] != ' ')
48 die("Malformed %s line", key);
50 memmove(buffer, p, strlen(p) + 1);
55 * Read a principal and password from standard input and do strength checking
56 * on that principal and password, returning the results expected by the
57 * Heimdal external-check interface. Takes the password strength checking
61 check_password(krb5_context ctx, krb5_pwqual_moddata data)
63 char principal[BUFSIZ], password[BUFSIZ], end[BUFSIZ];
67 read_key("principal", principal, sizeof(principal));
68 read_key("new-password", password, sizeof(password));
69 if (fgets(end, sizeof(end), stdin) == NULL)
70 sysdie("Cannot read end of entry");
71 if (strcmp(end, "end\n") != 0)
72 die("Malformed end line");
73 code = strength_check(ctx, data, principal, password);
77 message = krb5_get_error_message(ctx, code);
78 fprintf(stderr, "%s\n", message);
79 krb5_free_error_message(ctx, message);
85 * Main routine. There will be one argument, the principal, but we ignore it
86 * (we get it again via the input data).
88 * Heimdal 1.3 appears to pass the principal as argv[0], where the name of the
89 * program would normally be, so allow for that behavior as well.
92 main(int argc, char *argv[] UNUSED)
96 krb5_pwqual_moddata data;
98 /* Check command-line arguments. */
99 if (argc != 1 && argc != 2)
100 die("Usage: heimdal-strength <principal>");
102 /* Initialize Kerberos and the module. */
103 code = krb5_init_context(&ctx);
105 die_krb5(ctx, code, "Cannot create Kerberos context");
106 code = strength_init(ctx, NULL, &data);
108 die_krb5(ctx, code, "Cannot initialize strength checking");
110 /* Check the password and report results. */
111 check_password(ctx, data);
113 /* Close and free resources. */
114 strength_close(ctx, data);
115 krb5_free_context(ctx);