Support optional WANT_JUNK configuration
[s-mailx.git] / ssl.c
blob6a0b3222245a42cf1d94a6002596f7c24a2aac40
1 /*
2 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 */
6 /*
7 * Copyright (c) 2002
8 * Gunnar Ritter. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Gunnar Ritter
21 * and his contributors.
22 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
39 #ifndef lint
40 #ifdef DOSCCS
41 static char sccsid[] = "@(#)ssl.c 1.39 (gritter) 6/12/06";
42 #endif
43 #endif /* not lint */
45 #include "config.h"
47 #ifdef USE_SSL
49 #include "rcv.h"
50 #include "extern.h"
52 void
53 ssl_set_vrfy_level(const char *uhp)
55 char *cp;
56 char *vrvar;
58 ssl_vrfy_level = VRFY_ASK;
59 vrvar = ac_alloc(strlen(uhp) + 12);
60 strcpy(vrvar, "ssl-verify-");
61 strcpy(&vrvar[11], uhp);
62 if ((cp = value(vrvar)) == NULL)
63 cp = value("ssl-verify");
64 ac_free(vrvar);
65 if (cp != NULL) {
66 if (equal(cp, "strict"))
67 ssl_vrfy_level = VRFY_STRICT;
68 else if (equal(cp, "ask"))
69 ssl_vrfy_level = VRFY_ASK;
70 else if (equal(cp, "warn"))
71 ssl_vrfy_level = VRFY_WARN;
72 else if (equal(cp, "ignore"))
73 ssl_vrfy_level = VRFY_IGNORE;
74 else
75 fprintf(stderr, catgets(catd, CATSET, 265,
76 "invalid value of ssl-verify: %s\n"),
77 cp);
81 enum okay
82 ssl_vrfy_decide(void)
84 enum okay ok = STOP;
86 switch (ssl_vrfy_level) {
87 case VRFY_STRICT:
88 ok = STOP;
89 break;
90 case VRFY_ASK:
92 char *line = NULL;
93 size_t linesize = 0;
95 fprintf(stderr, catgets(catd, CATSET, 264,
96 "Continue (y/n)? "));
97 if (readline(stdin, &line, &linesize) > 0 &&
98 *line == 'y')
99 ok = OKAY;
100 else
101 ok = STOP;
102 if (line)
103 free(line);
105 break;
106 case VRFY_WARN:
107 case VRFY_IGNORE:
108 ok = OKAY;
110 return ok;
113 char *
114 ssl_method_string(const char *uhp)
116 char *cp, *mtvar;
118 mtvar = ac_alloc(strlen(uhp) + 12);
119 strcpy(mtvar, "ssl-method-");
120 strcpy(&mtvar[11], uhp);
121 if ((cp = value(mtvar)) == NULL)
122 cp = value("ssl-method");
123 ac_free(mtvar);
124 return cp;
127 enum okay
128 smime_split(FILE *ip, FILE **hp, FILE **bp, long xcount, int keep)
130 char *buf, *hn, *bn;
131 char *savedfields = NULL;
132 size_t bufsize, buflen, count, savedsize = 0;
133 int c;
135 if ((*hp = Ftemp(&hn, "Rh", "w+", 0600, 1)) == NULL ||
136 (*bp = Ftemp(&bn, "Rb", "w+", 0600, 1)) == NULL) {
137 perror("tempfile");
138 return STOP;
140 rm(hn);
141 rm(bn);
142 Ftfree(&hn);
143 Ftfree(&bn);
144 buf = smalloc(bufsize = LINESIZE);
145 savedfields = smalloc(savedsize = 1);
146 *savedfields = '\0';
147 if (xcount < 0)
148 count = fsize(ip);
149 else
150 count = xcount;
151 while (fgetline(&buf, &bufsize, &count, &buflen, ip, 0) != NULL &&
152 *buf != '\n') {
153 if (ascncasecmp(buf, "content-", 8) == 0) {
154 if (keep)
155 fputs("X-Encoded-", *hp);
156 for (;;) {
157 savedsize += buflen;
158 savedfields = srealloc(savedfields, savedsize);
159 strcat(savedfields, buf);
160 if (keep)
161 fwrite(buf, sizeof *buf, buflen, *hp);
162 c = getc(ip);
163 ungetc(c, ip);
164 if (!blankchar(c))
165 break;
166 fgetline(&buf, &bufsize, &count, &buflen,
167 ip, 0);
169 continue;
171 fwrite(buf, sizeof *buf, buflen, *hp);
173 fflush(*hp);
174 rewind(*hp);
175 fputs(savedfields, *bp);
176 putc('\n', *bp);
177 while (fgetline(&buf, &bufsize, &count, &buflen, ip, 0) != NULL)
178 fwrite(buf, sizeof *buf, buflen, *bp);
179 fflush(*bp);
180 rewind(*bp);
181 free(buf);
182 return OKAY;
185 FILE *
186 smime_sign_assemble(FILE *hp, FILE *bp, FILE *sp)
188 char *boundary, *cp;
189 FILE *op;
190 int c, lastc = EOF;
192 if ((op = Ftemp(&cp, "Rs", "w+", 0600, 1)) == NULL) {
193 perror("tempfile");
194 return NULL;
196 rm(cp);
197 Ftfree(&cp);
198 boundary = makeboundary();
199 while ((c = getc(hp)) != EOF) {
200 if (c == '\n' && lastc == '\n')
201 break;
202 putc(c, op);
203 lastc = c;
205 fprintf(op, "Content-Type: multipart/signed;\n"
206 " protocol=\"application/x-pkcs7-signature\"; micalg=sha1;\n"
207 " boundary=\"%s\"\n\n", boundary);
208 fprintf(op, "This is an S/MIME signed message.\n\n--%s\n",
209 boundary);
210 while ((c = getc(bp)) != EOF)
211 putc(c, op);
212 fprintf(op, "\n--%s\n", boundary);
213 fputs("Content-Type: application/x-pkcs7-signature; "
214 "name=\"smime.p7s\"\n"
215 "Content-Transfer-Encoding: base64\n"
216 "Content-Disposition: attachment; filename=\"smime.p7s\"\n\n",
217 op);
218 while ((c = getc(sp)) != EOF) {
219 if (c == '-') {
220 while ((c = getc(sp)) != EOF && c != '\n');
221 continue;
223 putc(c, op);
225 fprintf(op, "\n--%s--\n", boundary);
226 Fclose(hp);
227 Fclose(bp);
228 Fclose(sp);
229 fflush(op);
230 if (ferror(op)) {
231 perror("signed output data");
232 Fclose(op);
233 return NULL;
235 rewind(op);
236 return op;
239 FILE *
240 smime_encrypt_assemble(FILE *hp, FILE *yp)
242 char *cp;
243 FILE *op;
244 int c, lastc = EOF;
246 if ((op = Ftemp(&cp, "Rs", "w+", 0600, 1)) == NULL) {
247 perror("tempfile");
248 return NULL;
250 rm(cp);
251 Ftfree(&cp);
252 while ((c = getc(hp)) != EOF) {
253 if (c == '\n' && lastc == '\n')
254 break;
255 putc(c, op);
256 lastc = c;
258 fprintf(op, "Content-Type: application/x-pkcs7-mime; "
259 "name=\"smime.p7m\"\n"
260 "Content-Transfer-Encoding: base64\n"
261 "Content-Disposition: attachment; "
262 "filename=\"smime.p7m\"\n\n");
263 while ((c = getc(yp)) != EOF) {
264 if (c == '-') {
265 while ((c = getc(yp)) != EOF && c != '\n');
266 continue;
268 putc(c, op);
270 Fclose(hp);
271 Fclose(yp);
272 fflush(op);
273 if (ferror(op)) {
274 perror("encrypted output data");
275 Fclose(op);
276 return NULL;
278 rewind(op);
279 return op;
282 struct message *
283 smime_decrypt_assemble(struct message *m, FILE *hp, FILE *bp)
285 int binary = 0, lastnl = 0;
286 char *buf = NULL, *cp;
287 size_t bufsize = 0, buflen, count;
288 long lines = 0, octets = 0;
289 struct message *x;
290 off_t offset;
292 x = salloc(sizeof *x);
293 *x = *m;
294 fflush(mb.mb_otf);
295 fseek(mb.mb_otf, 0L, SEEK_END);
296 offset = ftell(mb.mb_otf);
297 count = fsize(hp);
298 while (fgetline(&buf, &bufsize, &count, &buflen, hp, 0) != NULL) {
299 if (buf[0] == '\n')
300 break;
301 if ((cp = thisfield(buf, "content-transfer-encoding")) != NULL)
302 if (ascncasecmp(cp, "binary", 7) == 0)
303 binary = 1;
304 fwrite(buf, sizeof *buf, buflen, mb.mb_otf);
305 octets += buflen;
306 lines++;
308 octets += mkdate(mb.mb_otf, "X-Decoding-Date");
309 lines++;
310 count = fsize(bp);
311 while (fgetline(&buf, &bufsize, &count, &buflen, bp, 0) != NULL) {
312 lines++;
313 if (!binary && buf[buflen-1] == '\n' && buf[buflen-2] == '\r')
314 buf[--buflen-1] = '\n';
315 fwrite(buf, sizeof *buf, buflen, mb.mb_otf);
316 octets += buflen;
317 if (buf[0] == '\n')
318 lastnl++;
319 else if (buf[buflen-1] == '\n')
320 lastnl = 1;
321 else
322 lastnl = 0;
324 while (!binary && lastnl < 2) {
325 putc('\n', mb.mb_otf);
326 lines++;
327 octets++;
328 lastnl++;
330 Fclose(hp);
331 Fclose(bp);
332 free(buf);
333 fflush(mb.mb_otf);
334 if (ferror(mb.mb_otf)) {
335 perror("decrypted output data");
336 return NULL;
338 x->m_size = x->m_xsize = octets;
339 x->m_lines = x->m_xlines = lines;
340 x->m_block = mailx_blockof(offset);
341 x->m_offset = mailx_offsetof(offset);
342 return x;
345 int
346 ccertsave(void *v)
348 int *ip;
349 int f, *msgvec;
350 char *file = NULL, *str = v;
351 int val = 0;
352 FILE *fp;
354 msgvec = salloc((msgCount + 2) * sizeof *msgvec);
355 if ((file = laststring(str, &f, 1)) == NULL) {
356 fprintf(stderr, "No file to save certificate given.\n");
357 return 1;
359 if (!f) {
360 *msgvec = first(0, MMNORM);
361 if (*msgvec == 0) {
362 if (inhook)
363 return 0;
364 fprintf(stderr,
365 "No messages to get certificates from.\n");
366 return 1;
368 msgvec[1] = 0;
369 } else if (getmsglist(str, msgvec, 0) < 0)
370 return 1;
371 if (*msgvec == 0) {
372 if (inhook)
373 return 0;
374 fprintf(stderr, "No applicable messages.\n");
375 return 1;
377 if ((fp = Fopen(file, "a")) == NULL) {
378 perror(file);
379 return 1;
381 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
382 if (smime_certsave(&message[*ip-1], *ip, fp) != OKAY)
383 val = 1;
384 Fclose(fp);
385 if (val == 0)
386 printf("Certificate(s) saved.\n");
387 return val;
389 enum okay
390 rfc2595_hostname_match(const char *host, const char *pattern)
392 if (pattern[0] == '*' && pattern[1] == '.') {
393 pattern++;
394 while (*host && *host != '.')
395 host++;
397 return asccasecmp(host, pattern) == 0 ? OKAY : STOP;
399 #endif /* USE_SSL */