[package] base-files: implement a --force option for sysupgrade to override image...
[openwrt.git] / package / uhttpd / src / uhttpd-tls.c
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
27 static 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
47 static 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
64 void SetCallbackIORecv_Ctx(SSL_CTX*, int (*)(char *, int, void *));
65 void SetCallbackIOSend_Ctx(SSL_CTX*, int (*)(char *, int, void *));
66
67 static 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
75 static 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
82 static 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
108 static 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
122 static 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
132 static 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
140 static void uh_tls_ctx_setup(SSL_CTX *ctx)
141 {
142 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
143 return;
144 }
145
146 static 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
161 SSL_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
174 int 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
184 int 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
194 void uh_tls_ctx_free(struct listener *l)
195 {
196 SSL_CTX_free(l->tls);
197 }
198
199
200 int 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
224 done:
225 return rv;
226
227 cleanup:
228 SSL_free(c->tls);
229 c->tls = NULL;
230 goto done;
231 }
232
233 int 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
239 int 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
245 void 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 }
This page took 0.053511 seconds and 5 git commands to generate.