/[imapfilter]/imapfilter/passwd.c
ViewVC logotype

Contents of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (show annotations)
Sun May 25 01:02:35 2003 UTC (20 years, 11 months ago) by lefcha
Branch: MAIN
Changes since 1.10: +13 -10 lines
File MIME type: text/plain
Multiple bug fixes in concerning encrypted passwords, uninitialized array of accounts, missed a step of writing to file when encrypting the passwords.

1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <limits.h>
5
6 #include "config.h"
7 #include "imapfilter.h"
8 #include "data.h"
9
10 #ifdef ENCRYPTED_PASSWORDS
11 #include <openssl/evp.h>
12 #endif
13
14
15 extern unsigned int flags;
16 extern account_t *accounts;
17
18 #ifdef ENCRYPTED_PASSWORDS
19 extern char *passphr;
20
21 #endif
22
23 /*
24 * Get password from user interactively.
25 */
26 void
27 get_password(char *passwd, size_t pwlen)
28 {
29 char *c;
30
31 tty_disable_echo();
32
33 if (fgets(passwd, pwlen, stdin))
34 if ((c = strchr(passwd, '\n')))
35 *c = '\0';
36
37 tty_restore();
38
39 putchar('\n');
40 }
41
42
43 #ifdef ENCRYPTED_PASSWORDS
44 /*
45 * Encrypt and Base64 encode passwords. Append the MD5 checksum of the
46 * passwords before encrypting them.
47 */
48 int
49 encrypt_passwords(FILE * fd, account_t * accts[])
50 {
51 int i;
52 char *c;
53 unsigned char iv[EVP_MAX_IV_LENGTH];
54 unsigned char *key;
55 unsigned char buf[ENCRYPTION_BUF];
56 unsigned char ebuf[ENCRYPTION_BUF];
57 unsigned char bbuf[ENCRYPTION_BUF];
58 unsigned char mdv[EVP_MAX_MD_SIZE];
59 int mdl, ebufl, bbufl;
60 EVP_CIPHER_CTX ctx;
61 EVP_MD_CTX mdctx;
62 EVP_ENCODE_CTX bctx;
63
64 key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);
65
66 srandom(time(NULL));
67
68 /* Initialization vector. */
69 c = ultostr(1 + random() % 100000000, 10);
70 snprintf(iv, EVP_MAX_IV_LENGTH, "%.8s", c);
71 fprintf(fd, "%s\n", iv);
72
73 EVP_CIPHER_CTX_init(&ctx);
74
75 EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr), 1,
76 key, NULL);
77
78 EVP_DigestInit(&mdctx, EVP_md5());
79 EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
80 EVP_EncodeInit(&bctx);
81
82 for (i = 0; accts[i] != NULL; i++) {
83 snprintf(buf, ENCRYPTION_BUF, "%s %s %s\n", accts[i]->server,
84 accts[i]->username, accts[i]->password);
85
86 EVP_DigestUpdate(&mdctx, buf, strlen(buf));
87 EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
88 EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
89
90 fwrite(bbuf, sizeof(char), bbufl, fd);
91 }
92
93 EVP_DigestFinal(&mdctx, mdv, &mdl);
94
95 xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);
96
97 /* MD5 checksum of data. */
98 for (i = 0; i < mdl; i++)
99 snprintf(2 + buf + i * 2, ENCRYPTION_BUF - 3 - i * 2, "%02x",
100 mdv[i]);
101
102 EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
103 EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
104 fwrite(bbuf, sizeof(char), bbufl, fd);
105
106 EVP_EncryptFinal(&ctx, ebuf, &ebufl);
107
108 EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
109 fwrite(bbuf, sizeof(char), bbufl, fd);
110
111 EVP_EncodeFinal(&bctx, bbuf, &bbufl);
112 fwrite(bbuf, sizeof(char), bbufl, fd);
113
114 EVP_CIPHER_CTX_cleanup(&ctx);
115
116 return 0;
117 }
118
119
120 /*
121 * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.
122 */
123 int
124 decrypt_passwords(unsigned char **buf, FILE * fd)
125 {
126 int i, j;
127 unsigned char iv[EVP_MAX_IV_LENGTH];
128 unsigned char *key;
129 unsigned char *c;
130 unsigned char ebuf[LINE_MAX];
131 unsigned char bbuf[LINE_MAX];
132 unsigned char mdv[EVP_MAX_MD_SIZE];
133 unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];
134 int mdl, bufl, ebufl;
135 EVP_CIPHER_CTX *ctx;
136 EVP_MD_CTX mdctx;
137 EVP_ENCODE_CTX bctx;
138
139 j = 1;
140
141 c = *buf = (unsigned char *)smalloc(DECRYPTION_BUF * sizeof(char));
142 key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);
143 ctx = (EVP_CIPHER_CTX *) smalloc(sizeof(EVP_CIPHER_CTX));
144
145 fgets(bbuf, LINE_MAX, fd);
146
147 memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
148
149 EVP_CIPHER_CTX_init(ctx);
150
151 EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
152 1, key, NULL);
153
154 EVP_DecryptInit(ctx, EVP_bf_cbc(), key, iv);
155 EVP_DecodeInit(&bctx);
156
157 while (fgets(bbuf, LINE_MAX, fd)) {
158 EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
159 if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl))
160 goto fail;
161
162 c += bufl;
163 *c = '\0';
164
165 if (c - *buf > DECRYPTION_BUF * j - 64) {
166 i = c - *buf;
167 *buf = (char *)srealloc(*buf, DECRYPTION_BUF * ++j);
168 c = *buf + i;
169 *c = '\0';
170 }
171 }
172
173 EVP_DecodeFinal(&bctx, ebuf, &ebufl);
174 if (!EVP_DecryptFinal(ctx, c, &bufl))
175 goto fail;
176
177 c += bufl;
178 *c = '\0';
179
180 /* Calculate the MD5 checksum and check if it is correct. */
181 if (!(c = strstr(*buf, "\n.\n")))
182 goto fail;
183
184 EVP_DigestInit(&mdctx, EVP_md5());
185 EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);
186 EVP_DigestFinal(&mdctx, mdv, &mdl);
187
188 for (i = 0; i < mdl; i++)
189 snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x",
190 mdv[i]);
191
192 c += 3;
193
194 if (strncmp(c, mdc, 32))
195 goto fail;
196
197 EVP_CIPHER_CTX_cleanup(ctx);
198
199 sfree(key);
200 sfree(ctx);
201
202 return 0;
203
204 fail:
205 error("Wrong master passphrase.\n");
206 EVP_CIPHER_CTX_cleanup(ctx);
207 sfree(*buf);
208 sfree(key);
209 sfree(ctx);
210
211 return ERROR_DECRYPT;
212 }
213
214
215 /*
216 * Interactive encrypted passwords editor.
217 */
218 void
219 password_editor(void)
220 {
221 int i, q, n;
222 char buf[LINE_MAX];
223 char *c;
224 char *p[2];
225 account_t *a, *accts[EDITOR_PASSWORDS_MAX + 1];
226
227 if (!(flags & FLAG_BLANK_PASSWORD)) {
228 error("no candidate passwords for encryption found\n");
229 return;
230 }
231 q = 0;
232
233 memset(accts, 0, (EDITOR_PASSWORDS_MAX + 1) * sizeof(account_t *));
234
235 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX && a != NULL;
236 a = a->next) {
237 if (a->passwdattr == PASSWORD_NONE ||
238 a->passwdattr == PASSWORD_ENCRYPTED)
239 accts[i++] = a;
240 }
241
242 do {
243 printf("cmd: ");
244 fgets(buf, LINE_MAX, stdin);
245 c = buf;
246 for (;; c++) {
247 if (*c == ' ' || *c == '\t')
248 continue;
249 else if (*c == '?' || *c == 'h')
250 printf("c\tclear a password entry\n"
251 "e\tedit a password entry\n"
252 "h\thelp\n"
253 "l\tlist entries\n"
254 "p\tchange master password\n"
255 "q\tquit without saving\n"
256 "s\tsave changes\n"
257 "x\tsave and exit\n");
258 else if (*c == 'q')
259 q = 1;
260 else if (*c == 'l')
261 for (i = 0; accts[i] != NULL; i++)
262 printf("%d %s %s %s\n", i + 1,
263 accts[i]->server,
264 accts[i]->username,
265 accts[i]->password);
266 else if (*c == 'e') {
267 n = atoi(++c);
268 if (n == 0 || n < 1 ||
269 n > EDITOR_PASSWORDS_MAX ||
270 accts[n - 1] == NULL)
271 break;
272 accts[n - 1]->password[0] = '\0';
273 printf("Enter new password: ");
274 if (fgets(accts[n - 1]->password, PASSWORD_LEN,
275 stdin) &&
276 (c = strchr(accts[n - 1]->password, '\n')))
277 *c = '\0';
278 } else if (*c == 'c') {
279 n = atoi(++c);
280 if (n == 0 || n < 1 ||
281 n > EDITOR_PASSWORDS_MAX ||
282 accts[n - 1] == NULL)
283 break;
284 accts[n - 1]->password[0] = '\0';
285 } else if (*c == 'p') {
286 p[0] = (char *)smalloc(PASSPHRASE_LEN);
287 p[1] = (char *)smalloc(PASSPHRASE_LEN);
288 do {
289 for (i = 0; i < 2; i++) {
290 printf("Enter %snew master "
291 "password: ",
292 i ? "again " : "");
293 get_password(p[i],
294 PASSPHRASE_LEN);
295 }
296 } while (strcmp(p[0], p[1]));
297 xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
298 sfree(p[0]);
299 sfree(p[1]);
300 } else if (*c == 's' || *c == 'w') {
301 store_passwords(accts);
302 } else if (*c == 'x') {
303 store_passwords(accts);
304 q = 1;
305 } else
306 break;
307 }
308 } while (!q);
309 }
310
311 #endif /* ENCRYPTED_PASSWORDS */

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26