/* * Send a response packet */ int dual_tls_send(rad_listen_t *listener, REQUEST *request) { listen_socket_t *sock = listener->data; rad_assert(request->listener == listener); rad_assert(listener->send == dual_tls_send); /* * Accounting reject's are silently dropped. * * We do it here to avoid polluting the rest of the * code with this knowledge */ if (request->reply->code == 0) return 0; /* * Pack the VPs */ if (rad_encode(request->reply, request->packet, request->client->secret) < 0) { RDEBUG("Failed encoding packet: %s", fr_strerror()); return 0; } /* * Sign the packet. */ if (rad_sign(request->reply, request->packet, request->client->secret) < 0) { RDEBUG("Failed signing packet: %s", fr_strerror()); return 0; } PTHREAD_MUTEX_LOCK(&sock->mutex); /* * Write the packet to the SSL buffers. */ sock->ssn->record_plus(&sock->ssn->clean_in, request->reply->data, request->reply->data_len); /* * Do SSL magic to get encrypted data. */ tls_handshake_send(request, sock->ssn); /* * And finally write the data to the socket. */ if (sock->ssn->dirty_out.used > 0) { dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used); tls_socket_write(listener, request); } PTHREAD_MUTEX_UNLOCK(&sock->mutex); return 0; }
/* * Convert VALUE_PAIR's to diameter attributes, and write them * to an SSL session. * * The ONLY VALUE_PAIR's which may be passed to this function * are ones which can go inside of a RADIUS (i.e. diameter) * packet. So no server-configuration attributes, or the like. */ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *first) { /* * RADIUS packets are no more than 4k in size, so if * we've got more than 4k of data to write, it's very * bad. */ uint8_t buffer[4096]; uint8_t *p; uint32_t attr; uint32_t length; uint32_t vendor; size_t total; uint64_t attr64; VALUE_PAIR *vp; vp_cursor_t cursor; p = buffer; total = 0; for (vp = fr_cursor_init(&cursor, &first); vp; vp = fr_cursor_next(&cursor)) { /* * Too much data: die. */ if ((total + vp->vp_length + 12) >= sizeof(buffer)) { RDEBUG2("output buffer is full!"); return 0; } /* * Hmm... we don't group multiple EAP-Messages * together. Maybe we should... */ length = vp->vp_length; vendor = vp->da->vendor; if (vendor != 0) { attr = vp->da->attr & 0xffff; length |= ((uint32_t)1 << 31); } else { attr = vp->da->attr; } /* * Hmm... set the M bit for all attributes? */ length |= (1 << 30); attr = ntohl(attr); memcpy(p, &attr, sizeof(attr)); p += 4; total += 4; length += 8; /* includes 8 bytes of attr & length */ if (vendor != 0) { length += 4; /* include 4 bytes of vendor */ length = ntohl(length); memcpy(p, &length, sizeof(length)); p += 4; total += 4; vendor = ntohl(vendor); memcpy(p, &vendor, sizeof(vendor)); p += 4; total += 4; } else { length = ntohl(length); memcpy(p, &length, sizeof(length)); p += 4; total += 4; } switch (vp->da->type) { case PW_TYPE_INTEGER: case PW_TYPE_DATE: attr = htonl(vp->vp_integer); /* stored in host order */ memcpy(p, &attr, sizeof(attr)); length = 4; break; case PW_TYPE_INTEGER64: attr64 = htonll(vp->vp_integer64); /* stored in host order */ memcpy(p, &attr64, sizeof(attr64)); length = 8; break; case PW_TYPE_IPV4_ADDR: memcpy(p, &vp->vp_ipaddr, 4); /* network order */ length = 4; break; case PW_TYPE_STRING: case PW_TYPE_OCTETS: default: memcpy(p, vp->vp_strvalue, vp->vp_length); length = vp->vp_length; break; } /* * Skip to the end of the data. */ p += length; total += length; /* * Align the data to a multiple of 4 bytes. */ if ((total & 0x03) != 0) { size_t i; length = 4 - (total & 0x03); for (i = 0; i < length; i++) { *p = '\0'; p++; total++; } } } /* loop over the VP's to write. */ /* * Write the data in the buffer to the SSL session. */ if (total > 0) { #ifndef NDEBUG size_t i; if ((rad_debug_lvl > 2) && fr_log_fp) { for (i = 0; i < total; i++) { if ((i & 0x0f) == 0) fprintf(fr_log_fp, " TTLS tunnel data out %04x: ", (int) i); fprintf(fr_log_fp, "%02x ", buffer[i]); if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n"); } if ((total & 0x0f) != 0) fprintf(fr_log_fp, "\n"); } #endif (tls_session->record_plus)(&tls_session->clean_in, buffer, total); /* * FIXME: Check the return code. */ tls_handshake_send(request, tls_session); } /* * Everything's OK. */ return 1; }
/* * Send a response packet */ int dual_tls_send(rad_listen_t *listener, REQUEST *request) { listen_socket_t *sock = listener->data; VERIFY_REQUEST(request); rad_assert(request->listener == listener); rad_assert(listener->send == dual_tls_send); if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0; /* * Accounting reject's are silently dropped. * * We do it here to avoid polluting the rest of the * code with this knowledge */ if (request->reply->code == 0) return 0; /* * Pack the VPs */ if (rad_encode(request->reply, request->packet, request->client->secret) < 0) { RERROR("Failed encoding packet: %s", fr_strerror()); return 0; } if (request->reply->data_len > (MAX_PACKET_LEN - 100)) { RWARN("Packet is large, and possibly truncated - %zd vs max %d", request->reply->data_len, MAX_PACKET_LEN); } /* * Sign the packet. */ if (rad_sign(request->reply, request->packet, request->client->secret) < 0) { RERROR("Failed signing packet: %s", fr_strerror()); return 0; } PTHREAD_MUTEX_LOCK(&sock->mutex); /* * Write the packet to the SSL buffers. */ sock->ssn->record_plus(&sock->ssn->clean_in, request->reply->data, request->reply->data_len); dump_hex("TUNNELED DATA < ", sock->ssn->clean_in.data, sock->ssn->clean_in.used); /* * Do SSL magic to get encrypted data. */ tls_handshake_send(request, sock->ssn); /* * And finally write the data to the socket. */ if (sock->ssn->dirty_out.used > 0) { dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used); tls_socket_write(listener, request); } PTHREAD_MUTEX_UNLOCK(&sock->mutex); return 0; }