2 * uhttpd - Tiny single-threaded httpd - TLS helper
4 * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include "uhttpd-tls.h"
21 #include "uhttpd-utils.h"
24 #define dbg(...) syslog(LOG_INFO, __VA_ARGS__)
27 static int uh_cyassl_recv_cb(char *buf
, int sz
, void *ctx
)
30 int socket
= *(int *)ctx
;
33 if (!(cl
= uh_client_lookup(socket
)))
34 return -1; /* unexpected error */
36 rv
= uh_tcp_recv_lowlevel(cl
, buf
, sz
);
39 return -4; /* interrupted */
42 return -5; /* connection closed */
47 static int uh_cyassl_send_cb(char *buf
, int sz
, void *ctx
)
50 int socket
= *(int *)ctx
;
53 if (!(cl
= uh_client_lookup(socket
)))
54 return -1; /* unexpected error */
56 rv
= uh_tcp_send_lowlevel(cl
, buf
, sz
);
59 return -5; /* connection dead */
64 void SetCallbackIORecv_Ctx(SSL_CTX
*, int (*)(char *, int, void *));
65 void SetCallbackIOSend_Ctx(SSL_CTX
*, int (*)(char *, int, void *));
67 static void uh_tls_ctx_setup(SSL_CTX
*ctx
)
69 SSL_CTX_set_verify(ctx
, SSL_VERIFY_NONE
, NULL
);
70 SetCallbackIORecv_Ctx(ctx
, uh_cyassl_recv_cb
);
71 SetCallbackIOSend_Ctx(ctx
, uh_cyassl_send_cb
);
75 static int uh_tls_client_ctx_setup(SSL
*ssl
, int socket
)
77 return SSL_set_fd(ssl
, socket
);
79 #endif /* TLS_IS_CYASSL */
82 static long uh_openssl_bio_ctrl_cb(BIO
*b
, int cmd
, long num
, void *ptr
)
89 b
->num
= *((int *)ptr
);
90 b
->shutdown
= (int)num
;
99 *((int *)ptr
) = b
->num
;
108 static int uh_openssl_bio_read_cb(BIO
*b
, char *out
, int outl
)
113 if (!(cl
= uh_client_lookup(b
->num
)))
117 rv
= uh_tcp_recv_lowlevel(cl
, out
, outl
);
122 static int uh_openssl_bio_write_cb(BIO
*b
, const char *in
, int inl
)
126 if (!(cl
= uh_client_lookup(b
->num
)))
129 return uh_tcp_send_lowlevel(cl
, in
, inl
);
132 static BIO_METHOD uh_openssl_bio_methods
= {
133 .type
= BIO_TYPE_SOCKET
,
135 .ctrl
= uh_openssl_bio_ctrl_cb
,
136 .bwrite
= uh_openssl_bio_write_cb
,
137 .bread
= uh_openssl_bio_read_cb
140 static void uh_tls_ctx_setup(SSL_CTX
*ctx
)
142 SSL_CTX_set_verify(ctx
, SSL_VERIFY_NONE
, NULL
);
146 static int uh_tls_client_ctx_setup(SSL
*ssl
, int socket
)
150 if (!(b
= BIO_new(&uh_openssl_bio_methods
)))
153 BIO_set_fd(b
, socket
, BIO_NOCLOSE
);
154 SSL_set_bio(ssl
, b
, b
);
158 #endif /* TLS_IS_OPENSSL */
161 SSL_CTX
* uh_tls_ctx_init()
165 SSL_load_error_strings();
168 if ((c
= SSL_CTX_new(TLSv1_server_method())) != NULL
)
174 int uh_tls_ctx_cert(SSL_CTX
*c
, const char *file
)
178 if( (rv
= SSL_CTX_use_certificate_file(c
, file
, SSL_FILETYPE_PEM
)) < 1 )
179 rv
= SSL_CTX_use_certificate_file(c
, file
, SSL_FILETYPE_ASN1
);
184 int uh_tls_ctx_key(SSL_CTX
*c
, const char *file
)
188 if( (rv
= SSL_CTX_use_PrivateKey_file(c
, file
, SSL_FILETYPE_PEM
)) < 1 )
189 rv
= SSL_CTX_use_PrivateKey_file(c
, file
, SSL_FILETYPE_ASN1
);
194 void uh_tls_ctx_free(struct listener
*l
)
196 SSL_CTX_free(l
->tls
);
200 int uh_tls_client_accept(struct client
*c
)
204 if( c
->server
&& c
->server
->tls
)
206 c
->tls
= SSL_new(c
->server
->tls
);
209 if( (rv
= uh_tls_client_ctx_setup(c
->tls
, c
->socket
)) < 1 )
212 if( (rv
= SSL_accept(c
->tls
)) < 1 )
233 int uh_tls_client_recv(struct client
*c
, void *buf
, int len
)
235 int rv
= SSL_read(c
->tls
, buf
, len
);
236 return (rv
> 0) ? rv
: -1;
239 int uh_tls_client_send(struct client
*c
, void *buf
, int len
)
241 int rv
= SSL_write(c
->tls
, buf
, len
);
242 return (rv
> 0) ? rv
: -1;
245 void uh_tls_client_close(struct client
*c
)
249 SSL_shutdown(c
->tls
);