connection_https.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00029 #include "internal.h"
00030 #include "connection.h"
00031 #include "memorypool.h"
00032 #include "response.h"
00033 #include "reason_phrase.h"
00034
00035
00036 #include "gnutls_int.h"
00037 #include "gnutls_record.h"
00038
00039
00040 #include "gnutls_errors.h"
00041
00052 static void
00053 MHD_tls_connection_close (struct MHD_Connection *connection,
00054 enum MHD_RequestTerminationCode termination_code)
00055 {
00056 MHD__gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
00057 connection->tls_session->internals.read_eof = 1;
00058 MHD_connection_close (connection, termination_code);
00059 }
00060
00071 static int
00072 MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
00073 {
00074 unsigned int timeout;
00075
00076 #if DEBUG_STATES
00077 MHD_DLOG (connection->daemon, "%s: state: %s\n",
00078 __FUNCTION__, MHD_state_to_string (connection->state));
00079 #endif
00080 timeout = connection->daemon->connection_timeout;
00081 if ((connection->socket_fd != -1) && (timeout != 0)
00082 && (time (NULL) - timeout > connection->last_activity))
00083 {
00084 MHD_tls_connection_close (connection,
00085 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
00086 return MHD_NO;
00087 }
00088 switch (connection->state)
00089 {
00090
00091 case MHD_TLS_CONNECTION_INIT:
00092 return MHD_YES;
00093
00094 case MHD_CONNECTION_CLOSED:
00095 if (connection->socket_fd != -1)
00096 MHD_tls_connection_close (connection,
00097 MHD_REQUEST_TERMINATED_COMPLETED_OK);
00098 return MHD_NO;
00099 case MHD_TLS_HANDSHAKE_FAILED:
00100 MHD_tls_connection_close (connection,
00101 MHD_REQUEST_TERMINATED_WITH_ERROR);
00102 return MHD_NO;
00103
00104 default:
00105 return MHD_connection_handle_idle (connection);
00106 }
00107 return MHD_YES;
00108 }
00109
00127 static int
00128 MHD_tls_connection_handle_read (struct MHD_Connection *connection)
00129 {
00130 int ret;
00131 unsigned char msg_type;
00132
00133 connection->last_activity = time (NULL);
00134 if (connection->state == MHD_CONNECTION_CLOSED ||
00135 connection->state == MHD_TLS_HANDSHAKE_FAILED)
00136 return MHD_NO;
00137
00138 #if DEBUG_STATES
00139 MHD_DLOG (connection->daemon, "%s: state: %s\n",
00140 __FUNCTION__, MHD_state_to_string (connection->state));
00141 #endif
00142
00143
00144 if (RECV (connection->socket_fd, &msg_type, 1, MSG_PEEK) == -1)
00145 {
00146 #if HAVE_MESSAGES
00147 MHD_DLOG (connection->daemon, "Failed to peek into TLS content type\n");
00148 #endif
00149 return MHD_NO;
00150 }
00151
00152 switch (msg_type)
00153 {
00154
00155 case GNUTLS_HANDSHAKE:
00156
00157 if (connection->state == MHD_TLS_CONNECTION_INIT ||
00158 connection->state == MHD_TLS_HELLO_REQUEST)
00159 {
00160 ret = MHD__gnutls_handshake (connection->tls_session);
00161 if (ret == 0)
00162 {
00163
00164 connection->state = MHD_CONNECTION_INIT;
00165 break;
00166 }
00167
00168 else
00169 {
00170 #if HAVE_MESSAGES
00171 MHD_DLOG (connection->daemon,
00172 "Error: Handshake has failed (%d)\n", ret);
00173 #endif
00174 connection->state = MHD_TLS_HANDSHAKE_FAILED;
00175 return MHD_NO;
00176 }
00177 }
00178
00179 else
00180 {
00181 #if HAVE_MESSAGES
00182 MHD_DLOG (connection->daemon,
00183 "Error: received handshake message out of context\n");
00184 #endif
00185 MHD_tls_connection_close (connection,
00186 MHD_REQUEST_TERMINATED_WITH_ERROR);
00187 return MHD_NO;
00188 }
00189
00190
00191 case GNUTLS_CHANGE_CIPHER_SPEC:
00192 MHD_tls_connection_close (connection,
00193 MHD_REQUEST_TERMINATED_WITH_ERROR);
00194 return MHD_NO;
00195
00196 case GNUTLS_ALERT:
00197
00198
00199
00200
00201 MHD_gtls_recv_int (connection->tls_session, GNUTLS_ALERT,
00202 GNUTLS_HANDSHAKE_FINISHED, 0, 0);
00203
00204
00205 if (connection->tls_session->internals.last_alert ==
00206 GNUTLS_A_CLOSE_NOTIFY)
00207 {
00208 connection->state = MHD_CONNECTION_CLOSED;
00209 return MHD_YES;
00210 }
00211
00212 else if (connection->tls_session->internals.last_alert_level !=
00213 GNUTLS_AL_FATAL)
00214 {
00215 #if HAVE_MESSAGES
00216 MHD_DLOG (connection->daemon,
00217 "Received TLS alert: %s\n",
00218 MHD__gnutls_alert_get_name ((int)
00219 connection->tls_session->
00220 internals.last_alert));
00221 #endif
00222 return MHD_YES;
00223 }
00224
00225 else if (connection->tls_session->internals.last_alert_level ==
00226 GNUTLS_AL_FATAL)
00227 {
00228 MHD_tls_connection_close (connection,
00229 MHD_REQUEST_TERMINATED_WITH_ERROR);
00230 return MHD_NO;
00231 }
00232
00233 else
00234 {
00235 #if HAVE_MESSAGES
00236 MHD_DLOG (connection->daemon,
00237 "Received unrecognized alert: %d\n",
00238 connection->tls_session->internals.last_alert);
00239 #endif
00240 return MHD_NO;
00241 }
00242
00243
00244
00245 case GNUTLS_APPLICATION_DATA:
00246 return MHD_connection_handle_read (connection);
00247
00248 case GNUTLS_INNER_APPLICATION:
00249 break;
00250 default:
00251 #if HAVE_MESSAGES
00252 MHD_DLOG (connection->daemon,
00253 "Error: unrecognized TLS message type: %d, connection state: %s. l: %d, f: %s\n",
00254 msg_type, MHD_state_to_string (connection->state), __LINE__,
00255 __FUNCTION__);
00256 #endif
00257
00258 MHD_tls_connection_close (connection,
00259 MHD_REQUEST_TERMINATED_WITH_ERROR);
00260 return MHD_NO;
00261 }
00262
00263 return MHD_YES;
00264 }
00265
00275 static int
00276 MHD_tls_connection_handle_write (struct MHD_Connection *connection)
00277 {
00278 connection->last_activity = time (NULL);
00279
00280 #if DEBUG_STATES
00281 MHD_DLOG (connection->daemon, "%s: state: %s\n",
00282 __FUNCTION__, MHD_state_to_string (connection->state));
00283 #endif
00284
00285 switch (connection->state)
00286 {
00287 case MHD_CONNECTION_CLOSED:
00288 case MHD_TLS_HANDSHAKE_FAILED:
00289 return MHD_NO;
00290
00291 default:
00292 return MHD_connection_handle_write (connection);
00293 }
00294 return MHD_NO;
00295 }
00296
00301 void
00302 MHD_set_https_calbacks (struct MHD_Connection *connection)
00303 {
00304 connection->read_handler = &MHD_tls_connection_handle_read;
00305 connection->write_handler = &MHD_tls_connection_handle_write;
00306 connection->idle_handler = &MHD_tls_connection_handle_idle;
00307 }
00308
00309