Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/kadm5/srv/pwqual_dict.c
39566 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* lib/kadm5/srv/pwqual_dict.c */
3
/*
4
* Copyright (C) 2010 by the Massachusetts Institute of Technology.
5
* All rights reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
/*
27
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
28
*/
29
30
/* Password quality module to look up passwords within the realm dictionary. */
31
32
#include "k5-platform.h"
33
#include <krb5/pwqual_plugin.h>
34
#include <sys/types.h>
35
#include <sys/stat.h>
36
#include <unistd.h>
37
#include <kadm5/admin.h>
38
#include "adm_proto.h"
39
#include <syslog.h>
40
#include "server_internal.h"
41
42
typedef struct dict_moddata_st {
43
char **word_list; /* list of word pointers */
44
char *word_block; /* actual word data */
45
unsigned int word_count; /* number of words */
46
} *dict_moddata;
47
48
49
/*
50
* Function: word_compare
51
*
52
* Purpose: compare two words in the dictionary.
53
*
54
* Arguments:
55
* w1 (input) pointer to first word
56
* w2 (input) pointer to second word
57
* <return value> result of strcmp
58
*
59
* Requires:
60
* w1 and w2 to point to valid memory
61
*
62
*/
63
64
static int
65
word_compare(const void *s1, const void *s2)
66
{
67
return (strcasecmp(*(const char **)s1, *(const char **)s2));
68
}
69
70
/*
71
* Function: init-dict
72
*
73
* Purpose: Initialize in memory word dictionary
74
*
75
* Arguments:
76
* none
77
* <return value> KADM5_OK on success errno on failure;
78
* (but success on ENOENT)
79
*
80
* Requires:
81
* If WORDFILE exists, it must contain a list of words,
82
* one word per-line.
83
*
84
* Effects:
85
* If WORDFILE exists, it is read into memory sorted for future
86
* use. If it does not exist, it syslogs an error message and returns
87
* success.
88
*
89
* Modifies:
90
* word_list to point to a chunk of allocated memory containing
91
* pointers to words
92
* word_block to contain the dictionary.
93
*
94
*/
95
96
static int
97
init_dict(dict_moddata dict, const char *dict_file)
98
{
99
int fd;
100
size_t len, i;
101
char *p, *t;
102
struct stat sb;
103
104
if (dict_file == NULL) {
105
krb5_klog_syslog(LOG_INFO,
106
_("No dictionary file specified, continuing without "
107
"one."));
108
return KADM5_OK;
109
}
110
if ((fd = open(dict_file, O_RDONLY)) == -1) {
111
if (errno == ENOENT) {
112
krb5_klog_syslog(LOG_ERR,
113
_("WARNING! Cannot find dictionary file %s, "
114
"continuing without one."), dict_file);
115
return KADM5_OK;
116
} else
117
return errno;
118
}
119
set_cloexec_fd(fd);
120
if (fstat(fd, &sb) == -1) {
121
close(fd);
122
return errno;
123
}
124
dict->word_block = malloc(sb.st_size + 1);
125
if (dict->word_block == NULL) {
126
(void)close(fd);
127
return ENOMEM;
128
}
129
if (read(fd, dict->word_block, sb.st_size) != sb.st_size) {
130
(void)close(fd);
131
return errno;
132
}
133
(void)close(fd);
134
dict->word_block[sb.st_size] = '\0';
135
136
p = dict->word_block;
137
len = sb.st_size;
138
while(len > 0 && (t = memchr(p, '\n', len)) != NULL) {
139
*t = '\0';
140
len -= t - p + 1;
141
p = t + 1;
142
dict->word_count++;
143
}
144
if ((dict->word_list = malloc(dict->word_count * sizeof(char *))) == NULL)
145
return ENOMEM;
146
p = dict->word_block;
147
for (i = 0; i < dict->word_count; i++) {
148
dict->word_list[i] = p;
149
p += strlen(p) + 1;
150
}
151
qsort(dict->word_list, dict->word_count, sizeof(char *), word_compare);
152
return KADM5_OK;
153
}
154
155
/*
156
* Function: destroy_dict
157
*
158
* Purpose: destroy in-core copy of dictionary.
159
*
160
* Arguments:
161
* none
162
* <return value> none
163
* Requires:
164
* nothing
165
* Effects:
166
* frees up memory occupied by word_list and word_block
167
* sets count back to 0, and resets the pointers to NULL
168
*
169
* Modifies:
170
* word_list, word_block, and word_count.
171
*
172
*/
173
174
static void
175
destroy_dict(dict_moddata dict)
176
{
177
if (dict == NULL)
178
return;
179
free(dict->word_list);
180
free(dict->word_block);
181
free(dict);
182
return;
183
}
184
185
/* Implement the password quality open method by reading in dict_file. */
186
static krb5_error_code
187
dict_open(krb5_context context, const char *dict_file,
188
krb5_pwqual_moddata *data)
189
{
190
krb5_error_code ret;
191
dict_moddata dict;
192
193
*data = NULL;
194
195
/* Allocate and initialize a dictionary structure. */
196
dict = malloc(sizeof(*dict));
197
if (dict == NULL)
198
return ENOMEM;
199
dict->word_list = NULL;
200
dict->word_block = NULL;
201
dict->word_count = 0;
202
203
/* Fill in the dictionary structure with data from dict_file. */
204
ret = init_dict(dict, dict_file);
205
if (ret != 0) {
206
destroy_dict(dict);
207
return ret;
208
}
209
210
*data = (krb5_pwqual_moddata)dict;
211
return 0;
212
}
213
214
/* Implement the password quality check method by checking the password
215
* against the dictionary, as well as against principal components. */
216
static krb5_error_code
217
dict_check(krb5_context context, krb5_pwqual_moddata data,
218
const char *password, const char *policy_name,
219
krb5_principal princ, const char **languages)
220
{
221
dict_moddata dict = (dict_moddata)data;
222
223
/* Don't check the dictionary for principals with no password policy. */
224
if (policy_name == NULL)
225
return 0;
226
227
/* Check against words in the dictionary if we successfully loaded one. */
228
if (dict->word_list != NULL &&
229
bsearch(&password, dict->word_list, dict->word_count, sizeof(char *),
230
word_compare) != NULL)
231
return KADM5_PASS_Q_DICT;
232
233
return 0;
234
}
235
236
/* Implement the password quality close method. */
237
static void
238
dict_close(krb5_context context, krb5_pwqual_moddata data)
239
{
240
destroy_dict((dict_moddata)data);
241
}
242
243
krb5_error_code
244
pwqual_dict_initvt(krb5_context context, int maj_ver, int min_ver,
245
krb5_plugin_vtable vtable)
246
{
247
krb5_pwqual_vtable vt;
248
249
if (maj_ver != 1)
250
return KRB5_PLUGIN_VER_NOTSUPP;
251
vt = (krb5_pwqual_vtable)vtable;
252
vt->name = "dict";
253
vt->open = dict_open;
254
vt->check = dict_check;
255
vt->close = dict_close;
256
return 0;
257
}
258
259