| #include <u.h> |
| #include <openssl/bio.h> |
| #include <openssl/ssl.h> |
| #include <openssl/err.h> |
| #include "a.h" |
| |
| AUTOLIB(ssl) |
| |
| static void |
| httpsinit(void) |
| { |
| ERR_load_crypto_strings(); |
| ERR_load_SSL_strings(); |
| SSL_load_error_strings(); |
| SSL_library_init(); |
| } |
| |
| struct Pfd |
| { |
| BIO *sbio; |
| }; |
| |
| static Pfd* |
| opensslconnect(char *host) |
| { |
| Pfd *pfd; |
| BIO *sbio; |
| SSL_CTX *ctx; |
| SSL *ssl; |
| static int didinit; |
| char buf[1024]; |
| |
| if(!didinit){ |
| httpsinit(); |
| didinit = 1; |
| } |
| |
| ctx = SSL_CTX_new(SSLv23_client_method()); |
| sbio = BIO_new_ssl_connect(ctx); |
| BIO_get_ssl(sbio, &ssl); |
| SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); |
| |
| snprint(buf, sizeof buf, "%s:https", host); |
| BIO_set_conn_hostname(sbio, buf); |
| |
| if(BIO_do_connect(sbio) <= 0 || BIO_do_handshake(sbio) <= 0){ |
| ERR_error_string_n(ERR_get_error(), buf, sizeof buf); |
| BIO_free_all(sbio); |
| werrstr("openssl: %s", buf); |
| return nil; |
| } |
| |
| pfd = emalloc(sizeof *pfd); |
| pfd->sbio = sbio; |
| return pfd; |
| } |
| |
| static void |
| opensslclose(Pfd *pfd) |
| { |
| if(pfd == nil) |
| return; |
| BIO_free_all(pfd->sbio); |
| free(pfd); |
| } |
| |
| static int |
| opensslwrite(Pfd *pfd, void *v, int n) |
| { |
| int m, total; |
| char *p; |
| |
| p = v; |
| total = 0; |
| while(total < n){ |
| if((m = BIO_write(pfd->sbio, p+total, n-total)) <= 0){ |
| if(total == 0) |
| return m; |
| return total; |
| } |
| total += m; |
| } |
| return total; |
| } |
| |
| static int |
| opensslread(Pfd *pfd, void *v, int n) |
| { |
| return BIO_read(pfd->sbio, v, n); |
| } |
| |
| Protocol https = |
| { |
| opensslconnect, |
| opensslread, |
| opensslwrite, |
| opensslclose |
| }; |