4 Copyright (C) 2010 Fedor Kozhevnikov
6 Licensed under GNU GPL v2 or later
20 #include <openssl/rsa.h>
21 #include <openssl/crypto.h>
22 #include <openssl/x509.h>
23 #include <openssl/pem.h>
24 #include <openssl/ssl.h>
25 #include <openssl/err.h>
28 #define _dprintf(args...) while (0) {}
37 static inline void mssl_cleanup(int err
)
39 if (err
) ERR_print_errors_fp(stderr
);
44 static ssize_t
mssl_read(void *cookie
, char *buf
, size_t len
)
46 _dprintf("%s()\n", __FUNCTION__
);
48 mssl_cookie_t
*kuki
= cookie
;
53 n
= SSL_read(kuki
->ssl
, &(buf
[total
]), len
- total
);
54 _dprintf("SSL_read(max=%d) returned %d\n", len
- total
, n
);
56 err
= SSL_get_error(kuki
->ssl
, n
);
61 case SSL_ERROR_ZERO_RETURN
:
64 case SSL_ERROR_WANT_WRITE
:
65 case SSL_ERROR_WANT_READ
:
68 _dprintf("%s(): SSL error %d\n", __FUNCTION__
, err
);
69 ERR_print_errors_fp(stderr
);
72 } while (SSL_pending(kuki
->ssl
));
75 _dprintf("%s() returns %d\n", __FUNCTION__
, total
);
79 static ssize_t
mssl_write(void *cookie
, const char *buf
, size_t len
)
81 _dprintf("%s()\n", __FUNCTION__
);
83 mssl_cookie_t
*kuki
= cookie
;
88 n
= SSL_write(kuki
->ssl
, &(buf
[total
]), len
- total
);
89 _dprintf("SSL_write(max=%d) returned %d\n", len
- total
, n
);
91 err
= SSL_get_error(kuki
->ssl
, n
);
96 case SSL_ERROR_ZERO_RETURN
:
99 case SSL_ERROR_WANT_WRITE
:
100 case SSL_ERROR_WANT_READ
:
103 _dprintf("%s(): SSL error %d\n", __FUNCTION__
, err
);
104 ERR_print_errors_fp(stderr
);
110 _dprintf("%s() returns %d\n", __FUNCTION__
, total
);
114 static int mssl_seek(void *cookie
, __offmax_t
*pos
, int whence
)
116 _dprintf("%s()\n", __FUNCTION__
);
121 static int mssl_close(void *cookie
)
123 _dprintf("%s()\n", __FUNCTION__
);
125 mssl_cookie_t
*kuki
= cookie
;
129 SSL_shutdown(kuki
->ssl
);
137 static const cookie_io_functions_t mssl
= {
138 mssl_read
, mssl_write
, mssl_seek
, mssl_close
141 static FILE *_ssl_fopen(int sd
, int client
)
147 _dprintf("%s()\n", __FUNCTION__
);
149 if ((kuki
= calloc(1, sizeof(*kuki
))) == NULL
) {
155 if ((kuki
->ssl
= SSL_new(ctx
)) == NULL
) {
156 _dprintf("%s: SSL_new failed\n", __FUNCTION__
);
160 SSL_set_fd(kuki
->ssl
, kuki
->sd
);
161 SSL_set_verify(kuki
->ssl
, SSL_VERIFY_NONE
, NULL
);
162 SSL_set_mode(kuki
->ssl
, SSL_MODE_AUTO_RETRY
);
164 r
= client
? SSL_connect(kuki
->ssl
) : SSL_accept(kuki
->ssl
);
166 _dprintf("%s: SSL handshake failed\n", __FUNCTION__
);
167 ERR_print_errors_fp(stderr
);
171 _dprintf("SSL connection using %s cipher\n", SSL_get_cipher(kuki
->ssl
));
173 if ((f
= fopencookie(kuki
, "r+", mssl
)) == NULL
) {
174 _dprintf("%s: fopencookie failed\n", __FUNCTION__
);
184 FILE *ssl_server_fopen(int sd
)
186 _dprintf("%s()\n", __FUNCTION__
);
187 return _ssl_fopen(sd
, 0);
190 FILE *ssl_client_fopen(int sd
)
192 _dprintf("%s()\n", __FUNCTION__
);
193 return _ssl_fopen(sd
, 1);
196 int mssl_init(char *cert
, char *priv
)
198 int client
= (cert
== NULL
);
200 _dprintf("%s()\n", __FUNCTION__
);
202 SSL_load_error_strings();
203 SSLeay_add_ssl_algorithms();
205 ctx
= SSL_CTX_new(client
? SSLv23_client_method() : SSLv23_server_method());
207 _dprintf("SSL_CTX_new() failed\n");
208 ERR_print_errors_fp(stderr
);
213 _dprintf("SSL_CTX_use_certificate_file(%s)\n", cert
);
214 if (SSL_CTX_use_certificate_file(ctx
, cert
, SSL_FILETYPE_PEM
) <= 0) {
215 _dprintf("SSL_CTX_use_certificate_file() failed\n");
221 _dprintf("SSL_CTX_use_PrivateKey_file(%s)\n", priv
);
222 if (SSL_CTX_use_PrivateKey_file(ctx
, priv
, SSL_FILETYPE_PEM
) <= 0) {
223 _dprintf("SSL_CTX_use_PrivateKey_file() failed\n");
227 if (!SSL_CTX_check_private_key(ctx
)) {
228 _dprintf("Private key does not match the certificate public key\n");
234 _dprintf("%s() success\n", __FUNCTION__
);