struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, int eap_type, int version, u8 id) { struct wpabuf *req; u8 flags; size_t send_len, plen; wpa_printf(MSG_DEBUG, "SSL: Generating Request"); if (data->tls_out == NULL) { wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__); return NULL; } flags = version; send_len = wpabuf_len(data->tls_out) - data->tls_out_pos; if (1 + send_len > data->tls_out_limit) { send_len = data->tls_out_limit - 1; flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; if (data->tls_out_pos == 0) { flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; send_len -= 4; } } plen = 1 + send_len; if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) plen += 4; req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id); if (req == NULL) return NULL; wpabuf_put_u8(req, flags); /* Flags */ if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) wpabuf_put_be32(req, wpabuf_len(data->tls_out)); wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, send_len); data->tls_out_pos += send_len; if (data->tls_out_pos == wpabuf_len(data->tls_out)) { wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " "(message sent completely)", (unsigned long) send_len); wpabuf_free(data->tls_out); data->tls_out = NULL; data->tls_out_pos = 0; data->state = MSG; } else { wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " "(%lu more to send)", (unsigned long) send_len, (unsigned long) wpabuf_len(data->tls_out) - data->tls_out_pos); data->state = WAIT_FRAG_ACK; } return req; }
struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version) { struct wpabuf *req; req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id); if (req == NULL) return NULL; wpa_printf(MSG_DEBUG, "SSL: Building ACK"); wpabuf_put_u8(req, version); /* Flags */ return req; }
/** * eap_peer_tls_build_ack - Build a TLS ACK frame * @id: EAP identifier for the response * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) * @peap_version: Version number for EAP-PEAP/TTLS * Returns: Pointer to the allocated ACK frame or %NULL on failure */ struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, int peap_version) { struct wpabuf *resp; resp = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)", (int) eap_type, id, peap_version); wpabuf_put_u8(resp, peap_version); /* Flags */ return resp; }
static struct wpabuf * eap_tls_build_start(struct eap_sm *sm, struct eap_tls_data *data, u8 id) { struct wpabuf *req; req = eap_tls_msg_alloc(data->eap_type, 1, EAP_CODE_REQUEST, id); if (req == NULL) { wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for " "request"); eap_tls_state(data, FAILURE); return NULL; } wpabuf_put_u8(req, EAP_TLS_FLAGS_START); eap_tls_state(data, CONTINUE); return req; }
/** * eap_tls_process_output - Process outgoing TLS message * @data: Data for TLS processing * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) * @peap_version: Version number for EAP-PEAP/TTLS * @id: EAP identifier for the response * @ret: Return value to use on success * @out_data: Buffer for returning the allocated output buffer * Returns: ret (0 or 1) on success, -1 on failure */ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, int peap_version, u8 id, int ret, struct wpabuf **out_data) { size_t len; u8 *flags; int more_fragments, length_included; if (data->tls_out == NULL) return -1; len = wpabuf_len(data->tls_out) - data->tls_out_pos; wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " "%lu bytes)", (unsigned long) len, (unsigned long) wpabuf_len(data->tls_out)); /* * Limit outgoing message to the configured maximum size. Fragment * message if needed. */ if (len > data->tls_out_limit) { more_fragments = 1; len = data->tls_out_limit; wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " "will follow", (unsigned long) len); } else more_fragments = 0; length_included = data->tls_out_pos == 0 && (wpabuf_len(data->tls_out) > data->tls_out_limit || data->include_tls_length); if (!length_included && eap_type == EAP_TYPE_PEAP && peap_version == 0 && !tls_connection_established(data->eap->ssl_ctx, data->conn)) { /* * Windows Server 2008 NPS really wants to have the TLS Message * length included in phase 0 even for unfragmented frames or * it will get very confused with Compound MAC calculation and * Outer TLVs. */ length_included = 1; } *out_data = eap_tls_msg_alloc(eap_type, 1 + length_included * 4 + len, EAP_CODE_RESPONSE, id); if (*out_data == NULL) return -1; flags = wpabuf_put(*out_data, 1); *flags = peap_version; if (more_fragments) *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; if (length_included) { *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out)); } wpabuf_put_data(*out_data, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, len); data->tls_out_pos += len; if (!more_fragments) eap_peer_tls_reset_output(data); return ret; }