blob: baccd3acd7eb8db99a4b26aa5f624d0a24eb936c [file] [log] [blame]
#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
};