?? ssl.c
字號:
} /* Reliable buffer to outgoing TCP/UDP (send up to CONTROL_SEND_ACK_MAX ACKs for previously received packets) */ if (!to_link->len && reliable_can_send (ks->send_reliable)) { int opcode; struct buffer b; buf = reliable_send (ks->send_reliable, &opcode); ASSERT (buf); b = *buf; INCR_SENT; write_control_auth (session, ks, &b, to_link_addr, opcode, CONTROL_SEND_ACK_MAX, true); *to_link = b; active = true; state_change = true; msg (D_TLS_DEBUG, "Reliable -> TCP/UDP"); break; }#ifndef TLS_AGGREGATE_ACK /* Send 1 or more ACKs (each received control packet gets one ACK) */ if (!to_link->len && !reliable_ack_empty (ks->rec_ack)) { buf = &ks->ack_write_buf; ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame))); write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1, RELIABLE_ACK_SIZE, false); *to_link = *buf; active = true; state_change = true; msg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP"); break; }#endif /* Write incoming ciphertext to TLS object */ buf = reliable_get_buf_sequenced (ks->rec_reliable); if (buf) { int status = 0; if (buf->len) { status = key_state_write_ciphertext (multi, ks, buf); if (status == -1) { msg (D_TLS_ERRORS, "TLS Error: Incoming Ciphertext -> TLS object write error"); goto error; } } else { status = 1; } if (status == 1) { reliable_mark_deleted (ks->rec_reliable, buf, true); state_change = true; msg (D_TLS_DEBUG, "Incoming Ciphertext -> TLS"); } } /* Read incoming plaintext from TLS object */ buf = &ks->plaintext_read_buf; if (!buf->len) { int status; ASSERT (buf_init (buf, 0)); status = key_state_read_plaintext (multi, ks, buf, PLAINTEXT_BUFFER_SIZE); update_time (); if (status == -1) { msg (D_TLS_ERRORS, "TLS Error: TLS object -> incoming plaintext read error"); goto error; } if (status == 1) { state_change = true; msg (D_TLS_DEBUG, "TLS -> Incoming Plaintext"); } } /* Send Key */ buf = &ks->plaintext_write_buf; if (!buf->len && ((ks->state == S_START && !session->opt->server) || (ks->state == S_GOT_KEY && session->opt->server))) { const int optlen = strlen (session->opt->local_options) + 1; if (session->opt->key_method == 1) { struct key key; ASSERT (buf_init (buf, 0)); generate_key_random (&key, &session->opt->key_type); if (!check_key (&key, &session->opt->key_type)) { msg (D_TLS_ERRORS, "TLS Error: Bad encrypting key generated"); goto error; } write_key (&key, &session->opt->key_type, buf); init_key_ctx (&ks->key.encrypt, &key, &session->opt->key_type, DO_ENCRYPT, "Data Channel Encrypt"); CLEAR (key); /* send local options string */ ASSERT (buf_write (buf, session->opt->local_options, optlen)); } else { ASSERT (session->opt->key_method == 2); ASSERT (buf_init (buf, 0)); /* write a uin32 0 */ ASSERT (buf_write_u32 (buf, 0)); /* write key_method + flags */ ASSERT (buf_write_u8 (buf, (session->opt->key_method & KEY_METHOD_MASK) | (session->opt->pass_config_info ? TLS_PASS_CONFIG_INFO : 0))); /* write key source material */ key_source2_randomize_write (ks->key_src, buf, session->opt->server); /* write options string */ ASSERT (optlen >= 0 && optlen < 65536); ASSERT (buf_write_u16 (buf, optlen)); ASSERT (buf_write (buf, session->opt->local_options, optlen)); if (session->opt->server) { if (!generate_key_expansion (&ks->key, &session->opt->key_type, ks->key_src, &ks->session_id_remote, &session->session_id, true)) goto error; CLEAR (*ks->key_src); } } state_change = true; msg (D_TLS_DEBUG_MED, "STATE S_SENT_KEY"); ks->state = S_SENT_KEY; } /* Receive Key */ buf = &ks->plaintext_read_buf; if (buf->len && ((ks->state == S_SENT_KEY && !session->opt->server) || (ks->state == S_START && session->opt->server))) { if (session->opt->key_method == 1) { int status; struct key key; status = read_key (&key, &session->opt->key_type, buf); if (status == -1) { msg (D_TLS_ERRORS, "TLS Error: Error reading data channel key from plaintext buffer"); goto error; } if (!check_key (&key, &session->opt->key_type)) { msg (D_TLS_ERRORS, "TLS Error: Bad decrypting key received from peer"); goto error; } ASSERT (buf->len > 0); /* compare received remote options string with our locally computed options string */ if (!session->opt->disable_occ && !options_cmp_equal (BPTR (buf), session->opt->remote_options, buf->len)) { options_warning (BPTR (buf), session->opt->remote_options, buf->len); } buf_clear (buf); if (status == 1) { init_key_ctx (&ks->key.decrypt, &key, &session->opt->key_type, DO_DECRYPT, "Data Channel Decrypt"); } CLEAR (key); if (status == 0) goto error; } else { int key_method_flags; int status; int optlen; ASSERT (session->opt->key_method >= 2); status = 0; /* discard leading uint32 */ ASSERT (buf_advance (buf, 4)); /* get key method */ key_method_flags = buf_read_u8 (buf); if ((key_method_flags & KEY_METHOD_MASK) != 2) { msg (D_TLS_ERRORS, "TLS ERROR: Unknown key_method/flags=%d received from remote host", key_method_flags); goto error; } /* verify TLS_PASS_CONFIG_INFO consistency between peers */ if (((key_method_flags & TLS_PASS_CONFIG_INFO) != 0) ^ (session->opt->pass_config_info == true)) { msg (D_TLS_ERRORS, "TLS ERROR: Inconsistent options between peers regarding configuration info exchange over the control channel"); goto error; } /* get key source material (not actual keys yet) */ if (!key_source2_read (ks->key_src, buf, session->opt->server)) { msg (D_TLS_ERRORS, "TLS Error: Error reading remote data channel key source entropy from plaintext buffer"); goto error; } /* get options */ optlen = buf_read_u16 (buf); if (optlen < 0 || optlen >= 65536) { msg (D_TLS_ERRORS, "TLS Error: Bad options string length: %d", optlen); goto error; } if (BLEN(buf) < optlen) { msg (D_TLS_ERRORS, "TLS Error: Options string truncation"); goto error; } /* check options consistency */ if (!session->opt->disable_occ && !options_cmp_equal (BPTR (buf), session->opt->remote_options, buf->len)) { options_warning (BPTR (buf), session->opt->remote_options, buf->len); } buf_clear (buf); if (!session->opt->server) { if (!generate_key_expansion (&ks->key, &session->opt->key_type, ks->key_src, &session->session_id, &ks->session_id_remote, false)) goto error; CLEAR (*ks->key_src); } } state_change = true; msg (D_TLS_DEBUG_MED, "STATE S_GOT_KEY"); ks->state = S_GOT_KEY; } /* Write outgoing plaintext to TLS object */ buf = &ks->plaintext_write_buf; if (buf->len) { int status = key_state_write_plaintext (multi, ks, buf); if (status == -1) { msg (D_TLS_ERRORS, "TLS ERROR: Outgoing Plaintext -> TLS object write error"); goto error; } if (status == 1) { state_change = true; msg (D_TLS_DEBUG, "Outgoing Plaintext -> TLS"); } } /* Outgoing Ciphertext to reliable buffer */ if (ks->state >= S_START) { buf = reliable_get_buf_output_sequenced (ks->send_reliable); if (buf) { int status = key_state_read_ciphertext (multi, ks, buf, PAYLOAD_SIZE_DYNAMIC (&multi->opt.frame)); if (status == -1) { msg (D_TLS_ERRORS, "TLS Error: Ciphertext -> reliable TCP/UDP transport read error"); goto error; } if (status == 1) { reliable_mark_active_outgoing (ks->send_reliable, buf, P_CONTROL_V1); INCR_GENERATED; state_change = true; msg (D_TLS_DEBUG, "Outgoing Ciphertext -> Reliable"); } } } } //mutex_cycle (multi->mutex); } while (state_change); update_time ();#ifdef TLS_AGGREGATE_ACK /* Send 1 or more ACKs (each received control packet gets one ACK) */ if (!to_link->len && !reliable_ack_empty (ks->rec_ack)) { buf = &ks->ack_write_buf; ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame))); write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1, RELIABLE_ACK_SIZE, false); *to_link = *buf; active = true; state_change = true; msg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP"); }#endif /* When should we wake up again? */ { if (ks->state >= S_INITIAL) { compute_earliest_wakeup (wakeup, reliable_send_timeout (ks->send_reliable)); if (ks->must_negotiate) compute_earliest_wakeup (wakeup, ks->must_negotiate - now); } if (ks->established && session->opt->renegotiate_seconds) compute_earliest_wakeup (wakeup, ks->established + session->opt->renegotiate_seconds - now); /* prevent event-loop spinning by setting minimum wakeup of 1 second */ if (*wakeup <= 0) { *wakeup = 1; /* if we had something to send to remote, but to_link was busy, let caller know we need to be called again soon */ active = true; } msg (D_TLS_DEBUG, "TLS: tls_process: timeout set to %d", *wakeup); gc_free (&gc); return active; }error: ks->state = S_ERROR; msg (D_TLS_ERRORS, "TLS Error: TLS handshake failed"); INCR_ERROR; gc_free (&gc); return false;}#undef ks#undef ks_lame/* * Called at the top of the event loop in openvpn.c. * * Basically decides if we should call tls_process for * the active or untrusted sessions. */booltls_multi_process (struct tls_multi *multi, struct buffer *to_link, struct sockaddr_in *to_link_addr, struct link_socket_info *to_link_socket_info, interval_t *wakeup){ struct gc_arena gc = gc_new (); int i; bool active = false; /* * Process each session object having state of S_INITIAL or greater, * and which has a defined remote IP addr. */ for (i = 0; i < TM_SIZE; ++i) { struct tls_session *session = &multi->session[i]; struct key_state *ks = &session->key[KS_PRIMARY]; struct key_state *ks_lame = &session->key[KS_LAME_DUCK]; /* set initial remote address */ if (i == TM_ACTIVE && ks->state == S_INITIAL && addr_defined (&to_link_socket_info->lsa->actual)) ks->remote_addr = to_link_socket_info->lsa->actual; msg (D_TLS_DEBUG, "TLS: tls_multi_process: i=%d state=%s, mysid=%s, stored-sid=%s, stored-ip=%s", i, state_name (ks->state), session_id_print (&session->session_id, &gc), session_id_print (&ks->session_id_remote, &gc), print_sockaddr (&ks->remote_addr, &gc)); if (ks->state >= S_INITIAL && addr_defined (&ks->remote_addr)) { update_time (); if (tls_process (multi, session, to_link, to_link_addr, to_link_socket_info, wakeup)) active = true; /* * If tls_process hits an error: * (1) If the session has an unexpired lame duck key, preserve it. * (2) Reinitialize the session. */ if (ks->state == S_ERROR) { ++multi->n_errors; if (i == TM_ACTIVE && ks_lame->state >= S_ACTIVE && !multi->opt.single_session) move_session (multi, TM_LAME_DUCK, TM_ACTIVE, true); else reset_session (multi, session); } } //mutex_cycle (multi->mutex); } update_time (); /* * If lame duck session expires, kill it. */ if (lame_duck_must_die (&multi->session[TM_LAME_DUCK], wakeup)) { tls_session_free (&multi->session[TM_LAME_DUCK], true); msg (D_TLS_DEBUG_LOW, "TLS: tls_multi_process: killed expiring key"); } /* * If untrusted session achieves TLS authentication, * move it to active session, usurping any prior session. */ if (DECRYPT_KEY_ENABLED (multi, &multi->session[TM_UNTRUSTED].key[KS_PRIMARY])) { move_session (multi, TM_ACTIVE, TM_UNTRUSTED, true); msg (D_TLS_DEBUG_LOW, "TLS: tls_multi_process: untrusted session promoted to trusted"); } gc_free (&gc); return active;}/* * Send a payload over the TLS control channel. * Called externally. */booltls_send_payload (struct tls_multi *multi, const struct buffer *buf){ struct tls_session *session; struct key_state *ks; bool ret = false; ASSERT (multi); session = &multi->session[TM_ACTIVE]; ks = &session->key[KS_PRIMARY]; if (ks->state >= S_ACTIVE && !BLEN (&ks->plaintext_write_buf)) { if (buf_copy (&ks->plaintext_write_buf, buf)) ret = true; } return ret;}booltls_rec_payload (struct tls_multi *multi, struct buffer *buf){ struct tls_session *session; struct key_state *ks; bool ret = false; ASSERT (multi); session = &multi->ses
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -