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

Contents of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (show annotations)
Sat Feb 22 16:06:41 2003 UTC (21 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.8: +232 -215 lines
File MIME type: text/plain
Coding style to KNF and some code cleanup.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26