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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (hide 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 lefcha 1.1 #include <stdio.h>
2     #include <string.h>
3 lefcha 1.2 #include <stdlib.h>
4     #include <limits.h>
5 lefcha 1.1
6 lefcha 1.2 #include "config.h"
7 lefcha 1.1 #include "imapfilter.h"
8     #include "data.h"
9    
10 lefcha 1.2 #ifdef ENCRYPTED_PASSWORDS
11     #include <openssl/evp.h>
12     #endif
13 lefcha 1.1
14    
15 lefcha 1.5 extern unsigned int flags;
16 lefcha 1.2 extern account_t *accounts;
17    
18     #ifdef ENCRYPTED_PASSWORDS
19 lefcha 1.3 extern char *passphr;
20 lefcha 1.9
21 lefcha 1.2 #endif
22 lefcha 1.1
23     /*
24     * Get password from user interactively.
25     */
26 lefcha 1.9 void
27     get_password(char *passwd, size_t pwlen)
28 lefcha 1.1 {
29 lefcha 1.9 char *c;
30 lefcha 1.2
31 lefcha 1.9 tty_disable_echo();
32 lefcha 1.8
33 lefcha 1.9 if (fgets(passwd, pwlen, stdin))
34     if ((c = strchr(passwd, '\n')))
35     *c = '\0';
36 lefcha 1.2
37 lefcha 1.9 tty_restore();
38 lefcha 1.1
39 lefcha 1.9 putchar('\n');
40 lefcha 1.1 }
41    
42    
43 lefcha 1.2 #ifdef ENCRYPTED_PASSWORDS
44 lefcha 1.1 /*
45 lefcha 1.9 * Encrypt and Base64 encode passwords. Append the MD5 checksum of the
46     * passwords before encrypting them.
47 lefcha 1.1 */
48 lefcha 1.9 int
49     encrypt_passwords(FILE * fd, account_t * accts[])
50 lefcha 1.1 {
51 lefcha 1.9 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 lefcha 1.11 snprintf(iv, EVP_MAX_IV_LENGTH, "%.8s", c);
71     fprintf(fd, "%s\n", iv);
72 lefcha 1.9
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 lefcha 1.2
90 lefcha 1.9 fwrite(bbuf, sizeof(char), bbufl, fd);
91     }
92 lefcha 1.6
93 lefcha 1.9 EVP_DigestFinal(&mdctx, mdv, &mdl);
94 lefcha 1.2
95 lefcha 1.9 xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);
96 lefcha 1.8
97 lefcha 1.9 /* MD5 checksum of data. */
98     for (i = 0; i < mdl; i++)
99 lefcha 1.11 snprintf(2 + buf + i * 2, ENCRYPTION_BUF - 3 - i * 2, "%02x",
100 lefcha 1.9 mdv[i]);
101 lefcha 1.8
102 lefcha 1.9 EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
103     EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
104     fwrite(bbuf, sizeof(char), bbufl, fd);
105 lefcha 1.8
106 lefcha 1.9 EVP_EncryptFinal(&ctx, ebuf, &ebufl);
107 lefcha 1.11
108 lefcha 1.9 EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
109 lefcha 1.11 fwrite(bbuf, sizeof(char), bbufl, fd);
110    
111 lefcha 1.9 EVP_EncodeFinal(&bctx, bbuf, &bbufl);
112     fwrite(bbuf, sizeof(char), bbufl, fd);
113 lefcha 1.8
114 lefcha 1.9 EVP_CIPHER_CTX_cleanup(&ctx);
115 lefcha 1.2
116 lefcha 1.9 return 0;
117 lefcha 1.1 }
118    
119    
120     /*
121 lefcha 1.3 * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.
122 lefcha 1.1 */
123 lefcha 1.9 int
124     decrypt_passwords(unsigned char **buf, FILE * fd)
125 lefcha 1.1 {
126 lefcha 1.9 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 lefcha 1.6 }
172 lefcha 1.8
173 lefcha 1.9 EVP_DecodeFinal(&bctx, ebuf, &ebufl);
174     if (!EVP_DecryptFinal(ctx, c, &bufl))
175     goto fail;
176 lefcha 1.2
177 lefcha 1.9 c += bufl;
178     *c = '\0';
179 lefcha 1.6
180 lefcha 1.9 /* Calculate the MD5 checksum and check if it is correct. */
181     if (!(c = strstr(*buf, "\n.\n")))
182     goto fail;
183 lefcha 1.6
184 lefcha 1.9 EVP_DigestInit(&mdctx, EVP_md5());
185     EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);
186     EVP_DigestFinal(&mdctx, mdv, &mdl);
187 lefcha 1.8
188 lefcha 1.9 for (i = 0; i < mdl; i++)
189     snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x",
190     mdv[i]);
191 lefcha 1.8
192 lefcha 1.9 c += 3;
193 lefcha 1.6
194 lefcha 1.9 if (strncmp(c, mdc, 32))
195     goto fail;
196 lefcha 1.2
197 lefcha 1.9 EVP_CIPHER_CTX_cleanup(ctx);
198 lefcha 1.8
199 lefcha 1.9 sfree(key);
200     sfree(ctx);
201 lefcha 1.8
202 lefcha 1.9 return 0;
203 lefcha 1.6
204     fail:
205 lefcha 1.9 error("Wrong master passphrase.\n");
206     EVP_CIPHER_CTX_cleanup(ctx);
207     sfree(*buf);
208     sfree(key);
209     sfree(ctx);
210 lefcha 1.8
211 lefcha 1.9 return ERROR_DECRYPT;
212 lefcha 1.2 }
213    
214    
215     /*
216     * Interactive encrypted passwords editor.
217     */
218 lefcha 1.9 void
219     password_editor(void)
220 lefcha 1.2 {
221 lefcha 1.9 int i, q, n;
222     char buf[LINE_MAX];
223     char *c;
224     char *p[2];
225 lefcha 1.11 account_t *a, *accts[EDITOR_PASSWORDS_MAX + 1];
226 lefcha 1.9
227     if (!(flags & FLAG_BLANK_PASSWORD)) {
228     error("no candidate passwords for encryption found\n");
229     return;
230 lefcha 1.2 }
231 lefcha 1.9 q = 0;
232    
233 lefcha 1.11 memset(accts, 0, (EDITOR_PASSWORDS_MAX + 1) * sizeof(account_t *));
234 lefcha 1.9
235 lefcha 1.11 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX && a != NULL;
236 lefcha 1.9 a = a->next) {
237     if (a->passwdattr == PASSWORD_NONE ||
238     a->passwdattr == PASSWORD_ENCRYPTED)
239     accts[i++] = a;
240     }
241    
242     do {
243 lefcha 1.10 printf("cmd: ");
244 lefcha 1.9 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 lefcha 1.11 if (n == 0 || n < 1 ||
269     n > EDITOR_PASSWORDS_MAX ||
270 lefcha 1.9 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 lefcha 1.11 if (n == 0 || n < 1 ||
281     n > EDITOR_PASSWORDS_MAX ||
282 lefcha 1.9 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 lefcha 1.10 } else if (*c == 's' || *c == 'w') {
301 lefcha 1.9 store_passwords(accts);
302     } else if (*c == 'x') {
303     store_passwords(accts);
304     q = 1;
305     } else
306     break;
307     }
308     } while (!q);
309 lefcha 1.1 }
310 lefcha 1.8
311 lefcha 1.9 #endif /* ENCRYPTED_PASSWORDS */

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26