yuezonghe | 824eb0c | 2024-06-27 02:32:26 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved. |
| 3 | * |
| 4 | * Licensed under the OpenSSL license (the "License"). You may not use |
| 5 | * this file except in compliance with the License. You can obtain a copy |
| 6 | * in the file LICENSE in the source distribution or at |
| 7 | * https://www.openssl.org/source/license.html |
| 8 | */ |
| 9 | |
| 10 | /*- |
| 11 | * A minimal program to do SSL to a passed host and port. |
| 12 | * It is actually using non-blocking IO but in a very simple manner |
| 13 | * sconnect host:port - it does a 'GET / HTTP/1.0' |
| 14 | * |
| 15 | * cc -I../../include sconnect.c -L../.. -lssl -lcrypto |
| 16 | */ |
| 17 | #include <stdio.h> |
| 18 | #include <stdlib.h> |
| 19 | #include <unistd.h> |
| 20 | #include <string.h> |
| 21 | #include <errno.h> |
| 22 | #include <openssl/err.h> |
| 23 | #include <openssl/ssl.h> |
| 24 | |
| 25 | #define HOSTPORT "localhost:4433" |
| 26 | #define CAFILE "root.pem" |
| 27 | |
| 28 | int main(int argc, char *argv[]) |
| 29 | { |
| 30 | const char *hostport = HOSTPORT; |
| 31 | const char *CAfile = CAFILE; |
| 32 | char *hostname; |
| 33 | char *cp; |
| 34 | BIO *out = NULL; |
| 35 | char buf[1024 * 10], *p; |
| 36 | SSL_CTX *ssl_ctx = NULL; |
| 37 | SSL *ssl; |
| 38 | BIO *ssl_bio; |
| 39 | int i, len, off, ret = EXIT_FAILURE; |
| 40 | |
| 41 | if (argc > 1) |
| 42 | hostport = argv[1]; |
| 43 | if (argc > 2) |
| 44 | CAfile = argv[2]; |
| 45 | |
| 46 | hostname = OPENSSL_strdup(hostport); |
| 47 | if ((cp = strchr(hostname, ':')) != NULL) |
| 48 | *cp = 0; |
| 49 | |
| 50 | #ifdef WATT32 |
| 51 | dbug_init(); |
| 52 | sock_init(); |
| 53 | #endif |
| 54 | |
| 55 | ssl_ctx = SSL_CTX_new(TLS_client_method()); |
| 56 | |
| 57 | /* Enable trust chain verification */ |
| 58 | SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); |
| 59 | SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL); |
| 60 | |
| 61 | /* Lets make a SSL structure */ |
| 62 | ssl = SSL_new(ssl_ctx); |
| 63 | SSL_set_connect_state(ssl); |
| 64 | |
| 65 | /* Enable peername verification */ |
| 66 | if (SSL_set1_host(ssl, hostname) <= 0) |
| 67 | goto err; |
| 68 | |
| 69 | /* Use it inside an SSL BIO */ |
| 70 | ssl_bio = BIO_new(BIO_f_ssl()); |
| 71 | BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); |
| 72 | |
| 73 | /* Lets use a connect BIO under the SSL BIO */ |
| 74 | out = BIO_new(BIO_s_connect()); |
| 75 | BIO_set_conn_hostname(out, hostport); |
| 76 | BIO_set_nbio(out, 1); |
| 77 | out = BIO_push(ssl_bio, out); |
| 78 | |
| 79 | p = "GET / HTTP/1.0\r\n\r\n"; |
| 80 | len = strlen(p); |
| 81 | |
| 82 | off = 0; |
| 83 | for (;;) { |
| 84 | i = BIO_write(out, &(p[off]), len); |
| 85 | if (i <= 0) { |
| 86 | if (BIO_should_retry(out)) { |
| 87 | fprintf(stderr, "write DELAY\n"); |
| 88 | sleep(1); |
| 89 | continue; |
| 90 | } else { |
| 91 | goto err; |
| 92 | } |
| 93 | } |
| 94 | off += i; |
| 95 | len -= i; |
| 96 | if (len <= 0) |
| 97 | break; |
| 98 | } |
| 99 | |
| 100 | for (;;) { |
| 101 | i = BIO_read(out, buf, sizeof(buf)); |
| 102 | if (i == 0) |
| 103 | break; |
| 104 | if (i < 0) { |
| 105 | if (BIO_should_retry(out)) { |
| 106 | fprintf(stderr, "read DELAY\n"); |
| 107 | sleep(1); |
| 108 | continue; |
| 109 | } |
| 110 | goto err; |
| 111 | } |
| 112 | fwrite(buf, 1, i, stdout); |
| 113 | } |
| 114 | |
| 115 | ret = EXIT_SUCCESS; |
| 116 | goto done; |
| 117 | |
| 118 | err: |
| 119 | if (ERR_peek_error() == 0) { /* system call error */ |
| 120 | fprintf(stderr, "errno=%d ", errno); |
| 121 | perror("error"); |
| 122 | } else { |
| 123 | ERR_print_errors_fp(stderr); |
| 124 | } |
| 125 | done: |
| 126 | BIO_free_all(out); |
| 127 | SSL_CTX_free(ssl_ctx); |
| 128 | return ret; |
| 129 | } |