kernel: fq_codel: dont reinit flow state
[openwrt/staging/chunkeey.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 SSL_CTX * uh_tls_ctx_init(void)
27 {
28 SSL_CTX *c;
29
30 SSL_load_error_strings();
31 SSL_library_init();
32
33 #if TLS_IS_OPENSSL
34 if ((c = SSL_CTX_new(SSLv23_server_method())) != NULL)
35 #else
36 if ((c = SSL_CTX_new(TLSv1_server_method())) != NULL)
37 #endif
38 SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
39
40 return c;
41 }
42
43 int uh_tls_ctx_cert(SSL_CTX *c, const char *file)
44 {
45 int rv;
46
47 if( (rv = SSL_CTX_use_certificate_file(c, file, SSL_FILETYPE_PEM)) < 1 )
48 rv = SSL_CTX_use_certificate_file(c, file, SSL_FILETYPE_ASN1);
49
50 return rv;
51 }
52
53 int uh_tls_ctx_key(SSL_CTX *c, const char *file)
54 {
55 int rv;
56
57 if( (rv = SSL_CTX_use_PrivateKey_file(c, file, SSL_FILETYPE_PEM)) < 1 )
58 rv = SSL_CTX_use_PrivateKey_file(c, file, SSL_FILETYPE_ASN1);
59
60 return rv;
61 }
62
63 void uh_tls_ctx_free(struct listener *l)
64 {
65 SSL_CTX_free(l->tls);
66 }
67
68
69 int uh_tls_client_accept(struct client *c)
70 {
71 int rv, err;
72 int fd = c->fd.fd;
73
74 if (!c->server || !c->server->tls)
75 {
76 c->tls = NULL;
77 return 1;
78 }
79
80 if ((c->tls = SSL_new(c->server->tls)))
81 {
82 if ((rv = SSL_set_fd(c->tls, fd)) < 1)
83 {
84 SSL_free(c->tls);
85 c->tls = NULL;
86 }
87 else
88 {
89 while (true)
90 {
91 rv = SSL_accept(c->tls);
92 err = SSL_get_error(c->tls, rv);
93
94 if ((rv != 1) &&
95 (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE))
96 {
97 if (uh_socket_wait(fd, c->server->conf->network_timeout,
98 (err == SSL_ERROR_WANT_WRITE)))
99 {
100 D("TLS: accept(%d) = retry\n", fd);
101 continue;
102 }
103
104 D("TLS: accept(%d) = timeout\n", fd);
105 }
106 else if (rv == 1)
107 {
108 D("TLS: accept(%d) = %p\n", fd, c->tls);
109 return 1;
110 }
111
112 #ifdef TLS_IS_OPENSSL
113 D("TLS: accept(%d) = failed: %s\n",
114 fd, ERR_error_string(ERR_get_error(), NULL));
115 #endif
116
117 SSL_free(c->tls);
118 c->tls = NULL;
119 break;
120 }
121 }
122 }
123
124 return 0;
125 }
126
127 int uh_tls_client_recv(struct client *c, char *buf, int len)
128 {
129 int rv = SSL_read(c->tls, buf, len);
130 int err = SSL_get_error(c->tls, 0);
131
132 if ((rv == -1) && (err == SSL_ERROR_WANT_READ))
133 {
134 D("TLS: recv(%d, %d) = retry\n", c->fd.fd, len);
135 errno = EAGAIN;
136 return -1;
137 }
138
139 D("TLS: recv(%d, %d) = %d\n", c->fd.fd, len, rv);
140 return rv;
141 }
142
143 int uh_tls_client_send(struct client *c, const char *buf, int len)
144 {
145 int rv = SSL_write(c->tls, buf, len);
146 int err = SSL_get_error(c->tls, 0);
147
148 if ((rv == -1) && (err == SSL_ERROR_WANT_WRITE))
149 {
150 D("TLS: send(%d, %d) = retry\n", c->fd.fd, len);
151 errno = EAGAIN;
152 return -1;
153 }
154
155 D("TLS: send(%d, %d) = %d\n", c->fd.fd, len, rv);
156 return rv;
157 }
158
159 void uh_tls_client_close(struct client *c)
160 {
161 if (c->tls)
162 {
163 D("TLS: close(%d)\n", c->fd.fd);
164
165 SSL_shutdown(c->tls);
166 SSL_free(c->tls);
167
168 c->tls = NULL;
169 }
170 }