"Fossies" - the Fresh Open Source Software Archive 
Member "passwdqc-2.0.3/pwqcheck.c" (23 Jun 2023, 5618 Bytes) of package /linux/privat/passwdqc-2.0.3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "pwqcheck.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.4.0_vs_2.0.0.
1 /*
2 * Copyright (c) 2008,2009 by Dmitry V. Levin
3 * Copyright (c) 2010,2016,2021 by Solar Designer
4 * See LICENSE
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "passwdqc.h"
12
13 static void clean(char *dst, size_t size)
14 {
15 if (!dst)
16 return;
17 _passwdqc_memzero(dst, size);
18 free(dst);
19 }
20
21 static char *read_line(size_t size, int eof_ok)
22 {
23 char *p, *buf = malloc(size + 1);
24
25 if (!buf) {
26 fprintf(stderr, "pwqcheck: Memory allocation failed.\n");
27 return NULL;
28 }
29
30 if (!fgets(buf, size + 1, stdin)) {
31 clean(buf, size + 1);
32 if (!eof_ok || !feof(stdin) || ferror(stdin))
33 fprintf(stderr,
34 "pwqcheck: Error reading standard input.\n");
35 return NULL;
36 }
37
38 if (strlen(buf) >= size) {
39 clean(buf, size + 1);
40 fprintf(stderr, "pwqcheck: Line too long.\n");
41 return NULL;
42 }
43
44 if ((p = strpbrk(buf, "\r\n")))
45 *p = '\0';
46
47 return buf;
48 }
49
50 static char *extract_string(char **stringp)
51 {
52 char *token = *stringp, *colon;
53
54 if (!token)
55 return "";
56
57 colon = strchr(token, ':');
58 if (colon) {
59 *colon = '\0';
60 *stringp = colon + 1;
61 } else
62 *stringp = NULL;
63
64 return token;
65 }
66
67 static struct passwd *parse_pwline(char *line, struct passwd *pw)
68 {
69 if (!strchr(line, ':')) {
70 #ifdef _MSC_VER
71 memset(pw, 0, sizeof(*pw));
72 pw->pw_name = line;
73 #else
74 struct passwd *p = getpwnam(line);
75 endpwent();
76 if (!p) {
77 fprintf(stderr, "pwqcheck: User not found.\n");
78 return NULL;
79 }
80 if (p->pw_passwd)
81 _passwdqc_memzero(p->pw_passwd, strlen(p->pw_passwd));
82 memcpy(pw, p, sizeof(*pw));
83 #endif
84 } else {
85 memset(pw, 0, sizeof(*pw));
86 pw->pw_name = extract_string(&line);
87 pw->pw_passwd = extract_string(&line);
88 extract_string(&line); /* uid */
89 extract_string(&line); /* gid */
90 pw->pw_gecos = extract_string(&line);
91 pw->pw_dir = extract_string(&line);
92 pw->pw_shell = line ? line : "";
93 if (!*pw->pw_name || !*pw->pw_dir) {
94 fprintf(stderr, "pwqcheck: Invalid passwd entry.\n");
95 return NULL;
96 }
97 }
98 return pw;
99 }
100
101 static void
102 print_help(void)
103 {
104 puts("Check passphrase quality.\n"
105 "\nFor each passphrase to check, pwqcheck reads up to 3 lines from standard input:\n"
106 " first line is a new passphrase,\n"
107 " second line is an old passphrase, and\n"
108 " third line is either an existing account name or a passwd entry.\n"
109 "\nUsage: pwqcheck [options]\n"
110 "\nValid options are:\n"
111 " min=N0,N1,N2,N3,N4\n"
112 " set minimum allowed lengths for different kinds of passphrases;\n"
113 " max=N\n"
114 " set maximum allowed passphrase length;\n"
115 " passphrase=N\n"
116 " set number of words required for a passphrase;\n"
117 " match=N\n"
118 " set length of common substring in substring check;\n"
119 " similar=permit|deny\n"
120 " whether a new passphrase is allowed to be similar to the old one;\n"
121 " wordlist=FILE\n"
122 " deny passwords that are based on lines of a tiny external text file;\n"
123 " denylist=FILE\n"
124 " deny passphrases directly appearing in a tiny external text file;\n"
125 " filter=FILE\n"
126 " deny passphrases directly appearing in a maybe huge binary filter file;\n"
127 " config=FILE\n"
128 " load config FILE in passwdqc.conf format;\n"
129 " -1\n"
130 " read just 1 line (new passphrase);\n"
131 " -2\n"
132 " read just 2 lines (new and old passphrases);\n"
133 " --multi\n"
134 " check multiple passphrases (until EOF);\n"
135 " --version\n"
136 " print program version and exit;\n"
137 " -h or --help\n"
138 " print this help text and exit.");
139 }
140
141 int main(int argc, const char **argv)
142 {
143 passwdqc_params_t params;
144 const char *check_reason;
145 char *parse_reason, *newpass, *oldpass, *pwline;
146 struct passwd pwbuf, *pw;
147 int lines_to_read = 3, multi = 0;
148 size_t size = 8192;
149 int rc = 1;
150
151 while (argc > 1 && argv[1][0] == '-') {
152 const char *arg = argv[1];
153
154 if (!strcmp("-h", arg) || !strcmp("--help", arg)) {
155 print_help();
156 return 0;
157 }
158
159 if (!strcmp("--version", arg)) {
160 printf("pwqcheck version %s\n", PASSWDQC_VERSION);
161 return 0;
162 }
163
164 if ((arg[1] == '1' || arg[1] == '2') && !arg[2]) {
165 lines_to_read = arg[1] - '0';
166 goto next_arg;
167 }
168
169 if (!strcmp("--multi", arg)) {
170 multi = 1;
171 goto next_arg;
172 }
173
174 break;
175
176 next_arg:
177 argc--; argv++;
178 }
179
180 passwdqc_params_reset(¶ms);
181 if (argc > 1 &&
182 passwdqc_params_parse(¶ms, &parse_reason, argc - 1,
183 argv + 1)) {
184 fprintf(stderr, "pwqcheck: %s\n",
185 (parse_reason ? parse_reason : "Out of memory"));
186 free(parse_reason);
187 return rc;
188 }
189
190 if ((size_t)params.qc.max + 1 > size)
191 size = (size_t)params.qc.max + 1;
192
193 next_pass:
194 oldpass = pwline = NULL; pw = NULL;
195 if (!(newpass = read_line(size, multi))) {
196 if (multi && feof(stdin) && !ferror(stdin) &&
197 fflush(stdout) >= 0)
198 rc = 0;
199 goto done;
200 }
201 if (lines_to_read >= 2 && !(oldpass = read_line(size, 0)))
202 goto done;
203 if (lines_to_read >= 3 && (!(pwline = read_line(size, 0)) ||
204 !parse_pwline(pwline, pw = &pwbuf)))
205 goto done;
206
207 check_reason = passwdqc_check(¶ms.qc, newpass, oldpass, pw);
208 if (!check_reason) {
209 if (multi)
210 printf("OK: %s\n", newpass);
211 else if (puts("OK") >= 0 && fflush(stdout) >= 0)
212 rc = 0;
213 goto cleanup;
214 }
215 if (multi)
216 printf("Bad passphrase (%s): %s\n", check_reason, newpass);
217 else
218 printf("Bad passphrase (%s)\n", check_reason);
219
220 cleanup:
221 _passwdqc_memzero(&pwbuf, sizeof(pwbuf));
222 clean(pwline, size);
223 clean(oldpass, size);
224 clean(newpass, size);
225
226 if (multi)
227 goto next_pass;
228
229 passwdqc_params_free(¶ms);
230
231 return rc;
232
233 done:
234 multi = 0;
235 goto cleanup;
236 }