int proxy_tls_recv(rad_listen_t *listener) { int rcode; size_t length; listen_socket_t *sock = listener->data; char buffer[256]; RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; uint8_t *data; if (!sock->data) sock->data = rad_malloc(sock->ssn->offset); data = sock->data; DEBUG3("Proxy SSL socket has data to read"); PTHREAD_MUTEX_LOCK(&sock->mutex); redo: rcode = SSL_read(sock->ssn->ssl, data, 4); if (rcode <= 0) { int err = SSL_get_error(sock->ssn->ssl, rcode); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: rcode = 0; goto redo; case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); case SSL_ERROR_SYSCALL: do_close: PTHREAD_MUTEX_UNLOCK(&sock->mutex); tls_socket_close(listener); return 0; default: while ((err = ERR_get_error())) { DEBUG("proxy recv says %s", ERR_error_string(err, NULL)); } goto do_close; } } length = (data[2] << 8) | data[3]; DEBUG3("Proxy received header saying we have a packet of %u bytes", (unsigned int) length); if (length > sock->ssn->offset) { radlog(L_INFO, "Received packet will be too large! Set \"fragment_size=%u\"", (data[2] << 8) | data[3]); goto do_close; } rcode = SSL_read(sock->ssn->ssl, data + 4, length); if (rcode <= 0) { switch (SSL_get_error(sock->ssn->ssl, rcode)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: rcode = 0; break; case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); goto do_close; default: goto do_close; } } PTHREAD_MUTEX_UNLOCK(&sock->mutex); packet = rad_alloc(0); packet->sockfd = listener->fd; packet->src_ipaddr = sock->other_ipaddr; packet->src_port = sock->other_port; packet->dst_ipaddr = sock->my_ipaddr; packet->dst_port = sock->my_port; packet->code = data[0]; packet->id = data[1]; packet->data_len = length; packet->data = rad_malloc(packet->data_len); memcpy(packet->data, data, packet->data_len); memcpy(packet->vector, packet->data + 4, 16); /* * FIXME: Client MIB updates? */ switch(packet->code) { case PW_AUTHENTICATION_ACK: case PW_ACCESS_CHALLENGE: case PW_AUTHENTICATION_REJECT: fun = rad_authenticate; break; #ifdef WITH_ACCOUNTING case PW_ACCOUNTING_RESPONSE: fun = rad_accounting; break; #endif default: /* * FIXME: Update MIB for packet types? */ radlog(L_ERR, "Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } if (!request_proxy_reply(packet)) { rad_free(&packet); return 0; } return 1; }
int proxy_tls_recv(rad_listen_t *listener) { listen_socket_t *sock = listener->data; char buffer[256]; RADIUS_PACKET *packet; uint8_t *data; ssize_t data_len; if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0; DEBUG3("Proxy SSL socket has data to read"); PTHREAD_MUTEX_LOCK(&sock->mutex); data_len = proxy_tls_read(listener); PTHREAD_MUTEX_UNLOCK(&sock->mutex); if (data_len < 0) { DEBUG("Closing TLS socket to home server"); PTHREAD_MUTEX_LOCK(&sock->mutex); tls_socket_close(listener); PTHREAD_MUTEX_UNLOCK(&sock->mutex); return 0; } if (data_len == 0) return 0; /* not done yet */ data = sock->data; packet = fr_radius_alloc(sock, false); packet->sockfd = listener->fd; packet->src_ipaddr = sock->other_ipaddr; packet->src_port = sock->other_port; packet->dst_ipaddr = sock->my_ipaddr; packet->dst_port = sock->my_port; packet->code = data[0]; packet->id = data[1]; packet->data_len = data_len; packet->data = talloc_array(packet, uint8_t, packet->data_len); memcpy(packet->data, data, packet->data_len); memcpy(packet->vector, packet->data + 4, 16); /* * FIXME: Client MIB updates? */ switch (packet->code) { case PW_CODE_ACCESS_ACCEPT: case PW_CODE_ACCESS_CHALLENGE: case PW_CODE_ACCESS_REJECT: break; #ifdef WITH_ACCOUNTING case PW_CODE_ACCOUNTING_RESPONSE: break; #endif default: /* * FIXME: Update MIB for packet types? */ ERROR("Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, fr_inet_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); fr_radius_free(&packet); return 0; } if (!request_proxy_reply(packet)) { fr_radius_free(&packet); return 0; } return 1; }