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

Contents of /imapfilter/passwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations)
Tue Jan 29 21:23:42 2002 UTC (22 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.2: +43 -24 lines
File MIME type: text/plain
Added secure memory allocation subsystem.

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;
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_disable_echo();
29
30 if (fgets(passwd, pwlen, stdin))
31 if ((c = strchr(passwd, '\n')))
32 *c = 0;
33
34 tty_restore();
35
36 putchar('\n');
37 }
38
39
40 #ifdef ENCRYPTED_PASSWORDS
41 /*
42 * Encrypt and Base64 encode passwords. Append the MD5 checksum of the passwords
43 * before encrypting them.
44 */
45 int encrypt_passwords(FILE *fd, account_t *accts[])
46 {
47 int i;
48 char *c;
49 unsigned char iv[EVP_MAX_IV_LENGTH];
50 unsigned char *key;
51 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
60 key = (unsigned char *) smalloc(EVP_MAX_KEY_LENGTH);
61
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
109 return 0;
110 }
111
112
113 /*
114 * Decode (Base64) passwords, decrypt them and verify the MD5 checksum.
115 */
116 int decrypt_passwords(unsigned char **buf, FILE *fd)
117 {
118 int i, j = 1;
119 unsigned char iv[EVP_MAX_IV_LENGTH];
120 unsigned char *key;
121 unsigned char *c;
122 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 EVP_CIPHER_CTX *ctx;
128 EVP_MD_CTX mdctx;
129 EVP_ENCODE_CTX bctx;
130
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
135 fgets(bbuf, LINE_MAX, fd);
136
137 memcpy(iv, bbuf, EVP_MAX_IV_LENGTH);
138
139 EVP_CIPHER_CTX_init(ctx);
140
141 EVP_BytesToKey(EVP_bf_cbc(), EVP_md5(), NULL, passphr, strlen(passphr),
142 1, key, NULL);
143
144 EVP_DecryptInit(ctx, EVP_bf_cbc(), key, iv);
145 EVP_DecodeInit(&bctx);
146
147 while (fgets(bbuf, LINE_MAX, fd)) {
148 EVP_DecodeUpdate(&bctx, ebuf, &ebufl, bbuf, strlen(bbuf));
149 if (!EVP_DecryptUpdate(ctx, c, &bufl, ebuf, ebufl)) {
150 error("Wrong master passphrase.\n");
151 sfree(*buf);
152 sfree(key);
153 sfree(ctx);
154 return 1;
155 }
156
157 c += bufl;
158 *c = 0;
159
160 if (c - *buf < DECRYPTION_BUF * j - 64)
161 *buf = (char *) srealloc(*buf, DECRYPTION_BUF * ++j);
162 }
163
164 EVP_DecodeFinal(&bctx, ebuf, &ebufl);
165 if (!EVP_DecryptFinal(ctx, c, &bufl)) {
166 fprintf(stderr, "Wrong master passphrase.\n");
167 sfree(*buf);
168 sfree(key);
169 sfree(ctx);
170 return 1;
171 }
172
173 c += bufl;
174 *c = 0;
175
176 if ((c = strstr(*buf, "\n.\n"))) {
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 putchar('\n');
184
185 *c = 0;
186 } else {
187 sfree(*buf);
188 sfree(key);
189 sfree(ctx);
190 return 1;
191 }
192
193 EVP_CIPHER_CTX_cleanup(ctx);
194
195 sfree(key);
196 sfree(ctx);
197
198 return 0;
199 }
200
201
202 /*
203 * Interactive encrypted passwords editor.
204 */
205 void password_editor(void)
206 {
207 int i, q, n;
208 char buf[LINE_MAX];
209 char *c;
210 char *p[2];
211 account_t *a, *accts[EDITOR_PASSWORDS_MAX];
212
213 q = 0;
214
215 memset(accts, 0, EDITOR_PASSWORDS_MAX);
216
217 for (i = 0, a = accounts; i < EDITOR_PASSWORDS_MAX - 1 && a; a = a->next) {
218 if (a->passwdattr == PASSWORD_NONE ||
219 a->passwdattr == PASSWORD_ENCRYPTED)
220 accts[i++] = a;
221 }
222
223 do {
224 printf("command: ");
225 fgets(buf, LINE_MAX, stdin);
226 c = buf;
227 for (;; c++) {
228 if (*c == ' ' || *c == '\t')
229 continue;
230 else if (*c == '?' || *c == 'h')
231 printf("c clear a password entry\n"
232 "e edit a password entry\n"
233 "h help\n"
234 "l list entries\n"
235 "p change master password\n"
236 "q quit without saving\n"
237 "x save and exit\n");
238 else if (*c == 'q')
239 q = 1;
240 else if (*c == 'l')
241 for (i = 0; accts[i]; i++)
242 printf("%d %s %s %s\n", i + 1, accts[i]->server,
243 accts[i]->username, accts[i]->password);
244 else if (*c == 'e') {
245 n = atoi(++c);
246 if (!n || n < 1 || n > 128 || !accts[n - 1])
247 break;
248 accts[n - 1]->password[0] = 0;
249 printf("Enter new password: ");
250 if (fgets(accts[n - 1]->password, PASSWORD_LEN, stdin))
251 if ((c = strchr(accts[n - 1]->password, '\n')))
252 *c = 0;
253 } else if (*c == 'c') {
254 n = atoi(++c);
255 if (!n || n < 1 || n > 128 || !accts[n - 1])
256 break;
257 accts[n - 1]->password[0] = 0;
258 } else if (*c == 'p') {
259 p[0] = (char *) smalloc(PASSPHRASE_LEN);
260 p[1] = (char *) smalloc(PASSPHRASE_LEN);
261 do {
262 for (i = 0; i < 2; i++) {
263 printf("Enter %snew master password: ",
264 i ? "again " : "");
265 get_password(p[i], PASSPHRASE_LEN);
266 }
267 } while (strcmp(p[0], p[1]));
268 xstrncpy(passphr, p[0], PASSPHRASE_LEN - 1);
269 } else if (*c == 'x') {
270 store_passwords(accts);
271 q = 1;
272 } else
273 break;
274 }
275 } while (!q);
276 }
277 #endif

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26