static int status_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request) { if (rad_verify(request->packet, NULL, request->client->secret) < 0) { return -1; } return rad_decode(request->packet, NULL, request->client->secret); }
/* * Receive one packet, maybe. */ static int recv_one_packet(int wait_time) { fd_set set; struct timeval tv; rc_request_t *request; RADIUS_PACKET *reply, **packet_p; volatile int max_fd; /* And wait for reply, timing out as necessary */ FD_ZERO(&set); max_fd = fr_packet_list_fd_set(pl, &set); if (max_fd < 0) exit(1); /* no sockets to listen on! */ tv.tv_sec = (wait_time <= 0) ? 0 : wait_time; tv.tv_usec = 0; /* * No packet was received. */ if (select(max_fd, &set, NULL, NULL, &tv) <= 0) return 0; /* * Look for the packet. */ reply = fr_packet_list_recv(pl, &set); if (!reply) { ERROR("Received bad packet"); #ifdef WITH_TCP /* * If the packet is bad, we close the socket. * I'm not sure how to do that now, so we just * die... */ if (proto) exit(1); #endif return -1; /* bad packet */ } /* * We don't use udpfromto. So if we bind to "*", we want * to find replies sent to 192.0.2.4. Therefore, we * force all replies to have the one address we know * about, no matter what real address they were sent to. * * This only works if were not using any of the * Packet-* attributes, or running with 'auto'. */ reply->dst_ipaddr = client_ipaddr; reply->dst_port = client_port; #ifdef WITH_TCP /* * TCP sockets don't use recvmsg(), and thus don't get * the source IP/port. However, since they're TCP, we * know what the source IP/port is, because that's where * we connected to. */ if (ipproto == IPPROTO_TCP) { reply->src_ipaddr = server_ipaddr; reply->src_port = server_port; } #endif packet_p = fr_packet_list_find_byreply(pl, reply); if (!packet_p) { ERROR("Received reply to request we did not send. (id=%d socket %d)", reply->id, reply->sockfd); rad_free(&reply); return -1; /* got reply to packet we didn't send */ } request = fr_packet2myptr(rc_request_t, packet, packet_p); /* * Fails the signature validation: not a real reply. * FIXME: Silently drop it and listen for another packet. */ if (rad_verify(reply, request->packet, secret) < 0) { REDEBUG("Reply verification failed"); stats.lost++; goto packet_done; /* shared secret is incorrect */ } if (print_filename) { RDEBUG("%s response code %d", request->files->packets, reply->code); } deallocate_id(request); request->reply = reply; reply = NULL; /* * If this fails, we're out of memory. */ if (rad_decode(request->reply, request->packet, secret) != 0) { REDEBUG("Reply decode failed"); stats.lost++; goto packet_done; } fr_packet_header_print(fr_log_fp, request->reply, true); if (fr_debug_lvl > 0) vp_printlist(fr_log_fp, request->reply->vps); /* * Increment counters... */ switch (request->reply->code) { case PW_CODE_ACCESS_ACCEPT: case PW_CODE_ACCOUNTING_RESPONSE: case PW_CODE_COA_ACK: case PW_CODE_DISCONNECT_ACK: stats.accepted++; break; case PW_CODE_ACCESS_CHALLENGE: break; default: stats.rejected++; } /* * If we had an expected response code, check to see if the * packet matched that. */ if (request->reply->code != request->filter_code) { if (is_radius_code(request->reply->code)) { REDEBUG("%s: Expected %s got %s", request->name, fr_packet_codes[request->filter_code], fr_packet_codes[request->reply->code]); } else { REDEBUG("%s: Expected %u got %i", request->name, request->filter_code, request->reply->code); } stats.failed++; /* * Check if the contents of the packet matched the filter */ } else if (!request->filter) { stats.passed++; } else { VALUE_PAIR const *failed[2]; fr_pair_list_sort(&request->reply->vps, fr_pair_cmp_by_da_tag); if (fr_pair_validate(failed, request->filter, request->reply->vps)) { RDEBUG("%s: Response passed filter", request->name); stats.passed++; } else { fr_pair_validate_debug(request, failed); REDEBUG("%s: Response for failed filter", request->name); stats.failed++; } } if (request->resend == resend_count) { request->done = true; } packet_done: rad_free(&request->reply); rad_free(&reply); /* may be NULL */ return 0; }
/* * Receive one packet, maybe. */ static int recv_one_packet(int wait_time) { fd_set set; struct timeval tv; radclient_t *radclient; RADIUS_PACKET *reply, **request_p; volatile int max_fd; /* And wait for reply, timing out as necessary */ FD_ZERO(&set); max_fd = fr_packet_list_fd_set(pl, &set); if (max_fd < 0) exit(1); /* no sockets to listen on! */ if (wait_time <= 0) { tv.tv_sec = 0; } else { tv.tv_sec = wait_time; } tv.tv_usec = 0; /* * No packet was received. */ if (select(max_fd, &set, NULL, NULL, &tv) <= 0) { return 0; } /* * Look for the packet. */ reply = fr_packet_list_recv(pl, &set); if (!reply) { fprintf(stderr, "radclient: received bad packet: %s\n", fr_strerror()); #ifdef WITH_TCP /* * If the packet is bad, we close the socket. * I'm not sure how to do that now, so we just * die... */ if (proto) exit(1); #endif return -1; /* bad packet */ } /* * udpfromto issues. We may have bound to "*", * and we want to find the replies that are sent to * (say) 127.0.0.1. */ reply->dst_ipaddr = client_ipaddr; reply->dst_port = client_port; #ifdef WITH_TCP reply->src_ipaddr = server_ipaddr; reply->src_port = server_port; #endif if (fr_debug_flag > 2) print_hex(reply); request_p = fr_packet_list_find_byreply(pl, reply); if (!request_p) { fprintf(stderr, "radclient: received response to request we did not send. (id=%d socket %d)\n", reply->id, reply->sockfd); rad_free(&reply); return -1; /* got reply to packet we didn't send */ } radclient = fr_packet2myptr(radclient_t, request, request_p); /* * Fails the signature validation: not a real reply. * FIXME: Silently drop it and listen for another packet. */ if (rad_verify(reply, radclient->request, secret) < 0) { fr_perror("rad_verify"); totallost++; goto packet_done; /* shared secret is incorrect */ } fr_packet_list_yank(pl, radclient->request); if (print_filename) printf("%s:%d %d\n", radclient->filename, radclient->packet_number, reply->code); deallocate_id(radclient); radclient->reply = reply; reply = NULL; /* * If this fails, we're out of memory. */ if (rad_decode(radclient->reply, radclient->request, secret) != 0) { fr_perror("rad_decode"); totallost++; goto packet_done; } /* libradius debug already prints out the value pairs for us */ if (!fr_debug_flag && do_output) { printf("Received response ID %d, code %d, length = %zd\n", radclient->reply->id, radclient->reply->code, radclient->reply->data_len); vp_printlist(stdout, radclient->reply->vps); } if ((radclient->reply->code == PW_AUTHENTICATION_ACK) || (radclient->reply->code == PW_ACCOUNTING_RESPONSE) || (radclient->reply->code == PW_COA_ACK) || (radclient->reply->code == PW_DISCONNECT_ACK)) { success = 1; /* have a good response */ totalapp++; } else { totaldeny++; } if (radclient->resend == resend_count) { radclient->done = 1; } packet_done: rad_free(&radclient->reply); rad_free(&reply); /* may be NULL */ return 0; }
static int send_packet(RADIUS_PACKET *req, RADIUS_PACKET **rep) { int i; struct timeval tv; if (!req || !rep || !*rep) return -1; for (i = 0; i < retries; i++) { fd_set rdfdesc; debug_packet(req, R_SENT); if (rad_send(req, NULL, secret) < 0) { fr_perror("radeapclient"); exit(1); } /* And wait for reply, timing out as necessary */ FD_ZERO(&rdfdesc); FD_SET(req->sockfd, &rdfdesc); tv.tv_sec = (int)timeout; tv.tv_usec = 1000000 * (timeout - (int) timeout); /* Something's wrong if we don't get exactly one fd. */ if (select(req->sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) { continue; } *rep = rad_recv(req->sockfd, 0); if (*rep != NULL) { /* * If we get a response from a machine * which we did NOT send a request to, * then complain. */ if (((*rep)->src_ipaddr.af != req->dst_ipaddr.af) || (memcmp(&(*rep)->src_ipaddr.ipaddr, &req->dst_ipaddr.ipaddr, ((req->dst_ipaddr.af == AF_INET ? /* AF_INET6? */ sizeof(req->dst_ipaddr.ipaddr.ip4addr) : /* FIXME: AF_INET6 */ sizeof(req->dst_ipaddr.ipaddr.ip6addr)))) != 0) || ((*rep)->src_port != req->dst_port)) { char src[128], dst[128]; ip_ntoh(&(*rep)->src_ipaddr, src, sizeof(src)); ip_ntoh(&req->dst_ipaddr, dst, sizeof(dst)); fprintf(stderr, "radclient: ERROR: Sent request to host %s port %d, got response from host %s port %d\n!", dst, req->dst_port, src, (*rep)->src_port); exit(1); } break; } else { /* NULL: couldn't receive the packet */ fr_perror("radclient"); exit(1); } } /* No response or no data read (?) */ if (i == retries) { fprintf(stderr, "radclient: no response from server\n"); exit(1); } /* * FIXME: Discard the packet & listen for another. * * Hmm... we should really be using eapol_test, which does * a lot more than radeapclient. */ if (rad_verify(*rep, req, secret) != 0) { fr_perror("rad_verify"); exit(1); } if (rad_decode(*rep, req, secret) != 0) { fr_perror("rad_decode"); exit(1); } /* libradius debug already prints out the value pairs for us */ if (!fr_debug_flag && do_output) { debug_packet(*rep, R_RECV); } if((*rep)->code == PW_CODE_AUTHENTICATION_ACK) { totalapp++; } else if ((*rep)->code == PW_CODE_AUTHENTICATION_REJECT) { totaldeny++; } return 0; }
/* * Receive one packet, maybe. */ static int recv_one_packet(int wait_time) { fd_set set; struct timeval tv; rc_request_t *request; RADIUS_PACKET *reply, **packet_p; volatile int max_fd; /* And wait for reply, timing out as necessary */ FD_ZERO(&set); max_fd = fr_packet_list_fd_set(pl, &set); if (max_fd < 0) exit(1); /* no sockets to listen on! */ if (wait_time <= 0) { tv.tv_sec = 0; } else { tv.tv_sec = wait_time; } tv.tv_usec = 0; /* * No packet was received. */ if (select(max_fd, &set, NULL, NULL, &tv) <= 0) { return 0; } /* * Look for the packet. */ reply = fr_packet_list_recv(pl, &set); if (!reply) { ERROR("Received bad packet"); #ifdef WITH_TCP /* * If the packet is bad, we close the socket. * I'm not sure how to do that now, so we just * die... */ if (proto) exit(1); #endif return -1; /* bad packet */ } /* * udpfromto issues. We may have bound to "*", * and we want to find the replies that are sent to * (say) 127.0.0.1. */ reply->dst_ipaddr = client_ipaddr; reply->dst_port = client_port; #ifdef WITH_TCP reply->src_ipaddr = server_ipaddr; reply->src_port = server_port; #endif packet_p = fr_packet_list_find_byreply(pl, reply); if (!packet_p) { ERROR("Received reply to request we did not send. (id=%d socket %d)", reply->id, reply->sockfd); rad_free(&reply); return -1; /* got reply to packet we didn't send */ } request = fr_packet2myptr(rc_request_t, packet, packet_p); /* * Fails the signature validation: not a real reply. * FIXME: Silently drop it and listen for another packet. */ if (rad_verify(reply, request->packet, secret) < 0) { REDEBUG("Reply verification failed"); stats.lost++; goto packet_done; /* shared secret is incorrect */ } if (print_filename) { RDEBUG("%s response code %d", request->files->packets, reply->code); } deallocate_id(request); request->reply = reply; reply = NULL; /* * If this fails, we're out of memory. */ if (rad_decode(request->reply, request->packet, secret) != 0) { REDEBUG("Reply decode failed"); stats.lost++; goto packet_done; } /* * Increment counters... */ switch (request->reply->code) { case PW_CODE_AUTHENTICATION_ACK: case PW_CODE_ACCOUNTING_RESPONSE: case PW_CODE_COA_ACK: case PW_CODE_DISCONNECT_ACK: stats.accepted++; break; case PW_CODE_ACCESS_CHALLENGE: break; default: stats.rejected++; } /* * If we had an expected response code, check to see if the * packet matched that. */ if (request->reply->code != request->filter_code) { if (is_radius_code(request->packet_code)) { REDEBUG("Expected %s got %s", fr_packet_codes[request->filter_code], fr_packet_codes[request->reply->code]); } else { REDEBUG("Expected %u got %i", request->filter_code, request->reply->code); } stats.failed++; /* * Check if the contents of the packet matched the filter */ } else if (!request->filter) { stats.passed++; } else { VALUE_PAIR const *failed[2]; pairsort(&request->reply->vps, attrtagcmp); if (pairvalidate(failed, request->filter, request->reply->vps)) { RDEBUG("Response passed filter"); stats.passed++; } else { pairvalidate_debug(request, failed); REDEBUG("Response failed filter"); stats.failed++; } } if (request->resend == resend_count) { request->done = true; } packet_done: rad_free(&request->reply); rad_free(&reply); /* may be NULL */ return 0; }
/* * Receive one packet, maybe. */ static int recv_one_packet(int wait_time) { fd_set set; struct timeval tv; radclient_t myclient, radclient; RADIUS_PACKET myrequest, *reply; /* And wait for reply, timing out as necessary */ FD_ZERO(&set); FD_SET(sockfd, &set); if (wait_time <= 0) { tv.tv_sec = 0; } else { tv.tv_sec = wait_time; } tv.tv_usec = 0; /* * No packet was received. */ if (select(sockfd + 1, &set, NULL, NULL, &tv) != 1) { return 0; } /* * Look for the packet. */ reply = rad_recv(sockfd); if (!reply) { fprintf(stderr, "radclient: received bad packet: %s\n", librad_errstr); return -1; /* bad packet */ } myclient.request = &myrequest; myrequest.id = reply->id; myrequest.dst_ipaddr = reply->src_ipaddr; myrequest.dst_port = reply->src_port; radclient.reply = reply; /* * FIXME: Do stuff to process the reply. */ #if 0 if (rad_verify(reply, radclient->request, secret) != 0) { printf("rad_verify\n"); librad_perror("rad_verify"); totallost++; goto packet_done; /* shared secret is incorrect */ } #endif if (rad_decode(reply, radclient.request, secret) != 0) { librad_perror("rad_decode"); totallost++; goto packet_done; /* shared secret is incorrect */ } /* libradius debug already prints out the value pairs for us */ if (reply->code != PW_AUTHENTICATION_REJECT) { totalapp++; } else { totaldeny++; } packet_done: /* * Once we've sent the packet as many times as requested, * mark it done. */ return reply->code; }
static int send_packet(RADIUS_PACKET *req, RADIUS_PACKET **rep) { int i; struct timeval tv; for (i = 0; i < retries; i++) { fd_set rdfdesc; rad_send(req, NULL, secret); /* And wait for reply, timing out as necessary */ FD_ZERO(&rdfdesc); FD_SET(req->sockfd, &rdfdesc); tv.tv_sec = (int)timeout; tv.tv_usec = 1000000 * (timeout - (int) timeout); /* Something's wrong if we don't get exactly one fd. */ if (select(req->sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) { continue; } *rep = rad_recv(req->sockfd); if (*rep != NULL) { /* * If we get a response from a machine * which we did NOT send a request to, * then complain. */ if (((*rep)->src_ipaddr != req->dst_ipaddr) || ((*rep)->src_port != req->dst_port)) { char src[64], dst[64]; ip_ntoa(src, (*rep)->src_ipaddr); ip_ntoa(dst, req->dst_ipaddr); fprintf(stderr, "radclient: ERROR: Sent request to host %s port %d, got response from host %s port %d\n!", dst, req->dst_port, src, (*rep)->src_port); exit(1); } break; } else { /* NULL: couldn't receive the packet */ librad_perror("radclient:"); exit(1); } } /* No response or no data read (?) */ if (i == retries) { fprintf(stderr, "radclient: no response from server\n"); exit(1); } /* * FIXME: Discard the packet & listen for another. * * Hmm... we should really be using eapol_test, which does * a lot more than radeapclient. */ if (rad_verify(*rep, req, secret) != 0) { librad_perror("rad_verify"); exit(1); } if (rad_decode(*rep, req, secret) != 0) { librad_perror("rad_decode"); exit(1); } /* libradius debug already prints out the value pairs for us */ if (!librad_debug && do_output) { printf("Received response ID %d, code %d, length = %d\n", (*rep)->id, (*rep)->code, (*rep)->data_len); vp_printlist(stdout, (*rep)->vps); } if((*rep)->code == PW_AUTHENTICATION_ACK) { totalapp++; } else { totaldeny++; } return 0; }