]> eyrie.org Git - kerberos/krb5-strength.git/blob - tools/heimdal-strength.c
Change my email address to eagle@eyrie.org
[kerberos/krb5-strength.git] / tools / heimdal-strength.c
1 /*
2  * Password strength checking program for Heimdal.
3  *
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
7  * dictionary.
8  *
9  * Written by Russ Allbery <eagle@eyrie.org>
10  * Copyright 2009, 2013
11  *     The Board of Trustees of the Leland Stanford Junior University
12  *
13  * See LICENSE for licensing terms.
14  */
15
16 #include <config.h>
17 #include <portable/krb5.h>
18 #include <portable/system.h>
19
20 #include <errno.h>
21
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>
27
28
29 /*
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.
33  */
34 static void
35 read_key(const char *key, char *buffer, size_t length)
36 {
37     char *p;
38
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);
49     p += 2;
50     memmove(buffer, p, strlen(p) + 1);
51 }
52
53
54 /*
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
58  * context.
59  */
60 static void
61 check_password(krb5_context ctx, krb5_pwqual_moddata data)
62 {
63     char principal[BUFSIZ], password[BUFSIZ], end[BUFSIZ];
64     krb5_error_code code;
65     const char *message;
66
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);
74     if (code == 0)
75         printf("APPROVED\n");
76     else {
77         message = krb5_get_error_message(ctx, code);
78         fprintf(stderr, "%s\n", message);
79         krb5_free_error_message(ctx, message);
80     }
81 }
82
83
84 /*
85  * Main routine.  There will be one argument, the principal, but we ignore it
86  * (we get it again via the input data).
87  *
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.
90  */
91 int
92 main(int argc, char *argv[] UNUSED)
93 {
94     krb5_context ctx;
95     krb5_error_code code;
96     krb5_pwqual_moddata data;
97
98     /* Check command-line arguments. */
99     if (argc != 1 && argc != 2)
100         die("Usage: heimdal-strength <principal>");
101
102     /* Initialize Kerberos and the module. */
103     code = krb5_init_context(&ctx);
104     if (code != 0)
105         die_krb5(ctx, code, "Cannot create Kerberos context");
106     code = strength_init(ctx, NULL, &data);
107     if (code != 0)
108         die_krb5(ctx, code, "Cannot initialize strength checking");
109
110     /* Check the password and report results. */
111     check_password(ctx, data);
112
113     /* Close and free resources. */
114     strength_close(ctx, data);
115     krb5_free_context(ctx);
116     exit(0);
117 }