struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { #ifdef CONFIG_TLS_INTERNAL_SERVER u8 *res; size_t res_len; struct wpabuf *out; if (conn->server == NULL) return NULL; if (appl_data) *appl_data = NULL; res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data), wpabuf_len(in_data), &res_len); if (res == NULL && tlsv1_server_established(conn->server)) return wpabuf_alloc(0); if (res == NULL) return NULL; out = wpabuf_alloc_ext_data(res, res_len); if (out == NULL) { os_free(res); return NULL; } return out; #else /* CONFIG_TLS_INTERNAL_SERVER */ return NULL; #endif /* CONFIG_TLS_INTERNAL_SERVER */ }
struct wpabuf * xml_get_base64_item(const char *data, const char *name, enum http_reply_code *ret) { char *msg; struct wpabuf *buf; unsigned char *decoded; size_t len; msg = xml_get_first_item(data, name); if (msg == NULL) { *ret = UPNP_ARG_VALUE_INVALID; return NULL; } decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len); os_free(msg); if (decoded == NULL) { *ret = UPNP_OUT_OF_MEMORY; return NULL; } buf = wpabuf_alloc_ext_data(decoded, len); if (buf == NULL) { os_free(decoded); *ret = UPNP_OUT_OF_MEMORY; return NULL; } return buf; }
static dbus_bool_t _wpa_dbus_dict_entry_get_binarray( DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry) { struct wpa_dbus_dict_entry tmpentry; size_t buflen = 0; int i; if (dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE) return FALSE; entry->array_type = WPAS_DBUS_TYPE_BINARRAY; entry->array_len = 0; entry->binarray_value = NULL; while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) { DBusMessageIter iter_array; if (entry->array_len == buflen) { struct wpabuf **newbuf; buflen += BIN_ARRAY_CHUNK_SIZE; newbuf = os_realloc_array(entry->binarray_value, buflen, BIN_ARRAY_ITEM_SIZE); if (!newbuf) goto cleanup; entry->binarray_value = newbuf; } dbus_message_iter_recurse(iter, &iter_array); if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry) == FALSE) goto cleanup; entry->binarray_value[entry->array_len] = wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value, tmpentry.array_len); if (entry->binarray_value[entry->array_len] == NULL) { wpa_dbus_dict_entry_clear(&tmpentry); goto cleanup; } entry->array_len++; dbus_message_iter_next(iter); } return TRUE; cleanup: for (i = 0; i < (int) entry->array_len; i++) wpabuf_free(entry->binarray_value[i]); os_free(entry->binarray_value); entry->array_len = 0; entry->binarray_value = NULL; return FALSE; }
struct wpabuf * tls_connection_handshake2(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data, int *need_more_data) { #ifdef CONFIG_TLS_INTERNAL_CLIENT u8 *res, *ad; size_t res_len, ad_len; struct wpabuf *out; if (conn->client == NULL) return NULL; ad = NULL; res = tlsv1_client_handshake(conn->client, in_data ? wpabuf_head(in_data) : NULL, in_data ? wpabuf_len(in_data) : 0, &res_len, &ad, &ad_len, need_more_data); if (res == NULL) return NULL; out = wpabuf_alloc_ext_data(res, res_len); if (out == NULL) { os_free(res); os_free(ad); return NULL; } if (appl_data) { if (ad) { *appl_data = wpabuf_alloc_ext_data(ad, ad_len); if (*appl_data == NULL) os_free(ad); } else *appl_data = NULL; } else os_free(ad); return out; #else /* CONFIG_TLS_INTERNAL_CLIENT */ return NULL; #endif /* CONFIG_TLS_INTERNAL_CLIENT */ }
/** * eap_tls_process_input - Process incoming TLS message * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @data: Data for TLS processing * @in_data: Message received from the server * @in_len: Length of in_data * @out_data: Buffer for returning a pointer to application data (if available) * Returns: 0 on success, 1 if more input data is needed, 2 if application data * is available, -1 on failure */ static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, const u8 *in_data, size_t in_len, struct wpabuf **out_data) { const u8 *msg; size_t msg_len; int need_more_input; u8 *appl_data; size_t appl_data_len; msg = eap_peer_tls_data_reassemble(data, in_data, in_len, &msg_len, &need_more_input); if (msg == NULL) return need_more_input ? 1 : -1; /* Full TLS message reassembled - continue handshake processing */ if (data->tls_out) { /* This should not happen.. */ wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending " "tls_out data even though tls_out_len = 0"); os_free(data->tls_out); WPA_ASSERT(data->tls_out == NULL); } appl_data = NULL; data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn, msg, msg_len, &data->tls_out_len, &appl_data, &appl_data_len); eap_peer_tls_reset_input(data); if (appl_data && tls_connection_established(sm->ssl_ctx, data->conn) && !tls_connection_get_failed(sm->ssl_ctx, data->conn)) { wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data", appl_data, appl_data_len); *out_data = wpabuf_alloc_ext_data(appl_data, appl_data_len); if (*out_data == NULL) { os_free(appl_data); return -1; } return 2; } os_free(appl_data); return 0; }
struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct wpabuf *out_data; wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u", in_data ? (unsigned int) wpabuf_len(in_data) : 0); if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) conn->pull_buf_len); os_free(conn->pull_buf); } conn->pull_buf = os_malloc(wpabuf_len(in_data)); if (conn->pull_buf == NULL) return NULL; os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = wpabuf_len(in_data); } SSL_ForceHandshake(conn->fd); if (conn->established && conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = os_malloc(1); } if (conn->push_buf == NULL) return NULL; out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); if (out_data == NULL) os_free(conn->push_buf); conn->push_buf = NULL; conn->push_buf_len = 0; return out_data; }
struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { PRInt32 res; struct wpabuf *buf; wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", (int) wpabuf_len(in_data)); res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0, 0); if (res < 0) { wpa_printf(MSG_ERROR, "NSS: Encryption failed"); return NULL; } if (conn->push_buf == NULL) return NULL; buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); if (buf == NULL) os_free(conn->push_buf); conn->push_buf = NULL; conn->push_buf_len = 0; return buf; }
static void TxEAP(pana_session_t * pacs, pana_packet_t * pktin) { paa_ctx_t * ctx = pacs->ctx; pana_avp_t * eap_payload = NULL; struct wpabuf * wtmp = NULL; struct wpabuf * eap_resp = NULL; if (pktin == NULL) { return; } eap_payload = get_avp_by_code(pktin->pp_avp_list, PAVP_EAP_PAYLOAD, AVP_GET_FIRST); if (!eap_payload) { return; } wtmp = wpabuf_alloc_ext_data(eap_payload->avp_value, eap_payload->avp_length); /* * TODO: */ if (eap_md5_check(ctx->method_data, wtmp)) { eap_md5_process(ctx->eap_config, ctx->method_data, wtmp); } wpabuf_free(wtmp); free_avp(eap_payload); if (eap_md5_isFailure(ctx->method_data)) { EAP_FAILURE_Set(); } else if(eap_md5_isSuccess(ctx->method_data)) { EAP_SUCCESS_Set(); } wpabuf_free(eap_resp); }
static int radius_server_request(struct radius_server_data *data, struct radius_msg *msg, struct sockaddr *from, socklen_t fromlen, struct radius_client *client, const char *from_addr, int from_port, struct radius_session *force_sess) { u8 *eap = NULL; size_t eap_len; int res, state_included = 0; u8 statebuf[4]; unsigned int state; struct radius_session *sess; struct radius_msg *reply; int is_complete = 0; if (force_sess) sess = force_sess; else { res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, sizeof(statebuf)); state_included = res >= 0; if (res == sizeof(statebuf)) { state = WPA_GET_BE32(statebuf); sess = radius_server_get_session(client, state); } else { sess = NULL; } } if (sess) { RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); } else if (state_included) { RADIUS_DEBUG("State attribute included but no session found"); radius_server_reject(data, client, msg, from, fromlen, from_addr, from_port); return -1; } else { sess = radius_server_get_new_session(data, client, msg); if (sess == NULL) { RADIUS_DEBUG("Could not create a new session"); radius_server_reject(data, client, msg, from, fromlen, from_addr, from_port); return -1; } } if (sess->last_from_port == from_port && sess->last_identifier == msg->hdr->identifier && os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) == 0) { RADIUS_DEBUG("Duplicate message from %s", from_addr); data->counters.dup_access_requests++; client->counters.dup_access_requests++; if (sess->last_reply) { res = sendto(data->auth_sock, sess->last_reply->buf, sess->last_reply->buf_used, 0, (struct sockaddr *) from, fromlen); if (res < 0) { perror("sendto[RADIUS SRV]"); } return 0; } RADIUS_DEBUG("No previous reply available for duplicate " "message"); return -1; } eap = radius_msg_get_eap(msg, &eap_len); if (eap == NULL) { RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", from_addr); data->counters.packets_dropped++; client->counters.packets_dropped++; return -1; } RADIUS_DUMP("Received EAP data", eap, eap_len); /* FIX: if Code is Request, Success, or Failure, send Access-Reject; * RFC3579 Sect. 2.6.2. * Include EAP-Response/Nak with no preferred method if * code == request. * If code is not 1-4, discard the packet silently. * Or is this already done by the EAP state machine? */ wpabuf_free(sess->eap_if->eapRespData); sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len); if (sess->eap_if->eapRespData == NULL) os_free(eap); eap = NULL; sess->eap_if->eapResp = TRUE; eap_server_sm_step(sess->eap); if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || sess->eap_if->eapFail) && sess->eap_if->eapReqData) { RADIUS_DUMP("EAP data from the state machine", wpabuf_head(sess->eap_if->eapReqData), wpabuf_len(sess->eap_if->eapReqData)); } else if (sess->eap_if->eapFail) { RADIUS_DEBUG("No EAP data from the state machine, but eapFail " "set"); } else if (eap_sm_method_pending(sess->eap)) { if (sess->last_msg) { radius_msg_free(sess->last_msg); os_free(sess->last_msg); } sess->last_msg = msg; sess->last_from_port = from_port; os_free(sess->last_from_addr); sess->last_from_addr = os_strdup(from_addr); sess->last_fromlen = fromlen; os_memcpy(&sess->last_from, from, fromlen); return -2; } else { RADIUS_DEBUG("No EAP data from the state machine - ignore this" " Access-Request silently (assuming it was a " "duplicate)"); data->counters.packets_dropped++; client->counters.packets_dropped++; return -1; } if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) is_complete = 1; reply = radius_server_encapsulate_eap(data, client, sess, msg); if (reply) { RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); if (wpa_debug_level <= MSG_MSGDUMP) { radius_msg_dump(reply); } switch (reply->hdr->code) { case RADIUS_CODE_ACCESS_ACCEPT: data->counters.access_accepts++; client->counters.access_accepts++; break; case RADIUS_CODE_ACCESS_REJECT: data->counters.access_rejects++; client->counters.access_rejects++; break; case RADIUS_CODE_ACCESS_CHALLENGE: data->counters.access_challenges++; client->counters.access_challenges++; break; } res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0, (struct sockaddr *) from, fromlen); if (res < 0) { perror("sendto[RADIUS SRV]"); } if (sess->last_reply) { radius_msg_free(sess->last_reply); os_free(sess->last_reply); } sess->last_reply = reply; sess->last_from_port = from_port; sess->last_identifier = msg->hdr->identifier; os_memcpy(sess->last_authenticator, msg->hdr->authenticator, 16); } else { data->counters.packets_dropped++; client->counters.packets_dropped++; } if (is_complete) { RADIUS_DEBUG("Removing completed session 0x%x after timeout", sess->sess_id); eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); eloop_register_timeout(10, 0, radius_server_session_remove_timeout, data, sess); } return 0; }