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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (hide annotations)
Thu Jan 31 17:06:38 2002 UTC (22 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.4: +6 -0 lines
File MIME type: text/plain
Return if no candidate passwords for encryption.

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.2
31     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    
88     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    
102     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.3
132     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.1
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    
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.3 if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl)) {
151 lefcha 1.2 error("Wrong master passphrase.\n");
152 lefcha 1.3 sfree(*buf);
153     sfree(key);
154     sfree(ctx);
155 lefcha 1.2 return 1;
156     }
157    
158     c += bufl;
159     *c = 0;
160    
161 lefcha 1.3 if (c - *buf < DECRYPTION_BUF * j - 64)
162     *buf = (char *) srealloc(*buf, DECRYPTION_BUF * ++j);
163 lefcha 1.2 }
164    
165     EVP_DecodeFinal(&bctx, ebuf, &ebufl);
166 lefcha 1.3 if (!EVP_DecryptFinal(ctx, c, &bufl)) {
167 lefcha 1.2 fprintf(stderr, "Wrong master passphrase.\n");
168 lefcha 1.3 sfree(*buf);
169     sfree(key);
170     sfree(ctx);
171 lefcha 1.2 return 1;
172 lefcha 1.1 }
173    
174 lefcha 1.2 c += bufl;
175     *c = 0;
176    
177 lefcha 1.3 if ((c = strstr(*buf, "\n.\n"))) {
178 lefcha 1.2 EVP_DigestInit(&mdctx, EVP_md5());
179 lefcha 1.3 EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);
180 lefcha 1.2 EVP_DigestFinal(&mdctx, mdv, &mdl);
181    
182     for (i = 0; i < mdl; i++)
183     snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x", mdv[i]);
184    
185     *c = 0;
186 lefcha 1.3 } else {
187     sfree(*buf);
188     sfree(key);
189     sfree(ctx);
190 lefcha 1.2 return 1;
191 lefcha 1.3 }
192 lefcha 1.2
193 lefcha 1.3 EVP_CIPHER_CTX_cleanup(ctx);
194    
195     sfree(key);
196     sfree(ctx);
197 lefcha 1.1
198 lefcha 1.2 return 0;
199     }
200    
201    
202     /*
203     * Interactive encrypted passwords editor.
204     */
205     void password_editor(void)
206     {
207     int i, q, n;
208     char buf[LINE_MAX];
209     char *c;
210 lefcha 1.3 char *p[2];
211 lefcha 1.2 account_t *a, *accts[EDITOR_PASSWORDS_MAX];
212 lefcha 1.5
213     if (!(flags & FLAG_BLANK_PASSWORD)) {
214     error("imapfilter: no candidate passwords for encryption found\n");
215     return;
216     }
217 lefcha 1.3
218 lefcha 1.2 q = 0;
219 lefcha 1.3
220     memset(accts, 0, EDITOR_PASSWORDS_MAX);
221 lefcha 1.2
222 lefcha 1.3 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX - 1 && a; a = a->next) {
223 lefcha 1.2 if (a->passwdattr == PASSWORD_NONE ||
224     a->passwdattr == PASSWORD_ENCRYPTED)
225     accts[i++] = a;
226     }
227    
228     do {
229     printf("command: ");
230     fgets(buf, LINE_MAX, stdin);
231     c = buf;
232     for (;; c++) {
233     if (*c == ' ' || *c == '\t')
234     continue;
235     else if (*c == '?' || *c == 'h')
236     printf("c clear a password entry\n"
237     "e edit a password entry\n"
238     "h help\n"
239     "l list entries\n"
240     "p change master password\n"
241     "q quit without saving\n"
242     "x save and exit\n");
243     else if (*c == 'q')
244     q = 1;
245     else if (*c == 'l')
246     for (i = 0; accts[i]; i++)
247     printf("%d %s %s %s\n", i + 1, accts[i]->server,
248     accts[i]->username, accts[i]->password);
249     else if (*c == 'e') {
250     n = atoi(++c);
251     if (!n || n < 1 || n > 128 || !accts[n - 1])
252     break;
253     accts[n - 1]->password[0] = 0;
254     printf("Enter new password: ");
255     if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
256     if ((c = strchr(accts[n - 1]->password, '\n')))
257     *c = 0;
258     } else if (*c == 'c') {
259     n = atoi(++c);
260     if (!n || n < 1 || n > 128 || !accts[n - 1])
261     break;
262     accts[n - 1]->password[0] = 0;
263     } else if (*c == 'p') {
264 lefcha 1.3 p[0] = (char *) smalloc(PASSPHRASE_LEN);
265     p[1] = (char *) smalloc(PASSPHRASE_LEN);
266 lefcha 1.2 do {
267     for (i = 0; i < 2; i++) {
268     printf("Enter %snew master password: ",
269     i ? "again " : "");
270     get_password(p[i], PASSPHRASE_LEN);
271     }
272     } while (strcmp(p[0], p[1]));
273     xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
274 lefcha 1.4 sfree(p[0]);
275     sfree(p[1]);
276 lefcha 1.2 } else if (*c == 'x') {
277     store_passwords(accts);
278     q = 1;
279     } else
280     break;
281     }
282     } while (!q);
283 lefcha 1.1 }
284 lefcha 1.2 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26