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

Contents of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8.2.1 - (show annotations)
Sun May 25 00:52:34 2003 UTC (20 years, 10 months ago) by lefcha
Branch: release-0_8-patches
Changes since 1.8: +11 -10 lines
File MIME type: text/plain
Multiple bug fixes in concerning encrypted passwords, uninitialized array of accounts, missed a step of writing to file when encrypting the passwords.

1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <limits.h>
5
6 #include "config.h"
7 #include "imapfilter.h"
8 #include "data.h"
9
10 #ifdef ENCRYPTED_PASSWORDS
11 #include <openssl/evp.h>
12 #endif
13
14
15 extern unsigned int flags;
16 extern account_t *accounts;
17
18 #ifdef ENCRYPTED_PASSWORDS
19 extern char *passphr;
20 #endif
21
22 /*
23 * Get password from user interactively.
24 */
25 void get_password(char *passwd, size_t pwlen)
26 {
27 char *c;
28
29 tty_disable_echo();
30
31 if (fgets(passwd, pwlen, stdin))
32 if ((c = strchr(passwd, '\n')))
33 *c = 0;
34
35 tty_restore();
36
37 putchar('\n');
38 }
39
40
41 #ifdef ENCRYPTED_PASSWORDS
42 /*
43 * Encrypt and Base64 encode passwords. Append the MD5 checksum of the passwords
44 * before encrypting them.
45 */
46 int encrypt_passwords(FILE * fd, account_t * accts[])
47 {
48 int i;
49 char *c;
50 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 c = ultostr(1 + random() % 100000000, 10);
67 snprintf(iv, EVP_MAX_IV_LENGTH, "%.8s", c);
68 fprintf(fd, "%s\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 /* MD5 checksum of data. */
95 for (i = 0; i < mdl; i++)
96 snprintf(2 + buf + i * 2, ENCRYPTION_BUF - 3 - 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
104 EVP_EncodeUpdate(&bctx, bbuf, &bbufl, ebuf, ebufl);
105 fwrite(bbuf, sizeof(char), bbufl, fd);
106
107 EVP_EncodeFinal(&bctx, bbuf, &bbufl);
108 fwrite(bbuf, sizeof(char), bbufl, fd);
109
110 EVP_CIPHER_CTX_cleanup(&ctx);
111
112 return 0;
113 }
114
115
116 /*
117 * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.
118 */
119 int decrypt_passwords(unsigned char **buf, FILE * fd)
120 {
121 int i, j = 1;
122 unsigned char iv[EVP_MAX_IV_LENGTH];
123 unsigned char *key;
124 unsigned char *c;
125 unsigned char ebuf[LINE_MAX];
126 unsigned char bbuf[LINE_MAX];
127 unsigned char mdv[EVP_MAX_MD_SIZE];
128 unsigned char mdc[EVP_MAX_MD_SIZE * 2 + 1];
129 int mdl, bufl, ebufl;
130 EVP_CIPHER_CTX *ctx;
131 EVP_MD_CTX mdctx;
132 EVP_ENCODE_CTX bctx;
133
134 c = *buf = (unsigned char *)smalloc(DECRYPTION_BUF * sizeof(char));
135 key = (unsigned char *)smalloc(EVP_MAX_KEY_LENGTH);
136 ctx = (EVP_CIPHER_CTX *) smalloc(sizeof(EVP_CIPHER_CTX));
137
138 fgets(bbuf, LINE_MAX, fd);
139
140 memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
141
142 EVP_CIPHER_CTX_init(ctx);
143
144 EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
145 1, key, NULL);
146
147 EVP_DecryptInit(ctx, EVP_bf_cbc(), key, iv);
148 EVP_DecodeInit(&bctx);
149
150 while (fgets(bbuf, LINE_MAX, fd)) {
151 EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
152 if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl))
153 goto fail;
154
155 c += bufl;
156 *c = 0;
157
158 if (c - *buf > DECRYPTION_BUF * j - 64) {
159 i = c - *buf;
160 *buf = (char *)srealloc(*buf, DECRYPTION_BUF * ++j);
161 c = *buf + i;
162 *c = 0;
163 }
164 }
165
166 EVP_DecodeFinal(&bctx, ebuf, &ebufl);
167 if (!EVP_DecryptFinal(ctx, c, &bufl))
168 goto fail;
169
170 c += bufl;
171 *c = 0;
172
173 /* Calculate the MD5 checksum and check if it is correct. */
174 if (!(c = strstr(*buf, "\n.\n")))
175 goto fail;
176
177 EVP_DigestInit(&mdctx, EVP_md5());
178 EVP_DigestUpdate(&mdctx, *buf, c - *buf + 1);
179 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 += 3;
185
186 if (strncmp(c, mdc, 32))
187 goto fail;
188
189 EVP_CIPHER_CTX_cleanup(ctx);
190
191 sfree(key);
192 sfree(ctx);
193
194 return 0;
195
196 fail:
197 error("Wrong master passphrase.\n");
198 EVP_CIPHER_CTX_cleanup(ctx);
199 sfree(*buf);
200 sfree(key);
201 sfree(ctx);
202
203 return ERROR_DECRYPT;
204 }
205
206
207 /*
208 * Interactive encrypted passwords editor.
209 */
210 void password_editor(void)
211 {
212 int i, q, n;
213 char buf[LINE_MAX];
214 char *c;
215 char *p[2];
216 account_t *a, *accts[EDITOR_PASSWORDS_MAX + 1];
217
218 if (!(flags & FLAG_BLANK_PASSWORD)) {
219 error("imapfilter: no candidate passwords for encryption found\n");
220 return;
221 }
222 q = 0;
223
224 memset(accts, 0, (EDITOR_PASSWORDS_MAX + 1) * sizeof(account_t *));
225
226 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX && a; a = a->next) {
227 if (a->passwdattr == PASSWORD_NONE ||
228 a->passwdattr == PASSWORD_ENCRYPTED)
229 accts[i++] = a;
230 }
231
232 do {
233 printf("command: ");
234 fgets(buf, LINE_MAX, stdin);
235 c = buf;
236 for (;; c++) {
237 if (*c == ' ' || *c == '\t')
238 continue;
239 else if (*c == '?' || *c == 'h')
240 printf("c clear a password entry\n"
241 "e edit a password entry\n"
242 "h help\n"
243 "l list entries\n"
244 "p change master password\n"
245 "q quit without saving\n"
246 "s save changes\n"
247 "x save and exit\n");
248 else if (*c == 'q')
249 q = 1;
250 else if (*c == 'l')
251 for (i = 0; accts[i]; i++)
252 printf("%d %s %s %s\n", i + 1, accts[i]->server,
253 accts[i]->username, accts[i]->password);
254 else if (*c == 'e') {
255 n = atoi(++c);
256 if (!n || n < 1 || n > EDITOR_PASSWORDS_MAX || !accts[n - 1])
257 break;
258 accts[n - 1]->password[0] = 0;
259 printf("Enter new password: ");
260 if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
261 if ((c = strchr(accts[n - 1]->password, '\n')))
262 *c = 0;
263 } else if (*c == 'c') {
264 n = atoi(++c);
265 if (!n || n < 1 || n > EDITOR_PASSWORDS_MAX || !accts[n - 1])
266 break;
267 accts[n - 1]->password[0] = 0;
268 } else if (*c == 'p') {
269 p[0] = (char *)smalloc(PASSPHRASE_LEN);
270 p[1] = (char *)smalloc(PASSPHRASE_LEN);
271 do {
272 for (i = 0; i < 2; i++) {
273 printf("Enter %snew master password: ",
274 i ? "again " : "");
275 get_password(p[i], PASSPHRASE_LEN);
276 }
277 } while (strcmp(p[0], p[1]));
278 xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
279 sfree(p[0]);
280 sfree(p[1]);
281 } else if (*c == 's') {
282 store_passwords(accts);
283 } else if (*c == 'x') {
284 store_passwords(accts);
285 q = 1;
286 } else
287 break;
288 }
289 } while (!q);
290 }
291
292 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26