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