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
00051 const union MHD_ConnectionInfo *
00052 MHD_get_connection_info (struct MHD_Connection *connection,
00053 enum MHD_ConnectionInfoType infoType, ...)
00054 {
00055 if (connection->tls_session == NULL)
00056 return NULL;
00057 switch (infoType)
00058 {
00059 #if HTTPS_SUPPORT
00060 case MHD_CONNECTION_INFO_CIPHER_ALGO:
00061 return (const union MHD_ConnectionInfo *) &connection->tls_session->
00062 security_parameters.read_bulk_cipher_algorithm;
00063 case MHD_CONNECTION_INFO_KX_ALGO:
00064 return (const union MHD_ConnectionInfo *) &connection->tls_session->
00065 security_parameters.kx_algorithm;
00066 case MHD_CONNECTION_INFO_CREDENTIALS_TYPE:
00067 return (const union MHD_ConnectionInfo *) &connection->tls_session->
00068 key->cred->algorithm;
00069 case MHD_CONNECTION_INFO_MAC_ALGO:
00070 return (const union MHD_ConnectionInfo *) &connection->tls_session->
00071 security_parameters.read_mac_algorithm;
00072 case MHD_CONNECTION_INFO_COMPRESSION_METHOD:
00073 return (const union MHD_ConnectionInfo *) &connection->tls_session->
00074 security_parameters.read_compression_algorithm;
00075 case MHD_CONNECTION_INFO_PROTOCOL:
00076 return (const union MHD_ConnectionInfo *) &connection->tls_session->
00077 security_parameters.version;
00078 case MHD_CONNECTION_INFO_CERT_TYPE:
00079 return (const union MHD_ConnectionInfo *) &connection->tls_session->
00080 security_parameters.cert_type;
00081 #endif
00082 default:
00083 return NULL;
00084 };
00085 }
00086
00097 static void
00098 MHD_tls_connection_close (struct MHD_Connection *connection,
00099 enum MHD_RequestTerminationCode termination_code)
00100 {
00101 MHD__gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
00102 connection->tls_session->internals.read_eof = 1;
00103 MHD_connection_close(connection,
00104 termination_code);
00105 }
00106
00117 static int
00118 MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
00119 {
00120 unsigned int timeout;
00121
00122 #if DEBUG_STATES
00123 MHD_DLOG (connection->daemon, "%s: state: %s\n",
00124 __FUNCTION__, MHD_state_to_string (connection->state));
00125 #endif
00126 timeout = connection->daemon->connection_timeout;
00127 if ((connection->socket_fd != -1) && (timeout != 0)
00128 && (time (NULL) - timeout > connection->last_activity))
00129 {
00130 MHD_tls_connection_close (connection,
00131 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
00132 return MHD_NO;
00133 }
00134 switch (connection->state)
00135 {
00136
00137 case MHD_TLS_CONNECTION_INIT:
00138 return MHD_YES;
00139
00140 case MHD_CONNECTION_CLOSED:
00141 if (connection->socket_fd != -1)
00142 MHD_tls_connection_close (connection,
00143 MHD_REQUEST_TERMINATED_COMPLETED_OK);
00144 return MHD_NO;
00145 case MHD_TLS_HANDSHAKE_FAILED:
00146 MHD_tls_connection_close (connection,
00147 MHD_REQUEST_TERMINATED_WITH_ERROR);
00148 return MHD_NO;
00149
00150 default:
00151 return MHD_connection_handle_idle (connection);
00152 }
00153 return MHD_YES;
00154 }
00155
00173 static int
00174 MHD_tls_connection_handle_read (struct MHD_Connection *connection)
00175 {
00176 int ret;
00177 unsigned char msg_type;
00178
00179 connection->last_activity = time (NULL);
00180 if (connection->state == MHD_CONNECTION_CLOSED ||
00181 connection->state == MHD_TLS_HANDSHAKE_FAILED)
00182 return MHD_NO;
00183
00184 #if DEBUG_STATES
00185 MHD_DLOG (connection->daemon, "%s: state: %s\n",
00186 __FUNCTION__, MHD_state_to_string (connection->state));
00187 #endif
00188
00189
00190 if (RECV (connection->socket_fd, &msg_type, 1, MSG_PEEK) == -1)
00191 {
00192 #if HAVE_MESSAGES
00193 MHD_DLOG (connection->daemon, "Failed to peek into TLS content type\n");
00194 #endif
00195 return MHD_NO;
00196 }
00197
00198 switch (msg_type)
00199 {
00200
00201 case GNUTLS_HANDSHAKE:
00202
00203 if (connection->state == MHD_TLS_CONNECTION_INIT ||
00204 connection->state == MHD_TLS_HELLO_REQUEST)
00205 {
00206 ret = MHD__gnutls_handshake (connection->tls_session);
00207 if (ret == 0)
00208 {
00209
00210 connection->state = MHD_CONNECTION_INIT;
00211 break;
00212 }
00213
00214 else
00215 {
00216 #if HAVE_MESSAGES
00217 MHD_DLOG (connection->daemon,
00218 "Error: Handshake has failed (%d)\n", ret);
00219 #endif
00220 connection->state = MHD_TLS_HANDSHAKE_FAILED;
00221 return MHD_NO;
00222 }
00223 }
00224
00225 else
00226 {
00227 #if HAVE_MESSAGES
00228 MHD_DLOG (connection->daemon,
00229 "Error: received handshake message out of context\n");
00230 #endif
00231 MHD_tls_connection_close (connection,
00232 MHD_REQUEST_TERMINATED_WITH_ERROR);
00233 return MHD_NO;
00234 }
00235
00236
00237 case GNUTLS_CHANGE_CIPHER_SPEC:
00238 MHD_tls_connection_close (connection,
00239 MHD_REQUEST_TERMINATED_WITH_ERROR);
00240 return MHD_NO;
00241
00242 case GNUTLS_ALERT:
00243
00244
00245
00246
00247 MHD_gtls_recv_int (connection->tls_session, GNUTLS_ALERT,
00248 GNUTLS_HANDSHAKE_FINISHED, 0, 0);
00249
00250
00251 if (connection->tls_session->internals.last_alert ==
00252 GNUTLS_A_CLOSE_NOTIFY)
00253 {
00254 connection->state = MHD_CONNECTION_CLOSED;
00255 return MHD_YES;
00256 }
00257
00258 else if (connection->tls_session->internals.last_alert_level !=
00259 GNUTLS_AL_FATAL)
00260 {
00261 #if HAVE_MESSAGES
00262 MHD_DLOG (connection->daemon,
00263 "Received TLS alert: %s\n",
00264 MHD__gnutls_alert_get_name ((int) connection->
00265 tls_session->internals.
00266 last_alert));
00267 #endif
00268 return MHD_YES;
00269 }
00270
00271 else if (connection->tls_session->internals.last_alert_level ==
00272 GNUTLS_AL_FATAL)
00273 {
00274 MHD_tls_connection_close (connection,
00275 MHD_REQUEST_TERMINATED_WITH_ERROR);
00276 return MHD_NO;
00277 }
00278
00279 else
00280 {
00281 #if HAVE_MESSAGES
00282 MHD_DLOG (connection->daemon,
00283 "Received unrecognized alert: %d\n",
00284 connection->tls_session->internals.last_alert);
00285 #endif
00286 return MHD_NO;
00287 }
00288
00289
00290
00291 case GNUTLS_APPLICATION_DATA:
00292 return MHD_connection_handle_read (connection);
00293
00294 case GNUTLS_INNER_APPLICATION:
00295 break;
00296 default:
00297 #if HAVE_MESSAGES
00298 MHD_DLOG (connection->daemon,
00299 "Error: unrecognized TLS message type: %d, connection state: %s. l: %d, f: %s\n",
00300 msg_type, MHD_state_to_string (connection->state), __LINE__,
00301 __FUNCTION__);
00302 #endif
00303
00304 MHD_tls_connection_close (connection,
00305 MHD_REQUEST_TERMINATED_WITH_ERROR);
00306 return MHD_NO;
00307 }
00308
00309 return MHD_YES;
00310 }
00311
00321 static int
00322 MHD_tls_connection_handle_write (struct MHD_Connection *connection)
00323 {
00324 connection->last_activity = time (NULL);
00325
00326 #if DEBUG_STATES
00327 MHD_DLOG (connection->daemon, "%s: state: %s\n",
00328 __FUNCTION__, MHD_state_to_string (connection->state));
00329 #endif
00330
00331 switch (connection->state)
00332 {
00333 case MHD_CONNECTION_CLOSED:
00334 case MHD_TLS_HANDSHAKE_FAILED:
00335 return MHD_NO;
00336
00337 default:
00338 return MHD_connection_handle_write (connection);
00339 }
00340 return MHD_NO;
00341 }
00342
00347 void
00348 MHD_set_https_calbacks (struct MHD_Connection *connection)
00349 {
00350 connection->read_handler = &MHD_tls_connection_handle_read;
00351 connection->write_handler = &MHD_tls_connection_handle_write;
00352 connection->idle_handler = &MHD_tls_connection_handle_idle;
00353 }
00354
00355