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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations)
Sat Jul 13 22:31:37 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_8
Branch point for: release-0_8-patches
Changes since 1.7: +33 -31 lines
File MIME type: text/plain
Comments and stylistic changes.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26