File: | src/usr.bin/openssl/s_client.c |
Warning: | line 1151, column 2 Value stored to 'tty_on' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: s_client.c,v 1.64 2023/12/29 12:15:49 tb Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. |
4 | * |
5 | * This package is an SSL implementation written |
6 | * by Eric Young (eay@cryptsoft.com). |
7 | * The implementation was written so as to conform with Netscapes SSL. |
8 | * |
9 | * This library is free for commercial and non-commercial use as long as |
10 | * the following conditions are aheared to. The following conditions |
11 | * apply to all code found in this distribution, be it the RC4, RSA, |
12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 | * included with this distribution is covered by the same copyright terms |
14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 | * |
16 | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | * the code are not to be removed. |
18 | * If this package is used in a product, Eric Young should be given attribution |
19 | * as the author of the parts of the library used. |
20 | * This can be in the form of a textual message at program startup or |
21 | * in documentation (online or textual) provided with the package. |
22 | * |
23 | * Redistribution and use in source and binary forms, with or without |
24 | * modification, are permitted provided that the following conditions |
25 | * are met: |
26 | * 1. Redistributions of source code must retain the copyright |
27 | * notice, this list of conditions and the following disclaimer. |
28 | * 2. Redistributions in binary form must reproduce the above copyright |
29 | * notice, this list of conditions and the following disclaimer in the |
30 | * documentation and/or other materials provided with the distribution. |
31 | * 3. All advertising materials mentioning features or use of this software |
32 | * must display the following acknowledgement: |
33 | * "This product includes cryptographic software written by |
34 | * Eric Young (eay@cryptsoft.com)" |
35 | * The word 'cryptographic' can be left out if the rouines from the library |
36 | * being used are not cryptographic related :-). |
37 | * 4. If you include any Windows specific code (or a derivative thereof) from |
38 | * the apps directory (application code) you must include an acknowledgement: |
39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 | * |
41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 | * SUCH DAMAGE. |
52 | * |
53 | * The licence and distribution terms for any publically available version or |
54 | * derivative of this code cannot be changed. i.e. this code cannot simply be |
55 | * copied and put under another distribution licence |
56 | * [including the GNU Public Licence.] |
57 | */ |
58 | /* ==================================================================== |
59 | * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. |
60 | * |
61 | * Redistribution and use in source and binary forms, with or without |
62 | * modification, are permitted provided that the following conditions |
63 | * are met: |
64 | * |
65 | * 1. Redistributions of source code must retain the above copyright |
66 | * notice, this list of conditions and the following disclaimer. |
67 | * |
68 | * 2. Redistributions in binary form must reproduce the above copyright |
69 | * notice, this list of conditions and the following disclaimer in |
70 | * the documentation and/or other materials provided with the |
71 | * distribution. |
72 | * |
73 | * 3. All advertising materials mentioning features or use of this |
74 | * software must display the following acknowledgment: |
75 | * "This product includes software developed by the OpenSSL Project |
76 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
77 | * |
78 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
79 | * endorse or promote products derived from this software without |
80 | * prior written permission. For written permission, please contact |
81 | * openssl-core@openssl.org. |
82 | * |
83 | * 5. Products derived from this software may not be called "OpenSSL" |
84 | * nor may "OpenSSL" appear in their names without prior written |
85 | * permission of the OpenSSL Project. |
86 | * |
87 | * 6. Redistributions of any form whatsoever must retain the following |
88 | * acknowledgment: |
89 | * "This product includes software developed by the OpenSSL Project |
90 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
91 | * |
92 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
93 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
94 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
95 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
96 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
97 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
98 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
99 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
100 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
101 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
102 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
103 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
104 | * ==================================================================== |
105 | * |
106 | * This product includes cryptographic software written by Eric Young |
107 | * (eay@cryptsoft.com). This product includes software written by Tim |
108 | * Hudson (tjh@cryptsoft.com). |
109 | * |
110 | */ |
111 | /* ==================================================================== |
112 | * Copyright 2005 Nokia. All rights reserved. |
113 | * |
114 | * The portions of the attached software ("Contribution") is developed by |
115 | * Nokia Corporation and is licensed pursuant to the OpenSSL open source |
116 | * license. |
117 | * |
118 | * The Contribution, originally written by Mika Kousa and Pasi Eronen of |
119 | * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites |
120 | * support (see RFC 4279) to OpenSSL. |
121 | * |
122 | * No patent licenses or other rights except those expressly stated in |
123 | * the OpenSSL open source license shall be deemed granted or received |
124 | * expressly, by implication, estoppel, or otherwise. |
125 | * |
126 | * No assurances are provided by Nokia that the Contribution does not |
127 | * infringe the patent or other intellectual property rights of any third |
128 | * party or that the license provides you with all the necessary rights |
129 | * to make use of the Contribution. |
130 | * |
131 | * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN |
132 | * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA |
133 | * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY |
134 | * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR |
135 | * OTHERWISE. |
136 | */ |
137 | |
138 | #include <sys/types.h> |
139 | #include <sys/socket.h> |
140 | |
141 | #include <netinet/in.h> |
142 | |
143 | #include <assert.h> |
144 | #include <ctype.h> |
145 | #include <limits.h> |
146 | #include <netdb.h> |
147 | #include <stdio.h> |
148 | #include <stdlib.h> |
149 | #include <string.h> |
150 | #include <unistd.h> |
151 | #include <poll.h> |
152 | |
153 | #include "apps.h" |
154 | |
155 | #include <openssl/bn.h> |
156 | #include <openssl/err.h> |
157 | #include <openssl/ocsp.h> |
158 | #include <openssl/pem.h> |
159 | #include <openssl/ssl.h> |
160 | #include <openssl/x509.h> |
161 | |
162 | #include "s_apps.h" |
163 | #include "timeouts.h" |
164 | |
165 | /*#define SSL_HOST_NAME "www.netscape.com" */ |
166 | /*#define SSL_HOST_NAME "193.118.187.102" */ |
167 | #define SSL_HOST_NAME"localhost" "localhost" |
168 | |
169 | /*#define TEST_CERT "client.pem" *//* no default cert. */ |
170 | |
171 | #define BUFSIZZ1024*8 1024*8 |
172 | |
173 | static void sc_usage(void); |
174 | static void print_stuff(BIO *berr, SSL *con, int full); |
175 | static int ocsp_resp_cb(SSL *s, void *arg); |
176 | static int ssl_servername_cb(SSL *s, int *ad, void *arg); |
177 | |
178 | enum { |
179 | PROTO_OFF = 0, |
180 | PROTO_SMTP, |
181 | PROTO_LMTP, |
182 | PROTO_POP3, |
183 | PROTO_IMAP, |
184 | PROTO_FTP, |
185 | PROTO_XMPP, |
186 | }; |
187 | |
188 | /* This is a context that we pass to callbacks */ |
189 | typedef struct tlsextctx_st { |
190 | BIO *biodebug; |
191 | int ack; |
192 | } tlsextctx; |
193 | |
194 | static struct { |
195 | int af; |
196 | char *alpn_in; |
197 | int bugs; |
198 | char *CAfile; |
199 | char *CApath; |
200 | char *cert_file; |
201 | int cert_format; |
202 | char *cipher; |
203 | unsigned int clr; |
204 | char *connect; |
205 | int crlf; |
206 | int debug; |
207 | int enable_timeouts; |
208 | const char *errstr; |
209 | char *groups_in; |
210 | char *host; |
211 | int ign_eof; |
212 | char *key_file; |
213 | int key_format; |
214 | char *keymatexportlabel; |
215 | int keymatexportlen; |
216 | uint16_t max_version; |
217 | uint16_t min_version; |
218 | const SSL_METHOD *meth; |
219 | int msg; |
220 | int nbio; |
221 | int nbio_test; |
222 | int no_servername; |
223 | char *npn_in; |
224 | unsigned int off; |
225 | char *passarg; |
226 | int peekaboo; |
227 | char *port; |
228 | int prexit; |
229 | char *proxy; |
230 | int quiet; |
231 | int reconnect; |
232 | char *servername; |
233 | char *sess_in; |
234 | char *sess_out; |
235 | int showcerts; |
236 | int socket_type; |
237 | long socket_mtu; |
238 | #ifndef OPENSSL_NO_SRTP |
239 | char *srtp_profiles; |
240 | #endif |
241 | int starttls_proto; |
242 | int state; |
243 | int status_req; |
244 | int tlsextdebug; |
245 | int verify; |
246 | X509_VERIFY_PARAM *vpm; |
247 | char *xmpphost; |
248 | } cfg; |
249 | |
250 | static int |
251 | s_client_opt_keymatexportlen(char *arg) |
252 | { |
253 | cfg.keymatexportlen = strtonum(arg, 1, INT_MAX0x7fffffff, |
254 | &cfg.errstr); |
255 | if (cfg.errstr != NULL((void *)0)) { |
256 | BIO_printf(bio_err, "invalid argument %s: %s\n", |
257 | arg, cfg.errstr); |
258 | return (1); |
259 | } |
260 | return (0); |
261 | } |
262 | |
263 | #ifndef OPENSSL_NO_DTLS |
264 | static int |
265 | s_client_opt_mtu(char *arg) |
266 | { |
267 | cfg.socket_mtu = strtonum(arg, 0, LONG_MAX0x7fffffffffffffffL, |
268 | &cfg.errstr); |
269 | if (cfg.errstr != NULL((void *)0)) { |
270 | BIO_printf(bio_err, "invalid argument %s: %s\n", |
271 | arg, cfg.errstr); |
272 | return (1); |
273 | } |
274 | return (0); |
275 | } |
276 | #endif |
277 | |
278 | static int |
279 | s_client_opt_port(char *arg) |
280 | { |
281 | if (*arg == '\0') |
282 | return (1); |
283 | |
284 | cfg.port = arg; |
285 | return (0); |
286 | } |
287 | |
288 | #ifndef OPENSSL_NO_DTLS |
289 | static int |
290 | s_client_opt_protocol_version_dtls(void) |
291 | { |
292 | cfg.meth = DTLS_client_method(); |
293 | cfg.socket_type = SOCK_DGRAM2; |
294 | return (0); |
295 | } |
296 | #endif |
297 | |
298 | #ifndef OPENSSL_NO_DTLS1_2 |
299 | static int |
300 | s_client_opt_protocol_version_dtls1_2(void) |
301 | { |
302 | cfg.meth = DTLS_client_method(); |
303 | cfg.min_version = DTLS1_2_VERSION0xFEFD; |
304 | cfg.max_version = DTLS1_2_VERSION0xFEFD; |
305 | cfg.socket_type = SOCK_DGRAM2; |
306 | return (0); |
307 | } |
308 | #endif |
309 | |
310 | static int |
311 | s_client_opt_protocol_version_tls1_2(void) |
312 | { |
313 | cfg.min_version = TLS1_2_VERSION0x0303; |
314 | cfg.max_version = TLS1_2_VERSION0x0303; |
315 | return (0); |
316 | } |
317 | |
318 | static int |
319 | s_client_opt_protocol_version_tls1_3(void) |
320 | { |
321 | cfg.min_version = TLS1_3_VERSION0x0304; |
322 | cfg.max_version = TLS1_3_VERSION0x0304; |
323 | return (0); |
324 | } |
325 | |
326 | static int |
327 | s_client_opt_quiet(void) |
328 | { |
329 | cfg.quiet = 1; |
330 | cfg.ign_eof = 1; |
331 | return (0); |
332 | } |
333 | |
334 | static int |
335 | s_client_opt_starttls(char *arg) |
336 | { |
337 | if (strcmp(arg, "smtp") == 0) |
338 | cfg.starttls_proto = PROTO_SMTP; |
339 | else if (strcmp(arg, "lmtp") == 0) |
340 | cfg.starttls_proto = PROTO_LMTP; |
341 | else if (strcmp(arg, "pop3") == 0) |
342 | cfg.starttls_proto = PROTO_POP3; |
343 | else if (strcmp(arg, "imap") == 0) |
344 | cfg.starttls_proto = PROTO_IMAP; |
345 | else if (strcmp(arg, "ftp") == 0) |
346 | cfg.starttls_proto = PROTO_FTP; |
347 | else if (strcmp(arg, "xmpp") == 0) |
348 | cfg.starttls_proto = PROTO_XMPP; |
349 | else |
350 | return (1); |
351 | return (0); |
352 | } |
353 | |
354 | static int |
355 | s_client_opt_verify(char *arg) |
356 | { |
357 | cfg.verify = SSL_VERIFY_PEER0x01; |
358 | |
359 | verify_depth = strtonum(arg, 0, INT_MAX0x7fffffff, &cfg.errstr); |
360 | if (cfg.errstr != NULL((void *)0)) { |
361 | BIO_printf(bio_err, "invalid argument %s: %s\n", |
362 | arg, cfg.errstr); |
363 | return (1); |
364 | } |
365 | BIO_printf(bio_err, "verify depth is %d\n", verify_depth); |
366 | return (0); |
367 | } |
368 | |
369 | static int |
370 | s_client_opt_verify_param(int argc, char **argv, int *argsused) |
371 | { |
372 | char **pargs = argv; |
373 | int pargc = argc; |
374 | int badarg = 0; |
375 | |
376 | if (!args_verify(&pargs, &pargc, &badarg, bio_err, |
377 | &cfg.vpm)) { |
378 | BIO_printf(bio_err, "unknown option %s\n", *argv); |
379 | return (1); |
380 | } |
381 | if (badarg) |
382 | return (1); |
383 | |
384 | *argsused = argc - pargc; |
385 | return (0); |
386 | } |
387 | |
388 | static const struct option s_client_options[] = { |
389 | { |
390 | .name = "4", |
391 | .desc = "Use IPv4 only", |
392 | .type = OPTION_VALUE, |
393 | .opt.value = &cfg.af, |
394 | .value = AF_INET2, |
395 | }, |
396 | { |
397 | .name = "6", |
398 | .desc = "Use IPv6 only", |
399 | .type = OPTION_VALUE, |
400 | .opt.value = &cfg.af, |
401 | .value = AF_INET624, |
402 | }, |
403 | { |
404 | .name = "alpn", |
405 | .argname = "protocols", |
406 | .desc = "Set the advertised protocols for ALPN" |
407 | " (comma-separated list)", |
408 | .type = OPTION_ARG, |
409 | .opt.arg = &cfg.alpn_in, |
410 | }, |
411 | { |
412 | .name = "bugs", |
413 | .desc = "Enable various workarounds for buggy implementations", |
414 | .type = OPTION_FLAG, |
415 | .opt.flag = &cfg.bugs, |
416 | }, |
417 | { |
418 | .name = "CAfile", |
419 | .argname = "file", |
420 | .desc = "PEM format file of CA certificates", |
421 | .type = OPTION_ARG, |
422 | .opt.arg = &cfg.CAfile, |
423 | }, |
424 | { |
425 | .name = "CApath", |
426 | .argname = "directory", |
427 | .desc = "PEM format directory of CA certificates", |
428 | .type = OPTION_ARG, |
429 | .opt.arg = &cfg.CApath, |
430 | }, |
431 | { |
432 | .name = "cert", |
433 | .argname = "file", |
434 | .desc = "Certificate file to use, PEM format assumed", |
435 | .type = OPTION_ARG, |
436 | .opt.arg = &cfg.cert_file, |
437 | }, |
438 | { |
439 | .name = "certform", |
440 | .argname = "fmt", |
441 | .desc = "Certificate format (PEM or DER) PEM default", |
442 | .type = OPTION_ARG_FORMAT, |
443 | .opt.value = &cfg.cert_format, |
444 | }, |
445 | { |
446 | .name = "cipher", |
447 | .argname = "cipherlist", |
448 | .desc = "Preferred cipher to use (see 'openssl ciphers')", |
449 | .type = OPTION_ARG, |
450 | .opt.arg = &cfg.cipher, |
451 | }, |
452 | { |
453 | .name = "connect", |
454 | .argname = "host:port", |
455 | .desc = "Who to connect to (default is localhost:4433)", |
456 | .type = OPTION_ARG, |
457 | .opt.arg = &cfg.connect, |
458 | }, |
459 | { |
460 | .name = "crlf", |
461 | .desc = "Convert LF from terminal into CRLF", |
462 | .type = OPTION_FLAG, |
463 | .opt.flag = &cfg.crlf, |
464 | }, |
465 | { |
466 | .name = "debug", |
467 | .desc = "Print extensive debugging information", |
468 | .type = OPTION_FLAG, |
469 | .opt.flag = &cfg.debug, |
470 | }, |
471 | #ifndef OPENSSL_NO_DTLS |
472 | { |
473 | .name = "dtls", |
474 | .desc = "Use any version of DTLS", |
475 | .type = OPTION_FUNC, |
476 | .opt.func = s_client_opt_protocol_version_dtls, |
477 | }, |
478 | #endif |
479 | #ifndef OPENSSL_NO_DTLS1_2 |
480 | { |
481 | .name = "dtls1_2", |
482 | .desc = "Just use DTLSv1.2", |
483 | .type = OPTION_FUNC, |
484 | .opt.func = s_client_opt_protocol_version_dtls1_2, |
485 | }, |
486 | #endif |
487 | { |
488 | .name = "groups", |
489 | .argname = "list", |
490 | .desc = "Specify EC groups (colon-separated list)", |
491 | .type = OPTION_ARG, |
492 | .opt.arg = &cfg.groups_in, |
493 | }, |
494 | { |
495 | .name = "host", |
496 | .argname = "host", |
497 | .desc = "Use -connect instead", |
498 | .type = OPTION_ARG, |
499 | .opt.arg = &cfg.host, |
500 | }, |
501 | { |
502 | .name = "ign_eof", |
503 | .desc = "Ignore input EOF (default when -quiet)", |
504 | .type = OPTION_VALUE, |
505 | .opt.value = &cfg.ign_eof, |
506 | .value = 1, |
507 | }, |
508 | { |
509 | .name = "key", |
510 | .argname = "file", |
511 | .desc = "Private key file to use, if not, -cert file is used", |
512 | .type = OPTION_ARG, |
513 | .opt.arg = &cfg.key_file, |
514 | }, |
515 | { |
516 | .name = "keyform", |
517 | .argname = "fmt", |
518 | .desc = "Key format (PEM or DER) PEM default", |
519 | .type = OPTION_ARG_FORMAT, |
520 | .opt.value = &cfg.key_format, |
521 | }, |
522 | { |
523 | .name = "keymatexport", |
524 | .argname = "label", |
525 | .desc = "Export keying material using label", |
526 | .type = OPTION_ARG, |
527 | .opt.arg = &cfg.keymatexportlabel, |
528 | }, |
529 | { |
530 | .name = "keymatexportlen", |
531 | .argname = "len", |
532 | .desc = "Export len bytes of keying material (default 20)", |
533 | .type = OPTION_ARG_FUNC, |
534 | .opt.argfunc = s_client_opt_keymatexportlen, |
535 | }, |
536 | { |
537 | .name = "legacy_renegotiation", |
538 | .type = OPTION_DISCARD, |
539 | }, |
540 | { |
541 | .name = "legacy_server_connect", |
542 | .desc = "Allow initial connection to servers that don't support RI", |
543 | .type = OPTION_VALUE_OR, |
544 | .opt.value = &cfg.off, |
545 | .value = SSL_OP_LEGACY_SERVER_CONNECT0x00000004L, |
546 | }, |
547 | { |
548 | .name = "msg", |
549 | .desc = "Show all protocol messages with hex dump", |
550 | .type = OPTION_FLAG, |
551 | .opt.flag = &cfg.msg, |
552 | }, |
553 | #ifndef OPENSSL_NO_DTLS |
554 | { |
555 | .name = "mtu", |
556 | .argname = "mtu", |
557 | .desc = "Set the link layer MTU on DTLS connections", |
558 | .type = OPTION_ARG_FUNC, |
559 | .opt.argfunc = s_client_opt_mtu, |
560 | }, |
561 | #endif |
562 | { |
563 | .name = "nbio", |
564 | .desc = "Turn on non-blocking I/O", |
565 | .type = OPTION_FLAG, |
566 | .opt.flag = &cfg.nbio, |
567 | }, |
568 | { |
569 | .name = "nbio_test", |
570 | .desc = "Test non-blocking I/O", |
571 | .type = OPTION_FLAG, |
572 | .opt.flag = &cfg.nbio_test, |
573 | }, |
574 | { |
575 | .name = "nextprotoneg", |
576 | .argname = "protocols", |
577 | .type = OPTION_ARG, |
578 | .opt.arg = &cfg.npn_in, /* Ignored. */ |
579 | }, |
580 | { |
581 | .name = "no_comp", |
582 | .type = OPTION_VALUE_OR, |
583 | .opt.value = &cfg.off, |
584 | .value = SSL_OP_NO_COMPRESSION0x0, |
585 | }, |
586 | { |
587 | .name = "no_ign_eof", |
588 | .desc = "Don't ignore input EOF", |
589 | .type = OPTION_VALUE, |
590 | .opt.value = &cfg.ign_eof, |
591 | .value = 0, |
592 | }, |
593 | { |
594 | .name = "no_legacy_server_connect", |
595 | .desc = "Disallow initial connection to servers that don't support RI", |
596 | .type = OPTION_VALUE_OR, |
597 | .opt.value = &cfg.clr, |
598 | .value = SSL_OP_LEGACY_SERVER_CONNECT0x00000004L, |
599 | }, |
600 | { |
601 | .name = "no_servername", |
602 | .desc = "Do not send a Server Name Indication (SNI) extension", |
603 | .type = OPTION_FLAG, |
604 | .opt.value = &cfg.no_servername, |
605 | }, |
606 | { |
607 | .name = "no_ssl2", |
608 | .type = OPTION_VALUE_OR, |
609 | .opt.value = &cfg.off, |
610 | .value = SSL_OP_NO_SSLv20x0, |
611 | }, |
612 | { |
613 | .name = "no_ssl3", |
614 | .type = OPTION_VALUE_OR, |
615 | .opt.value = &cfg.off, |
616 | .value = SSL_OP_NO_SSLv30x0, |
617 | }, |
618 | { |
619 | .name = "no_ticket", |
620 | .desc = "Disable use of RFC4507 session ticket support", |
621 | .type = OPTION_VALUE_OR, |
622 | .opt.value = &cfg.off, |
623 | .value = SSL_OP_NO_TICKET0x00004000L, |
624 | }, |
625 | { |
626 | .name = "no_tls1", |
627 | .type = OPTION_DISCARD, |
628 | }, |
629 | { |
630 | .name = "no_tls1_1", |
631 | .type = OPTION_DISCARD, |
632 | }, |
633 | { |
634 | .name = "no_tls1_2", |
635 | .desc = "Disable the use of TLSv1.2", |
636 | .type = OPTION_VALUE_OR, |
637 | .opt.value = &cfg.off, |
638 | .value = SSL_OP_NO_TLSv1_20x08000000L, |
639 | }, |
640 | { |
641 | .name = "no_tls1_3", |
642 | .desc = "Disable the use of TLSv1.3", |
643 | .type = OPTION_VALUE_OR, |
644 | .opt.value = &cfg.off, |
645 | .value = SSL_OP_NO_TLSv1_30x20000000L, |
646 | }, |
647 | { |
648 | .name = "noservername", |
649 | .type = OPTION_FLAG, |
650 | .opt.value = &cfg.no_servername, |
651 | }, |
652 | { |
653 | .name = "pass", |
654 | .argname = "arg", |
655 | .desc = "Private key file pass phrase source", |
656 | .type = OPTION_ARG, |
657 | .opt.arg = &cfg.passarg, |
658 | }, |
659 | { |
660 | .name = "pause", |
661 | .type = OPTION_DISCARD, |
662 | }, |
663 | { |
664 | .name = "peekaboo", |
665 | .type = OPTION_FLAG, |
666 | .opt.flag = &cfg.peekaboo, |
667 | }, |
668 | { |
669 | .name = "port", |
670 | .argname = "port", |
671 | .desc = "Use -connect instead", |
672 | .type = OPTION_ARG_FUNC, |
673 | .opt.argfunc = s_client_opt_port, |
674 | }, |
675 | { |
676 | .name = "prexit", |
677 | .desc = "Print session information when the program exits", |
678 | .type = OPTION_FLAG, |
679 | .opt.flag = &cfg.prexit, |
680 | }, |
681 | { |
682 | .name = "proxy", |
683 | .argname = "host:port", |
684 | .desc = "Connect to http proxy", |
685 | .type = OPTION_ARG, |
686 | .opt.arg = &cfg.proxy, |
687 | }, |
688 | { |
689 | .name = "quiet", |
690 | .desc = "Inhibit printing of session and certificate info", |
691 | .type = OPTION_FUNC, |
692 | .opt.func = s_client_opt_quiet, |
693 | }, |
694 | { |
695 | .name = "reconnect", |
696 | .desc = "Drop and re-make the connection with the same Session-ID", |
697 | .type = OPTION_VALUE, |
698 | .opt.value = &cfg.reconnect, |
699 | .value = 5, |
700 | }, |
701 | { |
702 | .name = "servername", |
703 | .argname = "name", |
704 | .desc = "Set TLS extension servername in ClientHello (SNI)", |
705 | .type = OPTION_ARG, |
706 | .opt.arg = &cfg.servername, |
707 | }, |
708 | { |
709 | .name = "serverpref", |
710 | .desc = "Use server's cipher preferences", |
711 | .type = OPTION_VALUE_OR, |
712 | .opt.value = &cfg.off, |
713 | .value = SSL_OP_CIPHER_SERVER_PREFERENCE0x00400000L, |
714 | }, |
715 | { |
716 | .name = "sess_in", |
717 | .argname = "file", |
718 | .desc = "File to read TLS session from", |
719 | .type = OPTION_ARG, |
720 | .opt.arg = &cfg.sess_in, |
721 | }, |
722 | { |
723 | .name = "sess_out", |
724 | .argname = "file", |
725 | .desc = "File to write TLS session to", |
726 | .type = OPTION_ARG, |
727 | .opt.arg = &cfg.sess_out, |
728 | }, |
729 | { |
730 | .name = "showcerts", |
731 | .desc = "Show all server certificates in the chain", |
732 | .type = OPTION_FLAG, |
733 | .opt.flag = &cfg.showcerts, |
734 | }, |
735 | { |
736 | .name = "starttls", |
737 | .argname = "protocol", |
738 | .desc = "Use the STARTTLS command before starting TLS,\n" |
739 | "smtp, lmtp, pop3, imap, ftp and xmpp are supported.", |
740 | .type = OPTION_ARG_FUNC, |
741 | .opt.argfunc = s_client_opt_starttls, |
742 | }, |
743 | { |
744 | .name = "state", |
745 | .desc = "Print the TLS session states", |
746 | .type = OPTION_FLAG, |
747 | .opt.flag = &cfg.state, |
748 | }, |
749 | { |
750 | .name = "status", |
751 | .desc = "Send a certificate status request to the server (OCSP)", |
752 | .type = OPTION_FLAG, |
753 | .opt.flag = &cfg.status_req, |
754 | }, |
755 | #ifndef OPENSSL_NO_DTLS |
756 | { |
757 | .name = "timeout", |
758 | .desc = "Enable send/receive timeout on DTLS connections", |
759 | .type = OPTION_FLAG, |
760 | .opt.flag = &cfg.enable_timeouts, |
761 | }, |
762 | #endif |
763 | { |
764 | .name = "tls1_2", |
765 | .desc = "Just use TLSv1.2", |
766 | .type = OPTION_FUNC, |
767 | .opt.func = s_client_opt_protocol_version_tls1_2, |
768 | }, |
769 | { |
770 | .name = "tls1_3", |
771 | .desc = "Just use TLSv1.3", |
772 | .type = OPTION_FUNC, |
773 | .opt.func = s_client_opt_protocol_version_tls1_3, |
774 | }, |
775 | { |
776 | .name = "tlsextdebug", |
777 | .desc = "Hex dump of all TLS extensions received", |
778 | .type = OPTION_FLAG, |
779 | .opt.flag = &cfg.tlsextdebug, |
780 | }, |
781 | #ifndef OPENSSL_NO_SRTP |
782 | { |
783 | .name = "use_srtp", |
784 | .argname = "profiles", |
785 | .desc = "Offer SRTP key management with a colon-separated profiles", |
786 | .type = OPTION_ARG, |
787 | .opt.arg = &cfg.srtp_profiles, |
788 | }, |
789 | #endif |
790 | { |
791 | .name = "verify", |
792 | .argname = "depth", |
793 | .desc = "Turn on peer certificate verification, with a max of depth", |
794 | .type = OPTION_ARG_FUNC, |
795 | .opt.argfunc = s_client_opt_verify, |
796 | }, |
797 | { |
798 | .name = "verify_return_error", |
799 | .desc = "Return verification error", |
800 | .type = OPTION_FLAG, |
801 | .opt.flag = &verify_return_error, |
802 | }, |
803 | { |
804 | .name = "xmpphost", |
805 | .argname = "host", |
806 | .desc = "Connect to this virtual host on the xmpp server", |
807 | .type = OPTION_ARG, |
808 | .opt.arg = &cfg.xmpphost, |
809 | }, |
810 | { |
811 | .name = NULL((void *)0), |
812 | .desc = "", |
813 | .type = OPTION_ARGV_FUNC, |
814 | .opt.argvfunc = s_client_opt_verify_param, |
815 | }, |
816 | { NULL((void *)0) }, |
817 | }; |
818 | |
819 | static void |
820 | sc_usage(void) |
821 | { |
822 | fprintf(stderr(&__sF[2]), "usage: s_client " |
823 | "[-4 | -6] [-alpn protocols] [-bugs] [-CAfile file]\n" |
824 | " [-CApath directory] [-cert file] [-certform der | pem] [-check_ss_sig]\n" |
825 | " [-cipher cipherlist] [-connect host[:port]] [-crl_check]\n" |
826 | " [-crl_check_all] [-crlf] [-debug] [-dtls] [-dtls1_2] [-extended_crl]\n" |
827 | " [-groups list] [-host host] [-ign_eof] [-ignore_critical]\n" |
828 | " [-issuer_checks] [-key keyfile] [-keyform der | pem]\n" |
829 | " [-keymatexport label] [-keymatexportlen len] [-legacy_server_connect]\n" |
830 | " [-msg] [-mtu mtu] [-nbio] [-nbio_test] [-no_comp] [-no_ign_eof]\n" |
831 | " [-no_legacy_server_connect] [-no_ticket] \n" |
832 | " [-no_tls1_2] [-no_tls1_3] [-pass arg] [-policy_check]\n" |
833 | " [-port port] [-prexit] [-proxy host:port] [-quiet] [-reconnect]\n" |
834 | " [-servername name] [-serverpref] [-sess_in file] [-sess_out file]\n" |
835 | " [-showcerts] [-starttls protocol] [-state] [-status] [-timeout]\n" |
836 | " [-tls1_2] [-tls1_3] [-tlsextdebug]\n" |
837 | " [-use_srtp profiles] [-verify depth] [-verify_return_error]\n" |
838 | " [-x509_strict] [-xmpphost host]\n"); |
839 | fprintf(stderr(&__sF[2]), "\n"); |
840 | options_usage(s_client_options); |
841 | fprintf(stderr(&__sF[2]), "\n"); |
842 | } |
843 | |
844 | int |
845 | s_client_main(int argc, char **argv) |
846 | { |
847 | SSL *con = NULL((void *)0); |
848 | int s, k, p = 0, pending = 0; |
849 | char *cbuf = NULL((void *)0), *sbuf = NULL((void *)0), *mbuf = NULL((void *)0), *pbuf = NULL((void *)0); |
850 | int cbuf_len, cbuf_off; |
851 | int sbuf_len, sbuf_off; |
852 | int full_log = 1; |
853 | const char *servername; |
854 | char *pass = NULL((void *)0); |
855 | X509 *cert = NULL((void *)0); |
856 | EVP_PKEY *key = NULL((void *)0); |
857 | int badop = 0; |
858 | int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; |
859 | SSL_CTX *ctx = NULL((void *)0); |
860 | int ret = 1, in_init = 1, i; |
861 | BIO *bio_c_out = NULL((void *)0); |
862 | BIO *sbio; |
863 | int mbuf_len = 0; |
864 | struct timeval timeout; |
865 | tlsextctx tlsextcbp = {NULL((void *)0), 0}; |
866 | struct sockaddr_storage peer; |
867 | int peerlen = sizeof(peer); |
868 | |
869 | if (pledge("stdio cpath wpath rpath inet dns tty", NULL((void *)0)) == -1) { |
870 | perror("pledge"); |
871 | exit(1); |
872 | } |
873 | |
874 | memset(&cfg, 0, sizeof(cfg)); |
875 | cfg.af = AF_UNSPEC0; |
876 | cfg.cert_format = FORMAT_PEM3; |
877 | cfg.host = SSL_HOST_NAME"localhost"; |
878 | cfg.key_format = FORMAT_PEM3; |
879 | cfg.keymatexportlen = 20; |
880 | cfg.meth = TLS_client_method(); |
881 | cfg.port = PORT_STR"4433"; |
882 | cfg.socket_type = SOCK_STREAM1; |
883 | cfg.starttls_proto = PROTO_OFF; |
884 | cfg.verify = SSL_VERIFY_NONE0x00; |
885 | |
886 | if (((cbuf = malloc(BUFSIZZ1024*8)) == NULL((void *)0)) || |
887 | ((sbuf = malloc(BUFSIZZ1024*8)) == NULL((void *)0)) || |
888 | ((pbuf = malloc(BUFSIZZ1024*8)) == NULL((void *)0)) || |
889 | ((mbuf = malloc(BUFSIZZ1024*8 + 1)) == NULL((void *)0))) { /* NUL byte */ |
890 | BIO_printf(bio_err, "out of memory\n"); |
891 | goto end; |
892 | } |
893 | verify_depth = 0; |
894 | |
895 | if (options_parse(argc, argv, s_client_options, NULL((void *)0), NULL((void *)0)) != 0) { |
896 | badop = 1; |
897 | goto bad; |
898 | } |
899 | if (cfg.proxy != NULL((void *)0)) { |
900 | if (!extract_host_port(cfg.proxy, |
901 | &cfg.host, NULL((void *)0), &cfg.port)) |
902 | goto bad; |
903 | if (cfg.connect == NULL((void *)0)) |
904 | cfg.connect = SSL_HOST_NAME"localhost"; |
905 | } else if (cfg.connect != NULL((void *)0)) { |
906 | if (!extract_host_port(cfg.connect, |
907 | &cfg.host, NULL((void *)0), &cfg.port)) |
908 | goto bad; |
909 | } |
910 | if (badop) { |
911 | bad: |
912 | if (cfg.errstr == NULL((void *)0)) |
913 | sc_usage(); |
914 | goto end; |
915 | } |
916 | |
917 | if (!app_passwd(bio_err, cfg.passarg, NULL((void *)0), &pass, NULL((void *)0))) { |
918 | BIO_printf(bio_err, "Error getting password\n"); |
919 | goto end; |
920 | } |
921 | if (cfg.key_file == NULL((void *)0)) |
922 | cfg.key_file = cfg.cert_file; |
923 | |
924 | |
925 | if (cfg.key_file) { |
926 | |
927 | key = load_key(bio_err, cfg.key_file, |
928 | cfg.key_format, 0, pass, |
929 | "client certificate private key file"); |
930 | if (!key) { |
931 | ERR_print_errors(bio_err); |
932 | goto end; |
933 | } |
934 | } |
935 | if (cfg.cert_file) { |
936 | cert = load_cert(bio_err, cfg.cert_file, |
937 | cfg.cert_format, |
938 | NULL((void *)0), "client certificate file"); |
939 | |
940 | if (!cert) { |
941 | ERR_print_errors(bio_err); |
942 | goto end; |
943 | } |
944 | } |
945 | if (cfg.quiet && !cfg.debug && |
946 | !cfg.msg) { |
947 | if ((bio_c_out = BIO_new(BIO_s_null())) == NULL((void *)0)) |
948 | goto end; |
949 | } else { |
950 | if ((bio_c_out = BIO_new_fp(stdout(&__sF[1]), BIO_NOCLOSE0x00)) == NULL((void *)0)) |
951 | goto end; |
952 | } |
953 | |
954 | ctx = SSL_CTX_new(cfg.meth); |
955 | if (ctx == NULL((void *)0)) { |
956 | ERR_print_errors(bio_err); |
957 | goto end; |
958 | } |
959 | |
960 | SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY)SSL_CTX_ctrl((ctx),78,(0x00000004L),((void *)0)); |
961 | |
962 | if (cfg.vpm) |
963 | SSL_CTX_set1_param(ctx, cfg.vpm); |
964 | |
965 | if (!SSL_CTX_set_min_proto_version(ctx, cfg.min_version)) |
966 | goto end; |
967 | if (!SSL_CTX_set_max_proto_version(ctx, cfg.max_version)) |
968 | goto end; |
969 | |
970 | #ifndef OPENSSL_NO_SRTP |
971 | if (cfg.srtp_profiles != NULL((void *)0)) |
972 | SSL_CTX_set_tlsext_use_srtp(ctx, cfg.srtp_profiles); |
973 | #endif |
974 | if (cfg.bugs) |
975 | SSL_CTX_set_options(ctx, SSL_OP_ALL | cfg.off)SSL_CTX_ctrl((ctx),32,((0x00000004L) | cfg.off),((void *)0)); |
976 | else |
977 | SSL_CTX_set_options(ctx, cfg.off)SSL_CTX_ctrl((ctx),32,(cfg.off),((void *)0)); |
978 | |
979 | if (cfg.clr) |
980 | SSL_CTX_clear_options(ctx, cfg.clr)SSL_CTX_ctrl((ctx),77,(cfg.clr),((void *)0)); |
981 | |
982 | if (cfg.alpn_in) { |
983 | unsigned short alpn_len; |
984 | unsigned char *alpn; |
985 | |
986 | alpn = next_protos_parse(&alpn_len, cfg.alpn_in); |
987 | if (alpn == NULL((void *)0)) { |
988 | BIO_printf(bio_err, "Error parsing -alpn argument\n"); |
989 | goto end; |
990 | } |
991 | SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); |
992 | free(alpn); |
993 | } |
994 | if (cfg.groups_in != NULL((void *)0)) { |
995 | if (SSL_CTX_set1_groups_list(ctx, cfg.groups_in) != 1) { |
996 | BIO_printf(bio_err, "Failed to set groups '%s'\n", |
997 | cfg.groups_in); |
998 | goto end; |
999 | } |
1000 | } |
1001 | |
1002 | if (cfg.state) |
1003 | SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); |
1004 | if (cfg.cipher != NULL((void *)0)) |
1005 | if (!SSL_CTX_set_cipher_list(ctx, cfg.cipher)) { |
1006 | BIO_printf(bio_err, "error setting cipher list\n"); |
1007 | ERR_print_errors(bio_err); |
1008 | goto end; |
1009 | } |
1010 | |
1011 | SSL_CTX_set_verify(ctx, cfg.verify, verify_callback); |
1012 | if (!set_cert_key_stuff(ctx, cert, key)) |
1013 | goto end; |
1014 | |
1015 | if ((cfg.CAfile || cfg.CApath) |
1016 | && !SSL_CTX_load_verify_locations(ctx, cfg.CAfile, |
1017 | cfg.CApath)) |
1018 | ERR_print_errors(bio_err); |
1019 | |
1020 | if (!SSL_CTX_set_default_verify_paths(ctx)) |
1021 | ERR_print_errors(bio_err); |
1022 | |
1023 | con = SSL_new(ctx); |
1024 | if (cfg.sess_in) { |
1025 | SSL_SESSION *sess; |
1026 | BIO *stmp = BIO_new_file(cfg.sess_in, "r"); |
1027 | if (!stmp) { |
1028 | BIO_printf(bio_err, "Can't open session file %s\n", |
1029 | cfg.sess_in); |
1030 | ERR_print_errors(bio_err); |
1031 | goto end; |
1032 | } |
1033 | sess = PEM_read_bio_SSL_SESSION(stmp, NULL((void *)0), 0, NULL((void *)0)); |
1034 | BIO_free(stmp); |
1035 | if (!sess) { |
1036 | BIO_printf(bio_err, "Can't open session file %s\n", |
1037 | cfg.sess_in); |
1038 | ERR_print_errors(bio_err); |
1039 | goto end; |
1040 | } |
1041 | SSL_set_session(con, sess); |
1042 | SSL_SESSION_free(sess); |
1043 | } |
1044 | |
1045 | /* Attempt to opportunistically use the host name for SNI. */ |
1046 | servername = cfg.servername; |
1047 | if (servername == NULL((void *)0)) |
1048 | servername = cfg.host; |
1049 | |
1050 | if (!cfg.no_servername && servername != NULL((void *)0) && |
1051 | !SSL_set_tlsext_host_name(con, servername)SSL_ctrl(con,55,0,(char *)servername)) { |
1052 | long ssl_err = ERR_peek_error(); |
1053 | |
1054 | if (cfg.servername != NULL((void *)0) || |
1055 | ERR_GET_LIB(ssl_err)(int)((((unsigned long)ssl_err)>>24L)&0xffL) != ERR_LIB_SSL20 || |
1056 | ERR_GET_REASON(ssl_err)(int)((ssl_err)&0xfffL) != SSL_R_SSL3_EXT_INVALID_SERVERNAME319) { |
1057 | BIO_printf(bio_err, |
1058 | "Unable to set TLS servername extension.\n"); |
1059 | ERR_print_errors(bio_err); |
1060 | goto end; |
1061 | } |
1062 | servername = NULL((void *)0); |
1063 | ERR_clear_error(); |
1064 | } |
1065 | if (!cfg.no_servername && servername != NULL((void *)0)) { |
1066 | tlsextcbp.biodebug = bio_err; |
1067 | SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb)SSL_CTX_callback_ctrl(ctx,53,(void (*)(void))ssl_servername_cb ); |
1068 | SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp)SSL_CTX_ctrl(ctx,54,0, (void *)&tlsextcbp); |
1069 | } |
1070 | |
1071 | re_start: |
1072 | |
1073 | if (init_client(&s, cfg.host, cfg.port, |
1074 | cfg.socket_type, cfg.af) == 0) { |
1075 | BIO_printf(bio_err, "connect:errno=%d\n", errno(*__errno())); |
1076 | goto end; |
1077 | } |
1078 | BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); |
1079 | |
1080 | if (cfg.nbio) { |
1081 | if (!cfg.quiet) |
1082 | BIO_printf(bio_c_out, "turning on non blocking io\n"); |
1083 | if (!BIO_socket_nbio(s, 1)) { |
1084 | ERR_print_errors(bio_err); |
1085 | goto end; |
1086 | } |
1087 | } |
1088 | |
1089 | if (SSL_is_dtls(con)) { |
1090 | sbio = BIO_new_dgram(s, BIO_NOCLOSE0x00); |
1091 | if (getsockname(s, (struct sockaddr *)&peer, |
1092 | (void *)&peerlen) == -1) { |
1093 | BIO_printf(bio_err, "getsockname:errno=%d\n", |
1094 | errno(*__errno())); |
1095 | shutdown(s, SHUT_RD0); |
1096 | close(s); |
1097 | goto end; |
1098 | } |
1099 | (void) BIO_ctrl_set_connected(sbio, 1, &peer)(int)BIO_ctrl(sbio, 32, 1, (char *)&peer); |
1100 | |
1101 | if (cfg.enable_timeouts) { |
1102 | timeout.tv_sec = 0; |
1103 | timeout.tv_usec = DGRAM_RCV_TIMEOUT250000; |
1104 | BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT33, 0, |
1105 | &timeout); |
1106 | |
1107 | timeout.tv_sec = 0; |
1108 | timeout.tv_usec = DGRAM_SND_TIMEOUT250000; |
1109 | BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT35, 0, |
1110 | &timeout); |
1111 | } |
1112 | if (cfg.socket_mtu > 28) { |
1113 | SSL_set_options(con, SSL_OP_NO_QUERY_MTU)SSL_ctrl((con),32,(0x00001000L),((void *)0)); |
1114 | SSL_set_mtu(con, cfg.socket_mtu - 28)SSL_ctrl((con),17,(cfg.socket_mtu - 28),((void *)0)); |
1115 | } else |
1116 | /* want to do MTU discovery */ |
1117 | BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER39, 0, NULL((void *)0)); |
1118 | } else |
1119 | sbio = BIO_new_socket(s, BIO_NOCLOSE0x00); |
1120 | |
1121 | if (cfg.nbio_test) { |
1122 | BIO *test; |
1123 | |
1124 | test = BIO_new(BIO_f_nbio_test()); |
1125 | sbio = BIO_push(test, sbio); |
1126 | } |
1127 | if (cfg.debug) { |
1128 | BIO_set_callback(sbio, bio_dump_callback); |
1129 | BIO_set_callback_arg(sbio, (char *) bio_c_out); |
1130 | } |
1131 | if (cfg.msg) { |
1132 | SSL_set_msg_callback(con, msg_cb); |
1133 | SSL_set_msg_callback_arg(con, bio_c_out)SSL_ctrl((con), 16, 0, (bio_c_out)); |
1134 | } |
1135 | if (cfg.tlsextdebug) { |
1136 | SSL_set_tlsext_debug_callback(con, tlsext_cb)SSL_callback_ctrl(con,56,(void (*)(void))tlsext_cb); |
1137 | SSL_set_tlsext_debug_arg(con, bio_c_out)SSL_ctrl(con,57,0, (void *)bio_c_out); |
1138 | } |
1139 | if (cfg.status_req) { |
1140 | SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp)SSL_ctrl(con,65,1, ((void *)0)); |
1141 | SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb)SSL_CTX_callback_ctrl(ctx,63,(void (*)(void))ocsp_resp_cb); |
1142 | SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out)SSL_CTX_ctrl(ctx,64,0,(void *)bio_c_out); |
1143 | } |
1144 | |
1145 | SSL_set_bio(con, sbio, sbio); |
1146 | SSL_set_connect_state(con); |
1147 | |
1148 | /* ok, lets connect */ |
1149 | read_tty = 1; |
1150 | write_tty = 0; |
1151 | tty_on = 0; |
Value stored to 'tty_on' is never read | |
1152 | read_ssl = 1; |
1153 | write_ssl = 1; |
1154 | |
1155 | cbuf_len = 0; |
1156 | cbuf_off = 0; |
1157 | sbuf_len = 0; |
1158 | sbuf_off = 0; |
1159 | |
1160 | /* This is an ugly hack that does a lot of assumptions */ |
1161 | /* |
1162 | * We do have to handle multi-line responses which may come in a |
1163 | * single packet or not. We therefore have to use BIO_gets() which |
1164 | * does need a buffering BIO. So during the initial chitchat we do |
1165 | * push a buffering BIO into the chain that is removed again later on |
1166 | * to not disturb the rest of the s_client operation. |
1167 | */ |
1168 | if (cfg.starttls_proto == PROTO_SMTP || |
1169 | cfg.starttls_proto == PROTO_LMTP) { |
1170 | int foundit = 0; |
1171 | BIO *fbio = BIO_new(BIO_f_buffer()); |
1172 | BIO_push(fbio, sbio); |
1173 | /* wait for multi-line response to end from SMTP */ |
1174 | do { |
1175 | mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ1024*8); |
1176 | } |
1177 | while (mbuf_len > 3 && mbuf[3] == '-'); |
1178 | /* STARTTLS command requires EHLO... */ |
1179 | BIO_printf(fbio, "%cHLO openssl.client.net\r\n", |
1180 | cfg.starttls_proto == PROTO_SMTP ? 'E' : 'L'); |
1181 | (void) BIO_flush(fbio)(int)BIO_ctrl(fbio,11,0,((void *)0)); |
1182 | /* wait for multi-line response to end EHLO SMTP response */ |
1183 | do { |
1184 | mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ1024*8); |
1185 | if (strstr(mbuf, "STARTTLS")) |
1186 | foundit = 1; |
1187 | } |
1188 | while (mbuf_len > 3 && mbuf[3] == '-'); |
1189 | (void) BIO_flush(fbio)(int)BIO_ctrl(fbio,11,0,((void *)0)); |
1190 | BIO_pop(fbio); |
1191 | BIO_free(fbio); |
1192 | if (!foundit) |
1193 | BIO_printf(bio_err, |
1194 | "didn't find starttls in server response," |
1195 | " try anyway...\n"); |
1196 | BIO_printf(sbio, "STARTTLS\r\n"); |
1197 | BIO_read(sbio, sbuf, BUFSIZZ1024*8); |
1198 | } else if (cfg.starttls_proto == PROTO_POP3) { |
1199 | mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ1024*8); |
1200 | if (mbuf_len == -1) { |
1201 | BIO_printf(bio_err, "BIO_read failed\n"); |
1202 | goto end; |
1203 | } |
1204 | BIO_printf(sbio, "STLS\r\n"); |
1205 | BIO_read(sbio, sbuf, BUFSIZZ1024*8); |
1206 | } else if (cfg.starttls_proto == PROTO_IMAP) { |
1207 | int foundit = 0; |
1208 | BIO *fbio = BIO_new(BIO_f_buffer()); |
1209 | BIO_push(fbio, sbio); |
1210 | BIO_gets(fbio, mbuf, BUFSIZZ1024*8); |
1211 | /* STARTTLS command requires CAPABILITY... */ |
1212 | BIO_printf(fbio, ". CAPABILITY\r\n"); |
1213 | (void) BIO_flush(fbio)(int)BIO_ctrl(fbio,11,0,((void *)0)); |
1214 | /* wait for multi-line CAPABILITY response */ |
1215 | do { |
1216 | mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ1024*8); |
1217 | if (strstr(mbuf, "STARTTLS")) |
1218 | foundit = 1; |
1219 | } |
1220 | while (mbuf_len > 3 && mbuf[0] != '.'); |
1221 | (void) BIO_flush(fbio)(int)BIO_ctrl(fbio,11,0,((void *)0)); |
1222 | BIO_pop(fbio); |
1223 | BIO_free(fbio); |
1224 | if (!foundit) |
1225 | BIO_printf(bio_err, |
1226 | "didn't find STARTTLS in server response," |
1227 | " try anyway...\n"); |
1228 | BIO_printf(sbio, ". STARTTLS\r\n"); |
1229 | BIO_read(sbio, sbuf, BUFSIZZ1024*8); |
1230 | } else if (cfg.starttls_proto == PROTO_FTP) { |
1231 | BIO *fbio = BIO_new(BIO_f_buffer()); |
1232 | BIO_push(fbio, sbio); |
1233 | /* wait for multi-line response to end from FTP */ |
1234 | do { |
1235 | mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ1024*8); |
1236 | } |
1237 | while (mbuf_len > 3 && mbuf[3] == '-'); |
1238 | (void) BIO_flush(fbio)(int)BIO_ctrl(fbio,11,0,((void *)0)); |
1239 | BIO_pop(fbio); |
1240 | BIO_free(fbio); |
1241 | BIO_printf(sbio, "AUTH TLS\r\n"); |
1242 | BIO_read(sbio, sbuf, BUFSIZZ1024*8); |
1243 | } else if (cfg.starttls_proto == PROTO_XMPP) { |
1244 | int seen = 0; |
1245 | BIO_printf(sbio, "<stream:stream " |
1246 | "xmlns:stream='http://etherx.jabber.org/streams' " |
1247 | "xmlns='jabber:client' to='%s' version='1.0'>", |
1248 | cfg.xmpphost ? |
1249 | cfg.xmpphost : cfg.host); |
1250 | seen = BIO_read(sbio, mbuf, BUFSIZZ1024*8); |
1251 | |
1252 | if (seen <= 0) |
1253 | goto shut; |
1254 | |
1255 | mbuf[seen] = 0; |
1256 | while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'") && |
1257 | !strstr(mbuf, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"")) { |
1258 | seen = BIO_read(sbio, mbuf, BUFSIZZ1024*8); |
1259 | |
1260 | if (seen <= 0) |
1261 | goto shut; |
1262 | |
1263 | mbuf[seen] = 0; |
1264 | } |
1265 | BIO_printf(sbio, |
1266 | "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); |
1267 | seen = BIO_read(sbio, sbuf, BUFSIZZ1024*8); |
1268 | sbuf[seen] = 0; |
1269 | if (!strstr(sbuf, "<proceed")) |
1270 | goto shut; |
1271 | mbuf[0] = 0; |
1272 | } else if (cfg.proxy != NULL((void *)0)) { |
1273 | BIO_printf(sbio, "CONNECT %s HTTP/1.0\r\n\r\n", |
1274 | cfg.connect); |
1275 | mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ1024*8); |
1276 | if (mbuf_len == -1) { |
1277 | BIO_printf(bio_err, "BIO_read failed\n"); |
1278 | goto end; |
1279 | } |
1280 | } |
1281 | for (;;) { |
1282 | struct pollfd pfd[3]; /* stdin, stdout, socket */ |
1283 | int ptimeout = -1; |
1284 | |
1285 | if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)SSL_ctrl(con,73,0, (void *)&timeout)) |
1286 | ptimeout = timeout.tv_sec * 1000 + |
1287 | timeout.tv_usec / 1000; |
1288 | |
1289 | if (SSL_in_init(con)(SSL_state((con))&(0x1000|0x2000)) && !SSL_total_renegotiations(con)SSL_ctrl((con),12,0,((void *)0))) { |
1290 | in_init = 1; |
1291 | tty_on = 0; |
1292 | } else { |
1293 | tty_on = 1; |
1294 | if (in_init) { |
1295 | in_init = 0; |
1296 | if (cfg.sess_out) { |
1297 | BIO *stmp = BIO_new_file( |
1298 | cfg.sess_out, "w"); |
1299 | if (stmp) { |
1300 | PEM_write_bio_SSL_SESSION(stmp, |
1301 | SSL_get_session(con)); |
1302 | BIO_free(stmp); |
1303 | } else |
1304 | BIO_printf(bio_err, |
1305 | "Error writing session file %s\n", |
1306 | cfg.sess_out); |
1307 | } |
1308 | print_stuff(bio_c_out, con, full_log); |
1309 | if (full_log > 0) |
1310 | full_log--; |
1311 | |
1312 | if (cfg.starttls_proto) { |
1313 | BIO_write(bio_err, mbuf, mbuf_len); |
1314 | /* We don't need to know any more */ |
1315 | cfg.starttls_proto = PROTO_OFF; |
1316 | } |
1317 | if (cfg.reconnect) { |
1318 | cfg.reconnect--; |
1319 | BIO_printf(bio_c_out, |
1320 | "drop connection and then reconnect\n"); |
1321 | SSL_shutdown(con); |
1322 | SSL_set_connect_state(con); |
1323 | shutdown(SSL_get_fd(con), SHUT_RD0); |
1324 | close(SSL_get_fd(con)); |
1325 | goto re_start; |
1326 | } |
1327 | } |
1328 | } |
1329 | |
1330 | ssl_pending = read_ssl && SSL_pending(con); |
1331 | |
1332 | pfd[0].fd = -1; |
1333 | pfd[1].fd = -1; |
1334 | if (!ssl_pending) { |
1335 | if (tty_on) { |
1336 | if (read_tty) { |
1337 | pfd[0].fd = fileno(stdin)(!__isthreaded ? (((&__sF[0]))->_file) : (fileno)((& __sF[0]))); |
1338 | pfd[0].events = POLLIN0x0001; |
1339 | } |
1340 | if (write_tty) { |
1341 | pfd[1].fd = fileno(stdout)(!__isthreaded ? (((&__sF[1]))->_file) : (fileno)((& __sF[1]))); |
1342 | pfd[1].events = POLLOUT0x0004; |
1343 | } |
1344 | } |
1345 | |
1346 | pfd[2].fd = SSL_get_fd(con); |
1347 | pfd[2].events = 0; |
1348 | if (read_ssl) |
1349 | pfd[2].events |= POLLIN0x0001; |
1350 | if (write_ssl) |
1351 | pfd[2].events |= POLLOUT0x0004; |
1352 | |
1353 | /* printf("mode tty(%d %d%d) ssl(%d%d)\n", |
1354 | tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ |
1355 | |
1356 | i = poll(pfd, 3, ptimeout); |
1357 | if (i == -1) { |
1358 | BIO_printf(bio_err, "bad select %d\n", |
1359 | errno(*__errno())); |
1360 | goto shut; |
1361 | /* goto end; */ |
1362 | } |
1363 | } |
1364 | if (SSL_is_dtls(con) && |
1365 | DTLSv1_handle_timeout(con)SSL_ctrl(con,74,0, ((void *)0)) > 0) |
1366 | BIO_printf(bio_err, "TIMEOUT occured\n"); |
1367 | if (!ssl_pending && |
1368 | (pfd[2].revents & (POLLOUT0x0004|POLLERR0x0008|POLLNVAL0x0020))) { |
1369 | if (pfd[2].revents & (POLLERR0x0008|POLLNVAL0x0020)) { |
1370 | BIO_printf(bio_err, "poll error"); |
1371 | goto shut; |
1372 | } |
1373 | k = SSL_write(con, &(cbuf[cbuf_off]), |
1374 | (unsigned int) cbuf_len); |
1375 | switch (SSL_get_error(con, k)) { |
1376 | case SSL_ERROR_NONE0: |
1377 | cbuf_off += k; |
1378 | cbuf_len -= k; |
1379 | if (k <= 0) |
1380 | goto end; |
1381 | /* we have done a write(con,NULL,0); */ |
1382 | if (cbuf_len <= 0) { |
1383 | read_tty = 1; |
1384 | write_ssl = 0; |
1385 | } else { /* if (cbuf_len > 0) */ |
1386 | read_tty = 0; |
1387 | write_ssl = 1; |
1388 | } |
1389 | break; |
1390 | case SSL_ERROR_WANT_WRITE3: |
1391 | BIO_printf(bio_c_out, "write W BLOCK\n"); |
1392 | write_ssl = 1; |
1393 | read_tty = 0; |
1394 | break; |
1395 | case SSL_ERROR_WANT_READ2: |
1396 | BIO_printf(bio_c_out, "write R BLOCK\n"); |
1397 | write_tty = 0; |
1398 | read_ssl = 1; |
1399 | write_ssl = 0; |
1400 | break; |
1401 | case SSL_ERROR_WANT_X509_LOOKUP4: |
1402 | BIO_printf(bio_c_out, "write X BLOCK\n"); |
1403 | break; |
1404 | case SSL_ERROR_ZERO_RETURN6: |
1405 | if (cbuf_len != 0) { |
1406 | BIO_printf(bio_c_out, "shutdown\n"); |
1407 | ret = 0; |
1408 | goto shut; |
1409 | } else { |
1410 | read_tty = 1; |
1411 | write_ssl = 0; |
1412 | break; |
1413 | } |
1414 | |
1415 | case SSL_ERROR_SYSCALL5: |
1416 | if ((k != 0) || (cbuf_len != 0)) { |
1417 | BIO_printf(bio_err, "write:errno=%d\n", |
1418 | errno(*__errno())); |
1419 | goto shut; |
1420 | } else { |
1421 | read_tty = 1; |
1422 | write_ssl = 0; |
1423 | } |
1424 | break; |
1425 | case SSL_ERROR_SSL1: |
1426 | ERR_print_errors(bio_err); |
1427 | goto shut; |
1428 | } |
1429 | } else if (!ssl_pending && |
1430 | (pfd[1].revents & (POLLOUT0x0004|POLLERR0x0008|POLLNVAL0x0020))) { |
1431 | if (pfd[1].revents & (POLLERR0x0008|POLLNVAL0x0020)) { |
1432 | BIO_printf(bio_err, "poll error"); |
1433 | goto shut; |
1434 | } |
1435 | i = write(fileno(stdout)(!__isthreaded ? (((&__sF[1]))->_file) : (fileno)((& __sF[1]))), &(sbuf[sbuf_off]), sbuf_len); |
1436 | |
1437 | if (i <= 0) { |
1438 | BIO_printf(bio_c_out, "DONE\n"); |
1439 | ret = 0; |
1440 | goto shut; |
1441 | /* goto end; */ |
1442 | } |
1443 | sbuf_len -= i; |
1444 | sbuf_off += i; |
1445 | if (sbuf_len <= 0) { |
1446 | read_ssl = 1; |
1447 | write_tty = 0; |
1448 | } |
1449 | } else if (ssl_pending || (pfd[2].revents & (POLLIN0x0001|POLLHUP0x0010))) { |
1450 | #ifdef RENEG |
1451 | { |
1452 | static int iiii; |
1453 | if (++iiii == 52) { |
1454 | SSL_renegotiate(con); |
1455 | iiii = 0; |
1456 | } |
1457 | } |
1458 | #endif |
1459 | if (cfg.peekaboo) { |
1460 | k = p = SSL_peek(con, pbuf, 1024 /* BUFSIZZ */ ); |
1461 | pending = SSL_pending(con); |
1462 | if (SSL_get_error(con, p) == SSL_ERROR_NONE0) { |
1463 | if (p <= 0) |
1464 | goto end; |
1465 | |
1466 | k = SSL_read(con, sbuf, p); |
1467 | } |
1468 | } else { |
1469 | k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); |
1470 | } |
1471 | |
1472 | switch (SSL_get_error(con, k)) { |
1473 | case SSL_ERROR_NONE0: |
1474 | if (k <= 0) |
1475 | goto end; |
1476 | sbuf_off = 0; |
1477 | sbuf_len = k; |
1478 | if (cfg.peekaboo) { |
1479 | if (p != pending) { |
1480 | ret = -1; |
1481 | BIO_printf(bio_err, |
1482 | "peeked %d but pending %d!\n", |
1483 | p, pending); |
1484 | goto shut; |
1485 | } |
1486 | if (k < p) { |
1487 | ret = -1; |
1488 | BIO_printf(bio_err, |
1489 | "read less than peek!\n"); |
1490 | goto shut; |
1491 | } |
1492 | if (p > 0 && |
1493 | (memcmp(sbuf, pbuf, p) != 0)) { |
1494 | ret = -1; |
1495 | BIO_printf(bio_err, |
1496 | "peek of %d different from read of %d!\n", |
1497 | p, k); |
1498 | goto shut; |
1499 | } |
1500 | } |
1501 | read_ssl = 0; |
1502 | write_tty = 1; |
1503 | break; |
1504 | case SSL_ERROR_WANT_WRITE3: |
1505 | BIO_printf(bio_c_out, "read W BLOCK\n"); |
1506 | write_ssl = 1; |
1507 | read_tty = 0; |
1508 | break; |
1509 | case SSL_ERROR_WANT_READ2: |
1510 | BIO_printf(bio_c_out, "read R BLOCK\n"); |
1511 | write_tty = 0; |
1512 | read_ssl = 1; |
1513 | if ((read_tty == 0) && (write_ssl == 0)) |
1514 | write_ssl = 1; |
1515 | break; |
1516 | case SSL_ERROR_WANT_X509_LOOKUP4: |
1517 | BIO_printf(bio_c_out, "read X BLOCK\n"); |
1518 | break; |
1519 | case SSL_ERROR_SYSCALL5: |
1520 | ret = errno(*__errno()); |
1521 | BIO_printf(bio_err, "read:errno=%d\n", ret); |
1522 | goto shut; |
1523 | case SSL_ERROR_ZERO_RETURN6: |
1524 | BIO_printf(bio_c_out, "closed\n"); |
1525 | ret = 0; |
1526 | goto shut; |
1527 | case SSL_ERROR_SSL1: |
1528 | ERR_print_errors(bio_err); |
1529 | goto shut; |
1530 | /* break; */ |
1531 | } |
1532 | } else if (pfd[0].revents) { |
1533 | if (pfd[0].revents & (POLLERR0x0008|POLLNVAL0x0020)) { |
1534 | BIO_printf(bio_err, "poll error"); |
1535 | goto shut; |
1536 | } |
1537 | if (cfg.crlf) { |
1538 | int j, lf_num; |
1539 | |
1540 | i = read(fileno(stdin)(!__isthreaded ? (((&__sF[0]))->_file) : (fileno)((& __sF[0]))), cbuf, BUFSIZZ1024*8 / 2); |
1541 | lf_num = 0; |
1542 | /* both loops are skipped when i <= 0 */ |
1543 | for (j = 0; j < i; j++) |
1544 | if (cbuf[j] == '\n') |
1545 | lf_num++; |
1546 | for (j = i - 1; j >= 0; j--) { |
1547 | cbuf[j + lf_num] = cbuf[j]; |
1548 | if (cbuf[j] == '\n') { |
1549 | lf_num--; |
1550 | i++; |
1551 | cbuf[j + lf_num] = '\r'; |
1552 | } |
1553 | } |
1554 | assert(lf_num == 0)((lf_num == 0) ? (void)0 : __assert2("/usr/src/usr.bin/openssl/s_client.c" , 1554, __func__, "lf_num == 0")); |
1555 | } else |
1556 | i = read(fileno(stdin)(!__isthreaded ? (((&__sF[0]))->_file) : (fileno)((& __sF[0]))), cbuf, BUFSIZZ1024*8); |
1557 | |
1558 | if ((!cfg.ign_eof) && |
1559 | ((i <= 0) || (cbuf[0] == 'Q'))) { |
1560 | BIO_printf(bio_err, "DONE\n"); |
1561 | ret = 0; |
1562 | goto shut; |
1563 | } |
1564 | if ((!cfg.ign_eof) && (cbuf[0] == 'R')) { |
1565 | BIO_printf(bio_err, "RENEGOTIATING\n"); |
1566 | SSL_renegotiate(con); |
1567 | cbuf_len = 0; |
1568 | } else { |
1569 | cbuf_len = i; |
1570 | cbuf_off = 0; |
1571 | } |
1572 | |
1573 | write_ssl = 1; |
1574 | read_tty = 0; |
1575 | } |
1576 | } |
1577 | |
1578 | ret = 0; |
1579 | shut: |
1580 | if (in_init) |
1581 | print_stuff(bio_c_out, con, full_log); |
1582 | SSL_shutdown(con); |
1583 | shutdown(SSL_get_fd(con), SHUT_RD0); |
1584 | close(SSL_get_fd(con)); |
1585 | end: |
1586 | if (con != NULL((void *)0)) { |
1587 | if (cfg.prexit != 0) |
1588 | print_stuff(bio_c_out, con, 1); |
1589 | SSL_free(con); |
1590 | } |
1591 | SSL_CTX_free(ctx); |
1592 | X509_free(cert); |
1593 | EVP_PKEY_free(key); |
1594 | free(pass); |
1595 | X509_VERIFY_PARAM_free(cfg.vpm); |
1596 | freezero(cbuf, BUFSIZZ1024*8); |
1597 | freezero(sbuf, BUFSIZZ1024*8); |
1598 | freezero(pbuf, BUFSIZZ1024*8); |
1599 | freezero(mbuf, BUFSIZZ1024*8); |
1600 | BIO_free(bio_c_out); |
1601 | |
1602 | return (ret); |
1603 | } |
1604 | |
1605 | static void |
1606 | print_stuff(BIO *bio, SSL *s, int full) |
1607 | { |
1608 | X509 *peer = NULL((void *)0); |
1609 | char *p; |
1610 | static const char *space = " "; |
1611 | char buf[BUFSIZ1024]; |
1612 | STACK_OF(X509)struct stack_st_X509 *sk; |
1613 | STACK_OF(X509_NAME)struct stack_st_X509_NAME *sk2; |
1614 | const SSL_CIPHER *c; |
1615 | X509_NAME *xn; |
1616 | int j, i; |
1617 | unsigned char *exportedkeymat; |
1618 | |
1619 | if (full) { |
1620 | int got_a_chain = 0; |
1621 | |
1622 | sk = SSL_get_peer_cert_chain(s); |
1623 | if (sk != NULL((void *)0)) { |
1624 | got_a_chain = 1; /* we don't have it for SSL2 |
1625 | * (yet) */ |
1626 | |
1627 | BIO_printf(bio, "---\nCertificate chain\n"); |
1628 | for (i = 0; i < sk_X509_num(sk)sk_num(((_STACK*) (1 ? (sk) : (struct stack_st_X509*)0))); i++) { |
1629 | X509_NAME_oneline(X509_get_subject_name( |
1630 | sk_X509_value(sk, i)((X509 *)sk_value(((_STACK*) (1 ? (sk) : (struct stack_st_X509 *)0)), (i)))), buf, sizeof buf); |
1631 | BIO_printf(bio, "%2d s:%s\n", i, buf); |
1632 | X509_NAME_oneline(X509_get_issuer_name( |
1633 | sk_X509_value(sk, i)((X509 *)sk_value(((_STACK*) (1 ? (sk) : (struct stack_st_X509 *)0)), (i)))), buf, sizeof buf); |
1634 | BIO_printf(bio, " i:%s\n", buf); |
1635 | if (cfg.showcerts) |
1636 | PEM_write_bio_X509(bio, |
1637 | sk_X509_value(sk, i)((X509 *)sk_value(((_STACK*) (1 ? (sk) : (struct stack_st_X509 *)0)), (i)))); |
1638 | } |
1639 | } |
1640 | BIO_printf(bio, "---\n"); |
1641 | peer = SSL_get_peer_certificate(s); |
1642 | if (peer != NULL((void *)0)) { |
1643 | BIO_printf(bio, "Server certificate\n"); |
1644 | if (!(cfg.showcerts && got_a_chain)) { |
1645 | /* Redundant if we showed the whole chain */ |
1646 | PEM_write_bio_X509(bio, peer); |
1647 | } |
1648 | X509_NAME_oneline(X509_get_subject_name(peer), |
1649 | buf, sizeof buf); |
1650 | BIO_printf(bio, "subject=%s\n", buf); |
1651 | X509_NAME_oneline(X509_get_issuer_name(peer), |
1652 | buf, sizeof buf); |
1653 | BIO_printf(bio, "issuer=%s\n", buf); |
1654 | } else |
1655 | BIO_printf(bio, "no peer certificate available\n"); |
1656 | |
1657 | sk2 = SSL_get_client_CA_list(s); |
1658 | if ((sk2 != NULL((void *)0)) && (sk_X509_NAME_num(sk2)sk_num(((_STACK*) (1 ? (sk2) : (struct stack_st_X509_NAME*)0) )) > 0)) { |
1659 | BIO_printf(bio, |
1660 | "---\nAcceptable client certificate CA names\n"); |
1661 | for (i = 0; i < sk_X509_NAME_num(sk2)sk_num(((_STACK*) (1 ? (sk2) : (struct stack_st_X509_NAME*)0) )); i++) { |
1662 | xn = sk_X509_NAME_value(sk2, i)((X509_NAME *)sk_value(((_STACK*) (1 ? (sk2) : (struct stack_st_X509_NAME *)0)), (i))); |
1663 | X509_NAME_oneline(xn, buf, sizeof(buf)); |
1664 | BIO_write(bio, buf, strlen(buf)); |
1665 | BIO_write(bio, "\n", 1); |
1666 | } |
1667 | } else { |
1668 | BIO_printf(bio, |
1669 | "---\nNo client certificate CA names sent\n"); |
1670 | } |
1671 | p = SSL_get_shared_ciphers(s, buf, sizeof buf); |
1672 | if (p != NULL((void *)0)) { |
1673 | /* |
1674 | * This works only for SSL 2. In later protocol |
1675 | * versions, the client does not know what other |
1676 | * ciphers (in addition to the one to be used in the |
1677 | * current connection) the server supports. |
1678 | */ |
1679 | |
1680 | BIO_printf(bio, |
1681 | "---\nCiphers common between both SSL endpoints:\n"); |
1682 | j = i = 0; |
1683 | while (*p) { |
1684 | if (*p == ':') { |
1685 | BIO_write(bio, space, 15 - j % 25); |
1686 | i++; |
1687 | j = 0; |
1688 | BIO_write(bio, |
1689 | ((i % 3) ? " " : "\n"), 1); |
1690 | } else { |
1691 | BIO_write(bio, p, 1); |
1692 | j++; |
1693 | } |
1694 | p++; |
1695 | } |
1696 | BIO_write(bio, "\n", 1); |
1697 | } |
1698 | |
1699 | ssl_print_tmp_key(bio, s); |
1700 | |
1701 | BIO_printf(bio, |
1702 | "---\nSSL handshake has read %ld bytes and written %ld bytes\n", |
1703 | BIO_number_read(SSL_get_rbio(s)), |
1704 | BIO_number_written(SSL_get_wbio(s))); |
1705 | } |
1706 | BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, ")); |
1707 | c = SSL_get_current_cipher(s); |
1708 | BIO_printf(bio, "%s, Cipher is %s\n", |
1709 | SSL_CIPHER_get_version(c), |
1710 | SSL_CIPHER_get_name(c)); |
1711 | if (peer != NULL((void *)0)) { |
1712 | EVP_PKEY *pktmp; |
1713 | |
1714 | pktmp = X509_get0_pubkey(peer); |
1715 | BIO_printf(bio, "Server public key is %d bit\n", |
1716 | EVP_PKEY_bits(pktmp)); |
1717 | } |
1718 | BIO_printf(bio, "Secure Renegotiation IS%s supported\n", |
1719 | SSL_get_secure_renegotiation_support(s)SSL_ctrl((s), 76, 0, ((void *)0)) ? "" : " NOT"); |
1720 | |
1721 | /* Compression is not supported and will always be none. */ |
1722 | BIO_printf(bio, "Compression: NONE\n"); |
1723 | BIO_printf(bio, "Expansion: NONE\n"); |
1724 | |
1725 | #ifdef SSL_DEBUG |
1726 | { |
1727 | /* Print out local port of connection: useful for debugging */ |
1728 | int sock; |
1729 | struct sockaddr_in ladd; |
1730 | socklen_t ladd_size = sizeof(ladd); |
1731 | sock = SSL_get_fd(s); |
1732 | getsockname(sock, (struct sockaddr *) & ladd, &ladd_size); |
1733 | BIO_printf(bio, "LOCAL PORT is %u\n", |
1734 | ntohs(ladd.sin_port)(__uint16_t)(__builtin_constant_p(ladd.sin_port) ? (__uint16_t )(((__uint16_t)(ladd.sin_port) & 0xffU) << 8 | ((__uint16_t )(ladd.sin_port) & 0xff00U) >> 8) : __swap16md(ladd .sin_port))); |
1735 | } |
1736 | #endif |
1737 | |
1738 | { |
1739 | const unsigned char *proto; |
1740 | unsigned int proto_len; |
1741 | SSL_get0_alpn_selected(s, &proto, &proto_len); |
1742 | if (proto_len > 0) { |
1743 | BIO_printf(bio, "ALPN protocol: "); |
1744 | BIO_write(bio, proto, proto_len); |
1745 | BIO_write(bio, "\n", 1); |
1746 | } else |
1747 | BIO_printf(bio, "No ALPN negotiated\n"); |
1748 | } |
1749 | |
1750 | #ifndef OPENSSL_NO_SRTP |
1751 | { |
1752 | SRTP_PROTECTION_PROFILE *srtp_profile; |
1753 | |
1754 | srtp_profile = SSL_get_selected_srtp_profile(s); |
1755 | if (srtp_profile) |
1756 | BIO_printf(bio, |
1757 | "SRTP Extension negotiated, profile=%s\n", |
1758 | srtp_profile->name); |
1759 | } |
1760 | #endif |
1761 | |
1762 | SSL_SESSION_print(bio, SSL_get_session(s)); |
1763 | if (cfg.keymatexportlabel != NULL((void *)0)) { |
1764 | BIO_printf(bio, "Keying material exporter:\n"); |
1765 | BIO_printf(bio, " Label: '%s'\n", |
1766 | cfg.keymatexportlabel); |
1767 | BIO_printf(bio, " Length: %i bytes\n", |
1768 | cfg.keymatexportlen); |
1769 | exportedkeymat = malloc(cfg.keymatexportlen); |
1770 | if (exportedkeymat != NULL((void *)0)) { |
1771 | if (!SSL_export_keying_material(s, exportedkeymat, |
1772 | cfg.keymatexportlen, |
1773 | cfg.keymatexportlabel, |
1774 | strlen(cfg.keymatexportlabel), |
1775 | NULL((void *)0), 0, 0)) { |
1776 | BIO_printf(bio, " Error\n"); |
1777 | } else { |
1778 | BIO_printf(bio, " Keying material: "); |
1779 | for (i = 0; i < cfg.keymatexportlen; i++) |
1780 | BIO_printf(bio, "%02X", |
1781 | exportedkeymat[i]); |
1782 | BIO_printf(bio, "\n"); |
1783 | } |
1784 | free(exportedkeymat); |
1785 | } |
1786 | } |
1787 | BIO_printf(bio, "---\n"); |
1788 | X509_free(peer); |
1789 | /* flush, or debugging output gets mixed with http response */ |
1790 | (void) BIO_flush(bio)(int)BIO_ctrl(bio,11,0,((void *)0)); |
1791 | } |
1792 | |
1793 | static int |
1794 | ocsp_resp_cb(SSL *s, void *arg) |
1795 | { |
1796 | const unsigned char *p; |
1797 | int len; |
1798 | OCSP_RESPONSE *rsp; |
1799 | len = SSL_get_tlsext_status_ocsp_resp(s, &p)SSL_ctrl(s,70,0, (void *)&p); |
1800 | BIO_puts(arg, "OCSP response: "); |
1801 | if (!p) { |
1802 | BIO_puts(arg, "no response sent\n"); |
1803 | return 1; |
1804 | } |
1805 | rsp = d2i_OCSP_RESPONSE(NULL((void *)0), &p, len); |
1806 | if (!rsp) { |
1807 | BIO_puts(arg, "response parse error\n"); |
1808 | BIO_dump_indent(arg, (char *) p, len, 4); |
1809 | return 0; |
1810 | } |
1811 | BIO_puts(arg, "\n======================================\n"); |
1812 | OCSP_RESPONSE_print(arg, rsp, 0); |
1813 | BIO_puts(arg, "======================================\n"); |
1814 | OCSP_RESPONSE_free(rsp); |
1815 | return 1; |
1816 | } |
1817 | |
1818 | static int |
1819 | ssl_servername_cb(SSL *s, int *ad, void *arg) |
1820 | { |
1821 | tlsextctx *p = (tlsextctx *) arg; |
1822 | const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name0); |
1823 | if (SSL_get_servername_type(s) != -1) |
1824 | p->ack = !SSL_session_reused(s)SSL_ctrl((s),8,0,((void *)0)) && hn != NULL((void *)0); |
1825 | else |
1826 | BIO_printf(bio_err, "Can't use SSL_get_servername\n"); |
1827 | |
1828 | return SSL_TLSEXT_ERR_OK0; |
1829 | } |
1830 |