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

Contents of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show 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 #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 account_t *accounts;
16
17 #ifdef ENCRYPTED_PASSWORDS
18 extern char passphr[PASSPHRASE_LEN];
19 #endif
20
21 /*
22 * Get password from user interactively.
23 */
24 void get_password(char *passwd, size_t pwlen)
25 {
26 char *c;
27
28 tty_store();
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[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
108 return 0;
109 }
110
111
112 /*
113 * Decode (Base64) and decrypt passwords and verify the MD5 checksum.
114 */
115 int decrypt_passwords(unsigned char *buf, FILE *fd)
116 {
117 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
134 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 }
161
162 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
180 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 }
258 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26