##一、使用BIO接口 openssl源碼裏s_client也是採用BIO接口 代碼來自http://www.ibm.com/developerworks/cn/linux/l-openssl.html 源代碼裏缺乏SSL_library_init()調用html
#include "openssl/ssl.h" #include "openssl/bio.h" #include "openssl/err.h" #include "stdio.h" #include "string.h" int main(int argc, char* argv[]) { BIO * bio; SSL * ssl; SSL_CTX * ctx; int p; char * request = "GET / HTTP/1.1\x0D\x0AHost: localhost\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A"; char r[1024]; /* Set up the library */ ERR_load_BIO_strings(); SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); /* Set up the SSL context */ ctx = SSL_CTX_new(SSLv23_client_method()); /* Load the trust store */ if(! SSL_CTX_load_verify_locations(ctx, "TrustStore.pem", NULL)) { fprintf(stderr, "Error loading trust store\n"); ERR_print_errors_fp(stderr); SSL_CTX_free(ctx); return 0; } /* Setup the connection */ bio = BIO_new_ssl_connect(ctx); /* Set the SSL_MODE_AUTO_RETRY flag */ BIO_get_ssl(bio, & ssl); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* Create and setup the connection */ BIO_set_conn_hostname(bio, "127.0.0.1:https"); if(BIO_do_connect(bio) <= 0) { fprintf(stderr, "Error attempting to connect\n"); ERR_print_errors_fp(stderr); BIO_free_all(bio); SSL_CTX_free(ctx); return 0; } /* Check the certificate */ if(SSL_get_verify_result(ssl) != X509_V_OK) { fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl)); BIO_free_all(bio); SSL_CTX_free(ctx); return 0; } /* Send the request */ BIO_write(bio, request, strlen(request)); /* Read in the response */ for(;;) { p = BIO_read(bio, r, 1023); if(p <= 0) break; r[p] = 0; printf("%s", r); } /* Close the connection and free the context */ BIO_free_all(bio); SSL_CTX_free(ctx); return 0; }
##二、使用socket 不使用BIO接口,代碼來自http://my.oschina.net/sincoder/blog/127339 發送請求時追加Host: localhost\r\nconnection: close\r\n,不然返回400linux
#include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <openssl/rand.h> #include <openssl/ssl.h> #include <openssl/err.h> // Simple structure to keep track of the handle, and // of what needs to be freed later. typedef struct { int socket; SSL *sslHandle; SSL_CTX *sslContext; } connection; // For this example, we'll be testing on openssl.org #define SERVER "127.0.0.1" #define PORT 443 // Establish a regular tcp connection int tcpConnect () { int error, handle; struct hostent *host; struct sockaddr_in server; host = gethostbyname (SERVER); handle = socket (AF_INET, SOCK_STREAM, 0); if (handle == -1) { perror ("Socket"); handle = 0; } else { server.sin_family = AF_INET; server.sin_port = htons (PORT); server.sin_addr = *((struct in_addr *) host->h_addr); bzero (&(server.sin_zero), 8); error = connect (handle, (struct sockaddr *) &server, sizeof (struct sockaddr)); if (error == -1) { perror ("Connect"); handle = 0; } } return handle; } // Establish a connection using an SSL layer connection *sslConnect (void) { connection *c; c = malloc (sizeof (connection)); c->sslHandle = NULL; c->sslContext = NULL; c->socket = tcpConnect (); if (c->socket) { // Register the error strings for libcrypto & libssl SSL_load_error_strings (); // Register the available ciphers and digests SSL_library_init (); OpenSSL_add_all_algorithms(); // New context saying we are a client, and using SSL 2 or 3 c->sslContext = SSL_CTX_new (SSLv23_client_method ()); if (c->sslContext == NULL) ERR_print_errors_fp (stderr); // Create an SSL struct for the connection c->sslHandle = SSL_new (c->sslContext); if (c->sslHandle == NULL) ERR_print_errors_fp (stderr); // Connect the SSL struct to our connection if (!SSL_set_fd (c->sslHandle, c->socket)) ERR_print_errors_fp (stderr); // Initiate SSL handshake if (SSL_connect (c->sslHandle) != 1) ERR_print_errors_fp (stderr); } else { perror ("Connect failed"); } return c; } // Disconnect & free connection struct void sslDisconnect (connection *c) { if (c->socket) close (c->socket); if (c->sslHandle) { SSL_shutdown (c->sslHandle); SSL_free (c->sslHandle); } if (c->sslContext) SSL_CTX_free (c->sslContext); free (c); } // Read all available text from the connection char *sslRead (connection *c) { const int readSize = 1024; char *rc = NULL; int received, count = 0; char buffer[1024]; if (c) { while (1) { if (!rc) rc = malloc (readSize * sizeof (char) + 1); else rc = realloc (rc, (count + 1) * readSize * sizeof (char) + 1); memset(rc,0,readSize + 1); received = SSL_read (c->sslHandle, buffer, readSize); buffer[received] = '\0'; if (received > 0) strcat (rc, buffer); if (received < readSize) break; count++; } } return rc; } // Write text to the connection void sslWrite (connection *c, char *text) { if (c) SSL_write (c->sslHandle, text, strlen (text)); } // Very basic main: we send GET / and print the response. int main (int argc, char **argv) { connection *c; char *response; c = sslConnect (); sslWrite (c, "GET / HTTP/1.1\r\nHost: localhost\r\nconnection: close\r\n\r\n"); response = sslRead (c); printf ("%s\n", response); sslDisconnect (c); free (response); return 0; }