1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
#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
};
|