?? ssl.c
字號:
* below this point must be called with the L_TLS lock held. */booltls_pre_decrypt (struct tls_multi *multi, struct sockaddr_in *from, struct buffer *buf, struct crypto_options *opt, time_t current){ bool ret = false; if (buf->len > 0) { int i; int op; int key_id; /* get opcode and key ID */ { uint8_t c = *BPTR (buf); op = c >> P_OPCODE_SHIFT; key_id = c & P_KEY_ID_MASK; } if (op == P_DATA_V1) { /* data channel packet */ for (i = 0; i < KEY_SCAN_SIZE; ++i) { struct key_state *ks = multi->key_scan[i]; if (DECRYPT_KEY_ENABLED (multi, ks) && key_id == ks->key_id && addr_match(from, &ks->remote_addr)) { /* return appropriate data channel decrypt key in opt */ opt->key_ctx_bi = &ks->key; opt->packet_id = multi->opt.packet_id ? &ks->packet_id : NULL; opt->packet_id_long_form = multi->opt.packet_id_long_form; ASSERT (buf_advance (buf, 1)); ++ks->n_packets; ks->n_bytes += buf->len; msg (D_TLS_DEBUG, "tls_pre_decrypt: data channel, key_id=%d, IP=%s", key_id, print_sockaddr (from)); return ret; } } msg (D_TLS_ERRORS, "TLS Error: Unknown data channel key ID or IP address received from %s: %d", print_sockaddr (from), key_id); } else /* control channel packet */ { bool do_burst = false; bool new_link = false; struct session_id sid; /* remote session ID */ /* verify legal opcode */ if (op < P_FIRST_OPCODE || op > P_LAST_OPCODE) { msg (D_TLS_ERRORS, "TLS Error: unknown opcode received from %s op=%d", print_sockaddr (from), op); goto done; } /* hard reset ? */ if (HARD_RESET(op)) { /* verify client -> server or server -> client connection */ if ((op == P_CONTROL_HARD_RESET_CLIENT_V1 && !multi->opt.server) || (op == P_CONTROL_HARD_RESET_SERVER_V1 && multi->opt.server)) { msg (D_TLS_ERRORS, "TLS Error: client->client or server->server connection attempted from %s", print_sockaddr (from)); goto done; } } /* * Authenticate Packet */ msg (D_TLS_DEBUG, "tls_pre_decrypt: control channel, op=%s, IP=%s", packet_opcode_name (op), print_sockaddr (from)); /* get remote session-id */ { struct buffer tmp = *buf; buf_advance (&tmp, 1); if (!session_id_read (&sid, &tmp) || !session_id_defined (&sid)) { msg (D_TLS_ERRORS, "TLS Error: session-id not found in packet from %s", print_sockaddr (from)); goto done; } } /* use session ID to match up packet with appropriate tls_session object */ for (i = 0; i < TM_SIZE; ++i) { struct tls_session *session = &multi->session[i]; struct key_state *ks = &session->key[KS_PRIMARY]; msg (D_TLS_DEBUG, "tls_pre_decrypt: initial packet test, i=%d state=%s, mysid=%s, rec-sid=%s, rec-ip=%s, stored-sid=%s, stored-ip=%s", i, state_name (ks->state), session_id_print (&session->session_id), session_id_print (&sid), print_sockaddr (from), session_id_print (&ks->session_id_remote), print_sockaddr (&ks->remote_addr)); if (session_id_equal (&ks->session_id_remote, &sid)) /* found a match */ { if (i == TM_LAME_DUCK) { msg (D_TLS_ERRORS, "TLS ERROR: received control packet with stale session-id=%s", session_id_print (&sid)); goto done; } msg (D_TLS_DEBUG, "tls_pre_decrypt: found match, session[%d], sid=%s", i, session_id_print (&sid)); break; } } /* * check if this is the first response from a host to which * we sent an initial packet */ if (i == TM_SIZE && HARD_RESET(op)) { struct tls_session *session = &multi->session[TM_ACTIVE]; struct key_state *ks = &session->key[KS_PRIMARY]; if (!session_id_defined (&ks->session_id_remote)) { msg (D_TLS_DEBUG_LOW, "tls_pre_decrypt: first response to initial packet sid=%s", session_id_print (&sid)); do_burst = true; new_link = true; i = TM_ACTIVE; } } if (i == TM_SIZE && HARD_RESET(op)) { /* * No match with existing sessions, * probably a new session. */ struct tls_session *session = &multi->session[TM_UNTRUSTED]; if (!read_control_auth (buf, &session->tls_auth, from, current)) goto done; /* * New session-initiating control packet is authenticated at this point * assuming that the --tls-auth command line option was used. * * Without --tls-auth, we leave authentication entirely up to TLS. */ msg (D_TLS_DEBUG_LOW, "tls_pre_decrypt: new session incoming connection from %s", print_sockaddr (from)); new_link = true; i = TM_UNTRUSTED; } else { struct tls_session *session = &multi->session[i]; struct key_state *ks = &session->key[KS_PRIMARY]; /* * Packet must belong to an existing session. */ if (i != TM_ACTIVE && i != TM_UNTRUSTED) { msg (D_TLS_ERRORS, "TLS Error: Unroutable control packet received from %s (si=%d op=%s)", print_sockaddr (from), i, packet_opcode_name (op)); goto done; } /* * Verify remote IP address */ if (!new_link && !addr_match (&ks->remote_addr, from)) { msg (D_TLS_ERRORS, "TLS Error: Received control packet from unexpected IP addr: %s", print_sockaddr (from)); goto done; } /* * Remote is requesting a key renegotiation */ if (op == P_CONTROL_SOFT_RESET_V1 && DECRYPT_KEY_ENABLED (multi, ks)) { if (!read_control_auth (buf, &session->tls_auth, from, current)) goto done; key_state_soft_reset (session, current); msg (D_TLS_DEBUG, "tls_pre_decrypt: received P_CONTROL_SOFT_RESET_V1 s=%d sid=%s", i, session_id_print (&sid)); } else { /* * Remote responding to our key renegotiation request? */ if (op == P_CONTROL_SOFT_RESET_V1) do_burst = true; if (!read_control_auth (buf, &session->tls_auth, from, current)) goto done; msg (D_TLS_DEBUG, "tls_pre_decrypt: received control channel packet s#=%d sid=%s", i, session_id_print (&sid)); } } /* * If --single-session, don't allow more than one session. */ if (multi->opt.single_session && new_link && multi->n_sessions) { msg (D_TLS_ERRORS, "TLS Error: Cannot accept new session request from %s due to --single-session", print_sockaddr (from)); goto done; } /* * We have an authenticated packet (if --tls-auth was set). * Now pass to our reliability level which deals with * packet acknowledgements, retransmits, sequencing, etc. */ { struct tls_session *session = &multi->session[i]; struct key_state *ks = &session->key[KS_PRIMARY]; /* Make sure we were initialized and that we're not in an error state */ ASSERT (ks->state != S_UNDEF); ASSERT (ks->state != S_ERROR); ASSERT (session_id_defined (&session->session_id)); /* Let our caller know we processed a control channel packet */ ret = true; /* * Set our remote address and remote session_id */ if (new_link) { ks->session_id_remote = sid; ks->remote_addr = *from; ++multi->n_sessions; } else if (!addr_match (&ks->remote_addr, from)) { msg (D_TLS_ERRORS, "TLS Error: Existing session control channel packet from unknown IP address: %s", print_sockaddr (from)); goto done; } /* * Should we do a retransmit of all unacknowledged packets in * the send buffer? This improves the start-up efficiency of the * initial key negotiation after the 2nd peer comes online. */ if (do_burst && !session->burst) { reliable_schedule_now (&ks->send_reliable, current); session->burst = true; } /* Check key_id */ if (ks->key_id != key_id) { msg (D_TLS_ERRORS, "TLS ERROR: local/remote key IDs out of sync (%d/%d) ID: %s", ks->key_id, key_id, print_key_id (multi)); goto done; } /* * Process incoming ACKs for packets we can now * delete from reliable send buffer */ { /* buffers all packet IDs to delete from send_reliable */ struct reliable_ack send_ack; send_ack.len = 0; if (!reliable_ack_read (&send_ack, buf, &session->session_id)) { msg (D_TLS_ERRORS, "TLS Error: reading acknowledgement record from packet"); goto done; } reliable_send_purge (&ks->send_reliable, &send_ack); } /* Process outgoing acknowledgment for packet just received */ if (op != P_ACK_V1 && reliable_can_get (&ks->rec_reliable)) { packet_id_type id; /* Save incoming ciphertext packet to reliable buffer */ if (reliable_ack_read_packet_id (&ks->rec_ack, buf, &id)) { struct buffer *in = reliable_get_buf (&ks->rec_reliable); ASSERT (in); ASSERT (buf_copy (in, buf)); reliable_mark_active_incoming (&ks->rec_reliable, in, id, op); } } } } } done: buf->len = 0; opt->key_ctx_bi = NULL; opt->packet_id = NULL; opt->packet_id_long_form = false; return ret;}/* Choose the key with which to encrypt a data packet */voidtls_pre_encrypt (struct tls_multi *multi, struct buffer *buf, struct crypto_options *opt){ multi->save_ks = NULL; if (buf->len > 0) { int i; for (i = 0; i < KEY_SCAN_SIZE; ++i) { struct key_state *ks = multi->key_scan[i]; if (ks->state == S_ACTIVE) { opt->key_ctx_bi = &ks->key; opt->packet_id = multi->opt.packet_id ? &ks->packet_id : NULL; opt->packet_id_long_form = multi->opt.packet_id_long_form; multi->save_ks = ks; msg (D_TLS_DEBUG, "tls_pre_encrypt: key_id=%d", ks->key_id); return; } } msg (D_TLS_NO_SEND_KEY, "TLS Warning: no data channel send key available: %s", print_key_id (multi)); } buf->len = 0; opt->key_ctx_bi = NULL; opt->packet_id = NULL; opt->packet_id_long_form = false;}/* Prepend the appropriate opcode to encrypted buffer prior to UDP send */voidtls_post_encrypt (struct tls_multi *multi, struct buffer *buf){ struct key_state *ks; uint8_t *op; ks = multi->save_ks; multi->save_ks = NULL; if (buf->len > 0) { ASSERT (ks); ASSERT (op = buf_prepend (buf, 1)); *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id; ++ks->n_packets; ks->n_bytes += buf->len; }}/* * Dump a human-readable rendition of an openvpn packet * into a garbage collectable string which is returned. */const char *protocol_dump (struct buffer *buffer, unsigned int flags){ struct buffer out = alloc_buf_gc (256); struct buffer buf = *buffer; uint8_t c; int op; int key_id; int tls_auth_hmac_size = (flags & PD_TLS_AUTH_HMAC_SIZE_MASK); if (buf.len <= 0) { buf_printf (&out, "DATA UNDEF len=%d", buf.len); goto done; } if (!(flags & PD_TLS)) goto print_data; /* * Initial byte (opcode) */ if (!buf_read (&buf, &c, sizeof (c))) goto done; op = (c >> P_OPCODE_SHIFT); key_id = c & P_KEY_ID_MASK; buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id); if (op == P_DATA_V1) goto print_data; /* * Session ID */ { struct session_id sid; if (!session_id_read (&sid, &buf)) goto done; buf_printf (&out, " sid=%s", session_id_print (&sid)); } /* * tls-auth hmac + packet_id */ if (tls_auth_hmac_size) { struct packet_id_net pin; uint8_t tls_auth_hmac[MAX_HMAC_KEY_LENGTH]; ASSERT (tls_auth_hmac_size <= MAX_HMAC_KEY_LENGTH); if (!buf_read (&buf, tls_auth_hmac, tls_auth_hmac_size)) goto done; buf_printf (&out, " tls_hmac=%s", format_hex (tls_auth_hmac, tls_auth_hmac_size, 0)); if (!packet_id_read (&pin, &buf, true)) goto done; buf_printf(&out, " pid=%s", packet_id_net_print (&pin)); } /* * ACK list */ buf_printf (&out, " %s", reliable_ack_print(&buf)); if (op == P_ACK_V1) goto done; /* * Packet ID */ { packet_id_type l; if (!buf_read (&buf, &l, sizeof (l))) goto done; l = ntohpid (l); buf_printf (&out, " pid=" packet_id_format, l); }print_data: if (flags & PD_SHOW_DATA) buf_printf (&out, " DATA %s", format_hex (BPTR (&buf), BLEN (&buf), 80)); else buf_printf (&out, " DATA len=%d", buf.len);done: return out.data;}#endif /* USE_CRYPTO && USE_SSL*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -