#include #include #include #include #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 };