1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ Generic SSL / SMIME commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2013 Steffen "Daode" Nurpmeso <sdaoden@users.sf.net>.
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
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
43 typedef int avoid_empty_file_compiler_warning
;
49 ssl_set_vrfy_level(const char *uhp
)
54 ssl_vrfy_level
= VRFY_ASK
;
56 vrvar
= ac_alloc(l
+ 12);
57 memcpy(vrvar
, "ssl-verify-", 11);
58 memcpy(vrvar
+ 11, uhp
, l
+ 1);
60 if ((cp
= value(vrvar
)) == NULL
)
61 cp
= value("ssl-verify");
64 if (strcmp(cp
, "strict") == 0)
65 ssl_vrfy_level
= VRFY_STRICT
;
66 else if (strcmp(cp
, "ask") == 0)
67 ssl_vrfy_level
= VRFY_ASK
;
68 else if (strcmp(cp
, "warn") == 0)
69 ssl_vrfy_level
= VRFY_WARN
;
70 else if (strcmp(cp
, "ignore") == 0)
71 ssl_vrfy_level
= VRFY_IGNORE
;
73 fprintf(stderr
, tr(265,
74 "invalid value of ssl-verify: %s\n"), cp
);
83 switch (ssl_vrfy_level
) {
92 fprintf(stderr
, catgets(catd
, CATSET
, 264,
94 if (readline_restart(stdin
, &line
, &linesize
, 0) > 0 &&
111 ssl_method_string(const char *uhp
)
117 mtvar
= ac_alloc(l
+ 12);
118 memcpy(mtvar
, "ssl-method-", 11);
119 memcpy(mtvar
+ 11, uhp
, l
+ 1);
120 if ((cp
= value(mtvar
)) == NULL
)
121 cp
= value("ssl-method");
127 smime_split(FILE *ip
, FILE **hp
, FILE **bp
, long xcount
, int keep
)
129 /* TODO like i said quite often now, the entire SSL stuff really needs
130 * TODO a review ASAP; also in respect to correct resource release, and
131 * TODO especially in case of errors; S-nail is a program that REALLY
132 * TODO may run for a week or longer!!! */
134 char *savedfields
= NULL
;
135 size_t bufsize
, buflen
, cnt
, savedsize
= 0;
138 if ((*hp
= Ftemp(&hn
, "Rh", "w+", 0600, 1)) == NULL
)
142 if ((*bp
= Ftemp(&bn
, "Rb", "w+", 0600, 1)) == NULL
) {
150 buf
= smalloc(bufsize
= LINESIZE
);
151 savedfields
= smalloc(savedsize
= 1);
158 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
&&
160 if (ascncasecmp(buf
, "content-", 8) == 0) {
162 fputs("X-Encoded-", *hp
);
165 savedfields
= srealloc(savedfields
, savedsize
);
166 memcpy(savedfields
+ strlen(savedfields
),
169 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
174 fgetline(&buf
, &bufsize
, &cnt
, &buflen
,
179 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
184 fputs(savedfields
, *bp
);
186 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
)
187 fwrite(buf
, sizeof *buf
, buflen
, *bp
);
197 smime_sign_assemble(FILE *hp
, FILE *bp
, FILE *sp
)
203 if ((op
= Ftemp(&cp
, "Rs", "w+", 0600, 1)) == NULL
) {
209 boundary
= mime_create_boundary();
210 while ((c
= getc(hp
)) != EOF
) {
211 if (c
== '\n' && lastc
== '\n')
216 fprintf(op
, "Content-Type: multipart/signed;\n"
217 " protocol=\"application/x-pkcs7-signature\"; micalg=sha1;\n"
218 " boundary=\"%s\"\n\n", boundary
);
219 fprintf(op
, "This is an S/MIME signed message.\n\n--%s\n",
221 while ((c
= getc(bp
)) != EOF
)
223 fprintf(op
, "\n--%s\n", boundary
);
224 fputs("Content-Type: application/x-pkcs7-signature; "
225 "name=\"smime.p7s\"\n"
226 "Content-Transfer-Encoding: base64\n"
227 "Content-Disposition: attachment; filename=\"smime.p7s\"\n\n",
229 while ((c
= getc(sp
)) != EOF
) {
231 while ((c
= getc(sp
)) != EOF
&& c
!= '\n');
236 fprintf(op
, "\n--%s--\n", boundary
);
242 perror("signed output data");
251 smime_encrypt_assemble(FILE *hp
, FILE *yp
)
257 if ((op
= Ftemp(&cp
, "Rs", "w+", 0600, 1)) == NULL
) {
263 while ((c
= getc(hp
)) != EOF
) {
264 if (c
== '\n' && lastc
== '\n')
269 fprintf(op
, "Content-Type: application/x-pkcs7-mime; "
270 "name=\"smime.p7m\"\n"
271 "Content-Transfer-Encoding: base64\n"
272 "Content-Disposition: attachment; "
273 "filename=\"smime.p7m\"\n\n");
274 while ((c
= getc(yp
)) != EOF
) {
276 while ((c
= getc(yp
)) != EOF
&& c
!= '\n');
285 perror("encrypted output data");
294 smime_decrypt_assemble(struct message
*m
, FILE *hp
, FILE *bp
)
296 int binary
= 0, lastnl
= 0;
298 size_t bufsize
= 0, buflen
, cnt
;
299 long lines
= 0, octets
= 0;
303 x
= salloc(sizeof *x
);
306 fseek(mb
.mb_otf
, 0L, SEEK_END
);
307 offset
= ftell(mb
.mb_otf
);
309 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, hp
, 0) != NULL
) {
313 if ((cp
= thisfield(buf
, "content-transfer-encoding")) != NULL
)
314 if (ascncasecmp(cp
, "binary", 7) == 0)
316 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
320 octets
+= mkdate(mb
.mb_otf
, "X-Decoding-Date");
323 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, bp
, 0) != NULL
) {
325 if (!binary
&& buf
[buflen
-1] == '\n' && buf
[buflen
-2] == '\r')
326 buf
[--buflen
-1] = '\n';
327 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
331 else if (buf
[buflen
-1] == '\n')
336 while (!binary
&& lastnl
< 2) {
337 putc('\n', mb
.mb_otf
);
346 if (ferror(mb
.mb_otf
)) {
347 perror("decrypted output data");
350 x
->m_size
= x
->m_xsize
= octets
;
351 x
->m_lines
= x
->m_xlines
= lines
;
352 x
->m_block
= mailx_blockof(offset
);
353 x
->m_offset
= mailx_offsetof(offset
);
362 char *file
= NULL
, *str
= v
;
366 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
367 if ((file
= laststring(str
, &f
, 1)) == NULL
) {
368 fprintf(stderr
, "No file to save certificate given.\n");
372 *msgvec
= first(0, MMNORM
);
377 "No messages to get certificates from.\n");
381 } else if (getmsglist(str
, msgvec
, 0) < 0)
386 fprintf(stderr
, "No applicable messages.\n");
389 if ((fp
= Fopen(file
, "a")) == NULL
) {
393 for (ip
= msgvec
; *ip
&& ip
-msgvec
< msgCount
; ip
++)
394 if (smime_certsave(&message
[*ip
-1], *ip
, fp
) != OKAY
)
398 printf("Certificate(s) saved.\n");
403 rfc2595_hostname_match(const char *host
, const char *pattern
)
405 if (pattern
[0] == '*' && pattern
[1] == '.') {
407 while (*host
&& *host
!= '.')
410 return asccasecmp(host
, pattern
) == 0 ? OKAY
: STOP
;
412 #endif /* HAVE_SSL */