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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8.2.2 - (hide annotations)
Mon May 26 08:14:17 2003 UTC (20 years, 10 months ago) by lefcha
Branch: release-0_8-patches
Changes since 1.8.2.1: +1 -1 lines
File MIME type: text/plain
Fixed bug related to ivec causing problems during encryption/decryption of 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.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.8
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.8 int encrypt_passwords(FILE * fd, account_t * accts[])
47 lefcha 1.1 {
48 lefcha 1.8 int i;
49 lefcha 1.2 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.8
61     key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);
62 lefcha 1.2
63     srandom(time(NULL));
64    
65 lefcha 1.8 /* Initialization vector. */
66 lefcha 1.2 c = ultostr(1 + random() % 100000000, 10);
67 lefcha 1.8.2.2 snprintf(iv, EVP_MAX_IV_LENGTH, "%08s", c);
68 lefcha 1.8.2.1 fprintf(fd, "%s\n", iv);
69 lefcha 1.2
70     EVP_CIPHER_CTX_init(&ctx);
71    
72     EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr), 1,
73     key, NULL);
74 lefcha 1.8
75 lefcha 1.2 EVP_DigestInit(&mdctx, EVP_md5());
76     EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
77     EVP_EncodeInit(&bctx);
78    
79     for (i = 0; accts[i]; i++) {
80     snprintf(buf, ENCRYPTION_BUF, "%s %s %s\n", accts[i]->server, accts[i]->username,
81     accts[i]->password);
82    
83     EVP_DigestUpdate(&mdctx, buf, strlen(buf));
84     EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
85     EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
86 lefcha 1.6
87 lefcha 1.2 fwrite(bbuf, sizeof(char), bbufl, fd);
88     }
89    
90     EVP_DigestFinal(&mdctx, mdv, &mdl);
91 lefcha 1.8
92 lefcha 1.2 xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);
93 lefcha 1.8
94     /* MD5 checksum of data. */
95 lefcha 1.2 for (i = 0; i < mdl; i++)
96 lefcha 1.8.2.1 snprintf(2 + buf + i * 2, ENCRYPTION_BUF - 3 - i * 2, "%02x", mdv[i]);
97 lefcha 1.8
98 lefcha 1.2 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 lefcha 1.8.2.1
104 lefcha 1.2 EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
105 lefcha 1.8.2.1 fwrite(bbuf, sizeof(char), bbufl, fd);
106 lefcha 1.8
107 lefcha 1.8.2.1 EVP_EncodeFinal(&bctx, bbuf, &bbufl);
108 lefcha 1.2 fwrite(bbuf, sizeof(char), bbufl, fd);
109    
110     EVP_CIPHER_CTX_cleanup(&ctx);
111 lefcha 1.8
112 lefcha 1.2 return 0;
113 lefcha 1.1 }
114    
115    
116     /*
117 lefcha 1.3 * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.
118 lefcha 1.1 */
119 lefcha 1.8 int decrypt_passwords(unsigned char **buf, FILE * fd)
120 lefcha 1.1 {
121 lefcha 1.2 int i, j = 1;
122     unsigned char iv[EVP_MAX_IV_LENGTH];
123 lefcha 1.3 unsigned char *key;
124     unsigned char *c;
125 lefcha 1.2 unsigned char ebuf[LINE_MAX];
126     unsigned char bbuf[LINE_MAX];
127     unsigned char mdv[EVP_MAX_MD_SIZE];
128     unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];
129     int mdl, bufl, ebufl;
130 lefcha 1.3 EVP_CIPHER_CTX *ctx;
131 lefcha 1.2 EVP_MD_CTX mdctx;
132     EVP_ENCODE_CTX bctx;
133 lefcha 1.8
134     c = *buf = (unsigned char *)smalloc(DECRYPTION_BUF * sizeof(char));
135     key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);
136 lefcha 1.3 ctx = (EVP_CIPHER_CTX *) smalloc(sizeof(EVP_CIPHER_CTX));
137 lefcha 1.8
138 lefcha 1.2 fgets(bbuf, LINE_MAX, fd);
139    
140     memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
141 lefcha 1.6
142 lefcha 1.3 EVP_CIPHER_CTX_init(ctx);
143 lefcha 1.2
144     EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
145     1, key, NULL);
146 lefcha 1.8
147 lefcha 1.3 EVP_DecryptInit(ctx, EVP_bf_cbc(), key, iv);
148 lefcha 1.2 EVP_DecodeInit(&bctx);
149    
150     while (fgets(bbuf, LINE_MAX, fd)) {
151     EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
152 lefcha 1.6 if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl))
153     goto fail;
154    
155 lefcha 1.2 c += bufl;
156     *c = 0;
157 lefcha 1.6
158     if (c - *buf > DECRYPTION_BUF * j - 64) {
159     i = c - *buf;
160 lefcha 1.8 *buf = (char *)srealloc(*buf, DECRYPTION_BUF * ++j);
161 lefcha 1.6 c = *buf + i;
162     *c = 0;
163     }
164 lefcha 1.2 }
165 lefcha 1.8
166 lefcha 1.6 EVP_DecodeFinal(&bctx, ebuf, &ebufl);
167     if (!EVP_DecryptFinal(ctx, c, &bufl))
168     goto fail;
169 lefcha 1.2
170     c += bufl;
171     *c = 0;
172 lefcha 1.6
173 lefcha 1.8 /* Calculate the MD5 checksum and check if it is correct. */
174 lefcha 1.6 if (!(c = strstr(*buf, "\n.\n")))
175     goto fail;
176    
177     EVP_DigestInit(&mdctx, EVP_md5());
178     EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);
179     EVP_DigestFinal(&mdctx, mdv, &mdl);
180 lefcha 1.8
181 lefcha 1.6 for (i = 0; i < mdl; i++)
182     snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x", mdv[i]);
183 lefcha 1.8
184 lefcha 1.6 c += 3;
185    
186     if (strncmp(c, mdc, 32))
187     goto fail;
188 lefcha 1.2
189 lefcha 1.3 EVP_CIPHER_CTX_cleanup(ctx);
190 lefcha 1.8
191 lefcha 1.3 sfree(key);
192     sfree(ctx);
193 lefcha 1.8
194 lefcha 1.2 return 0;
195 lefcha 1.6
196     fail:
197     error("Wrong master passphrase.\n");
198 lefcha 1.8 EVP_CIPHER_CTX_cleanup(ctx);
199 lefcha 1.6 sfree(*buf);
200     sfree(key);
201     sfree(ctx);
202 lefcha 1.8
203 lefcha 1.6 return ERROR_DECRYPT;
204 lefcha 1.2 }
205    
206    
207     /*
208     * Interactive encrypted passwords editor.
209     */
210     void password_editor(void)
211     {
212     int i, q, n;
213     char buf[LINE_MAX];
214     char *c;
215 lefcha 1.3 char *p[2];
216 lefcha 1.8.2.1 account_t *a, *accts[EDITOR_PASSWORDS_MAX + 1];
217 lefcha 1.8
218 lefcha 1.5 if (!(flags & FLAG_BLANK_PASSWORD)) {
219     error("imapfilter: no candidate passwords for encryption found\n");
220     return;
221     }
222 lefcha 1.2 q = 0;
223 lefcha 1.8
224 lefcha 1.8.2.1 memset(accts, 0, (EDITOR_PASSWORDS_MAX + 1) * sizeof(account_t *));
225 lefcha 1.2
226 lefcha 1.8.2.1 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX && a; a = a->next) {
227 lefcha 1.2 if (a->passwdattr == PASSWORD_NONE ||
228     a->passwdattr == PASSWORD_ENCRYPTED)
229     accts[i++] = a;
230     }
231    
232     do {
233     printf("command: ");
234     fgets(buf, LINE_MAX, stdin);
235     c = buf;
236     for (;; c++) {
237     if (*c == ' ' || *c == '\t')
238     continue;
239     else if (*c == '?' || *c == 'h')
240     printf("c clear a password entry\n"
241     "e edit a password entry\n"
242     "h help\n"
243     "l list entries\n"
244     "p change master password\n"
245     "q quit without saving\n"
246 lefcha 1.6 "s save changes\n"
247 lefcha 1.2 "x save and exit\n");
248     else if (*c == 'q')
249     q = 1;
250     else if (*c == 'l')
251     for (i = 0; accts[i]; i++)
252     printf("%d %s %s %s\n", i + 1, accts[i]->server,
253     accts[i]->username, accts[i]->password);
254     else if (*c == 'e') {
255     n = atoi(++c);
256 lefcha 1.8.2.1 if (!n || n < 1 || n > EDITOR_PASSWORDS_MAX || !accts[n - 1])
257 lefcha 1.2 break;
258     accts[n - 1]->password[0] = 0;
259     printf("Enter new password: ");
260     if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
261     if ((c = strchr(accts[n - 1]->password, '\n')))
262     *c = 0;
263     } else if (*c == 'c') {
264     n = atoi(++c);
265 lefcha 1.8.2.1 if (!n || n < 1 || n > EDITOR_PASSWORDS_MAX || !accts[n - 1])
266 lefcha 1.2 break;
267     accts[n - 1]->password[0] = 0;
268     } else if (*c == 'p') {
269 lefcha 1.8 p[0] = (char *)smalloc(PASSPHRASE_LEN);
270     p[1] = (char *)smalloc(PASSPHRASE_LEN);
271 lefcha 1.2 do {
272     for (i = 0; i < 2; i++) {
273     printf("Enter %snew master password: ",
274     i ? "again " : "");
275     get_password(p[i], PASSPHRASE_LEN);
276     }
277     } while (strcmp(p[0], p[1]));
278     xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
279 lefcha 1.4 sfree(p[0]);
280     sfree(p[1]);
281 lefcha 1.6 } else if (*c == 's') {
282     store_passwords(accts);
283 lefcha 1.2 } else if (*c == 'x') {
284     store_passwords(accts);
285     q = 1;
286     } else
287     break;
288     }
289     } while (!q);
290 lefcha 1.1 }
291 lefcha 1.8
292 lefcha 1.2 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26