1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ Generic SSL / S/MIME commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2014 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
40 #ifndef HAVE_AMALGAMATION
46 struct ssl_verify_levels
{
47 char const sv_name
[8];
48 enum ssl_verify_level sv_level
;
51 /* Supported SSL/TLS verification methods: update manual on change! */
52 static struct ssl_verify_levels
const _ssl_verify_levels
[] = {
53 {"strict", SSL_VERIFY_STRICT
},
54 {"ask", SSL_VERIFY_ASK
},
55 {"warn", SSL_VERIFY_WARN
},
56 {"ignore", SSL_VERIFY_IGNORE
}
60 ssl_set_verify_level(char const *uhp
)
66 ssl_verify_level
= SSL_VERIFY_ASK
;
69 vrvar
= ac_alloc(11u + i
+1);
70 memcpy(vrvar
, "ssl-verify-", 11u);
71 memcpy(vrvar
+ 11u, uhp
, i
+1);
73 cp
= vok_vlook(vrvar
);
76 cp
= ok_vlook(ssl_verify
);
80 for (i
= 0; i
< NELEM(_ssl_verify_levels
); ++i
)
81 if (!strcmp(_ssl_verify_levels
[i
].sv_name
, cp
)) {
82 ssl_verify_level
= _ssl_verify_levels
[i
].sv_level
;
85 fprintf(stderr
, tr(265, "Invalid value of %s: %s\n"), vrvar
, cp
);
93 ssl_verify_decide(void)
98 switch (ssl_verify_level
) {
99 case SSL_VERIFY_STRICT
:
103 rv
= getapproval(NULL
, FAL0
) ? OKAY
: STOP
;
105 case SSL_VERIFY_WARN
:
106 case SSL_VERIFY_IGNORE
:
115 ssl_method_string(char const *uhp
)
122 mtvar
= ac_alloc(11u + l
+1);
123 memcpy(mtvar
, "ssl-method-", 11);
124 memcpy(mtvar
+ 11, uhp
, l
+1);
125 if ((cp
= vok_vlook(mtvar
)) == NULL
)
126 cp
= ok_vlook(ssl_method
);
133 smime_split(FILE *ip
, FILE **hp
, FILE **bp
, long xcount
, int keep
)
135 char *buf
, *savedfields
/* TODO use struct str or local per-line xy */ = NULL
;
136 size_t bufsize
, buflen
, cnt
, savedsize
= 0;
141 if ((*hp
= Ftmp(NULL
, "smimeh", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
144 if ((*bp
= Ftmp(NULL
, "smimeb", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
152 buf
= smalloc(bufsize
= LINESIZE
);
153 savedfields
= smalloc(savedsize
= 1);
160 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
&&
162 if (!ascncasecmp(buf
, "content-", 8)) {
164 fputs("X-Encoded-", *hp
);
167 savedfields
= srealloc(savedfields
, savedsize
);
168 strcat(savedfields
, buf
);
170 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
175 fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0);
179 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
183 fputs(savedfields
, *bp
);
185 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
)
186 fwrite(buf
, sizeof *buf
, buflen
, *bp
);
198 smime_sign_assemble(FILE *hp
, FILE *bp
, FILE *sp
)
205 if ((op
= Ftmp(NULL
, "smimea", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
211 while ((c
= getc(hp
)) != EOF
) {
212 if (c
== '\n' && lastc
== '\n')
218 boundary
= mime_create_boundary();
219 fprintf(op
, "Content-Type: multipart/signed;\n"
220 " protocol=\"application/x-pkcs7-signature\"; micalg=sha1;\n"
221 " boundary=\"%s\"\n\n", boundary
);
222 fprintf(op
, "This is an S/MIME signed message.\n\n--%s\n", boundary
);
223 while ((c
= getc(bp
)) != EOF
)
226 fprintf(op
, "\n--%s\n", boundary
);
227 fputs("Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"\n"
228 "Content-Transfer-Encoding: base64\n"
229 "Content-Disposition: attachment; filename=\"smime.p7s\"\n\n", op
);
230 while ((c
= getc(sp
)) != EOF
) {
232 while ((c
= getc(sp
)) != EOF
&& c
!= '\n');
238 fprintf(op
, "\n--%s--\n", boundary
);
246 perror("signed output data");
258 smime_encrypt_assemble(FILE *hp
, FILE *yp
)
264 if ((op
= Ftmp(NULL
, "smimee", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
270 while ((c
= getc(hp
)) != EOF
) {
271 if (c
== '\n' && lastc
== '\n')
277 fprintf(op
, "Content-Type: application/x-pkcs7-mime; name=\"smime.p7m\"\n"
278 "Content-Transfer-Encoding: base64\n"
279 "Content-Disposition: attachment; filename=\"smime.p7m\"\n\n");
280 while ((c
= getc(yp
)) != EOF
) {
282 while ((c
= getc(yp
)) != EOF
&& c
!= '\n');
293 perror("encrypted output data");
305 smime_decrypt_assemble(struct message
*m
, FILE *hp
, FILE *bp
)
310 size_t bufsize
= 0, buflen
, cnt
;
311 long lines
= 0, octets
= 0;
316 x
= salloc(sizeof *x
);
319 fseek(mb
.mb_otf
, 0L, SEEK_END
);
320 offset
= ftell(mb
.mb_otf
);
323 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, hp
, 0) != NULL
) {
327 if ((cp
= thisfield(buf
, "content-transfer-encoding")) != NULL
)
328 if (!ascncasecmp(cp
, "binary", 7))
330 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
335 octets
+= mkdate(mb
.mb_otf
, "X-Decoding-Date");
339 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, bp
, 0) != NULL
) {
341 if (!binary
&& buf
[buflen
- 1] == '\n' && buf
[buflen
- 2] == '\r')
342 buf
[--buflen
- 1] = '\n';
343 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
347 else if (buf
[buflen
- 1] == '\n')
353 while (!binary
&& lastnl
< 2) {
354 putc('\n', mb
.mb_otf
);
365 if (ferror(mb
.mb_otf
)) {
366 perror("decrypted output data");
370 x
->m_size
= x
->m_xsize
= octets
;
371 x
->m_lines
= x
->m_xlines
= lines
;
372 x
->m_block
= mailx_blockof(offset
);
373 x
->m_offset
= mailx_offsetof(offset
);
382 int *ip
, *msgvec
, val
;
383 char *file
= NULL
, *str
= v
;
388 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
391 if ((file
= laststring(str
, &f
, 1)) == NULL
) {
392 fprintf(stderr
, "No file to save certificate given.\n");
396 *msgvec
= first(0, MMNORM
);
401 fprintf(stderr
, "No messages to get certificates from.\n");
405 } else if (getmsglist(str
, msgvec
, 0) < 0)
412 fprintf(stderr
, "No applicable messages.\n");
416 if ((fp
= Fopen(file
, "a")) == NULL
) {
420 for (val
= 0, ip
= msgvec
;
421 *ip
!= 0 && UICMP(z
, PTR2SIZE(ip
- msgvec
), <, msgCount
); ++ip
)
422 if (smime_certsave(&message
[*ip
- 1], *ip
, fp
) != OKAY
)
427 printf("Certificate(s) saved.\n");
434 rfc2595_hostname_match(char const *host
, char const *pattern
)
439 if (pattern
[0] == '*' && pattern
[1] == '.') {
441 while (*host
&& *host
!= '.')
444 rv
= !asccasecmp(host
, pattern
) ? OKAY
: STOP
;
448 #endif /* HAVE_SSL */
450 /* vim:set fenc=utf-8:s-it-mode */