GNU libmicrohttpd  0.9.72
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 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
29 #include "internal.h"
30 #include "connection.h"
31 #include "connection_https.h"
32 #include "memorypool.h"
33 #include "response.h"
34 #include "mhd_mono_clock.h"
35 #include <gnutls/gnutls.h>
36 
37 
47 static ssize_t
48 recv_tls_adapter (struct MHD_Connection *connection,
49  void *other,
50  size_t i)
51 {
52  ssize_t res;
53 
54  if (i > SSIZE_MAX)
55  i = SSIZE_MAX;
56 
57  res = gnutls_record_recv (connection->tls_session,
58  other,
59  i);
60  if ( (GNUTLS_E_AGAIN == res) ||
61  (GNUTLS_E_INTERRUPTED == res) )
62  {
63 #ifdef EPOLL_SUPPORT
64  if (GNUTLS_E_AGAIN == res)
65  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
66 #endif
67  /* Any network errors means that buffer is empty. */
68  connection->tls_read_ready = false;
69  return MHD_ERR_AGAIN_;
70  }
71  if (res < 0)
72  {
73  /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication
74  disrupted); interpret as a hard error */
75  connection->tls_read_ready = false;
76  return MHD_ERR_NOTCONN_;
77  }
78 
79 #ifdef EPOLL_SUPPORT
80  /* Unlike non-TLS connections, do not reset "read-ready" if
81  * received amount smaller than provided amount, as TLS
82  * connections may receive data by fixed-size chunks. */
83 #endif /* EPOLL_SUPPORT */
84 
85  /* Check whether TLS buffers still have some unread data. */
86  connection->tls_read_ready = ( ((size_t) res == i) &&
87  (0 != gnutls_record_check_pending (
88  connection->tls_session)) );
89  return res;
90 }
91 
92 
102 bool
104 {
105  int ret;
106 
107  if ((MHD_TLS_CONN_INIT == connection->tls_state) ||
108  (MHD_TLS_CONN_HANDSHAKING == connection->tls_state))
109  {
110  ret = gnutls_handshake (connection->tls_session);
111  if (ret == GNUTLS_E_SUCCESS)
112  {
113  /* set connection TLS state to enable HTTP processing */
114  connection->tls_state = MHD_TLS_CONN_CONNECTED;
115  MHD_update_last_activity_ (connection);
116  return true;
117  }
118  if ( (GNUTLS_E_AGAIN == ret) ||
119  (GNUTLS_E_INTERRUPTED == ret) )
120  {
121  connection->tls_state = MHD_TLS_CONN_HANDSHAKING;
122  /* handshake not done */
123  return false;
124  }
125  /* handshake failed */
126  connection->tls_state = MHD_TLS_CONN_TLS_FAILED;
127 #ifdef HAVE_MESSAGES
128  MHD_DLOG (connection->daemon,
129  _ ("Error: received handshake message out of context.\n"));
130 #endif
131  MHD_connection_close_ (connection,
133  return false;
134  }
135  return true;
136 }
137 
138 
145 void
147 {
148  connection->recv_cls = &recv_tls_adapter;
149 }
150 
151 
158 bool
160 {
161  if (MHD_TLS_CONN_WR_CLOSED > connection->tls_state)
162  {
163  const int res =
164  gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
165  if (GNUTLS_E_SUCCESS == res)
166  {
167  connection->tls_state = MHD_TLS_CONN_WR_CLOSED;
168  return true;
169  }
170  if ((GNUTLS_E_AGAIN == res) ||
171  (GNUTLS_E_INTERRUPTED == res))
172  {
173  connection->tls_state = MHD_TLS_CONN_WR_CLOSING;
174  return true;
175  }
176  else
177  connection->tls_state = MHD_TLS_CONN_TLS_FAILED;
178  }
179  return false;
180 }
181 
182 
183 /* end of connection_https.c */
Methods for managing connections.
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
Definition: microhttpd.h:1846
@ 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
internal shared structures
@ MHD_TLS_CONN_WR_CLOSING
Definition: internal.h:598
@ MHD_TLS_CONN_WR_CLOSED
Definition: internal.h:599
@ MHD_TLS_CONN_INIT
Definition: internal.h:595
@ MHD_TLS_CONN_TLS_FAILED
Definition: internal.h:602
@ MHD_TLS_CONN_CONNECTED
Definition: internal.h:597
@ MHD_TLS_CONN_HANDSHAKING
Definition: internal.h:596
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
#define SSIZE_MAX
Definition: mhd_limits.h:111
internal monotonic clock functions implementations
Methods for managing response objects.
bool tls_read_ready
Definition: internal.h:769
ReceiveCallback recv_cls
Definition: internal.h:706
struct MHD_Daemon * daemon
Definition: internal.h:675