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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations)
Tue Jun 18 21:21:09 2002 UTC (21 years, 9 months ago) by lefcha
Branch: MAIN
Changes since 1.5: +44 -40 lines
File MIME type: text/plain
Bug fixes and improvements.

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     sfree(*buf);
196     sfree(key);
197     sfree(ctx);
198    
199     return ERROR_DECRYPT;
200 lefcha 1.2 }
201    
202    
203     /*
204     * Interactive encrypted passwords editor.
205     */
206     void password_editor(void)
207     {
208     int i, q, n;
209     char buf[LINE_MAX];
210     char *c;
211 lefcha 1.3 char *p[2];
212 lefcha 1.2 account_t *a, *accts[EDITOR_PASSWORDS_MAX];
213 lefcha 1.5
214     if (!(flags & FLAG_BLANK_PASSWORD)) {
215     error("imapfilter: no candidate passwords for encryption found\n");
216     return;
217     }
218 lefcha 1.3
219 lefcha 1.2 q = 0;
220 lefcha 1.3
221     memset(accts, 0, EDITOR_PASSWORDS_MAX);
222 lefcha 1.2
223 lefcha 1.3 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX - 1 && a; a = a->next) {
224 lefcha 1.2 if (a->passwdattr == PASSWORD_NONE ||
225     a->passwdattr == PASSWORD_ENCRYPTED)
226     accts[i++] = a;
227     }
228    
229     do {
230     printf("command: ");
231     fgets(buf, LINE_MAX, stdin);
232     c = buf;
233     for (;; c++) {
234     if (*c == ' ' || *c == '\t')
235     continue;
236     else if (*c == '?' || *c == 'h')
237     printf("c clear a password entry\n"
238     "e edit a password entry\n"
239     "h help\n"
240     "l list entries\n"
241     "p change master password\n"
242     "q quit without saving\n"
243 lefcha 1.6 "s save changes\n"
244 lefcha 1.2 "x save and exit\n");
245     else if (*c == 'q')
246     q = 1;
247     else if (*c == 'l')
248     for (i = 0; accts[i]; i++)
249     printf("%d %s %s %s\n", i + 1, accts[i]->server,
250     accts[i]->username, accts[i]->password);
251     else if (*c == 'e') {
252     n = atoi(++c);
253     if (!n || n < 1 || n > 128 || !accts[n - 1])
254     break;
255     accts[n - 1]->password[0] = 0;
256     printf("Enter new password: ");
257     if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
258     if ((c = strchr(accts[n - 1]->password, '\n')))
259     *c = 0;
260     } else if (*c == 'c') {
261     n = atoi(++c);
262     if (!n || n < 1 || n > 128 || !accts[n - 1])
263     break;
264     accts[n - 1]->password[0] = 0;
265     } else if (*c == 'p') {
266 lefcha 1.3 p[0] = (char *) smalloc(PASSPHRASE_LEN);
267     p[1] = (char *) smalloc(PASSPHRASE_LEN);
268 lefcha 1.2 do {
269     for (i = 0; i < 2; i++) {
270     printf("Enter %snew master password: ",
271     i ? "again " : "");
272     get_password(p[i], PASSPHRASE_LEN);
273     }
274     } while (strcmp(p[0], p[1]));
275     xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
276 lefcha 1.4 sfree(p[0]);
277     sfree(p[1]);
278 lefcha 1.6 } else if (*c == 's') {
279     store_passwords(accts);
280 lefcha 1.2 } else if (*c == 'x') {
281     store_passwords(accts);
282     q = 1;
283     } else
284     break;
285     }
286     } while (!q);
287 lefcha 1.1 }
288 lefcha 1.2 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26