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);
71 memcpy(vrvar
, "ssl-verify-", 11);
72 memcpy(vrvar
+ 11, uhp
, i
+1);
73 cp
= vok_vlook(vrvar
);
77 cp
= ok_vlook(ssl_verify
);
81 for (i
= 0; i
< NELEM(_ssl_verify_levels
); ++i
)
82 if (!strcmp(_ssl_verify_levels
[i
].sv_name
, cp
)) {
83 ssl_verify_level
= _ssl_verify_levels
[i
].sv_level
;
86 fprintf(stderr
, tr(265, "Invalid value of %s: %s\n"), vrvar
, cp
);
94 ssl_verify_decide(void)
99 switch (ssl_verify_level
) {
100 case SSL_VERIFY_STRICT
:
104 rv
= getapproval(NULL
, FAL0
) ? OKAY
: STOP
;
106 case SSL_VERIFY_WARN
:
107 case SSL_VERIFY_IGNORE
:
116 ssl_method_string(char const *uhp
)
123 mtvar
= ac_alloc(11 + l
+1);
125 memcpy(mtvar
, "ssl-method-", 11);
126 memcpy(mtvar
+ 11, uhp
, l
+1);
127 if ((cp
= vok_vlook(mtvar
)) == NULL
)
128 cp
= ok_vlook(ssl_method
);
136 smime_split(FILE *ip
, FILE **hp
, FILE **bp
, long xcount
, int keep
)
138 char *buf
, *savedfields
/* TODO use struct str or local per-line xy */ = NULL
;
139 size_t bufsize
, buflen
, cnt
, savedsize
= 0;
144 if ((*hp
= Ftmp(NULL
, "smimeh", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
147 if ((*bp
= Ftmp(NULL
, "smimeb", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
155 buf
= smalloc(bufsize
= LINESIZE
);
156 savedfields
= smalloc(savedsize
= 1);
163 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
&&
165 if (!ascncasecmp(buf
, "content-", 8)) {
167 fputs("X-Encoded-", *hp
);
170 savedfields
= srealloc(savedfields
, savedsize
);
171 strcat(savedfields
, buf
);
173 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
178 fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0);
182 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
186 fputs(savedfields
, *bp
);
188 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
)
189 fwrite(buf
, sizeof *buf
, buflen
, *bp
);
201 smime_sign_assemble(FILE *hp
, FILE *bp
, FILE *sp
)
208 if ((op
= Ftmp(NULL
, "smimea", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
214 while ((c
= getc(hp
)) != EOF
) {
215 if (c
== '\n' && lastc
== '\n')
221 boundary
= mime_create_boundary();
222 fprintf(op
, "Content-Type: multipart/signed;\n"
223 " protocol=\"application/x-pkcs7-signature\"; micalg=sha1;\n"
224 " boundary=\"%s\"\n\n", boundary
);
225 fprintf(op
, "This is an S/MIME signed message.\n\n--%s\n", boundary
);
226 while ((c
= getc(bp
)) != EOF
)
229 fprintf(op
, "\n--%s\n", boundary
);
230 fputs("Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"\n"
231 "Content-Transfer-Encoding: base64\n"
232 "Content-Disposition: attachment; filename=\"smime.p7s\"\n\n", op
);
233 while ((c
= getc(sp
)) != EOF
) {
235 while ((c
= getc(sp
)) != EOF
&& c
!= '\n');
241 fprintf(op
, "\n--%s--\n", boundary
);
249 perror("signed output data");
261 smime_encrypt_assemble(FILE *hp
, FILE *yp
)
267 if ((op
= Ftmp(NULL
, "smimee", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
273 while ((c
= getc(hp
)) != EOF
) {
274 if (c
== '\n' && lastc
== '\n')
280 fprintf(op
, "Content-Type: application/x-pkcs7-mime; name=\"smime.p7m\"\n"
281 "Content-Transfer-Encoding: base64\n"
282 "Content-Disposition: attachment; filename=\"smime.p7m\"\n\n");
283 while ((c
= getc(yp
)) != EOF
) {
285 while ((c
= getc(yp
)) != EOF
&& c
!= '\n');
296 perror("encrypted output data");
308 smime_decrypt_assemble(struct message
*m
, FILE *hp
, FILE *bp
)
313 size_t bufsize
= 0, buflen
, cnt
;
314 long lines
= 0, octets
= 0;
319 x
= salloc(sizeof *x
);
322 fseek(mb
.mb_otf
, 0L, SEEK_END
);
323 offset
= ftell(mb
.mb_otf
);
326 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, hp
, 0) != NULL
) {
330 if ((cp
= thisfield(buf
, "content-transfer-encoding")) != NULL
)
331 if (!ascncasecmp(cp
, "binary", 7))
333 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
338 { struct time_current save
= time_current
;
339 time_current_update(&time_current
, TRU1
);
340 octets
+= mkdate(mb
.mb_otf
, "X-Decoding-Date");
346 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, bp
, 0) != NULL
) {
348 if (!binary
&& buf
[buflen
- 1] == '\n' && buf
[buflen
- 2] == '\r')
349 buf
[--buflen
- 1] = '\n';
350 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
354 else if (buf
[buflen
- 1] == '\n')
360 while (!binary
&& lastnl
< 2) {
361 putc('\n', mb
.mb_otf
);
372 if (ferror(mb
.mb_otf
)) {
373 perror("decrypted output data");
377 x
->m_size
= x
->m_xsize
= octets
;
378 x
->m_lines
= x
->m_xlines
= lines
;
379 x
->m_block
= mailx_blockof(offset
);
380 x
->m_offset
= mailx_offsetof(offset
);
389 int *ip
, *msgvec
, val
;
390 char *file
= NULL
, *str
= v
;
395 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
398 if ((file
= laststring(str
, &f
, 1)) == NULL
||
399 (file
= file_expand(file
)) == NULL
) {
400 fprintf(stderr
, "No file to save certificate given.\n");
406 *msgvec
= first(0, MMNORM
);
408 getmsglist(str
, msgvec
, 0);
413 fprintf(stderr
, "No applicable messages.\n");
417 if ((fp
= Fopen(file
, "a")) == NULL
) {
421 for (val
= 0, ip
= msgvec
;
422 *ip
!= 0 && UICMP(z
, PTR2SIZE(ip
- msgvec
), <, msgCount
); ++ip
)
423 if (smime_certsave(&message
[*ip
- 1], *ip
, fp
) != OKAY
)
428 printf("Certificate(s) saved.\n");
435 rfc2595_hostname_match(char const *host
, char const *pattern
)
440 if (pattern
[0] == '*' && pattern
[1] == '.') {
442 while (*host
&& *host
!= '.')
445 rv
= !asccasecmp(host
, pattern
) ? OKAY
: STOP
;
449 #endif /* HAVE_SSL */
451 /* vim:set fenc=utf-8:s-it-mode */