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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (hide annotations)
Thu Jul 31 15:53:19 2003 UTC (20 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.13: +0 -3 lines
File MIME type: text/plain
Broke up program files and created some new header files.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26