|
1 /* apps/s_client.c */ |
|
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-2001 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 #include <assert.h> |
|
113 #include <stdio.h> |
|
114 #include <stdlib.h> |
|
115 #include <string.h> |
|
116 #include <sys/select.h> |
|
117 #include <openssl/e_os2.h> |
|
118 #ifdef OPENSSL_NO_STDIO |
|
119 #define APPS_WIN16 |
|
120 #endif |
|
121 |
|
122 /* With IPv6, it looks like Digital has mixed up the proper order of |
|
123 recursive header file inclusion, resulting in the compiler complaining |
|
124 that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which |
|
125 is needed to have fileno() declared correctly... So let's define u_int */ |
|
126 #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) |
|
127 #define __U_INT |
|
128 typedef unsigned int u_int; |
|
129 #endif |
|
130 |
|
131 #define USE_SOCKETS |
|
132 #include "apps.h" |
|
133 #include <openssl/x509.h> |
|
134 #include <openssl/ssl.h> |
|
135 #include <openssl/err.h> |
|
136 #include <openssl/pem.h> |
|
137 #include <openssl/rand.h> |
|
138 #include "s_apps.h" |
|
139 #include "timeouts.h" |
|
140 |
|
141 #ifdef OPENSSL_SYS_WINCE |
|
142 /* Windows CE incorrectly defines fileno as returning void*, so to avoid problems below... */ |
|
143 #ifdef fileno |
|
144 #undef fileno |
|
145 #endif |
|
146 #define fileno(a) (int)_fileno(a) |
|
147 #endif |
|
148 |
|
149 |
|
150 #if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) |
|
151 /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ |
|
152 #undef FIONBIO |
|
153 #endif |
|
154 |
|
155 #undef PROG |
|
156 #define PROG s_client_main |
|
157 |
|
158 /*#define SSL_HOST_NAME "www.netscape.com" */ |
|
159 /*#define SSL_HOST_NAME "193.118.187.102" */ |
|
160 #define SSL_HOST_NAME "localhost" |
|
161 |
|
162 /*#define TEST_CERT "client.pem" */ /* no default cert. */ |
|
163 |
|
164 #undef BUFSIZZ |
|
165 #define BUFSIZZ 1024*8 |
|
166 |
|
167 extern int verify_depth; |
|
168 extern int verify_error; |
|
169 |
|
170 #ifdef FIONBIO |
|
171 static int c_nbio=0; |
|
172 #endif |
|
173 static int c_Pause=0; |
|
174 static int c_debug=0; |
|
175 static int c_msg=0; |
|
176 static int c_showcerts=0; |
|
177 |
|
178 static void sc_usage(void); |
|
179 static void print_stuff(BIO *berr,SSL *con,int full); |
|
180 static BIO *bio_c_out=NULL; |
|
181 static int c_quiet=0; |
|
182 static int c_ign_eof=0; |
|
183 |
|
184 |
|
185 static void sc_usage(void) |
|
186 { |
|
187 BIO_printf(bio_err,"usage: s_client args\n"); |
|
188 BIO_printf(bio_err,"\n"); |
|
189 BIO_printf(bio_err," -host host - use -connect instead\n"); |
|
190 BIO_printf(bio_err," -port port - use -connect instead\n"); |
|
191 BIO_printf(bio_err," -connect host:port - who to connect to (default is %s:%s)\n",SSL_HOST_NAME,PORT_STR); |
|
192 |
|
193 BIO_printf(bio_err," -verify depth - turn on peer certificate verification\n"); |
|
194 BIO_printf(bio_err," -cert arg - certificate file to use, PEM format assumed\n"); |
|
195 BIO_printf(bio_err," -certform arg - certificate format (PEM or DER) PEM default\n"); |
|
196 BIO_printf(bio_err," -key arg - Private key file to use, in cert file if\n"); |
|
197 BIO_printf(bio_err," not specified but cert file is.\n"); |
|
198 BIO_printf(bio_err," -keyform arg - key format (PEM or DER) PEM default\n"); |
|
199 BIO_printf(bio_err," -pass arg - private key file pass phrase source\n"); |
|
200 BIO_printf(bio_err," -CApath arg - PEM format directory of CA's\n"); |
|
201 BIO_printf(bio_err," -CAfile arg - PEM format file of CA's\n"); |
|
202 BIO_printf(bio_err," -reconnect - Drop and re-make the connection with the same Session-ID\n"); |
|
203 BIO_printf(bio_err," -pause - sleep(1) after each read(2) and write(2) system call\n"); |
|
204 BIO_printf(bio_err," -showcerts - show all certificates in the chain\n"); |
|
205 BIO_printf(bio_err," -debug - extra output\n"); |
|
206 #ifdef WATT32 |
|
207 BIO_printf(bio_err," -wdebug - WATT-32 tcp debugging\n"); |
|
208 #endif |
|
209 BIO_printf(bio_err," -msg - Show protocol messages\n"); |
|
210 BIO_printf(bio_err," -nbio_test - more ssl protocol testing\n"); |
|
211 BIO_printf(bio_err," -state - print the 'ssl' states\n"); |
|
212 #ifdef FIONBIO |
|
213 BIO_printf(bio_err," -nbio - Run with non-blocking IO\n"); |
|
214 #endif |
|
215 BIO_printf(bio_err," -crlf - convert LF from terminal into CRLF\n"); |
|
216 BIO_printf(bio_err," -quiet - no s_client output\n"); |
|
217 BIO_printf(bio_err," -ign_eof - ignore input eof (default when -quiet)\n"); |
|
218 BIO_printf(bio_err," -ssl2 - just use SSLv2\n"); |
|
219 BIO_printf(bio_err," -ssl3 - just use SSLv3\n"); |
|
220 BIO_printf(bio_err," -tls1 - just use TLSv1\n"); |
|
221 BIO_printf(bio_err," -dtls1 - just use DTLSv1\n"); |
|
222 BIO_printf(bio_err," -mtu - set the MTU\n"); |
|
223 BIO_printf(bio_err," -no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n"); |
|
224 BIO_printf(bio_err," -bugs - Switch on all SSL implementation bug workarounds\n"); |
|
225 BIO_printf(bio_err," -serverpref - Use server's cipher preferences (only SSLv2)\n"); |
|
226 BIO_printf(bio_err," -cipher - preferred cipher to use, use the 'openssl ciphers'\n"); |
|
227 BIO_printf(bio_err," command to see what is available\n"); |
|
228 BIO_printf(bio_err," -starttls prot - use the STARTTLS command before starting TLS\n"); |
|
229 BIO_printf(bio_err," for those protocols that support it, where\n"); |
|
230 BIO_printf(bio_err," 'prot' defines which one to assume. Currently,\n"); |
|
231 BIO_printf(bio_err," only \"smtp\", \"pop3\", \"imap\", and \"ftp\" are supported.\n"); |
|
232 #ifndef OPENSSL_NO_ENGINE |
|
233 BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n"); |
|
234 #endif |
|
235 BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); |
|
236 BIO_printf(bio_err," -sess_out arg - file to write SSL session to\n"); |
|
237 BIO_printf(bio_err," -sess_in arg - file to read SSL session from\n"); |
|
238 } |
|
239 |
|
240 enum |
|
241 { |
|
242 PROTO_OFF = 0, |
|
243 PROTO_SMTP, |
|
244 PROTO_POP3, |
|
245 PROTO_IMAP, |
|
246 PROTO_FTP |
|
247 }; |
|
248 |
|
249 int MAIN(int, char **); |
|
250 |
|
251 int MAIN(int argc, char **argv) |
|
252 { |
|
253 int off=0; |
|
254 SSL *con=NULL,*con2=NULL; |
|
255 X509_STORE *store = NULL; |
|
256 int s,k,width,state=0; |
|
257 char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; |
|
258 int cbuf_len,cbuf_off; |
|
259 int sbuf_len,sbuf_off; |
|
260 fd_set readfds,writefds; |
|
261 short port=PORT; |
|
262 int full_log=1; |
|
263 char *host=SSL_HOST_NAME; |
|
264 char *cert_file=NULL,*key_file=NULL; |
|
265 int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; |
|
266 char *passarg = NULL, *pass = NULL; |
|
267 X509 *cert = NULL; |
|
268 EVP_PKEY *key = NULL; |
|
269 char *CApath=NULL,*CAfile=NULL,*cipher=NULL; |
|
270 int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0; |
|
271 int crlf=0; |
|
272 int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending; |
|
273 SSL_CTX *ctx=NULL; |
|
274 int ret=1,in_init=1,i,nbio_test=0; |
|
275 int starttls_proto = PROTO_OFF; |
|
276 int prexit = 0, vflags = 0; |
|
277 SSL_METHOD *meth=NULL; |
|
278 #ifdef sock_type |
|
279 #undef sock_type |
|
280 #endif |
|
281 int sock_type=SOCK_STREAM; |
|
282 BIO *sbio; |
|
283 char *inrand=NULL; |
|
284 int mbuf_len=0; |
|
285 #ifndef OPENSSL_NO_ENGINE |
|
286 char *engine_id=NULL; |
|
287 ENGINE *e=NULL; |
|
288 #endif |
|
289 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) |
|
290 struct timeval tv; |
|
291 #endif |
|
292 |
|
293 char *sess_in = NULL; |
|
294 char *sess_out = NULL; |
|
295 struct sockaddr peer; |
|
296 int peerlen = sizeof(peer); |
|
297 int enable_timeouts = 0 ; |
|
298 long mtu = 0; |
|
299 |
|
300 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) |
|
301 meth=SSLv23_client_method(); |
|
302 #elif !defined(OPENSSL_NO_SSL3) |
|
303 meth=SSLv3_client_method(); |
|
304 #elif !defined(OPENSSL_NO_SSL2) |
|
305 meth=SSLv2_client_method(); |
|
306 #endif |
|
307 |
|
308 apps_startup(); |
|
309 c_Pause=0; |
|
310 c_quiet=0; |
|
311 c_ign_eof=0; |
|
312 c_debug=0; |
|
313 c_msg=0; |
|
314 c_showcerts=0; |
|
315 |
|
316 if (bio_err == NULL) |
|
317 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); |
|
318 |
|
319 if (!load_config(bio_err, NULL)) |
|
320 goto end; |
|
321 |
|
322 if ( ((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || |
|
323 ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || |
|
324 ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL)) |
|
325 { |
|
326 BIO_printf(bio_err,"out of memory\n"); |
|
327 goto end; |
|
328 } |
|
329 |
|
330 verify_depth=0; |
|
331 verify_error=X509_V_OK; |
|
332 #ifdef FIONBIO |
|
333 c_nbio=0; |
|
334 #endif |
|
335 |
|
336 argc--; |
|
337 argv++; |
|
338 while (argc >= 1) |
|
339 { |
|
340 if (strcmp(*argv,"-host") == 0) |
|
341 { |
|
342 if (--argc < 1) goto bad; |
|
343 host= *(++argv); |
|
344 } |
|
345 else if (strcmp(*argv,"-port") == 0) |
|
346 { |
|
347 if (--argc < 1) goto bad; |
|
348 port=atoi(*(++argv)); |
|
349 if (port == 0) goto bad; |
|
350 } |
|
351 else if (strcmp(*argv,"-connect") == 0) |
|
352 { |
|
353 if (--argc < 1) goto bad; |
|
354 if (!extract_host_port(*(++argv),&host,NULL,&port)) |
|
355 goto bad; |
|
356 } |
|
357 else if (strcmp(*argv,"-verify") == 0) |
|
358 { |
|
359 verify=SSL_VERIFY_PEER; |
|
360 if (--argc < 1) goto bad; |
|
361 verify_depth=atoi(*(++argv)); |
|
362 BIO_printf(bio_err,"verify depth is %d\n",verify_depth); |
|
363 } |
|
364 else if (strcmp(*argv,"-cert") == 0) |
|
365 { |
|
366 if (--argc < 1) goto bad; |
|
367 cert_file= *(++argv); |
|
368 } |
|
369 else if (strcmp(*argv,"-sess_out") == 0) |
|
370 { |
|
371 if (--argc < 1) goto bad; |
|
372 sess_out = *(++argv); |
|
373 } |
|
374 else if (strcmp(*argv,"-sess_in") == 0) |
|
375 { |
|
376 if (--argc < 1) goto bad; |
|
377 sess_in = *(++argv); |
|
378 } |
|
379 else if (strcmp(*argv,"-certform") == 0) |
|
380 { |
|
381 if (--argc < 1) goto bad; |
|
382 cert_format = str2fmt(*(++argv)); |
|
383 } |
|
384 else if (strcmp(*argv,"-crl_check") == 0) |
|
385 vflags |= X509_V_FLAG_CRL_CHECK; |
|
386 else if (strcmp(*argv,"-crl_check_all") == 0) |
|
387 vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; |
|
388 else if (strcmp(*argv,"-prexit") == 0) |
|
389 prexit=1; |
|
390 else if (strcmp(*argv,"-crlf") == 0) |
|
391 crlf=1; |
|
392 else if (strcmp(*argv,"-quiet") == 0) |
|
393 { |
|
394 c_quiet=1; |
|
395 c_ign_eof=1; |
|
396 } |
|
397 else if (strcmp(*argv,"-ign_eof") == 0) |
|
398 c_ign_eof=1; |
|
399 else if (strcmp(*argv,"-pause") == 0) |
|
400 c_Pause=1; |
|
401 else if (strcmp(*argv,"-debug") == 0) |
|
402 c_debug=1; |
|
403 #ifdef WATT32 |
|
404 else if (strcmp(*argv,"-wdebug") == 0) |
|
405 dbug_init(); |
|
406 #endif |
|
407 else if (strcmp(*argv,"-msg") == 0) |
|
408 c_msg=1; |
|
409 else if (strcmp(*argv,"-showcerts") == 0) |
|
410 c_showcerts=1; |
|
411 else if (strcmp(*argv,"-nbio_test") == 0) |
|
412 nbio_test=1; |
|
413 else if (strcmp(*argv,"-state") == 0) |
|
414 state=1; |
|
415 #ifndef OPENSSL_NO_SSL2 |
|
416 else if (strcmp(*argv,"-ssl2") == 0) |
|
417 meth=SSLv2_client_method(); |
|
418 #endif |
|
419 #ifndef OPENSSL_NO_SSL3 |
|
420 else if (strcmp(*argv,"-ssl3") == 0) |
|
421 meth=SSLv3_client_method(); |
|
422 #endif |
|
423 #ifndef OPENSSL_NO_TLS1 |
|
424 else if (strcmp(*argv,"-tls1") == 0) |
|
425 meth=TLSv1_client_method(); |
|
426 #endif |
|
427 #ifndef OPENSSL_NO_DTLS1 |
|
428 else if (strcmp(*argv,"-dtls1") == 0) |
|
429 { |
|
430 meth=DTLSv1_client_method(); |
|
431 sock_type=SOCK_DGRAM; |
|
432 } |
|
433 else if (strcmp(*argv,"-timeout") == 0) |
|
434 enable_timeouts=1; |
|
435 else if (strcmp(*argv,"-mtu") == 0) |
|
436 { |
|
437 if (--argc < 1) goto bad; |
|
438 mtu = atol(*(++argv)); |
|
439 } |
|
440 #endif |
|
441 else if (strcmp(*argv,"-bugs") == 0) |
|
442 bugs=1; |
|
443 else if (strcmp(*argv,"-keyform") == 0) |
|
444 { |
|
445 if (--argc < 1) goto bad; |
|
446 key_format = str2fmt(*(++argv)); |
|
447 } |
|
448 else if (strcmp(*argv,"-pass") == 0) |
|
449 { |
|
450 if (--argc < 1) goto bad; |
|
451 passarg = *(++argv); |
|
452 } |
|
453 else if (strcmp(*argv,"-key") == 0) |
|
454 { |
|
455 if (--argc < 1) goto bad; |
|
456 key_file= *(++argv); |
|
457 } |
|
458 else if (strcmp(*argv,"-reconnect") == 0) |
|
459 { |
|
460 reconnect=5; |
|
461 } |
|
462 else if (strcmp(*argv,"-CApath") == 0) |
|
463 { |
|
464 if (--argc < 1) goto bad; |
|
465 CApath= *(++argv); |
|
466 } |
|
467 else if (strcmp(*argv,"-CAfile") == 0) |
|
468 { |
|
469 if (--argc < 1) goto bad; |
|
470 CAfile= *(++argv); |
|
471 } |
|
472 else if (strcmp(*argv,"-no_tls1") == 0) |
|
473 off|=SSL_OP_NO_TLSv1; |
|
474 else if (strcmp(*argv,"-no_ssl3") == 0) |
|
475 off|=SSL_OP_NO_SSLv3; |
|
476 else if (strcmp(*argv,"-no_ssl2") == 0) |
|
477 off|=SSL_OP_NO_SSLv2; |
|
478 else if (strcmp(*argv,"-serverpref") == 0) |
|
479 off|=SSL_OP_CIPHER_SERVER_PREFERENCE; |
|
480 else if (strcmp(*argv,"-cipher") == 0) |
|
481 { |
|
482 if (--argc < 1) goto bad; |
|
483 cipher= *(++argv); |
|
484 } |
|
485 #ifdef FIONBIO |
|
486 else if (strcmp(*argv,"-nbio") == 0) |
|
487 { c_nbio=1; } |
|
488 #endif |
|
489 else if (strcmp(*argv,"-starttls") == 0) |
|
490 { |
|
491 if (--argc < 1) goto bad; |
|
492 ++argv; |
|
493 if (strcmp(*argv,"smtp") == 0) |
|
494 starttls_proto = PROTO_SMTP; |
|
495 else if (strcmp(*argv,"pop3") == 0) |
|
496 starttls_proto = PROTO_POP3; |
|
497 else if (strcmp(*argv,"imap") == 0) |
|
498 starttls_proto = PROTO_IMAP; |
|
499 else if (strcmp(*argv,"ftp") == 0) |
|
500 starttls_proto = PROTO_FTP; |
|
501 else |
|
502 goto bad; |
|
503 } |
|
504 #ifndef OPENSSL_NO_ENGINE |
|
505 else if (strcmp(*argv,"-engine") == 0) |
|
506 { |
|
507 if (--argc < 1) goto bad; |
|
508 engine_id = *(++argv); |
|
509 } |
|
510 #endif |
|
511 else if (strcmp(*argv,"-rand") == 0) |
|
512 { |
|
513 if (--argc < 1) goto bad; |
|
514 inrand= *(++argv); |
|
515 } |
|
516 |
|
517 else |
|
518 { |
|
519 BIO_printf(bio_err,"unknown option %s\n",*argv); |
|
520 badop=1; |
|
521 break; |
|
522 } |
|
523 argc--; |
|
524 argv++; |
|
525 } |
|
526 if (badop) |
|
527 { |
|
528 bad: |
|
529 sc_usage(); |
|
530 goto end; |
|
531 } |
|
532 |
|
533 OpenSSL_add_ssl_algorithms(); |
|
534 SSL_load_error_strings(); |
|
535 |
|
536 #ifndef OPENSSL_NO_ENGINE |
|
537 e = setup_engine(bio_err, engine_id, 1); |
|
538 #endif |
|
539 if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) |
|
540 { |
|
541 BIO_printf(bio_err, "Error getting password\n"); |
|
542 goto end; |
|
543 } |
|
544 |
|
545 if (key_file == NULL) |
|
546 key_file = cert_file; |
|
547 |
|
548 |
|
549 if (key_file) |
|
550 |
|
551 { |
|
552 |
|
553 key = load_key(bio_err, key_file, key_format, 0, pass, e, |
|
554 "client certificate private key file"); |
|
555 if (!key) |
|
556 { |
|
557 ERR_print_errors(bio_err); |
|
558 goto end; |
|
559 } |
|
560 |
|
561 } |
|
562 |
|
563 if (cert_file) |
|
564 |
|
565 { |
|
566 cert = load_cert(bio_err,cert_file,cert_format, |
|
567 NULL, e, "client certificate file"); |
|
568 |
|
569 if (!cert) |
|
570 { |
|
571 ERR_print_errors(bio_err); |
|
572 goto end; |
|
573 } |
|
574 } |
|
575 |
|
576 if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL |
|
577 && !RAND_status()) |
|
578 { |
|
579 BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); |
|
580 } |
|
581 if (inrand != NULL) |
|
582 BIO_printf(bio_err,"%ld semi-random bytes loaded\n", |
|
583 app_RAND_load_files(inrand)); |
|
584 |
|
585 if (bio_c_out == NULL) |
|
586 { |
|
587 if (c_quiet && !c_debug && !c_msg) |
|
588 { |
|
589 bio_c_out=BIO_new(BIO_s_null()); |
|
590 } |
|
591 else |
|
592 { |
|
593 if (bio_c_out == NULL) |
|
594 bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE); |
|
595 |
|
596 } |
|
597 } |
|
598 |
|
599 ctx=SSL_CTX_new(meth); |
|
600 if (ctx == NULL) |
|
601 { |
|
602 ERR_print_errors(bio_err); |
|
603 goto end; |
|
604 } |
|
605 |
|
606 if (bugs) |
|
607 SSL_CTX_set_options(ctx,SSL_OP_ALL|off); |
|
608 else |
|
609 SSL_CTX_set_options(ctx,off); |
|
610 /* DTLS: partial reads end up discarding unread UDP bytes :-( |
|
611 * Setting read ahead solves this problem. |
|
612 */ |
|
613 if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); |
|
614 |
|
615 if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); |
|
616 if (cipher != NULL) |
|
617 if(!SSL_CTX_set_cipher_list(ctx,cipher)) { |
|
618 BIO_printf(bio_err,"error setting cipher list\n"); |
|
619 ERR_print_errors(bio_err); |
|
620 goto end; |
|
621 } |
|
622 #if 0 |
|
623 else |
|
624 SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER")); |
|
625 #endif |
|
626 |
|
627 SSL_CTX_set_verify(ctx,verify,verify_callback); |
|
628 if (!set_cert_key_stuff(ctx,cert,key)) |
|
629 goto end; |
|
630 |
|
631 if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || |
|
632 (!SSL_CTX_set_default_verify_paths(ctx))) |
|
633 { |
|
634 /* BIO_printf(bio_err,"error setting default verify locations\n"); */ |
|
635 ERR_print_errors(bio_err); |
|
636 /* goto end; */ |
|
637 } |
|
638 |
|
639 store = SSL_CTX_get_cert_store(ctx); |
|
640 X509_STORE_set_flags(store, vflags); |
|
641 |
|
642 con=SSL_new(ctx); |
|
643 if (sess_in) |
|
644 { |
|
645 SSL_SESSION *sess; |
|
646 BIO *stmp = BIO_new_file(sess_in, "r"); |
|
647 if (!stmp) |
|
648 { |
|
649 BIO_printf(bio_err, "Can't open session file %s\n", |
|
650 sess_in); |
|
651 ERR_print_errors(bio_err); |
|
652 goto end; |
|
653 } |
|
654 sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); |
|
655 BIO_free(stmp); |
|
656 if (!sess) |
|
657 { |
|
658 BIO_printf(bio_err, "Can't open session file %s\n", |
|
659 sess_in); |
|
660 ERR_print_errors(bio_err); |
|
661 goto end; |
|
662 } |
|
663 SSL_set_session(con, sess); |
|
664 SSL_SESSION_free(sess); |
|
665 } |
|
666 |
|
667 #ifndef OPENSSL_NO_KRB5 |
|
668 if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) |
|
669 { |
|
670 kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); |
|
671 } |
|
672 #endif /* OPENSSL_NO_KRB5 */ |
|
673 /* SSL_set_cipher_list(con,"RC4-MD5"); */ |
|
674 |
|
675 re_start: |
|
676 |
|
677 if (init_client(&s,host,port,sock_type) == 0) |
|
678 { |
|
679 BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); |
|
680 SHUTDOWN(s); |
|
681 goto end; |
|
682 } |
|
683 BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s); |
|
684 |
|
685 #ifdef FIONBIO |
|
686 if (c_nbio) |
|
687 { |
|
688 unsigned long l=1; |
|
689 BIO_printf(bio_c_out,"turning on non blocking io\n"); |
|
690 if (BIO_socket_ioctl(s,FIONBIO,&l) < 0) |
|
691 { |
|
692 ERR_print_errors(bio_err); |
|
693 goto end; |
|
694 } |
|
695 } |
|
696 #endif |
|
697 if (c_Pause & 0x01) con->debug=1; |
|
698 |
|
699 if ( SSL_version(con) == DTLS1_VERSION) |
|
700 { |
|
701 struct timeval timeout; |
|
702 |
|
703 sbio=BIO_new_dgram(s,BIO_NOCLOSE); |
|
704 if (getsockname(s, &peer, (void *)&peerlen) < 0) |
|
705 { |
|
706 BIO_printf(bio_err, "getsockname:errno=%d\n", |
|
707 get_last_socket_error()); |
|
708 SHUTDOWN(s); |
|
709 goto end; |
|
710 } |
|
711 |
|
712 (void)BIO_ctrl_set_connected(sbio, 1, &peer); |
|
713 |
|
714 if ( enable_timeouts) |
|
715 { |
|
716 timeout.tv_sec = 0; |
|
717 timeout.tv_usec = DGRAM_RCV_TIMEOUT; |
|
718 BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); |
|
719 |
|
720 timeout.tv_sec = 0; |
|
721 timeout.tv_usec = DGRAM_SND_TIMEOUT; |
|
722 BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); |
|
723 } |
|
724 |
|
725 if ( mtu > 0) |
|
726 { |
|
727 SSL_set_options(con, SSL_OP_NO_QUERY_MTU); |
|
728 SSL_set_mtu(con, mtu); |
|
729 } |
|
730 else |
|
731 /* want to do MTU discovery */ |
|
732 BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); |
|
733 } |
|
734 else |
|
735 sbio=BIO_new_socket(s,BIO_NOCLOSE); |
|
736 |
|
737 |
|
738 |
|
739 if (nbio_test) |
|
740 { |
|
741 BIO *test; |
|
742 |
|
743 test=BIO_new(BIO_f_nbio_test()); |
|
744 sbio=BIO_push(test,sbio); |
|
745 } |
|
746 |
|
747 if (c_debug) |
|
748 { |
|
749 con->debug=1; |
|
750 BIO_set_callback(sbio,bio_dump_callback); |
|
751 BIO_set_callback_arg(sbio,(char *)bio_c_out); |
|
752 } |
|
753 if (c_msg) |
|
754 { |
|
755 SSL_set_msg_callback(con, msg_cb); |
|
756 SSL_set_msg_callback_arg(con, bio_c_out); |
|
757 } |
|
758 |
|
759 SSL_set_bio(con,sbio,sbio); |
|
760 SSL_set_connect_state(con); |
|
761 |
|
762 /* ok, lets connect */ |
|
763 width=SSL_get_fd(con)+1; |
|
764 |
|
765 read_tty=1; |
|
766 write_tty=0; |
|
767 tty_on=0; |
|
768 read_ssl=1; |
|
769 write_ssl=1; |
|
770 |
|
771 cbuf_len=0; |
|
772 cbuf_off=0; |
|
773 sbuf_len=0; |
|
774 sbuf_off=0; |
|
775 |
|
776 /* This is an ugly hack that does a lot of assumptions */ |
|
777 /* We do have to handle multi-line responses which may come |
|
778 in a single packet or not. We therefore have to use |
|
779 BIO_gets() which does need a buffering BIO. So during |
|
780 the initial chitchat we do push a buffering BIO into the |
|
781 chain that is removed again later on to not disturb the |
|
782 rest of the s_client operation. */ |
|
783 if (starttls_proto == PROTO_SMTP) |
|
784 { |
|
785 int foundit=0; |
|
786 BIO *fbio = BIO_new(BIO_f_buffer()); |
|
787 BIO_push(fbio, sbio); |
|
788 /* wait for multi-line response to end from SMTP */ |
|
789 do |
|
790 { |
|
791 mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); |
|
792 } |
|
793 while (mbuf_len>3 && mbuf[3]=='-'); |
|
794 /* STARTTLS command requires EHLO... */ |
|
795 BIO_printf(fbio,"EHLO openssl.client.net\r\n"); |
|
796 (void)BIO_flush(fbio); |
|
797 /* wait for multi-line response to end EHLO SMTP response */ |
|
798 do |
|
799 { |
|
800 mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); |
|
801 if (strstr(mbuf,"STARTTLS")) |
|
802 foundit=1; |
|
803 } |
|
804 while (mbuf_len>3 && mbuf[3]=='-'); |
|
805 (void)BIO_flush(fbio); |
|
806 BIO_pop(fbio); |
|
807 BIO_free(fbio); |
|
808 if (!foundit) |
|
809 BIO_printf(bio_err, |
|
810 "didn't found starttls in server response," |
|
811 " try anyway...\n"); |
|
812 BIO_printf(sbio,"STARTTLS\r\n"); |
|
813 BIO_read(sbio,sbuf,BUFSIZZ); |
|
814 } |
|
815 else if (starttls_proto == PROTO_POP3) |
|
816 { |
|
817 BIO_read(sbio,mbuf,BUFSIZZ); |
|
818 BIO_printf(sbio,"STLS\r\n"); |
|
819 BIO_read(sbio,sbuf,BUFSIZZ); |
|
820 } |
|
821 else if (starttls_proto == PROTO_IMAP) |
|
822 { |
|
823 int foundit=0; |
|
824 BIO *fbio = BIO_new(BIO_f_buffer()); |
|
825 BIO_push(fbio, sbio); |
|
826 BIO_gets(fbio,mbuf,BUFSIZZ); |
|
827 /* STARTTLS command requires CAPABILITY... */ |
|
828 BIO_printf(fbio,". CAPABILITY\r\n"); |
|
829 (void)BIO_flush(fbio); |
|
830 /* wait for multi-line CAPABILITY response */ |
|
831 do |
|
832 { |
|
833 mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); |
|
834 if (strstr(mbuf,"STARTTLS")) |
|
835 foundit=1; |
|
836 } |
|
837 while (mbuf_len>3 && mbuf[0]!='.'); |
|
838 (void)BIO_flush(fbio); |
|
839 BIO_pop(fbio); |
|
840 BIO_free(fbio); |
|
841 if (!foundit) |
|
842 BIO_printf(bio_err, |
|
843 "didn't found STARTTLS in server response," |
|
844 " try anyway...\n"); |
|
845 BIO_printf(sbio,". STARTTLS\r\n"); |
|
846 BIO_read(sbio,sbuf,BUFSIZZ); |
|
847 } |
|
848 else if (starttls_proto == PROTO_FTP) |
|
849 { |
|
850 BIO *fbio = BIO_new(BIO_f_buffer()); |
|
851 BIO_push(fbio, sbio); |
|
852 /* wait for multi-line response to end from FTP */ |
|
853 do |
|
854 { |
|
855 mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); |
|
856 } |
|
857 while (mbuf_len>3 && mbuf[3]=='-'); |
|
858 (void)BIO_flush(fbio); |
|
859 BIO_pop(fbio); |
|
860 BIO_free(fbio); |
|
861 BIO_printf(sbio,"AUTH TLS\r\n"); |
|
862 BIO_read(sbio,sbuf,BUFSIZZ); |
|
863 } |
|
864 |
|
865 for (;;) |
|
866 { |
|
867 FD_ZERO(&readfds); |
|
868 FD_ZERO(&writefds); |
|
869 |
|
870 if (SSL_in_init(con) && !SSL_total_renegotiations(con)) |
|
871 { |
|
872 in_init=1; |
|
873 tty_on=0; |
|
874 } |
|
875 else |
|
876 { |
|
877 tty_on=1; |
|
878 if (in_init) |
|
879 { |
|
880 in_init=0; |
|
881 if (sess_out) |
|
882 { |
|
883 BIO *stmp = BIO_new_file(sess_out, "w"); |
|
884 if (stmp) |
|
885 { |
|
886 PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); |
|
887 BIO_free(stmp); |
|
888 } |
|
889 else |
|
890 BIO_printf(bio_err, "Error writing session file %s\n", sess_out); |
|
891 } |
|
892 print_stuff(bio_c_out,con,full_log); |
|
893 if (full_log > 0) full_log--; |
|
894 |
|
895 if (starttls_proto) |
|
896 { |
|
897 BIO_printf(bio_err,"%s",mbuf); |
|
898 /* We don't need to know any more */ |
|
899 starttls_proto = PROTO_OFF; |
|
900 } |
|
901 |
|
902 if (reconnect) |
|
903 { |
|
904 reconnect--; |
|
905 BIO_printf(bio_c_out,"drop connection and then reconnect\n"); |
|
906 SSL_shutdown(con); |
|
907 SSL_set_connect_state(con); |
|
908 SHUTDOWN(SSL_get_fd(con)); |
|
909 goto re_start; |
|
910 } |
|
911 } |
|
912 } |
|
913 |
|
914 ssl_pending = read_ssl && SSL_pending(con); |
|
915 |
|
916 if (!ssl_pending) |
|
917 { |
|
918 #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) |
|
919 if (tty_on) |
|
920 { |
|
921 if (read_tty) FD_SET(fileno(stdin),&readfds); |
|
922 if (write_tty) FD_SET(fileno(stdout),&writefds); |
|
923 |
|
924 } |
|
925 if (read_ssl) |
|
926 FD_SET(SSL_get_fd(con),&readfds); |
|
927 if (write_ssl) |
|
928 FD_SET(SSL_get_fd(con),&writefds); |
|
929 #else |
|
930 if(!tty_on || !write_tty) { |
|
931 if (read_ssl) |
|
932 FD_SET(SSL_get_fd(con),&readfds); |
|
933 if (write_ssl) |
|
934 FD_SET(SSL_get_fd(con),&writefds); |
|
935 } |
|
936 #endif |
|
937 /* printf("mode tty(%d %d%d) ssl(%d%d)\n", |
|
938 tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ |
|
939 |
|
940 /* Note: under VMS with SOCKETSHR the second parameter |
|
941 * is currently of type (int *) whereas under other |
|
942 * systems it is (void *) if you don't have a cast it |
|
943 * will choke the compiler: if you do have a cast then |
|
944 * you can either go for (int *) or (void *). |
|
945 */ |
|
946 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) |
|
947 /* Under Windows/DOS we make the assumption that we can |
|
948 * always write to the tty: therefore if we need to |
|
949 * write to the tty we just fall through. Otherwise |
|
950 * we timeout the select every second and see if there |
|
951 * are any keypresses. Note: this is a hack, in a proper |
|
952 * Windows application we wouldn't do this. |
|
953 */ |
|
954 i=0; |
|
955 if(!write_tty) { |
|
956 if(read_tty) { |
|
957 tv.tv_sec = 1; |
|
958 tv.tv_usec = 0; |
|
959 i=select(width,(void *)&readfds,(void *)&writefds, |
|
960 NULL,&tv); |
|
961 #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) |
|
962 if(!i && (!_kbhit() || !read_tty) ) continue; |
|
963 #else |
|
964 if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue; |
|
965 #endif |
|
966 } else i=select(width,(void *)&readfds,(void *)&writefds, |
|
967 NULL,NULL); |
|
968 } |
|
969 #elif defined(OPENSSL_SYS_NETWARE) |
|
970 if(!write_tty) { |
|
971 if(read_tty) { |
|
972 tv.tv_sec = 1; |
|
973 tv.tv_usec = 0; |
|
974 i=select(width,(void *)&readfds,(void *)&writefds, |
|
975 NULL,&tv); |
|
976 } else i=select(width,(void *)&readfds,(void *)&writefds, |
|
977 NULL,NULL); |
|
978 } |
|
979 #else |
|
980 i=select(width,(void *)&readfds,(void *)&writefds, |
|
981 NULL,NULL); |
|
982 #endif |
|
983 if ( i < 0) |
|
984 { |
|
985 BIO_printf(bio_err,"bad select %d\n", |
|
986 get_last_socket_error()); |
|
987 goto shut; |
|
988 /* goto end; */ |
|
989 } |
|
990 } |
|
991 |
|
992 if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds)) |
|
993 { |
|
994 k=SSL_write(con,&(cbuf[cbuf_off]), |
|
995 (unsigned int)cbuf_len); |
|
996 switch (SSL_get_error(con,k)) |
|
997 { |
|
998 case SSL_ERROR_NONE: |
|
999 cbuf_off+=k; |
|
1000 cbuf_len-=k; |
|
1001 if (k <= 0) goto end; |
|
1002 /* we have done a write(con,NULL,0); */ |
|
1003 if (cbuf_len <= 0) |
|
1004 { |
|
1005 read_tty=1; |
|
1006 write_ssl=0; |
|
1007 } |
|
1008 else /* if (cbuf_len > 0) */ |
|
1009 { |
|
1010 read_tty=0; |
|
1011 write_ssl=1; |
|
1012 } |
|
1013 break; |
|
1014 case SSL_ERROR_WANT_WRITE: |
|
1015 BIO_printf(bio_c_out,"write W BLOCK\n"); |
|
1016 write_ssl=1; |
|
1017 read_tty=0; |
|
1018 break; |
|
1019 case SSL_ERROR_WANT_READ: |
|
1020 BIO_printf(bio_c_out,"write R BLOCK\n"); |
|
1021 write_tty=0; |
|
1022 read_ssl=1; |
|
1023 write_ssl=0; |
|
1024 break; |
|
1025 case SSL_ERROR_WANT_X509_LOOKUP: |
|
1026 BIO_printf(bio_c_out,"write X BLOCK\n"); |
|
1027 break; |
|
1028 case SSL_ERROR_ZERO_RETURN: |
|
1029 if (cbuf_len != 0) |
|
1030 { |
|
1031 BIO_printf(bio_c_out,"shutdown\n"); |
|
1032 goto shut; |
|
1033 } |
|
1034 else |
|
1035 { |
|
1036 read_tty=1; |
|
1037 write_ssl=0; |
|
1038 break; |
|
1039 } |
|
1040 |
|
1041 case SSL_ERROR_SYSCALL: |
|
1042 if ((k != 0) || (cbuf_len != 0)) |
|
1043 { |
|
1044 BIO_printf(bio_err,"write:errno=%d\n", |
|
1045 get_last_socket_error()); |
|
1046 goto shut; |
|
1047 } |
|
1048 else |
|
1049 { |
|
1050 read_tty=1; |
|
1051 write_ssl=0; |
|
1052 } |
|
1053 break; |
|
1054 case SSL_ERROR_SSL: |
|
1055 ERR_print_errors(bio_err); |
|
1056 goto shut; |
|
1057 } |
|
1058 } |
|
1059 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) |
|
1060 /* Assume Windows/DOS can always write */ |
|
1061 else if (!ssl_pending && write_tty) |
|
1062 #else |
|
1063 |
|
1064 else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) |
|
1065 |
|
1066 #endif |
|
1067 { |
|
1068 #ifdef CHARSET_EBCDIC |
|
1069 ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len); |
|
1070 #endif |
|
1071 |
|
1072 i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len); |
|
1073 |
|
1074 if (i <= 0) |
|
1075 { |
|
1076 BIO_printf(bio_c_out,"DONE\n"); |
|
1077 goto shut; |
|
1078 /* goto end; */ |
|
1079 } |
|
1080 |
|
1081 sbuf_len-=i;; |
|
1082 sbuf_off+=i; |
|
1083 if (sbuf_len <= 0) |
|
1084 { |
|
1085 read_ssl=1; |
|
1086 write_tty=0; |
|
1087 } |
|
1088 } |
|
1089 else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds)) |
|
1090 { |
|
1091 #ifdef RENEG |
|
1092 { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } } |
|
1093 #endif |
|
1094 #if 1 |
|
1095 k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ ); |
|
1096 #else |
|
1097 /* Demo for pending and peek :-) */ |
|
1098 k=SSL_read(con,sbuf,16); |
|
1099 { char zbuf[10240]; |
|
1100 printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240)); |
|
1101 |
|
1102 } |
|
1103 #endif |
|
1104 |
|
1105 switch (SSL_get_error(con,k)) |
|
1106 { |
|
1107 case SSL_ERROR_NONE: |
|
1108 if (k <= 0) |
|
1109 goto end; |
|
1110 sbuf_off=0; |
|
1111 sbuf_len=k; |
|
1112 |
|
1113 read_ssl=0; |
|
1114 write_tty=1; |
|
1115 break; |
|
1116 case SSL_ERROR_WANT_WRITE: |
|
1117 BIO_printf(bio_c_out,"read W BLOCK\n"); |
|
1118 write_ssl=1; |
|
1119 read_tty=0; |
|
1120 break; |
|
1121 case SSL_ERROR_WANT_READ: |
|
1122 BIO_printf(bio_c_out,"read R BLOCK\n"); |
|
1123 write_tty=0; |
|
1124 read_ssl=1; |
|
1125 if ((read_tty == 0) && (write_ssl == 0)) |
|
1126 write_ssl=1; |
|
1127 break; |
|
1128 case SSL_ERROR_WANT_X509_LOOKUP: |
|
1129 BIO_printf(bio_c_out,"read X BLOCK\n"); |
|
1130 break; |
|
1131 case SSL_ERROR_SYSCALL: |
|
1132 BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error()); |
|
1133 goto shut; |
|
1134 case SSL_ERROR_ZERO_RETURN: |
|
1135 BIO_printf(bio_c_out,"closed\n"); |
|
1136 goto shut; |
|
1137 case SSL_ERROR_SSL: |
|
1138 ERR_print_errors(bio_err); |
|
1139 goto shut; |
|
1140 /* break; */ |
|
1141 } |
|
1142 } |
|
1143 |
|
1144 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) |
|
1145 #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) |
|
1146 else if (_kbhit()) |
|
1147 #else |
|
1148 else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) |
|
1149 #endif |
|
1150 #elif defined (OPENSSL_SYS_NETWARE) |
|
1151 else if (_kbhit()) |
|
1152 #else |
|
1153 else if (FD_ISSET(fileno(stdin),&readfds)) |
|
1154 |
|
1155 #endif |
|
1156 { |
|
1157 if (crlf) |
|
1158 { |
|
1159 int j, lf_num; |
|
1160 i=read(fileno(stdin),cbuf,BUFSIZZ/2); |
|
1161 |
|
1162 lf_num = 0; |
|
1163 /* both loops are skipped when i <= 0 */ |
|
1164 for (j = 0; j < i; j++) |
|
1165 if (cbuf[j] == '\n') |
|
1166 lf_num++; |
|
1167 for (j = i-1; j >= 0; j--) |
|
1168 { |
|
1169 cbuf[j+lf_num] = cbuf[j]; |
|
1170 if (cbuf[j] == '\n') |
|
1171 { |
|
1172 lf_num--; |
|
1173 i++; |
|
1174 cbuf[j+lf_num] = '\r'; |
|
1175 } |
|
1176 } |
|
1177 assert(lf_num == 0); |
|
1178 } |
|
1179 else |
|
1180 i=read(fileno(stdin),cbuf,BUFSIZZ); |
|
1181 |
|
1182 if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) |
|
1183 { |
|
1184 BIO_printf(bio_err,"DONE\n"); |
|
1185 goto shut; |
|
1186 } |
|
1187 |
|
1188 if ((!c_ign_eof) && (cbuf[0] == 'R')) |
|
1189 { |
|
1190 BIO_printf(bio_err,"RENEGOTIATING\n"); |
|
1191 SSL_renegotiate(con); |
|
1192 cbuf_len=0; |
|
1193 } |
|
1194 else |
|
1195 { |
|
1196 cbuf_len=i; |
|
1197 cbuf_off=0; |
|
1198 #ifdef CHARSET_EBCDIC |
|
1199 ebcdic2ascii(cbuf, cbuf, i); |
|
1200 #endif |
|
1201 } |
|
1202 |
|
1203 write_ssl=1; |
|
1204 read_tty=0; |
|
1205 } |
|
1206 } |
|
1207 shut: |
|
1208 SSL_shutdown(con); |
|
1209 SHUTDOWN(SSL_get_fd(con)); |
|
1210 ret=0; |
|
1211 end: |
|
1212 if(prexit) print_stuff(bio_c_out,con,1); |
|
1213 if (con != NULL) SSL_free(con); |
|
1214 if (con2 != NULL) SSL_free(con2); |
|
1215 if (ctx != NULL) SSL_CTX_free(ctx); |
|
1216 if (cert) |
|
1217 X509_free(cert); |
|
1218 if (key) |
|
1219 EVP_PKEY_free(key); |
|
1220 if (pass) |
|
1221 OPENSSL_free(pass); |
|
1222 if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } |
|
1223 if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } |
|
1224 if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } |
|
1225 if (bio_c_out != NULL) |
|
1226 { |
|
1227 BIO_free(bio_c_out); |
|
1228 bio_c_out=NULL; |
|
1229 } |
|
1230 apps_shutdown(); |
|
1231 OPENSSL_EXIT(ret); |
|
1232 } |
|
1233 |
|
1234 |
|
1235 static void print_stuff(BIO *bio, SSL *s, int full) |
|
1236 { |
|
1237 X509 *peer=NULL; |
|
1238 char *p; |
|
1239 static const char *space=" "; |
|
1240 char buf[BUFSIZ]; |
|
1241 STACK_OF(X509) *sk; |
|
1242 STACK_OF(X509_NAME) *sk2; |
|
1243 SSL_CIPHER *c; |
|
1244 X509_NAME *xn; |
|
1245 int j,i; |
|
1246 #ifndef OPENSSL_NO_COMP |
|
1247 const COMP_METHOD *comp, *expansion; |
|
1248 #endif |
|
1249 |
|
1250 if (full) |
|
1251 { |
|
1252 int got_a_chain = 0; |
|
1253 |
|
1254 sk=SSL_get_peer_cert_chain(s); |
|
1255 if (sk != NULL) |
|
1256 { |
|
1257 got_a_chain = 1; /* we don't have it for SSL2 (yet) */ |
|
1258 |
|
1259 BIO_printf(bio,"---\nCertificate chain\n"); |
|
1260 for (i=0; i<sk_X509_num(sk); i++) |
|
1261 { |
|
1262 X509_NAME_oneline(X509_get_subject_name( |
|
1263 sk_X509_value(sk,i)),buf,sizeof buf); |
|
1264 BIO_printf(bio,"%2d s:%s\n",i,buf); |
|
1265 X509_NAME_oneline(X509_get_issuer_name( |
|
1266 sk_X509_value(sk,i)),buf,sizeof buf); |
|
1267 BIO_printf(bio," i:%s\n",buf); |
|
1268 if (c_showcerts) |
|
1269 PEM_write_bio_X509(bio,sk_X509_value(sk,i)); |
|
1270 } |
|
1271 } |
|
1272 |
|
1273 BIO_printf(bio,"---\n"); |
|
1274 peer=SSL_get_peer_certificate(s); |
|
1275 if (peer != NULL) |
|
1276 { |
|
1277 BIO_printf(bio,"Server certificate\n"); |
|
1278 if (!(c_showcerts && got_a_chain)) /* Redundant if we showed the whole chain */ |
|
1279 PEM_write_bio_X509(bio,peer); |
|
1280 X509_NAME_oneline(X509_get_subject_name(peer), |
|
1281 buf,sizeof buf); |
|
1282 BIO_printf(bio,"subject=%s\n",buf); |
|
1283 X509_NAME_oneline(X509_get_issuer_name(peer), |
|
1284 buf,sizeof buf); |
|
1285 BIO_printf(bio,"issuer=%s\n",buf); |
|
1286 } |
|
1287 else |
|
1288 BIO_printf(bio,"no peer certificate available\n"); |
|
1289 |
|
1290 sk2=SSL_get_client_CA_list(s); |
|
1291 if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) |
|
1292 { |
|
1293 BIO_printf(bio,"---\nAcceptable client certificate CA names\n"); |
|
1294 for (i=0; i<sk_X509_NAME_num(sk2); i++) |
|
1295 { |
|
1296 xn=sk_X509_NAME_value(sk2,i); |
|
1297 X509_NAME_oneline(xn,buf,sizeof(buf)); |
|
1298 BIO_write(bio,buf,strlen(buf)); |
|
1299 BIO_write(bio,"\n",1); |
|
1300 } |
|
1301 } |
|
1302 else |
|
1303 { |
|
1304 BIO_printf(bio,"---\nNo client certificate CA names sent\n"); |
|
1305 } |
|
1306 p=SSL_get_shared_ciphers(s,buf,sizeof buf); |
|
1307 if (p != NULL) |
|
1308 { |
|
1309 /* This works only for SSL 2. In later protocol |
|
1310 * versions, the client does not know what other |
|
1311 * ciphers (in addition to the one to be used |
|
1312 * in the current connection) the server supports. */ |
|
1313 |
|
1314 BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n"); |
|
1315 j=i=0; |
|
1316 while (*p) |
|
1317 { |
|
1318 if (*p == ':') |
|
1319 { |
|
1320 BIO_write(bio,space,15-j%25); |
|
1321 i++; |
|
1322 j=0; |
|
1323 BIO_write(bio,((i%3)?" ":"\n"),1); |
|
1324 } |
|
1325 else |
|
1326 { |
|
1327 BIO_write(bio,p,1); |
|
1328 j++; |
|
1329 } |
|
1330 p++; |
|
1331 } |
|
1332 BIO_write(bio,"\n",1); |
|
1333 } |
|
1334 |
|
1335 BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n", |
|
1336 BIO_number_read(SSL_get_rbio(s)), |
|
1337 BIO_number_written(SSL_get_wbio(s))); |
|
1338 } |
|
1339 BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, ")); |
|
1340 c=SSL_get_current_cipher(s); |
|
1341 BIO_printf(bio,"%s, Cipher is %s\n", |
|
1342 SSL_CIPHER_get_version(c), |
|
1343 SSL_CIPHER_get_name(c)); |
|
1344 if (peer != NULL) { |
|
1345 EVP_PKEY *pktmp; |
|
1346 pktmp = X509_get_pubkey(peer); |
|
1347 BIO_printf(bio,"Server public key is %d bit\n", |
|
1348 EVP_PKEY_bits(pktmp)); |
|
1349 EVP_PKEY_free(pktmp); |
|
1350 } |
|
1351 #ifndef OPENSSL_NO_COMP |
|
1352 comp=SSL_get_current_compression(s); |
|
1353 expansion=SSL_get_current_expansion(s); |
|
1354 BIO_printf(bio,"Compression: %s\n", |
|
1355 comp ? SSL_COMP_get_name(comp) : "NONE"); |
|
1356 BIO_printf(bio,"Expansion: %s\n", |
|
1357 expansion ? SSL_COMP_get_name(expansion) : "NONE"); |
|
1358 #endif |
|
1359 SSL_SESSION_print(bio,SSL_get_session(s)); |
|
1360 BIO_printf(bio,"---\n"); |
|
1361 if (peer != NULL) |
|
1362 X509_free(peer); |
|
1363 /* flush, or debugging output gets mixed with http response */ |
|
1364 (void)BIO_flush(bio); |
|
1365 } |
|
1366 |