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

Contents of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (show annotations)
Sun Jul 27 15:55:40 2003 UTC (20 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.12: +3 -4 lines
File MIME type: text/plain
Corrected appending of initialization vector to passwords file.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26