pike.git / lib / modules / SSL.pmod / Connection.pike

version» Context lines:

pike.git/lib/modules/SSL.pmod/Connection.pike:525:    return 0;   }      //! Do handshake processing. Type is one of HANDSHAKE_*, data is the   //! contents of the packet, and raw is the raw packet received (needed   //! for supporting SSLv2 hello messages).   //!   //! This function returns 0 if handshake is in progress, 1 if handshake   //! is finished, and -1 if a fatal error occurred. It uses the   //! send_packet() function to transmit packets. - int(-1..1) handle_handshake(int type, string(0..255) data, string(0..255) raw) - { -  ADT.struct input = ADT.struct(data); - #ifdef SSL3_PROFILING -  addRecord(type,0); - #endif - #ifdef SSL3_DEBUG_HANDSHAKE_STATE -  werror("SSL.handshake: state %s, type %s\n", -  fmt_constant(handshake_state, "STATE"), -  fmt_constant(type, "HANDSHAKE")); -  werror("sizeof(data)="+sizeof(data)+"\n"); - #endif + int(-1..1) handle_handshake(int type, string(0..255) data, string(0..255) raw);    -  switch(handshake_state) -  { -  default: -  error( "Internal error\n" ); -  case STATE_server_wait_for_hello: -  { -  array(int) cipher_suites; -  -  /* Reset all extra state variables */ -  expect_change_cipher = certificate_state = 0; -  ke = 0; -  -  handshake_messages = raw; -  -  -  // The first four bytes of the client_random is specified to be -  // the timestamp on the client side. This is to guard against bad -  // random generators, where a client could produce the same -  // random numbers if the seed is reused. This argument is flawed, -  // since a broken random generator will make the connection -  // insecure anyways. The standard explicitly allows these bytes -  // to not be correct, so sending random data instead is safer and -  // reduces client fingerprinting. -  server_random = context->random(32); -  -  switch(type) -  { -  default: -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Expected client_hello.\n")); -  return -1; -  case HANDSHAKE_client_hello: -  { -  string id; -  int cipher_len; -  array(int) cipher_suites; -  array(int) compression_methods; -  -  SSL3_DEBUG_MSG("SSL.handshake: CLIENT_HELLO\n"); -  -  if ( -  catch{ -  client_version = -  [int(0x300..0x300)|ProtocolVersion]input->get_uint(2); -  client_random = input->get_fix_string(32); -  id = input->get_var_string(1); -  cipher_len = input->get_uint(2); -  cipher_suites = input->get_fix_uint_array(2, cipher_len/2); -  compression_methods = input->get_var_uint_array(1, 1); -  SSL3_DEBUG_MSG("STATE_server_wait_for_hello: received hello\n" -  "version = %s\n" -  "id=%O\n" -  "cipher suites:\n%s\n" -  "compression methods: %O\n", -  fmt_version(client_version), -  id, .Constants.fmt_cipher_suites(cipher_suites), -  compression_methods); -  -  } -  || (cipher_len & 1)) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Invalid client_hello.\n")); -  return -1; -  } -  if (((client_version & ~0xff) != PROTOCOL_SSL_3_0) || -  (client_version < context->min_version)) { -  SSL3_DEBUG_MSG("Unsupported version of SSL: %s.\n", -  fmt_version(client_version)); -  send_packet(Alert(ALERT_fatal, ALERT_protocol_version, -  "Unsupported version.\n")); -  return -1; -  } -  if (client_version > version) { -  SSL3_DEBUG_MSG("Falling back client from %s to %s.\n", -  fmt_version(client_version), -  fmt_version(version)); -  } else if (version > client_version) { -  SSL3_DEBUG_MSG("Falling back server from %s to %s.\n", -  fmt_version(version), -  fmt_version(client_version)); -  version = client_version; -  } -  -  ADT.struct extensions; -  if (!input->is_empty()) { -  extensions = ADT.struct(input->get_var_string(2)); -  } -  - #ifdef SSL3_DEBUG -  if (!input->is_empty()) -  werror("SSL.handshake->handle_handshake: " -  "extra data in hello message ignored\n"); -  -  if (sizeof(id)) -  werror("SSL.handshake: Looking up session %O\n", id); - #endif -  session = sizeof(id) && context->lookup_session(id); -  if (session && -  has_value(cipher_suites, session->cipher_suite) && -  has_value(compression_methods, session->compression_algorithm)) { -  // SSL3 5.6.1.2: -  // If the session_id field is not empty (implying a session -  // resumption request) this vector [cipher_suites] must -  // include at least the cipher_suite from that session. -  // ... -  // If the session_id field is not empty (implying a session -  // resumption request) this vector [compression_methods] -  // must include at least the compression_method from -  // that session. -  SSL3_DEBUG_MSG("SSL.handshake: Reusing session %O\n", id); -  /* Reuse session */ -  reuse = 1; -  } else { -  session = context->new_session(); -  reuse = 0; -  } -  -  int missing_secure_renegotiation = secure_renegotiation; -  if (extensions) { -  int maybe_safari_10_8 = 1; -  while (!extensions->is_empty()) { -  int extension_type = extensions->get_uint(2); -  string(8bit) raw = extensions->get_var_string(2); -  ADT.struct extension_data = ADT.struct(raw); -  SSL3_DEBUG_MSG("SSL.handshake->handle_handshake: " -  "Got extension %s.\n", -  fmt_constant(extension_type, "EXTENSION")); -  remote_extensions[extension_type] = 1; -  extensions: -  switch(extension_type) { -  case EXTENSION_signature_algorithms: -  if (!remote_extensions[EXTENSION_ec_point_formats] || -  (raw != "\0\12\5\1\4\1\2\1\4\3\2\3") || -  (client_version != PROTOCOL_TLS_1_2)) { -  maybe_safari_10_8 = 0; -  } -  // RFC 5246 -  string bytes = extension_data->get_var_string(2); -  // Pairs of <hash_alg, signature_alg>. -  session->signature_algorithms = ((array(int))bytes)/2; -  SSL3_DEBUG_MSG("New signature_algorithms:\n"+ -  fmt_signature_pairs(session->signature_algorithms)); -  break; -  case EXTENSION_elliptic_curves: -  if (!remote_extensions[EXTENSION_server_name] || -  (raw != "\0\6\0\x17\0\x18\0\x19")) { -  maybe_safari_10_8 = 0; -  } -  int sz = extension_data->get_uint(2)/2; -  session->ecc_curves = -  filter(reverse(sort(extension_data->get_fix_uint_array(2, sz))), -  ECC_CURVES); -  SSL3_DEBUG_MSG("Elliptic curves: %O\n", -  map(session->ecc_curves, fmt_constant, "CURVE")); -  break; -  case EXTENSION_ec_point_formats: -  if (!remote_extensions[EXTENSION_elliptic_curves] || -  (raw != "\1\0")) { -  maybe_safari_10_8 = 0; -  } -  array(int) ecc_point_formats = -  extension_data->get_var_uint_array(1, 1); -  // NB: We only support the uncompressed point format for now. -  if (has_value(ecc_point_formats, POINT_uncompressed)) { -  session->ecc_point_format = POINT_uncompressed; -  } else { -  // Not a supported point format. -  session->ecc_point_format = -1; -  } -  SSL3_DEBUG_MSG("Elliptic point format: %O\n", -  session->ecc_point_format); -  break; -  case EXTENSION_server_name: -  if (sizeof(remote_extensions) != 1) { -  maybe_safari_10_8 = 0; -  } -  // RFC 4366 3.1 "Server Name Indication" -  // Example: "\0\f\0\0\tlocalhost" -  session->server_names = ({}); -  while (!extension_data->is_empty()) { -  ADT.struct server_name = -  ADT.struct(extension_data->get_var_string(2)); -  switch(server_name->get_uint(1)) { // name_type -  case 0: // host_name -  session->server_names += ({ server_name->get_var_string(2) }); -  break; -  default: -  // Ignore other NameTypes for now. -  break; -  } -  } -  SSL3_DEBUG_MSG("SNI extension: %O\n", session->server_names); -  break; -  case EXTENSION_max_fragment_length: -  // RFC 3546 3.2 "Maximum Fragment Length Negotiation" -  int mfsz = !extension_data->is_empty() && -  extension_data->get_uint(1); -  if (!extension_data->is_empty()) mfsz = 0; -  switch(mfsz) { -  case FRAGMENT_512: session->max_packet_size = 512; break; -  case FRAGMENT_1024: session->max_packet_size = 1024; break; -  case FRAGMENT_2048: session->max_packet_size = 2048; break; -  case FRAGMENT_4096: session->max_packet_size = 4096; break; -  default: -  send_packet(Alert(ALERT_fatal, ALERT_illegal_parameter, -  "Invalid fragment size.\n")); -  return -1; -  } -  SSL3_DEBUG_MSG("Maximum frame size %O.\n", session->max_packet_size); -  break; -  case EXTENSION_truncated_hmac: -  // RFC 3546 3.5 "Truncated HMAC" -  if (!extension_data->is_empty()) { -  send_packet(Alert(ALERT_fatal, ALERT_illegal_parameter, -  "Invalid trusted HMAC extension.\n")); -  } -  session->truncated_hmac = 1; -  SSL3_DEBUG_MSG("Trucated HMAC\n"); -  break; -  -  case EXTENSION_renegotiation_info: -  string renegotiated_connection = -  extension_data->get_var_string(1); -  if ((renegotiated_connection != client_verify_data) || -  (handshake_finished && !secure_renegotiation)) { -  // RFC 5746 3.7: (secure_renegotiation) -  // The server MUST verify that the value of the -  // "renegotiated_connection" field is equal to the saved -  // client_verify_data value; if it is not, the server MUST -  // abort the handshake. -  // -  // RFC 5746 4.4: (!secure_renegotiation) -  // The server MUST verify that the "renegotiation_info" -  // extension is not present; if it is, the server MUST -  // abort the handshake. -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Invalid renegotiation data.\n")); -  return -1; -  } -  secure_renegotiation = 1; -  missing_secure_renegotiation = 0; -  SSL3_DEBUG_MSG("Renego extension: %O\n", renegotiated_connection); -  break; -  -  case EXTENSION_application_layer_protocol_negotiation: -  { -  has_application_layer_protocol_negotiation = 1; -  if( !context->advertised_protocols ) -  break; -  multiset(string) protocols = (<>); -  if( extension_data->get_uint(2) != sizeof(extension_data) ) -  { -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "ALPN: Length mismatch.\n")); -  return -1; -  } -  while (!extension_data->is_empty()) { -  string server_name = extension_data->get_var_string(1); -  if( sizeof(server_name)==0 ) -  { -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "ALPN: Empty protocol.\n")); -  return -1; -  } -  protocols[ server_name ] = 1; -  } -  -  if( !sizeof(protocols) ) -  { -  // FIXME: What does an empty list mean? Ignore, no -  // protocol failure or handshake failure? Currently -  // it will hit the no compatible protocol fatal -  // alert below. -  } -  -  // Although the protocol list is sent in client -  // preference order, it is the server preference that -  // wins. -  next_protocol = 0; -  foreach(context->advertised_protocols;; string(0..255) prot) -  if( protocols[prot] ) -  { -  next_protocol = prot; -  break; -  } -  if( !next_protocol ) -  send_packet(Alert(ALERT_fatal, ALERT_no_application_protocol, -  "ALPN: No compatible protocol.\n")); -  SSL3_DEBUG_MSG("ALPN extension: %O %O\n", -  protocols, next_protocol); -  } -  break; -  -  case EXTENSION_heartbeat: -  { -  int hb_mode; -  if (extension_data->is_empty() || -  !(hb_mode = extension_data->get_uint(1)) || -  !extension_data->is_empty() || -  ((hb_mode != HEARTBEAT_MODE_peer_allowed_to_send) && -  (hb_mode != HEARTBEAT_MODE_peer_not_allowed_to_send))) { -  // RFC 6520 2: -  // Upon reception of an unknown mode, an error Alert -  // message using illegal_parameter as its -  // AlertDescription MUST be sent in response. -  send_packet(Alert(ALERT_fatal, ALERT_illegal_parameter, -  "Heartbeat: Invalid extension.\n")); -  } -  SSL3_DEBUG_MSG("heartbeat extension: %s\n", -  fmt_constant(hb_mode, "HEARTBEAT_MODE")); -  session->heartbeat_mode = [int(0..1)]hb_mode; -  } -  break; -  -  default: - #ifdef SSL3_DEBUG -  werror("Unhandled extension %O (%d bytes)\n", -  extension_data->buffer, sizeof(extension_data->buffer)); - #endif -  break; -  } -  } -  if (maybe_safari_10_8) { -  // According to OpenSSL (ssl/t1_lib.c:ssl_check_for_safari()), -  // the Safari browser versions 10.8.0..10.8.3 have -  // broken support for ECDHE_ECDSA, but advertise such -  // suites anyway. We attempt to fingerprint Safari 10.8 -  // above by the set of extensions and the order it -  // sends them in. -  SSL3_DEBUG_MSG("Client version: %s\n" -  "Number of extensions: %d\n", -  fmt_version(client_version), -  sizeof(remote_extensions)); -  if (((client_version == PROTOCOL_TLS_1_2) && -  ((sizeof(remote_extensions) != 4) || -  !remote_extensions[EXTENSION_signature_algorithms])) || -  ((client_version < PROTOCOL_TLS_1_2) && -  ((sizeof(remote_extensions) != 3) || -  !remote_extensions[EXTENSION_ec_point_formats]))) { -  maybe_safari_10_8 = 0; -  } -  if (maybe_safari_10_8) { -  SSL3_DEBUG_MSG("Safari 10.8 (or similar) detected.\n"); -  cipher_suites = filter(cipher_suites, -  lambda(int suite) { -  return CIPHER_SUITES[suite] && -  (CIPHER_SUITES[suite][0] != -  KE_ecdhe_ecdsa); -  }); -  SSL3_DEBUG_MSG("Remaining cipher suites:\n" -  "%s\n", -  .Constants.fmt_cipher_suites(cipher_suites)); -  } -  } -  } -  if (missing_secure_renegotiation) { -  // RFC 5746 3.7: (secure_renegotiation) -  // The server MUST verify that the "renegotiation_info" extension is -  // present; if it is not, the server MUST abort the handshake. -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Missing secure renegotiation extension.\n")); -  return -1; -  } -  if (has_value(cipher_suites, TLS_empty_renegotiation_info_scsv)) { -  if (secure_renegotiation || handshake_finished) { -  // RFC 5746 3.7: (secure_renegotiation) -  // When a ClientHello is received, the server MUST verify that it -  // does not contain the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If -  // the SCSV is present, the server MUST abort the handshake. -  // -  // RFC 5746 4.4: (!secure_renegotiation) -  // When a ClientHello is received, the server MUST verify -  // that it does not contain the -  // TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If the SCSV is -  // present, the server MUST abort the handshake. -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "SCSV is present.\n")); -  return -1; -  } else { -  // RFC 5746 3.6: -  // When a ClientHello is received, the server MUST check if it -  // includes the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it -  // does, set the secure_renegotiation flag to TRUE. -  secure_renegotiation = 1; -  } -  } -  - #ifdef SSL3_DEBUG -  if (!input->is_empty()) -  werror("SSL.handshake->handle_handshake: " -  "extra data in hello message ignored\n"); -  -  if (sizeof(id)) -  werror("SSL.handshake: Looking up session %O\n", id); - #endif -  if (reuse) { -  /* Reuse session */ -  SSL3_DEBUG_MSG("SSL.handshake: Reusing session %O\n", id); -  if (! ( (cipher_suites & ({ session->cipher_suite })) -  && (compression_methods & ({ session->compression_algorithm })))) -  { -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Unsupported saved session state.\n")); -  return -1; -  } -  send_packet(server_hello_packet()); -  -  array(.state) res; -  mixed err; -  if( err = catch(res = session->new_server_states(this, -  client_random, -  server_random, -  version)) ) -  { -  // DES/DES3 throws an exception if a weak key is used. We -  // could possibly send ALERT_insufficient_security instead. -  send_packet(Alert(ALERT_fatal, ALERT_internal_error, -  "Internal error.\n")); -  return -1; -  } -  pending_read_state = res[0]; -  pending_write_state = res[1]; -  send_packet(change_cipher_packet()); -  if(version == PROTOCOL_SSL_3_0) -  send_packet(finished_packet("SRVR")); -  else if(version >= PROTOCOL_TLS_1_0) -  send_packet(finished_packet("server finished")); -  -  if (session->heartbeat_mode == HEARTBEAT_MODE_peer_allowed_to_send) { -  // Probe for the Heartbleed vulnerability (CVE-2014-0160). -  send_packet(heartbleed_packet()); -  } -  -  expect_change_cipher = 1; -  -  handshake_state = STATE_server_wait_for_finish; -  } else { -  /* New session, do full handshake. */ -  -  int(-1..0) err = reply_new_session(cipher_suites, -  compression_methods); -  if (err) -  return err; -  handshake_state = STATE_server_wait_for_client; -  } -  break; -  } -  } -  break; -  } -  case STATE_server_wait_for_finish: -  switch(type) -  { -  default: -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Expected next protocol or finished.\n")); -  return -1; -  case HANDSHAKE_next_protocol: -  { -  next_protocol = input->get_var_string(1); -  handshake_messages += raw; -  return 1; -  } -  case HANDSHAKE_finished: -  { -  string(0..255) my_digest; -  string(0..255) digest; -  -  SSL3_DEBUG_MSG("SSL.handshake: FINISHED\n"); -  -  if(version == PROTOCOL_SSL_3_0) { -  my_digest=hash_messages("CLNT"); -  if (catch { -  digest = input->get_fix_string(36); -  } || !input->is_empty()) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Invalid handshake finished message.\n")); -  return -1; -  } -  } else if(version >= PROTOCOL_TLS_1_0) { -  my_digest=hash_messages("client finished"); -  if (catch { -  digest = input->get_fix_string(12); -  } || !input->is_empty()) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Invalid handshake finished message.\n")); -  return -1; -  } -  -  -  } -  -  if ((ke && ke->message_was_bad) /* Error delayed until now */ -  || (my_digest != digest)) -  { -  if(ke && ke->message_was_bad) -  SSL3_DEBUG_MSG("message_was_bad\n"); -  if(my_digest != digest) -  SSL3_DEBUG_MSG("digests differ\n"); -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Key exchange failure.\n")); -  return -1; -  } -  handshake_messages += raw; /* Second hash includes this message, -  * the first doesn't */ -  /* Handshake complete */ -  -  client_verify_data = digest; -  -  if (!reuse) -  { -  send_packet(change_cipher_packet()); -  if(version == PROTOCOL_SSL_3_0) -  send_packet(finished_packet("SRVR")); -  else if(version >= PROTOCOL_TLS_1_0) -  send_packet(finished_packet("server finished")); -  -  if (session->heartbeat_mode == HEARTBEAT_MODE_peer_allowed_to_send) { -  // Probe for the Heartbleed vulnerability (CVE-2014-0160). -  send_packet(heartbleed_packet()); -  } -  -  expect_change_cipher = 1; -  context->record_session(session); /* Cache this session */ -  } -  handshake_state = STATE_server_wait_for_hello; -  -  return 1; -  } -  } -  break; -  case STATE_server_wait_for_client: -  // NB: ALERT_no_certificate can be valid in this state, and -  // is handled directly by connection:handle_alert(). -  handshake_messages += raw; -  switch(type) -  { -  default: -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Expected client KEX or cert.\n")); -  return -1; -  case HANDSHAKE_client_key_exchange: -  SSL3_DEBUG_MSG("SSL.handshake: CLIENT_KEY_EXCHANGE\n"); -  -  if (certificate_state == CERT_requested) -  { /* Certificate must be sent before key exchange message */ -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Expected client cert.\n")); -  return -1; -  } -  -  if (!(session->master_secret = server_derive_master_secret(data))) -  { -  return -1; -  } else { -  -  // trace(1); -  array(.state) res = -  session->new_server_states(this, client_random, server_random, -  version); -  pending_read_state = res[0]; -  pending_write_state = res[1]; -  -  SSL3_DEBUG_MSG("certificate_state: %d\n", certificate_state); -  } -  // TODO: we need to determine whether the certificate has signing abilities. -  if (certificate_state == CERT_received) -  { -  handshake_state = STATE_server_wait_for_verify; -  } -  else -  { -  handshake_state = STATE_server_wait_for_finish; -  expect_change_cipher = 1; -  } -  -  break; -  case HANDSHAKE_certificate: -  { -  SSL3_DEBUG_MSG("SSL.handshake: CLIENT_CERTIFICATE\n"); -  -  if (certificate_state != CERT_requested) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Unexpected client cert.\n")); -  return -1; -  } -  mixed e; -  if (e = catch { -  int certs_len = input->get_uint(3); - #ifdef SSL3_DEBUG -  werror("got %d certificate bytes\n", certs_len); - #else -  certs_len; // Fix warning. - #endif -  array(string(8bit)) certs = ({ }); -  while(!input->is_empty()) -  certs += ({ input->get_var_string(3) }); -  -  // we have the certificate chain in hand, now we must verify them. -  if((!sizeof(certs) && context->auth_level == AUTHLEVEL_require) || -  !verify_certificate_chain(certs)) -  { -  send_packet(Alert(ALERT_fatal, ALERT_bad_certificate, -  "Bad client certificate.\n")); -  return -1; -  } -  else -  { -  session->peer_certificate_chain = certs; -  } -  } || !input->is_empty()) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Unexpected client cert.\n")); -  return -1; -  } -  -  if(session->peer_certificate_chain && -  sizeof(session->peer_certificate_chain)) -  certificate_state = CERT_received; -  else certificate_state = CERT_no_certificate; -  break; -  } -  } -  break; -  case STATE_server_wait_for_verify: -  // compute challenge first, then update handshake_messages /Sigge -  switch(type) -  { -  default: -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Expected cert verify.\n")); -  return -1; -  case HANDSHAKE_certificate_verify: -  SSL3_DEBUG_MSG("SSL.handshake: CERTIFICATE_VERIFY\n"); -  -  if (!ke->message_was_bad) -  { -  int(0..1) verification_ok; -  mixed err = catch { -  ADT.struct handshake_messages_struct = ADT.struct(); -  handshake_messages_struct->put_fix_string(handshake_messages); -  verification_ok = session->cipher_spec->verify( -  session, "", handshake_messages_struct, input); -  }; - #ifdef SSL3_DEBUG -  if (err) { -  master()->handle_error(err); -  } - #endif -  err = UNDEFINED; // Get rid of warning. -  if (!verification_ok) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Verification of CertificateVerify failed.\n")); -  return -1; -  } -  } -  handshake_messages += raw; -  handshake_state = STATE_server_wait_for_finish; -  expect_change_cipher = 1; -  break; -  } -  break; -  -  case STATE_client_wait_for_hello: -  if(type != HANDSHAKE_server_hello) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Expected server hello.\n")); -  return -1; -  } -  else -  { -  SSL3_DEBUG_MSG("SSL.handshake: SERVER_HELLO\n"); -  -  handshake_messages += raw; -  string id; -  int cipher_suite, compression_method; -  -  version = [int(0x300..0x300)|ProtocolVersion]input->get_uint(2); -  server_random = input->get_fix_string(32); -  id = input->get_var_string(1); -  cipher_suite = input->get_uint(2); -  compression_method = input->get_uint(1); -  -  if( !has_value(context->preferred_suites, cipher_suite) || -  !has_value(context->preferred_compressors, compression_method) || -  !session->is_supported_suite(cipher_suite, ~0, version)) -  { -  // The server tried to trick us to use some other cipher suite -  // or compression method than we wanted -  version = client_version; -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Server selected bad suite.\n")); -  return -1; -  } -  -  if (((version & ~0xff) != PROTOCOL_SSL_3_0) || -  (version < context->min_version)) { -  SSL3_DEBUG_MSG("Unsupported version of SSL: %s.\n", -  fmt_version(version)); -  version = client_version; -  send_packet(Alert(ALERT_fatal, ALERT_protocol_version, -  "Unsupported version.\n")); -  return -1; -  } -  if (client_version > version) { -  SSL3_DEBUG_MSG("Falling back client from %s to %s.\n", -  fmt_version(client_version), -  fmt_version(version)); -  } else if (version > client_version) { -  SSL3_DEBUG_MSG("Falling back server from %s to %s.\n", -  fmt_version(version), -  fmt_version(client_version)); -  version = client_version; -  } -  -  if (!session->set_cipher_suite(cipher_suite, version, -  session->signature_algorithms, -  512)) { -  // Unsupported or obsolete cipher suite selected. -  SSL3_DEBUG_MSG("Unsupported or obsolete cipher suite selected.\n"); -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Unsupported or obsolete cipher suite.\n")); -  return -1; -  } -  session->set_compression_method(compression_method); -  SSL3_DEBUG_MSG("STATE_client_wait_for_hello: received hello\n" -  "version = %s\n" -  "id=%O\n" -  "cipher suite: %O\n" -  "compression method: %O\n", -  fmt_version(version), -  id, cipher_suite, compression_method); -  -  int missing_secure_renegotiation = secure_renegotiation; -  -  if (!input->is_empty()) { -  ADT.struct extensions = ADT.struct(input->get_var_string(2)); -  -  while (!extensions->is_empty()) { -  int extension_type = extensions->get_uint(2); -  ADT.struct extension_data = -  ADT.struct(extensions->get_var_string(2)); -  SSL3_DEBUG_MSG("SSL.handshake->handle_handshake: " -  "Got extension %s.\n", -  fmt_constant(extension_type, "EXTENSION")); -  switch(extension_type) { -  case EXTENSION_renegotiation_info: -  string renegotiated_connection = extension_data->get_var_string(1); -  if ((renegotiated_connection != -  (client_verify_data + server_verify_data)) || -  (handshake_finished && !secure_renegotiation)) { -  // RFC 5746 3.5: (secure_renegotiation) -  // The client MUST then verify that the first half of the -  // "renegotiated_connection" field is equal to the saved -  // client_verify_data value, and the second half is equal to the -  // saved server_verify_data value. If they are not, the client -  // MUST abort the handshake. -  // -  // RFC 5746 4.2: (!secure_renegotiation) -  // When the ServerHello is received, the client MUST -  // verify that it does not contain the -  // "renegotiation_info" extension. If it does, the client -  // MUST abort the handshake. (Because the server has -  // already indicated it does not support secure -  // renegotiation, the only way that this can happen is if -  // the server is broken or there is an attack.) -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Invalid renegotiation data.\n")); -  return -1; -  } -  secure_renegotiation = 1; -  missing_secure_renegotiation = 0; -  break; -  case EXTENSION_ec_point_formats: -  array(int) ecc_point_formats = -  extension_data->get_var_uint_array(1, 1); -  // NB: We only support the uncompressed point format for now. -  if (has_value(ecc_point_formats, POINT_uncompressed)) { -  session->ecc_point_format = POINT_uncompressed; -  } else { -  // Not a supported point format. -  session->ecc_point_format = -1; -  } -  break; -  case EXTENSION_server_name: -  break; -  -  case EXTENSION_heartbeat: -  { -  int hb_mode; -  if (extension_data->is_empty() || -  !(hb_mode = extension_data->get_uint(1)) || -  !extension_data->is_empty() || -  ((hb_mode != HEARTBEAT_MODE_peer_allowed_to_send) && -  (hb_mode != HEARTBEAT_MODE_peer_not_allowed_to_send))) { -  // RFC 6520 2: -  // Upon reception of an unknown mode, an error Alert -  // message using illegal_parameter as its -  // AlertDescription MUST be sent in response. -  send_packet(Alert(ALERT_fatal, ALERT_illegal_parameter, -  "Invalid heartbeat extension.\n")); -  } -  SSL3_DEBUG_MSG("heartbeat extension: %s\n", -  fmt_constant(hb_mode, "HEARTBEAT_MODE")); -  session->heartbeat_mode = [int(0..1)]hb_mode; -  } -  break; -  -  default: -  // RFC 5246 7.4.1.4: -  // If a client receives an extension type in ServerHello -  // that it did not request in the associated ClientHello, it -  // MUST abort the handshake with an unsupported_extension -  // fatal alert. -  send_packet(Alert(ALERT_fatal, ALERT_unsupported_extension, -  "Unrequested extension.\n")); -  return -1; -  } -  } -  } -  if (missing_secure_renegotiation) { -  // RFC 5746 3.5: -  // When a ServerHello is received, the client MUST verify that the -  // "renegotiation_info" extension is present; if it is not, the -  // client MUST abort the handshake. -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Missing secure renegotiation extension.\n")); -  return -1; -  } -  -  handshake_state = STATE_client_wait_for_server; -  break; -  } -  break; -  -  case STATE_client_wait_for_server: -  handshake_messages += raw; -  switch(type) -  { -  default: -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Unexpected server message.\n")); -  return -1; -  case HANDSHAKE_certificate: -  { -  SSL3_DEBUG_MSG("SSL.handshake: CERTIFICATE\n"); -  -  // we're anonymous, so no certificate is requred. -  if(ke && ke->anonymous) -  break; -  -  SSL3_DEBUG_MSG("Handshake: Certificate message received\n"); -  int certs_len = input->get_uint(3); certs_len; -  array(string(8bit)) certs = ({ }); -  while(!input->is_empty()) -  certs += ({ input->get_var_string(3) }); -  -  // we have the certificate chain in hand, now we must verify them. -  if(!verify_certificate_chain(certs)) -  { -  werror("Unable to verify peer certificate chain.\n"); -  send_packet(Alert(ALERT_fatal, ALERT_bad_certificate, -  "Bad server certificate chain.\n")); -  return -1; -  } -  else -  { -  session->peer_certificate_chain = certs; -  } -  -  mixed error=catch -  { -  session->peer_public_key = Standards.X509.decode_certificate( -  session->peer_certificate_chain[0])->public_key->pkc; - #if constant(Crypto.ECC.Curve) -  if (session->peer_public_key->curve) { -  session->curve = -  ([object(Crypto.ECC.SECP_521R1.ECDSA)]session->peer_public_key)-> -  curve(); -  } - #endif -  }; -  -  if(error) -  { -  session->peer_certificate_chain = UNDEFINED; -  SSL3_DEBUG_MSG("Failed to decode certificate!\n"); -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Failed to decode server certificate.\n")); -  return -1; -  } -  -  certificate_state = CERT_received; -  break; -  } -  -  case HANDSHAKE_server_key_exchange: -  { -  if (ke) error("KE!\n"); -  ke = session->ke_factory(context, session, this, client_version); -  if (ke->server_key_exchange(input, client_random, server_random) < 0) { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Verification of ServerKeyExchange failed.\n")); -  return -1; -  } -  break; -  } -  -  case HANDSHAKE_certificate_request: -  SSL3_DEBUG_MSG("SSL.handshake: CERTIFICATE_REQUEST\n"); -  -  // it is a fatal handshake_failure alert for an anonymous server to -  // request client authentication. -  if(ke->anonymous) -  { -  send_packet(Alert(ALERT_fatal, ALERT_handshake_failure, -  "Anonymous server requested authentication by " -  "certificate.\n")); -  return -1; -  } -  -  client_cert_types = input->get_var_uint_array(1, 1); -  client_cert_distinguished_names = ({}); -  -  if (version >= PROTOCOL_TLS_1_2) { -  // TLS 1.2 has var_uint_array of hash and sign pairs here. -  string bytes = input->get_var_string(2); -  // Pairs of <hash_alg, signature_alg>. -  session->signature_algorithms = ((array(int))bytes)/2; -  SSL3_DEBUG_MSG("New signature_algorithms:\n"+ -  fmt_signature_pairs(session->signature_algorithms)); -  } -  -  int num_distinguished_names = input->get_uint(2); -  if(num_distinguished_names) -  { -  ADT.struct s = -  ADT.struct(input->get_fix_string(num_distinguished_names)); -  while(!s->is_empty()) -  { -  string(8bit) der = s->get_var_string(2); -  Standards.ASN1.Types.Sequence seq = -  [object(Standards.ASN1.Types.Sequence)] -  Standards.ASN1.Decode.simple_der_decode(der); -  if(object_program(seq) != Standards.ASN1.Types.Sequence) -  { -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Badly formed Certificate Request.\n")); -  } -  client_cert_distinguished_names += ({ der }); -  SSL3_DEBUG_MSG("got an authorized issuer: %O\n", -  Standards.PKCS.Certificate.get_dn_string( seq )); -  } -  } -  -  certificate_state = CERT_requested; -  break; -  -  case HANDSHAKE_server_hello_done: -  SSL3_DEBUG_MSG("SSL.handshake: SERVER_HELLO_DONE\n"); -  -  /* Send Certificate, ClientKeyExchange, CertificateVerify and -  * ChangeCipherSpec as appropriate, and then Finished. -  */ -  /* only send a certificate if it's been requested. */ -  if(certificate_state == CERT_requested) -  { -  // okay, we have a list of certificate types and dns that are -  // acceptable to the remote server. we should weed out the certs -  // we have so that we only send certificates that match what they -  // want. -  -  array(CertificatePair) certs = [array(CertificatePair)] -  filter(context->find_cert(client_cert_distinguished_names, 1) || ({}), -  lambda(CertificatePair cp, array(int)) { -  return has_value(client_cert_types, cp->cert_type); -  }, client_cert_types); -  -  if (sizeof(certs)) { -  session->private_key = certs[0]->key; -  session->certificate_chain = certs[0]->certs; - #ifdef SSL3_DEBUG -  foreach(session->certificate_chain, string c) -  { -  werror("sending certificate: " + Standards.PKCS.Certificate.get_dn_string(Standards.X509.decode_certificate(c)->subject) + "\n"); -  } - #endif -  -  send_packet(certificate_packet(session->certificate_chain)); -  certificate_state = CERT_received; // we use this as a way of saying "the server received our certificate" -  } else { -  send_packet(certificate_packet(({}))); -  certificate_state = CERT_no_certificate; -  } -  } -  -  -  if( !session->has_required_certificates() ) -  { -  SSL3_DEBUG_MSG("Certificate message required from server.\n"); -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Certificate message missing.\n")); -  return -1; -  } -  -  Packet key_exchange = client_key_exchange_packet(); -  -  if (key_exchange) -  send_packet(key_exchange); -  -  -  // FIXME: The certificate code has changed, so this no longer -  // works, if it every did. - #if 0 -  // FIXME: Certificate verify; we should redo this so it makes more sense -  if(certificate_state == CERT_received && -  sizeof(context->cert_pairs) && -  context->private_key) -  // we sent a certificate, so we should send the verification. -  { -  send_packet(certificate_verify_packet()); -  } - #endif -  -  send_packet(change_cipher_packet()); -  -  if(version == PROTOCOL_SSL_3_0) -  send_packet(finished_packet("CLNT")); -  else if(version >= PROTOCOL_TLS_1_0) -  send_packet(finished_packet("client finished")); -  -  if (session->heartbeat_mode == HEARTBEAT_MODE_peer_allowed_to_send) { -  // Probe for the Heartbleed vulnerability (CVE-2014-0160). -  send_packet(heartbleed_packet()); -  } -  -  handshake_state = STATE_client_wait_for_finish; -  expect_change_cipher = 1; -  break; -  } -  break; -  -  case STATE_client_wait_for_finish: -  { -  if((type) != HANDSHAKE_finished) -  { -  SSL3_DEBUG_MSG("Expected type HANDSHAKE_finished(%d), got %d\n", -  HANDSHAKE_finished, type); -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Expected handshake finished.\n")); -  return -1; -  } else { -  SSL3_DEBUG_MSG("SSL.handshake: FINISHED\n"); -  -  string my_digest; -  if (version == PROTOCOL_SSL_3_0) { -  server_verify_data = input->get_fix_string(36); -  my_digest = hash_messages("SRVR"); -  } else if (version >= PROTOCOL_TLS_1_0) { -  server_verify_data = input->get_fix_string(12); -  my_digest = hash_messages("server finished"); -  } -  -  if (my_digest != server_verify_data) { -  SSL3_DEBUG_MSG("Digests differ.\n"); -  send_packet(Alert(ALERT_fatal, ALERT_unexpected_message, -  "Digests differ.\n")); -  return -1; -  } -  -  return 1; // We're done shaking hands -  } -  } -  } -  // SSL3_DEBUG_MSG("SSL.handshake: messages = %O\n", handshake_messages); -  return 0; - } -  +    //! @param is_server   //! Whether this is the server end of the connection or not.   //! @param ctx   //! The context for the connection.   protected void create(SSL.context ctx)   {    current_read_state = SSL.state(this);    current_write_state = SSL.state(this);       if ((ctx->max_version < PROTOCOL_SSL_3_0) ||