tchain1.c - mixmaster - mixmaster 3.0 patched for libressl
HTML git clone git://parazyd.org/mixmaster.git
DIR Log
DIR Files
DIR Refs
DIR README
---
tchain1.c (8551B)
---
1 /* Mixmaster version 3.0 -- (C) 1999 - 2006 Anonymizer Inc. and others.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Encrypt message for Cypherpunk remailer chain
9 $Id: chain1.c 934 2006-06-24 13:40:39Z rabbi $ */
10
11
12 #include "mix3.h"
13 #include "pgp.h"
14 #include <string.h>
15 #include <ctype.h>
16
17 #define N(X) (isdigit(X) ? (X)-'0' : 0)
18
19 int t1_rlist(REMAILER remailer[], int badchains[MAXREM][MAXREM])
20 {
21 FILE *list, *excl;
22 int i, listed = 0;
23 int n = 0;
24 char line[2 * LINELEN], l2[LINELEN], name[LINELEN], *flags;
25 BUFFER *starex;
26
27 starex = buf_new();
28 excl = mix_openfile(STAREX, "r");
29 if (excl != NULL) {
30 buf_read(starex, excl);
31 fclose(excl);
32 }
33
34 list = mix_openfile(TYPE1LIST, "r");
35 if (list == NULL) {
36 buf_free(starex);
37 return (-1);
38 }
39
40 while (fgets(line, sizeof(line), list) != NULL && n < MAXREM) {
41 if (strleft(line, "$remailer") &&
42 strchr(line, '<') && strchr(line, '>') &&
43 strchr(line, '{') && strchr(line, '{') + 4 < strchr(line, '}')) {
44 if (line[strlen(line) - 1] == '\n')
45 line[strlen(line) - 1] = '\0';
46 if (line[strlen(line) - 1] == '\r')
47 line[strlen(line) - 1] = '\0';
48 while (line[strlen(line) - 1] == ' ')
49 line[strlen(line) - 1] = '\0';
50 if (line[strlen(line) - 1] != ';'
51 && fgets(l2, sizeof(l2), list) != NULL)
52 strcatn(line, l2, LINELEN);
53 flags = strchr(line, '>');
54 strncpy(name, strchr(line, '{') + 2,
55 strchr(line, '}') - strchr(line, '{') - 3);
56 name[strchr(line, '}') - strchr(line, '{') - 3] = '\0';
57 name[20] = '\0';
58
59 for (i = 1; i <= n; i++)
60 if (streq(name, remailer[i].name))
61 break;
62 if (i > n) {
63 /* not in mix list */
64 n++;
65 strcpy(remailer[i].name, name);
66 strncpy(remailer[i].addr, strchr(line, '<') + 1,
67 strchr(line, '>') - strchr(line, '<'));
68 remailer[i].addr[strchr(line, '>') - strchr(line, '<') - 1]
69 = '\0';
70 remailer[i].flags.mix = 0;
71 remailer[i].flags.post = strifind(flags, " post");
72 }
73 remailer[i].flags.cpunk = strfind(flags, " cpunk");
74 remailer[i].flags.pgp = strfind(flags, " pgp");
75 remailer[i].flags.pgponly = strfind(flags, " pgponly");
76 remailer[i].flags.latent = strfind(flags, " latent");
77 remailer[i].flags.middle = strfind(flags, " middle");
78 remailer[i].flags.ek = strfind(flags, " ek");
79 remailer[i].flags.esub = strfind(flags, " esub");
80 remailer[i].flags.newnym = strfind(flags, " newnym");
81 remailer[i].flags.nym = strfind(flags, " nym");
82 remailer[i].info[1].reliability = 0;
83 remailer[i].info[1].latency = 0;
84 remailer[i].info[1].history[0] = '\0';
85 remailer[i].flags.star_ex = bufifind(starex, name);
86 }
87 if (strleft(line,
88 "-----------------------------------------------------------------------"))
89 break;
90 }
91 n++; /* ?? */
92 while (fgets(line, sizeof(line), list) != NULL) {
93 if (strlen(line) >= 72 && strlen(line) <= 73)
94 for (i = 1; i < n; i++)
95 if (strleft(line, remailer[i].name) &&
96 line[strlen(remailer[i].name)] == ' ') {
97 strncpy(remailer[i].info[1].history, line + 42, 12);
98 remailer[i].info[1].history[12] = '\0';
99 remailer[i].info[1].reliability = 10000 * N(line[64])
100 + 1000 * N(line[65]) + 100 * N(line[66])
101 + 10 * N(line[68]) + N(line[69]);
102 remailer[i].info[1].latency = 36000 * N(line[55])
103 + 3600 * N(line[56]) + 600 * N(line[58])
104 + 60 * N(line[59]) + 10 * N(line[61])
105 + N(line[62]);
106 listed++;
107 }
108 }
109 fclose(list);
110 parse_badchains(badchains, TYPE1LIST, "Broken type-I remailer chains", remailer, n);
111 if (listed < 4) /* we have no valid reliability info */
112 for (i = 1; i < n; i++)
113 remailer[i].info[1].reliability = 10000;
114
115 #ifdef USE_PGP
116 pgp_rlist(remailer, n);
117 #endif /* USE_PGP */
118 buf_free(starex);
119 return (n);
120 }
121
122 int t1_ek(BUFFER *key, BUFFER *seed, int num)
123 {
124 buf_reset(key);
125 buf_appendc(key, (byte) num);
126 buf_cat(key, seed);
127 digest_md5(key, key);
128 encode(key, 0);
129 #ifdef DEBUG
130 fprintf(stderr, "passphrase=%s (%2X%2X%2X%2X %d)\n", key->data,
131 seed->data[0], seed->data[1], seed->data[2], seed->data[3], num);
132 #endif /* DEBUG */
133 return (0);
134 }
135
136 int t1_encrypt(int type, BUFFER *message, char *chainstr, int latency,
137 BUFFER *ek, BUFFER *feedback)
138 {
139 BUFFER *b, *rem, *dest, *line, *field, *content;
140 REMAILER remailer[MAXREM];
141 int badchains[MAXREM][MAXREM];
142 int maxrem, chainlen = 0;
143 int chain[20];
144 int hop;
145 int hashmark = 0;
146 int err = 0;
147
148 b = buf_new();
149 rem = buf_new();
150 dest = buf_new();
151 line = buf_new();
152 field = buf_new();
153 content = buf_new();
154
155 maxrem = t1_rlist(remailer, badchains);
156 if (maxrem < 1) {
157 clienterr(feedback, "No remailer list!");
158 err = -1;
159 goto end;
160 }
161 chainlen = chain_select(chain, chainstr, maxrem, remailer, 1, line);
162 if (chainlen < 1) {
163 if (line->length)
164 clienterr(feedback, line->data);
165 else
166 clienterr(feedback, "Invalid remailer chain!");
167 err = -1;
168 goto end;
169 }
170 if (chain[0] == 0)
171 chain[0] = chain_randfinal(type, remailer, badchains, maxrem, 1, chain, chainlen, 0);
172
173 if (chain[0] == -1) {
174 clienterr(feedback, "Invalid remailer chain!");
175 err = -1;
176 goto end;
177 }
178 if (chain_rand(remailer, badchains, maxrem, chain, chainlen, 1, 0) == -1) {
179 clienterr(feedback, "No reliable remailers!");
180 err = -1;
181 goto end;
182 }
183 while (buf_getheader(message, field, content) == 0) {
184 hdr_encode(content, 0);
185 if (type == MSG_POST && bufieq(field, "newsgroups") &&
186 remailer[chain[0]].flags.post) {
187 buf_appendf(dest, "Anon-Post-To: %b\n", content);
188 } else if (type == MSG_MAIL && bufieq(field, "to")) {
189 buf_appendf(dest, "Anon-To: %b\n", content);
190 } else {
191 /* paste header */
192 if (type == MSG_POST && bufieq(field, "newsgroups"))
193 buf_appendf(dest, "Anon-To: %s\n", MAILtoNEWS);
194 if (hashmark == 0) {
195 buf_appends(b, "##\n");
196 hashmark = 1;
197 }
198 buf_appendheader(b, field, content);
199 }
200 }
201 buf_nl(b);
202 buf_rest(b, message);
203 buf_move(message, b);
204
205 if (type != MSG_NULL && dest->length == 0) {
206 clienterr(feedback, "No destination address!");
207 err = -1;
208 goto end;
209 }
210 if (type == MSG_NULL) {
211 buf_sets(dest, "Null:\n");
212 }
213 for (hop = 0; hop < chainlen; hop++) {
214 if (hop == 0) {
215 buf_sets(b, "::\n");
216 buf_cat(b, dest);
217 } else {
218 buf_sets(b, "::\nAnon-To: ");
219 buf_appends(b, remailer[chain[hop - 1]].addr);
220 buf_nl(b);
221 }
222 if (remailer[chain[hop]].flags.latent && latency > 0)
223 buf_appendf(b, "Latent-Time: +%d:00r\n", latency);
224 if (ek && remailer[chain[hop]].flags.ek) {
225 t1_ek(line, ek, hop);
226 buf_appendf(b, "Encrypt-Key: %b\n", line);
227 }
228 buf_nl(b);
229 buf_cat(b, message);
230 #ifdef USE_PGP
231 if (remailer[chain[hop]].flags.pgp) {
232 buf_clear(message);
233 buf_clear(rem);
234 buf_setf(rem, "<%s>", remailer[chain[hop]].addr);
235 err = pgp_encrypt(PGP_ENCRYPT | PGP_REMAIL | PGP_TEXT, b, rem,
236 NULL, NULL, NULL, NULL);
237 if (err < 0) {
238 buf_setf(line, "No PGP key for remailer %s!\n",
239 remailer[chain[hop]].name);
240 clienterr(feedback, line->data);
241 goto end;
242 }
243 buf_appends(message, "::\nEncrypted: PGP\n\n");
244 buf_cat(message, b);
245 } else
246 #endif /* USE_PGP */
247 {
248 if (remailer[chain[hop]].flags.pgponly) {
249 buf_setf(line, "PGP encryption needed for remailer %s!\n",
250 remailer[chain[hop]].name);
251 clienterr(feedback, line->data);
252 goto end;
253 }
254 buf_move(message, b);
255 }
256 if (ek && remailer[chain[hop]].flags.ek)
257 buf_appends(message, "\n**\n");
258 }
259 buf_clear(b);
260 if (chainlen == 0) {
261 buf_appends(b, "::\n");
262 buf_cat(b, dest);
263 } else {
264 buf_appendf(b, "%s: %s\n", ek ? "::\nAnon-To" : "To",
265 remailer[chain[chainlen - 1]].addr);
266 }
267 buf_nl(b);
268 buf_cat(b, message);
269 buf_move(message, b);
270 end:
271 buf_free(b);
272 buf_free(rem);
273 buf_free(dest);
274 buf_free(line);
275 buf_free(field);
276 buf_free(content);
277 return (err);
278 }
279
280 #ifdef USE_PGP
281 int t1_getreply(BUFFER *msg, BUFFER *ek, int len)
282 {
283 BUFFER *key, *decrypt;
284 int err = -1;
285 int hop = 0;
286
287 key = buf_new();
288 decrypt = buf_new();
289
290 do {
291 t1_ek(key, ek, hop);
292 buf_set(decrypt, msg);
293 if (pgp_decrypt(decrypt, key, NULL, NULL, NULL) == 0
294 && decrypt->data != NULL)
295 err = 0, buf_move(msg, decrypt);
296 }
297 while (hop++ < len);
298 return (err);
299 }
300
301 #endif /* USE_PGP */