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

Annotation of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Wed Jan 30 13:16:17 2002 UTC (22 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.3: +2 -1 lines
File MIME type: text/plain
Small fixes.

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 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.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_disable_echo();
29 lefcha 1.2
30     if (fgets(passwd, pwlen, stdin))
31 lefcha 1.1 if ((c = strchr(passwd, '\n')))
32     *c = 0;
33 lefcha 1.2
34 lefcha 1.1 tty_restore();
35    
36     putchar('\n');
37     }
38    
39    
40 lefcha 1.2 #ifdef ENCRYPTED_PASSWORDS
41 lefcha 1.1 /*
42 lefcha 1.2 * Encrypt and Base64 encode passwords. Append the MD5 checksum of the passwords
43     * before encrypting them.
44 lefcha 1.1 */
45 lefcha 1.2 int encrypt_passwords(FILE *fd, account_t *accts[])
46 lefcha 1.1 {
47 lefcha 1.2 int i;
48     char *c;
49     unsigned char iv[EVP_MAX_IV_LENGTH];
50 lefcha 1.3 unsigned char *key;
51 lefcha 1.2 unsigned char buf[ENCRYPTION_BUF];
52     unsigned char ebuf[ENCRYPTION_BUF];
53     unsigned char bbuf[ENCRYPTION_BUF];
54     unsigned char mdv[EVP_MAX_MD_SIZE];
55     int mdl, ebufl, bbufl;
56     EVP_CIPHER_CTX ctx;
57     EVP_MD_CTX mdctx;
58     EVP_ENCODE_CTX bctx;
59 lefcha 1.3
60     key = (unsigned char *) smalloc(EVP_MAX_KEY_LENGTH);
61 lefcha 1.2
62     srandom(time(NULL));
63    
64     c = ultostr(1 + random() % 100000000, 10);
65     memset(iv, '0', EVP_MAX_IV_LENGTH);
66     memcpy(iv + 8 - strlen(c), c, min(8, strlen(c)));
67    
68     fprintf(fd, "%.8s\n", iv);
69    
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]; i++) {
80     snprintf(buf, ENCRYPTION_BUF, "%s %s %s\n", accts[i]->server, accts[i]->username,
81     accts[i]->password);
82    
83     EVP_DigestUpdate(&mdctx, buf, strlen(buf));
84     EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
85     EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
86    
87     fwrite(bbuf, sizeof(char), bbufl, fd);
88     }
89    
90     EVP_DigestFinal(&mdctx, mdv, &mdl);
91    
92     xstrncpy(buf, ".\n", ENCRYPTION_BUF - 1);
93    
94     for (i = 0; i < mdl; i++)
95     snprintf(2 + buf + i * 2, ENCRYPTION_BUF - i * 2, "%02x", mdv[i]);
96    
97     EVP_EncryptUpdate(&ctx, ebuf, &ebufl, buf, strlen(buf));
98     EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
99     fwrite(bbuf, sizeof(char), bbufl, fd);
100    
101     EVP_EncryptFinal(&ctx, ebuf, &ebufl);
102     EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
103     EVP_EncodeFinal(&bctx, bbuf, &bbufl);
104    
105     fwrite(bbuf, sizeof(char), bbufl, fd);
106    
107     EVP_CIPHER_CTX_cleanup(&ctx);
108 lefcha 1.1
109 lefcha 1.2 return 0;
110 lefcha 1.1 }
111    
112    
113     /*
114 lefcha 1.3 * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.
115 lefcha 1.1 */
116 lefcha 1.3 int decrypt_passwords(unsigned char **buf, FILE *fd)
117 lefcha 1.1 {
118 lefcha 1.2 int i, j = 1;
119     unsigned char iv[EVP_MAX_IV_LENGTH];
120 lefcha 1.3 unsigned char *key;
121     unsigned char *c;
122 lefcha 1.2 unsigned char ebuf[LINE_MAX];
123     unsigned char bbuf[LINE_MAX];
124     unsigned char mdv[EVP_MAX_MD_SIZE];
125     unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];
126     int mdl, bufl, ebufl;
127 lefcha 1.3 EVP_CIPHER_CTX *ctx;
128 lefcha 1.2 EVP_MD_CTX mdctx;
129     EVP_ENCODE_CTX bctx;
130 lefcha 1.3
131     c = *buf = (unsigned char *) smalloc(DECRYPTION_BUF * sizeof(char));
132     key = (unsigned char *) smalloc(EVP_MAX_KEY_LENGTH);
133     ctx = (EVP_CIPHER_CTX *) smalloc(sizeof(EVP_CIPHER_CTX));
134 lefcha 1.2
135     fgets(bbuf, LINE_MAX, fd);
136    
137     memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
138 lefcha 1.1
139 lefcha 1.3 EVP_CIPHER_CTX_init(ctx);
140 lefcha 1.2
141     EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
142     1, key, NULL);
143    
144 lefcha 1.3 EVP_DecryptInit(ctx, EVP_bf_cbc(), key, iv);
145 lefcha 1.2 EVP_DecodeInit(&bctx);
146    
147     while (fgets(bbuf, LINE_MAX, fd)) {
148     EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
149 lefcha 1.3 if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl)) {
150 lefcha 1.2 error("Wrong master passphrase.\n");
151 lefcha 1.3 sfree(*buf);
152     sfree(key);
153     sfree(ctx);
154 lefcha 1.2 return 1;
155     }
156    
157     c += bufl;
158     *c = 0;
159    
160 lefcha 1.3 if (c - *buf < DECRYPTION_BUF * j - 64)
161     *buf = (char *) srealloc(*buf, DECRYPTION_BUF * ++j);
162 lefcha 1.2 }
163    
164     EVP_DecodeFinal(&bctx, ebuf, &ebufl);
165 lefcha 1.3 if (!EVP_DecryptFinal(ctx, c, &bufl)) {
166 lefcha 1.2 fprintf(stderr, "Wrong master passphrase.\n");
167 lefcha 1.3 sfree(*buf);
168     sfree(key);
169     sfree(ctx);
170 lefcha 1.2 return 1;
171 lefcha 1.1 }
172    
173 lefcha 1.2 c += bufl;
174     *c = 0;
175    
176 lefcha 1.3 if ((c = strstr(*buf, "\n.\n"))) {
177 lefcha 1.2 EVP_DigestInit(&mdctx, EVP_md5());
178 lefcha 1.3 EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);
179 lefcha 1.2 EVP_DigestFinal(&mdctx, mdv, &mdl);
180    
181     for (i = 0; i < mdl; i++)
182     snprintf(mdc + i * 2, EVP_MAX_MD_SIZE * 2 + 1 - i * 2, "%02x", mdv[i]);
183    
184     *c = 0;
185 lefcha 1.3 } else {
186     sfree(*buf);
187     sfree(key);
188     sfree(ctx);
189 lefcha 1.2 return 1;
190 lefcha 1.3 }
191 lefcha 1.2
192 lefcha 1.3 EVP_CIPHER_CTX_cleanup(ctx);
193    
194     sfree(key);
195     sfree(ctx);
196 lefcha 1.1
197 lefcha 1.2 return 0;
198     }
199    
200    
201     /*
202     * Interactive encrypted passwords editor.
203     */
204     void password_editor(void)
205     {
206     int i, q, n;
207     char buf[LINE_MAX];
208     char *c;
209 lefcha 1.3 char *p[2];
210 lefcha 1.2 account_t *a, *accts[EDITOR_PASSWORDS_MAX];
211 lefcha 1.3
212 lefcha 1.2 q = 0;
213 lefcha 1.3
214     memset(accts, 0, EDITOR_PASSWORDS_MAX);
215 lefcha 1.2
216 lefcha 1.3 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX - 1 && a; a = a->next) {
217 lefcha 1.2 if (a->passwdattr == PASSWORD_NONE ||
218     a->passwdattr == PASSWORD_ENCRYPTED)
219     accts[i++] = a;
220     }
221    
222     do {
223     printf("command: ");
224     fgets(buf, LINE_MAX, stdin);
225     c = buf;
226     for (;; c++) {
227     if (*c == ' ' || *c == '\t')
228     continue;
229     else if (*c == '?' || *c == 'h')
230     printf("c clear a password entry\n"
231     "e edit a password entry\n"
232     "h help\n"
233     "l list entries\n"
234     "p change master password\n"
235     "q quit without saving\n"
236     "x save and exit\n");
237     else if (*c == 'q')
238     q = 1;
239     else if (*c == 'l')
240     for (i = 0; accts[i]; i++)
241     printf("%d %s %s %s\n", i + 1, accts[i]->server,
242     accts[i]->username, accts[i]->password);
243     else if (*c == 'e') {
244     n = atoi(++c);
245     if (!n || n < 1 || n > 128 || !accts[n - 1])
246     break;
247     accts[n - 1]->password[0] = 0;
248     printf("Enter new password: ");
249     if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
250     if ((c = strchr(accts[n - 1]->password, '\n')))
251     *c = 0;
252     } else if (*c == 'c') {
253     n = atoi(++c);
254     if (!n || n < 1 || n > 128 || !accts[n - 1])
255     break;
256     accts[n - 1]->password[0] = 0;
257     } else if (*c == 'p') {
258 lefcha 1.3 p[0] = (char *) smalloc(PASSPHRASE_LEN);
259     p[1] = (char *) smalloc(PASSPHRASE_LEN);
260 lefcha 1.2 do {
261     for (i = 0; i < 2; i++) {
262     printf("Enter %snew master password: ",
263     i ? "again " : "");
264     get_password(p[i], PASSPHRASE_LEN);
265     }
266     } while (strcmp(p[0], p[1]));
267     xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
268 lefcha 1.4 sfree(p[0]);
269     sfree(p[1]);
270 lefcha 1.2 } else if (*c == 'x') {
271     store_passwords(accts);
272     q = 1;
273     } else
274     break;
275     }
276     } while (!q);
277 lefcha 1.1 }
278 lefcha 1.2 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26