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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Mon Jan 14 18:12:38 2002 UTC (22 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.1: +219 -49 lines
File MIME type: text/plain
Added encrypted passwords support.

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.2 extern account_t *accounts;
16    
17     #ifdef ENCRYPTED_PASSWORDS
18     extern char passphr[PASSPHRASE_LEN];
19     #endif
20 lefcha 1.1
21     /*
22     * Get password from user interactively.
23     */
24 lefcha 1.2 void get_password(char *passwd, size_t pwlen)
25 lefcha 1.1 {
26     char *c;
27 lefcha 1.2
28 lefcha 1.1 tty_store();
29     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     unsigned char key[EVP_MAX_KEY_LENGTH];
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     srandom(time(NULL));
62    
63     c = ultostr(1 + random() % 100000000, 10);
64     memset(iv, '0', EVP_MAX_IV_LENGTH);
65     memcpy(iv + 8 - strlen(c), c, min(8, strlen(c)));
66    
67     fprintf(fd, "%.8s\n", iv);
68    
69     EVP_CIPHER_CTX_init(&ctx);
70    
71     EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr), 1,
72     key, NULL);
73    
74     EVP_DigestInit(&mdctx, EVP_md5());
75     EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
76     EVP_EncodeInit(&bctx);
77    
78     for (i = 0; accts[i]; i++) {
79     snprintf(buf, ENCRYPTION_BUF, "%s %s %s\n", accts[i]->server, accts[i]->username,
80     accts[i]->password);
81    
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    
86     fwrite(bbuf, sizeof(char), bbufl, fd);
87     }
88    
89     EVP_DigestFinal(&mdctx, mdv, &mdl);
90    
91     xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);
92    
93     for (i = 0; i < mdl; i++)
94     snprintf(2 + buf + i * 2, ENCRYPTION_BUF - i * 2, "%02x", mdv[i]);
95    
96     EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
97     EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
98     fwrite(bbuf, sizeof(char), bbufl, fd);
99    
100     EVP_EncryptFinal(&ctx, ebuf, &ebufl);
101     EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
102     EVP_EncodeFinal(&bctx, bbuf, &bbufl);
103    
104     fwrite(bbuf, sizeof(char), bbufl, fd);
105    
106     EVP_CIPHER_CTX_cleanup(&ctx);
107 lefcha 1.1
108 lefcha 1.2 return 0;
109 lefcha 1.1 }
110    
111    
112     /*
113 lefcha 1.2 * Decode (Base64) and decrypt passwords and verify the MD5 checksum.
114 lefcha 1.1 */
115 lefcha 1.2 int decrypt_passwords(unsigned char *buf, FILE *fd)
116 lefcha 1.1 {
117 lefcha 1.2 int i, j = 1;
118     unsigned char iv[EVP_MAX_IV_LENGTH];
119     unsigned char key[EVP_MAX_KEY_LENGTH];
120     unsigned char *c = buf;
121     unsigned char ebuf[LINE_MAX];
122     unsigned char bbuf[LINE_MAX];
123     unsigned char mdv[EVP_MAX_MD_SIZE];
124     unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];
125     int mdl, bufl, ebufl;
126     EVP_CIPHER_CTX ctx;
127     EVP_MD_CTX mdctx;
128     EVP_ENCODE_CTX bctx;
129    
130     fgets(bbuf, LINE_MAX, fd);
131    
132     memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
133 lefcha 1.1
134 lefcha 1.2 EVP_CIPHER_CTX_init(&ctx);
135    
136     EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
137     1, key, NULL);
138    
139     EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
140     EVP_DecodeInit(&bctx);
141    
142     while (fgets(bbuf, LINE_MAX, fd)) {
143     EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
144     if (!EVP_DecryptUpdate(&ctx, c, &bufl, ebuf, ebufl)) {
145     error("Wrong master passphrase.\n");
146     return 1;
147     }
148    
149     c += bufl;
150     *c = 0;
151    
152     if (c - buf < DECRYPTION_BUF * j - 64)
153     buf = (char *) xrealloc(buf, DECRYPTION_BUF * ++j);
154     }
155    
156     EVP_DecodeFinal(&bctx, ebuf, &ebufl);
157     if (!EVP_DecryptFinal(&ctx, c, &bufl)) {
158     fprintf(stderr, "Wrong master passphrase.\n");
159     return 1;
160 lefcha 1.1 }
161    
162 lefcha 1.2 c += bufl;
163     *c = 0;
164    
165     if ((c = strstr(buf, "\n.\n"))) {
166     EVP_DigestInit(&mdctx, EVP_md5());
167     EVP_DigestUpdate(&mdctx, buf, c - buf + 1);
168     EVP_DigestFinal(&mdctx, mdv, &mdl);
169    
170     for (i = 0; i < mdl; i++)
171     snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x", mdv[i]);
172     putchar('\n');
173    
174     *c = 0;
175     } else
176     return 1;
177    
178     EVP_CIPHER_CTX_cleanup(&ctx);
179 lefcha 1.1
180 lefcha 1.2 return 0;
181     }
182    
183    
184     /*
185     * Interactive encrypted passwords editor.
186     */
187     void password_editor(void)
188     {
189     int i, q, n;
190     char buf[LINE_MAX];
191     char *c;
192     char p[2][PASSPHRASE_LEN];
193     account_t *a, *accts[EDITOR_PASSWORDS_MAX];
194    
195     q = 0;
196    
197     for (i = 0; i < EDITOR_PASSWORDS_MAX; i++)
198     accts[i] = NULL;
199    
200     for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX && a; a = a->next) {
201     if (a->passwdattr == PASSWORD_NONE ||
202     a->passwdattr == PASSWORD_ENCRYPTED)
203     accts[i++] = a;
204     }
205    
206     do {
207     printf("command: ");
208     fgets(buf, LINE_MAX, stdin);
209     c = buf;
210     for (;; c++) {
211     if (*c == ' ' || *c == '\t')
212     continue;
213     else if (*c == '?' || *c == 'h')
214     printf("c clear a password entry\n"
215     "e edit a password entry\n"
216     "h help\n"
217     "l list entries\n"
218     "p change master password\n"
219     "q quit without saving\n"
220     "x save and exit\n");
221     else if (*c == 'q')
222     q = 1;
223     else if (*c == 'l')
224     for (i = 0; accts[i]; i++)
225     printf("%d %s %s %s\n", i + 1, accts[i]->server,
226     accts[i]->username, accts[i]->password);
227     else if (*c == 'e') {
228     n = atoi(++c);
229     if (!n || n < 1 || n > 128 || !accts[n - 1])
230     break;
231     accts[n - 1]->password[0] = 0;
232     printf("Enter new password: ");
233     if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
234     if ((c = strchr(accts[n - 1]->password, '\n')))
235     *c = 0;
236     } else if (*c == 'c') {
237     n = atoi(++c);
238     if (!n || n < 1 || n > 128 || !accts[n - 1])
239     break;
240     accts[n - 1]->password[0] = 0;
241     } else if (*c == 'p') {
242     do {
243     for (i = 0; i < 2; i++) {
244     printf("Enter %snew master password: ",
245     i ? "again " : "");
246     get_password(p[i], PASSPHRASE_LEN);
247     }
248     } while (strcmp(p[0], p[1]));
249     xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
250     } else if (*c == 'x') {
251     store_passwords(accts);
252     q = 1;
253     } else
254     break;
255     }
256     } while (!q);
257 lefcha 1.1 }
258 lefcha 1.2 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26