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
, _("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
)
139 struct myline
*ml_next
;
141 char ml_buf
[VFIELD_SIZE(sizeof(uiz_t
))];
144 size_t bufsize
, buflen
, cnt
;
149 if ((*hp
= Ftmp(NULL
, "smimeh", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
152 if ((*bp
= Ftmp(NULL
, "smimeb", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
161 buf
= smalloc(bufsize
= LINESIZE
);
162 cnt
= (xcount
< 0) ? fsize(ip
) : xcount
;
164 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
&&
166 if (!ascncasecmp(buf
, "content-", 8)) {
168 fputs("X-Encoded-", *hp
);
170 struct myline
*ml
= smalloc(sizeof *ml
-
171 VFIELD_SIZEOF(struct myline
, ml_buf
) + buflen
+1);
179 memcpy(ml
->ml_buf
, buf
, buflen
+1);
181 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
186 fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0);
190 fwrite(buf
, sizeof *buf
, buflen
, *hp
);
194 while (head
!= NULL
) {
195 fwrite(head
->ml_buf
, sizeof *head
->ml_buf
, head
->ml_len
, *bp
);
197 head
= head
->ml_next
;
201 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, ip
, 0) != NULL
)
202 fwrite(buf
, sizeof *buf
, buflen
, *bp
);
213 smime_sign_assemble(FILE *hp
, FILE *bp
, FILE *sp
)
220 if ((op
= Ftmp(NULL
, "smimea", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
226 while ((c
= getc(hp
)) != EOF
) {
227 if (c
== '\n' && lastc
== '\n')
233 boundary
= mime_create_boundary();
234 fprintf(op
, "Content-Type: multipart/signed;\n"
235 " protocol=\"application/x-pkcs7-signature\"; micalg=sha1;\n"
236 " boundary=\"%s\"\n\n", boundary
);
237 fprintf(op
, "This is an S/MIME signed message.\n\n--%s\n", boundary
);
238 while ((c
= getc(bp
)) != EOF
)
241 fprintf(op
, "\n--%s\n", boundary
);
242 fputs("Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"\n"
243 "Content-Transfer-Encoding: base64\n"
244 "Content-Disposition: attachment; filename=\"smime.p7s\"\n\n", op
);
245 while ((c
= getc(sp
)) != EOF
) {
247 while ((c
= getc(sp
)) != EOF
&& c
!= '\n');
253 fprintf(op
, "\n--%s--\n", boundary
);
261 perror("signed output data");
273 smime_encrypt_assemble(FILE *hp
, FILE *yp
)
279 if ((op
= Ftmp(NULL
, "smimee", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
285 while ((c
= getc(hp
)) != EOF
) {
286 if (c
== '\n' && lastc
== '\n')
292 fprintf(op
, "Content-Type: application/x-pkcs7-mime; name=\"smime.p7m\"\n"
293 "Content-Transfer-Encoding: base64\n"
294 "Content-Disposition: attachment; filename=\"smime.p7m\"\n\n");
295 while ((c
= getc(yp
)) != EOF
) {
297 while ((c
= getc(yp
)) != EOF
&& c
!= '\n');
308 perror("encrypted output data");
320 smime_decrypt_assemble(struct message
*m
, FILE *hp
, FILE *bp
)
325 size_t bufsize
= 0, buflen
, cnt
;
326 long lines
= 0, octets
= 0;
331 x
= salloc(sizeof *x
);
334 fseek(mb
.mb_otf
, 0L, SEEK_END
);
335 offset
= ftell(mb
.mb_otf
);
338 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, hp
, 0) != NULL
) {
342 if ((cp
= thisfield(buf
, "content-transfer-encoding")) != NULL
)
343 if (!ascncasecmp(cp
, "binary", 7))
345 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
350 { struct time_current save
= time_current
;
351 time_current_update(&time_current
, TRU1
);
352 octets
+= mkdate(mb
.mb_otf
, "X-Decoding-Date");
358 while (fgetline(&buf
, &bufsize
, &cnt
, &buflen
, bp
, 0) != NULL
) {
360 if (!binary
&& buf
[buflen
- 1] == '\n' && buf
[buflen
- 2] == '\r')
361 buf
[--buflen
- 1] = '\n';
362 fwrite(buf
, sizeof *buf
, buflen
, mb
.mb_otf
);
366 else if (buf
[buflen
- 1] == '\n')
372 while (!binary
&& lastnl
< 2) {
373 putc('\n', mb
.mb_otf
);
384 if (ferror(mb
.mb_otf
)) {
385 perror("decrypted output data");
389 x
->m_size
= x
->m_xsize
= octets
;
390 x
->m_lines
= x
->m_xlines
= lines
;
391 x
->m_block
= mailx_blockof(offset
);
392 x
->m_offset
= mailx_offsetof(offset
);
401 int *ip
, *msgvec
, val
;
402 char *file
= NULL
, *str
= v
;
407 msgvec
= salloc((msgCount
+ 2) * sizeof *msgvec
);
410 if ((file
= laststring(str
, &f
, TRU1
)) == NULL
||
411 (file
= file_expand(file
)) == NULL
) {
412 fprintf(stderr
, "No file to save certificate given.\n");
418 *msgvec
= first(0, MMNORM
);
420 getmsglist(str
, msgvec
, 0);
425 fprintf(stderr
, "No applicable messages.\n");
429 if ((fp
= Fopen(file
, "a")) == NULL
) {
433 for (val
= 0, ip
= msgvec
;
434 *ip
!= 0 && UICMP(z
, PTR2SIZE(ip
- msgvec
), <, msgCount
); ++ip
)
435 if (smime_certsave(&message
[*ip
- 1], *ip
, fp
) != OKAY
)
440 printf("Certificate(s) saved.\n");
447 rfc2595_hostname_match(char const *host
, char const *pattern
)
452 if (pattern
[0] == '*' && pattern
[1] == '.') {
454 while (*host
&& *host
!= '.')
457 rv
= !asccasecmp(host
, pattern
) ? OKAY
: STOP
;
461 #endif /* HAVE_SSL */