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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (hide annotations)
Thu Jun 20 08:49:23 2002 UTC (21 years, 9 months ago) by lefcha
Branch: MAIN
Changes since 1.6: +1 -0 lines
File MIME type: text/plain
Cipher CTX cleanup when failed.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26