GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
connection_https.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007, 2008, 2010 Daniel Pittman and Christian Grothoff
4 Copyright (C) 2015-2021 Karlson2k (Evgeny Grin)
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20*/
21
31#include "internal.h"
32#include "connection.h"
33#include "connection_https.h"
34#include "memorypool.h"
35#include "response.h"
36#include "mhd_mono_clock.h"
37#include <gnutls/gnutls.h>
38#include "mhd_send.h"
39
40
50static ssize_t
51recv_tls_adapter (struct MHD_Connection *connection,
52 void *other,
53 size_t i)
54{
55 ssize_t res;
56
57 if (i > SSIZE_MAX)
58 i = SSIZE_MAX;
59
60 res = gnutls_record_recv (connection->tls_session,
61 other,
62 i);
63 if ( (GNUTLS_E_AGAIN == res) ||
64 (GNUTLS_E_INTERRUPTED == res) )
65 {
66#ifdef EPOLL_SUPPORT
67 if (GNUTLS_E_AGAIN == res)
68 connection->epoll_state &=
70#endif
71 /* Any network errors means that buffer is empty. */
72 connection->tls_read_ready = false;
73 return MHD_ERR_AGAIN_;
74 }
75 if (res < 0)
76 {
77 connection->tls_read_ready = false;
78 if ( (GNUTLS_E_DECRYPTION_FAILED == res) ||
79 (GNUTLS_E_INVALID_SESSION == res) ||
80 (GNUTLS_E_DECOMPRESSION_FAILED == res) ||
81 (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER == res) ||
82 (GNUTLS_E_UNSUPPORTED_VERSION_PACKET == res) ||
83 (GNUTLS_E_UNEXPECTED_PACKET_LENGTH == res) ||
84 (GNUTLS_E_UNEXPECTED_PACKET == res) ||
85 (GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET == res) ||
86 (GNUTLS_E_EXPIRED == res) ||
87 (GNUTLS_E_REHANDSHAKE == res) )
88 return MHD_ERR_TLS_;
89 if ( (GNUTLS_E_PULL_ERROR == res) ||
90 (GNUTLS_E_INTERNAL_ERROR == res) ||
91 (GNUTLS_E_CRYPTODEV_IOCTL_ERROR == res) ||
92 (GNUTLS_E_CRYPTODEV_DEVICE_ERROR == res) )
93 return MHD_ERR_PIPE_;
94#if defined(GNUTLS_E_PREMATURE_TERMINATION)
95 if (GNUTLS_E_PREMATURE_TERMINATION == res)
96 return MHD_ERR_CONNRESET_;
97#elif defined(GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
98 if (GNUTLS_E_UNEXPECTED_PACKET_LENGTH == res)
99 return MHD_ERR_CONNRESET_;
100#endif /* GNUTLS_E_UNEXPECTED_PACKET_LENGTH */
101 if (GNUTLS_E_MEMORY_ERROR == res)
102 return MHD_ERR_NOMEM_;
103 /* Treat any other error as a hard error. */
104 return MHD_ERR_NOTCONN_;
105 }
106
107#ifdef EPOLL_SUPPORT
108 /* Unlike non-TLS connections, do not reset "read-ready" if
109 * received amount smaller than provided amount, as TLS
110 * connections may receive data by fixed-size chunks. */
111#endif /* EPOLL_SUPPORT */
112
113 /* Check whether TLS buffers still have some unread data. */
114 connection->tls_read_ready = ( ((size_t) res == i) &&
115 (0 != gnutls_record_check_pending (
116 connection->tls_session)) );
117 return res;
118}
119
120
130bool
132{
133 int ret;
134
135 if ((MHD_TLS_CONN_INIT == connection->tls_state) ||
136 (MHD_TLS_CONN_HANDSHAKING == connection->tls_state))
137 {
138#if 0
139 /* According to real-live testing, Nagel's Algorithm is not blocking
140 * partial packets on just connected sockets on modern OSes. As TLS setup
141 * is performed as the fist action upon socket connection, the next
142 * optimisation typically is not required. If any specific OS will
143 * require this optimization, it could be enabled by allowing the next
144 * lines for this specific OS. */
145 if (_MHD_ON != connection->sk_nodelay)
146 MHD_connection_set_nodelay_state_ (connection, true);
147#endif
148 ret = gnutls_handshake (connection->tls_session);
149 if (ret == GNUTLS_E_SUCCESS)
150 {
151 /* set connection TLS state to enable HTTP processing */
152 connection->tls_state = MHD_TLS_CONN_CONNECTED;
153 MHD_update_last_activity_ (connection);
154 return true;
155 }
156 if ( (GNUTLS_E_AGAIN == ret) ||
157 (GNUTLS_E_INTERRUPTED == ret) )
158 {
159 connection->tls_state = MHD_TLS_CONN_HANDSHAKING;
160 /* handshake not done */
161 return false;
162 }
163 /* handshake failed */
164 connection->tls_state = MHD_TLS_CONN_TLS_FAILED;
165#ifdef HAVE_MESSAGES
166 MHD_DLOG (connection->daemon,
167 _ ("Error: received handshake message out of context.\n"));
168#endif
169 MHD_connection_close_ (connection,
171 return false;
172 }
173 return true;
174}
175
176
183void
185{
186 connection->recv_cls = &recv_tls_adapter;
187}
188
189
196bool
198{
199 if (MHD_TLS_CONN_WR_CLOSED > connection->tls_state)
200 {
201 const int res =
202 gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
203 if (GNUTLS_E_SUCCESS == res)
204 {
205 connection->tls_state = MHD_TLS_CONN_WR_CLOSED;
206 return true;
207 }
208 if ((GNUTLS_E_AGAIN == res) ||
209 (GNUTLS_E_INTERRUPTED == res))
210 {
211 connection->tls_state = MHD_TLS_CONN_WR_CLOSING;
212 return true;
213 }
214 else
215 connection->tls_state = MHD_TLS_CONN_TLS_FAILED;
216 }
217 return false;
218}
219
220
221/* end of connection_https.c */
Methods for managing connections.
#define MHD_ERR_TLS_
Definition connection.h:77
#define MHD_ERR_PIPE_
Definition connection.h:72
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
static ssize_t recv_tls_adapter(struct MHD_Connection *connection, void *other, size_t i)
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
Methods for managing connections.
void MHD_update_last_activity_(struct MHD_Connection *connection)
@ MHD_REQUEST_TERMINATED_WITH_ERROR
#define MHD_ERR_CONNRESET_
Definition internal.h:1868
#define MHD_ERR_NOMEM_
Definition internal.h:1879
MHD_EpollState
Definition internal.h:588
@ MHD_EPOLL_STATE_READ_READY
Definition internal.h:600
#define MHD_ERR_AGAIN_
Definition internal.h:1863
#define MHD_ERR_NOTCONN_
Definition internal.h:1874
#define _(String)
Definition mhd_options.h:42
bool MHD_connection_set_nodelay_state_(struct MHD_Connection *connection, bool nodelay_state)
Definition mhd_send.c:170
Declarations of send() wrappers.
MHD internal shared structures.
@ MHD_TLS_CONN_WR_CLOSING
Definition internal.h:718
@ MHD_TLS_CONN_WR_CLOSED
Definition internal.h:719
@ MHD_TLS_CONN_INIT
Definition internal.h:715
@ MHD_TLS_CONN_TLS_FAILED
Definition internal.h:722
@ MHD_TLS_CONN_CONNECTED
Definition internal.h:717
@ MHD_TLS_CONN_HANDSHAKING
Definition internal.h:716
@ _MHD_ON
Definition internal.h:187
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
#define SSIZE_MAX
Definition mhd_limits.h:113
internal monotonic clock functions implementations
Methods for managing response objects.
enum MHD_tristate sk_nodelay
Definition internal.h:1207
bool tls_read_ready
Definition internal.h:769
ReceiveCallback recv_cls
Definition internal.h:706
struct MHD_Daemon * daemon
Definition internal.h:675