source: branches/backfire/package/uhttpd/src/uhttpd-tls.c @ 28790

Last change on this file since 28790 was 28790, checked in by jow, 5 years ago

[backfire] merge all uhttpd changes from trunk

File size: 4.7 KB
Line 
1/*
2 * uhttpd - Tiny single-threaded httpd - TLS helper
3 *
4 *   Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
5 *
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
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
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.
17 */
18
19#include "uhttpd.h"
20#include "uhttpd-tls.h"
21#include "uhttpd-utils.h"
22
23#include <syslog.h>
24#define dbg(...) syslog(LOG_INFO, __VA_ARGS__)
25
26#ifdef TLS_IS_CYASSL
27static int uh_cyassl_recv_cb(char *buf, int sz, void *ctx)
28{
29        int rv;
30        int socket = *(int *)ctx;
31        struct client *cl;
32
33        if (!(cl = uh_client_lookup(socket)))
34                return -1; /* unexpected error */
35
36        rv = uh_tcp_recv_lowlevel(cl, buf, sz);
37
38        if (rv < 0)
39                return -4; /* interrupted */
40
41        if (rv == 0)
42                return -5; /* connection closed */
43
44        return rv;
45}
46
47static int uh_cyassl_send_cb(char *buf, int sz, void *ctx)
48{
49        int rv;
50        int socket = *(int *)ctx;
51        struct client *cl;
52
53        if (!(cl = uh_client_lookup(socket)))
54                return -1; /* unexpected error */
55
56        rv = uh_tcp_send_lowlevel(cl, buf, sz);
57
58        if (rv <= 0)
59                return -5; /* connection dead */
60
61        return rv;
62}
63
64void SetCallbackIORecv_Ctx(SSL_CTX*, int (*)(char *, int, void *));
65void SetCallbackIOSend_Ctx(SSL_CTX*, int (*)(char *, int, void *));
66
67static void uh_tls_ctx_setup(SSL_CTX *ctx)
68{
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);
72        return;
73}
74
75static int uh_tls_client_ctx_setup(SSL *ssl, int socket)
76{
77        return SSL_set_fd(ssl, socket);
78}
79#endif /* TLS_IS_CYASSL */
80
81#ifdef TLS_IS_OPENSSL
82static long uh_openssl_bio_ctrl_cb(BIO *b, int cmd, long num, void *ptr)
83{
84        long rv = 1;
85
86        switch (cmd)
87        {
88                case BIO_C_SET_FD:
89                        b->num      = *((int *)ptr);
90                        b->shutdown = (int)num;
91                        b->init     = 1;
92                        break;
93
94                case BIO_C_GET_FD:
95                        if (!b->init)
96                                return -1;
97
98                        if (ptr)
99                                *((int *)ptr) = b->num;
100
101                        rv = b->num;
102                        break;
103        }
104
105        return rv;
106}
107
108static int uh_openssl_bio_read_cb(BIO *b, char *out, int outl)
109{
110        int rv = 0;
111        struct client *cl;
112
113        if (!(cl = uh_client_lookup(b->num)))
114                return -1;
115
116        if (out != NULL)
117                rv = uh_tcp_recv_lowlevel(cl, out, outl);
118
119        return rv;
120}
121
122static int uh_openssl_bio_write_cb(BIO *b, const char *in, int inl)
123{
124        struct client *cl;
125
126        if (!(cl = uh_client_lookup(b->num)))
127                return -1;
128
129        return uh_tcp_send_lowlevel(cl, in, inl);
130}
131
132static BIO_METHOD uh_openssl_bio_methods = {
133        .type   = BIO_TYPE_SOCKET,
134        .name   = "uhsocket",
135        .ctrl   = uh_openssl_bio_ctrl_cb,
136        .bwrite = uh_openssl_bio_write_cb,
137        .bread  = uh_openssl_bio_read_cb
138};
139
140static void uh_tls_ctx_setup(SSL_CTX *ctx)
141{
142        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
143        return;
144}
145
146static int uh_tls_client_ctx_setup(SSL *ssl, int socket)
147{
148        BIO *b;
149
150        if (!(b = BIO_new(&uh_openssl_bio_methods)))
151                return 0;
152
153        BIO_set_fd(b, socket, BIO_NOCLOSE);
154        SSL_set_bio(ssl, b, b);
155
156        return 1;
157}
158#endif /* TLS_IS_OPENSSL */
159
160
161SSL_CTX * uh_tls_ctx_init()
162{
163        SSL_CTX *c;
164
165        SSL_load_error_strings();
166        SSL_library_init();
167
168        if ((c = SSL_CTX_new(TLSv1_server_method())) != NULL)
169                uh_tls_ctx_setup(c);
170
171        return c;
172}
173
174int uh_tls_ctx_cert(SSL_CTX *c, const char *file)
175{
176        int rv;
177
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);
180
181        return rv;
182}
183
184int uh_tls_ctx_key(SSL_CTX *c, const char *file)
185{
186        int rv;
187
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);
190
191        return rv;
192}
193
194void uh_tls_ctx_free(struct listener *l)
195{
196        SSL_CTX_free(l->tls);
197}
198
199
200int uh_tls_client_accept(struct client *c)
201{
202        int rv;
203
204        if( c->server && c->server->tls )
205        {
206                c->tls = SSL_new(c->server->tls);
207                if( c->tls )
208                {
209                        if( (rv = uh_tls_client_ctx_setup(c->tls, c->socket)) < 1 )
210                                goto cleanup;
211
212                        if( (rv = SSL_accept(c->tls)) < 1 )
213                                goto cleanup;
214                }
215                else
216                        rv = 0;
217        }
218        else
219        {
220                c->tls = NULL;
221                rv = 1;
222        }
223
224done:
225        return rv;
226
227cleanup:
228        SSL_free(c->tls);
229        c->tls = NULL;
230        goto done;
231}
232
233int uh_tls_client_recv(struct client *c, void *buf, int len)
234{
235        int rv = SSL_read(c->tls, buf, len);
236        return (rv > 0) ? rv : -1;
237}
238
239int uh_tls_client_send(struct client *c, void *buf, int len)
240{
241        int rv = SSL_write(c->tls, buf, len);
242        return (rv > 0) ? rv : -1;
243}
244
245void uh_tls_client_close(struct client *c)
246{
247        if( c->tls )
248        {
249                SSL_shutdown(c->tls);
250                SSL_free(c->tls);
251
252                c->tls = NULL;
253        }
254}
Note: See TracBrowser for help on using the repository browser.