4 * The public APIs of the password strength checking kadmind plugin.
6 * Provides the public pwcheck_init, pwcheck_check, and pwcheck_close APIs for
16 * Used to store local state. Currently, all we have is the dictionary path,
17 * which we get from kadmind rather than from krb5.conf since it's already a
24 /* The public function exported by the cracklib library. */
25 extern char *FascistCheck(const char *password, const char *dict);
28 * Initialize the module. Ensure that the dictionary file exists and is
29 * readable and store the path in the module context. Returns 0 on success,
30 * non-zero on failure. This function returns failure only if it could not
33 * The dictionary file should not include the trailing .pwd extension.
34 * Currently, we don't cope with a NULL dictionary path.
37 pwcheck_init(void **context, const char *dictionary)
43 if (dictionary == NULL)
45 length = strlen(dictionary) + strlen(".pwd") + 1;
46 path = malloc(length);
49 snprintf(path, length, "%s.pwd", dictionary);
50 if (access(path, R_OK) != 0)
52 path[strlen(path) - strlen(".pwd")] = '\0';
53 ctx = malloc(sizeof(struct context));
56 ctx->dictionary = path;
63 * Check a given password. Takes our local context, the password, the
64 * principal the password is for, and a buffer and buffer length into which to
65 * put any failure message.
68 pwcheck_check(void *context, const char *password, const char *principal,
69 char *errstr, int errstrlen)
75 struct context *ctx = context;
78 * We get the principal (in krb5_unparse_name format) from kadmind and we
79 * want to be sure that the password doesn't match the username or the
80 * username reversed. We therefore have to copy the string so that we can
81 * manipulate it a bit.
83 if (strcasecmp(password, principal) == 0) {
84 snprintf(errstr, errstrlen, "Password based on username");
85 errstr[errstrlen - 1] = '\0';
88 user = strdup(principal);
90 snprintf(errstr, errstrlen, "Cannot allocate memory");
91 errstr[errstrlen - 1] = '\0';
94 for (p = user; p[0] != '\0'; p++) {
95 if (p[0] == '\\' && p[1] != '\0') {
104 if (strlen(password) == strlen(user)) {
105 if (strcasecmp(password, user) == 0) {
107 snprintf(errstr, errstrlen, "Password based on username");
108 errstr[errstrlen - 1] = '\0';
111 for (i = 0, j = strlen(user) - 1; i < j; i++, j--) {
116 if (strcasecmp(password, user) == 0) {
118 snprintf(errstr, errstrlen, "Password based on username");
119 errstr[errstrlen - 1] = '\0';
124 result = FascistCheck(password, ctx->dictionary);
125 if (result != NULL) {
126 strncpy(errstr, result, errstrlen);
127 errstr[errstrlen - 1] = '\0';
135 * Cleanly shut down the password strength plugin. The only thing we have to
136 * do is free our context memory.
139 pwcheck_close(void *context)
141 struct context *ctx = context;
144 if (ctx->dictionary != NULL)
145 free(ctx->dictionary);