static void send_stop_packet(discovery_service *svc) { void *buffer; size_t len = peerton(peerstore_get_local_peer(svc->peers), &buffer); jnx_uint8 *message = malloc(4 + len); memcpy(message, "STOP", 4); memcpy(message + 4, buffer, len); jnx_socket_udp_send(svc->sock_send, svc->broadcast_group_address, port_to_string(svc), message, len + 4); #ifdef DEBUG debug_packet(svc, "STOP"); #endif }
/** * cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply * * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer */ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg) { struct cros_ec_spi *ec_spi = ec_dev->priv; struct spi_transfer trans; struct spi_message msg; int i, len; u8 *ptr; int sum; int ret = 0, final_ret; /* * We have the shared ec_dev buffer plus we do lots of separate spi_sync * calls, so we need to make sure only one person is using this at a * time. */ mutex_lock(&ec_spi->lock); len = cros_ec_prepare_tx(ec_dev, ec_msg); dev_dbg(ec_dev->dev, "prepared, len=%d\n", len); /* If it's too soon to do another transaction, wait */ if (ec_spi->last_transfer_ns) { unsigned long delay; /* The delay completed so far */ delay = ktime_get_ns() - ec_spi->last_transfer_ns; if (delay < EC_SPI_RECOVERY_TIME_NS) ndelay(EC_SPI_RECOVERY_TIME_NS - delay); } /* Transmit phase - send our message */ debug_packet(ec_dev->dev, "out", ec_dev->dout, len); memset(&trans, 0, sizeof(trans)); trans.tx_buf = ec_dev->dout; trans.len = len; trans.cs_change = 1; spi_message_init(&msg); spi_message_add_tail(&trans, &msg); ret = spi_sync(ec_spi->spi, &msg); /* Get the response */ if (!ret) { ret = cros_ec_spi_receive_response(ec_dev, ec_msg->insize + EC_MSG_TX_PROTO_BYTES); } else { dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); } /* * Turn off CS, possibly adding a delay to ensure the rising edge * doesn't come too soon after the end of the data. */ spi_message_init(&msg); memset(&trans, 0, sizeof(trans)); trans.delay_usecs = ec_spi->end_of_msg_delay; spi_message_add_tail(&trans, &msg); final_ret = spi_sync(ec_spi->spi, &msg); ec_spi->last_transfer_ns = ktime_get_ns(); if (!ret) ret = final_ret; if (ret < 0) { dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); goto exit; } ptr = ec_dev->din; /* check response error code */ ec_msg->result = ptr[0]; ret = cros_ec_check_result(ec_dev, ec_msg); if (ret) goto exit; len = ptr[1]; sum = ptr[0] + ptr[1]; if (len > ec_msg->insize) { dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)", len, ec_msg->insize); ret = -ENOSPC; goto exit; } /* copy response packet payload and compute checksum */ for (i = 0; i < len; i++) { sum += ptr[i + 2]; if (ec_msg->insize) ec_msg->indata[i] = ptr[i + 2]; } sum &= 0xff; debug_packet(ec_dev->dev, "in", ptr, len + 3); if (sum != ptr[len + 2]) { dev_err(ec_dev->dev, "bad packet checksum, expected %02x, got %02x\n", sum, ptr[len + 2]); ret = -EBADMSG; goto exit; } ret = len; exit: mutex_unlock(&ec_spi->lock); return ret; }
/** * cros_ec_spi_receive_response - Receive a response from the EC. * * This function has two phases: reading the preamble bytes (since if we read * data from the EC before it is ready to send, we just get preamble) and * reading the actual message. * * The received data is placed into ec_dev->din. * * @ec_dev: ChromeOS EC device * @need_len: Number of message bytes we need to read */ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev, int need_len) { struct cros_ec_spi *ec_spi = ec_dev->priv; struct spi_transfer trans; struct spi_message msg; u8 *ptr, *end; int ret; unsigned long deadline; int todo; /* Receive data until we see the header byte */ deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS); while (true) { unsigned long start_jiffies = jiffies; memset(&trans, 0, sizeof(trans)); trans.cs_change = 1; trans.rx_buf = ptr = ec_dev->din; trans.len = EC_MSG_PREAMBLE_COUNT; spi_message_init(&msg); spi_message_add_tail(&trans, &msg); ret = spi_sync(ec_spi->spi, &msg); if (ret < 0) { dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); return ret; } for (end = ptr + EC_MSG_PREAMBLE_COUNT; ptr != end; ptr++) { if (*ptr == EC_MSG_HEADER) { dev_dbg(ec_dev->dev, "msg found at %zd\n", ptr - ec_dev->din); break; } } if (ptr != end) break; /* * Use the time at the start of the loop as a timeout. This * gives us one last shot at getting the transfer and is useful * in case we got context switched out for a while. */ if (time_after(start_jiffies, deadline)) { dev_warn(ec_dev->dev, "EC failed to respond in time\n"); return -ETIMEDOUT; } } /* * ptr now points to the header byte. Copy any valid data to the * start of our buffer */ todo = end - ++ptr; BUG_ON(todo < 0 || todo > ec_dev->din_size); todo = min(todo, need_len); memmove(ec_dev->din, ptr, todo); ptr = ec_dev->din + todo; dev_dbg(ec_dev->dev, "need %d, got %d bytes from preamble\n", need_len, todo); need_len -= todo; /* Receive data until we have it all */ while (need_len > 0) { /* * We can't support transfers larger than the SPI FIFO size * unless we have DMA. We don't have DMA on the ISP SPI ports * for Exynos. We need a way of asking SPI driver for * maximum-supported transfer size. */ todo = min(need_len, 256); dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%zd\n", todo, need_len, ptr - ec_dev->din); memset(&trans, 0, sizeof(trans)); trans.cs_change = 1; trans.rx_buf = ptr; trans.len = todo; spi_message_init(&msg); spi_message_add_tail(&trans, &msg); /* send command to EC and read answer */ BUG_ON((u8 *)trans.rx_buf - ec_dev->din + todo > ec_dev->din_size); ret = spi_sync(ec_spi->spi, &msg); if (ret < 0) { dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); return ret; } debug_packet(ec_dev->dev, "interim", ptr, todo); ptr += todo; need_len -= todo; } dev_dbg(ec_dev->dev, "loop done, ptr=%zd\n", ptr - ec_dev->din); return 0; }
static int sendrecv_eap(RADIUS_PACKET *rep) { RADIUS_PACKET *req = NULL; VALUE_PAIR *vp, *vpnext; int tried_eap_md5 = 0; if (!rep) return -1; /* * Keep a copy of the the User-Password attribute. */ if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, vp->vp_strvalue, sizeof(password)); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, vp->vp_strvalue, sizeof(password)); /* * Otherwise keep a copy of the CHAP-Password attribute. */ } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, vp->vp_strvalue, sizeof(password)); } else { *password = '******'; } again: rep->id++; /* * if there are EAP types, encode them into an EAP-Message * */ map_eap_methods(rep); /* * Fix up Digest-Attributes issues */ for (vp = rep->vps; vp != NULL; vp = vp->next) { switch (vp->da->attr) { default: break; case PW_DIGEST_REALM: case PW_DIGEST_NONCE: case PW_DIGEST_METHOD: case PW_DIGEST_URI: case PW_DIGEST_QOP: case PW_DIGEST_ALGORITHM: case PW_DIGEST_BODY_DIGEST: case PW_DIGEST_CNONCE: case PW_DIGEST_NONCE_COUNT: case PW_DIGEST_USER_NAME: /* overlapping! */ { DICT_ATTR const *da; uint8_t *p, *q; p = talloc_array(vp, uint8_t, vp->length + 2); memcpy(p + 2, vp->vp_octets, vp->length); p[0] = vp->da->attr - PW_DIGEST_REALM + 1; vp->length += 2; p[1] = vp->length; da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0); vp->da = da; /* * Re-do pairmemsteal ourselves, * because we play games with * vp->da, and pairmemsteal goes * to GREAT lengths to sanitize * and fix and change and * double-check the various * fields. */ memcpy(&q, &vp->vp_octets, sizeof(q)); talloc_free(q); vp->vp_octets = talloc_steal(vp, p); vp->type = VT_DATA; VERIFY_VP(vp); } break; } } /* * If we've already sent a packet, free up the old * one, and ensure that the next packet has a unique * ID and authentication vector. */ if (rep->data) { talloc_free(rep->data); rep->data = NULL; } fr_md5_calc(rep->vector, rep->vector, sizeof(rep->vector)); if (*password != '\0') { if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); uint8_t *p; p = talloc_zero_array(vp, uint8_t, 17); rad_chap_encode(rep, p, rep->id, vp); pairmemsteal(vp, p); } } /* there WAS a password */ /* send the response, wait for the next request */ send_packet(rep, &req); if (!req) return -1; /* okay got back the packet, go and decode the EAP-Message. */ unmap_eap_methods(req); debug_packet(req, R_RECV); /* now look for the code type. */ for (vp = req->vps; vp != NULL; vp = vpnext) { vpnext = vp->next; switch (vp->da->attr) { default: break; case ATTRIBUTE_EAP_BASE+PW_EAP_MD5: if(respond_eap_md5(req, rep) && tried_eap_md5 < 3) { tried_eap_md5++; goto again; } break; case ATTRIBUTE_EAP_BASE+PW_EAP_SIM: if(respond_eap_sim(req, rep)) { goto again; } break; } } return 1; }
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; }
/** * cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply * * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer */ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev, struct cros_ec_command *ec_msg) { struct cros_ec_spi *ec_spi = ec_dev->priv; struct spi_transfer trans; struct spi_message msg; int i, len; u8 *ptr; u8 *rx_buf; int sum; int ret = 0, final_ret; len = cros_ec_prepare_tx(ec_dev, ec_msg); dev_dbg(ec_dev->dev, "prepared, len=%d\n", len); /* If it's too soon to do another transaction, wait */ if (ec_spi->last_transfer_ns) { unsigned long delay; /* The delay completed so far */ delay = ktime_get_ns() - ec_spi->last_transfer_ns; if (delay < EC_SPI_RECOVERY_TIME_NS) ndelay(EC_SPI_RECOVERY_TIME_NS - delay); } rx_buf = kzalloc(len, GFP_KERNEL); if (!rx_buf) { ret = -ENOMEM; goto exit; } /* Transmit phase - send our message */ debug_packet(ec_dev->dev, "out", ec_dev->dout, len); memset(&trans, 0, sizeof(trans)); trans.tx_buf = ec_dev->dout; trans.rx_buf = rx_buf; trans.len = len; trans.cs_change = 1; spi_message_init(&msg); spi_message_add_tail(&trans, &msg); ret = spi_sync(ec_spi->spi, &msg); /* Get the response */ if (!ret) { /* Verify that EC can process command */ for (i = 0; i < len; i++) { switch (rx_buf[i]) { case EC_SPI_PAST_END: case EC_SPI_RX_BAD_DATA: case EC_SPI_NOT_READY: ret = -EAGAIN; ec_msg->result = EC_RES_IN_PROGRESS; default: break; } if (ret) break; } if (!ret) ret = cros_ec_spi_receive_response(ec_dev, ec_msg->insize + EC_MSG_TX_PROTO_BYTES); } else { dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); } final_ret = terminate_request(ec_dev); if (!ret) ret = final_ret; if (ret < 0) goto exit; ptr = ec_dev->din; /* check response error code */ ec_msg->result = ptr[0]; ret = cros_ec_check_result(ec_dev, ec_msg); if (ret) goto exit; len = ptr[1]; sum = ptr[0] + ptr[1]; if (len > ec_msg->insize) { dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)", len, ec_msg->insize); ret = -ENOSPC; goto exit; } /* copy response packet payload and compute checksum */ for (i = 0; i < len; i++) { sum += ptr[i + 2]; if (ec_msg->insize) ec_msg->data[i] = ptr[i + 2]; } sum &= 0xff; debug_packet(ec_dev->dev, "in", ptr, len + 3); if (sum != ptr[len + 2]) { dev_err(ec_dev->dev, "bad packet checksum, expected %02x, got %02x\n", sum, ptr[len + 2]); ret = -EBADMSG; goto exit; } ret = len; exit: kfree(rx_buf); if (ec_msg->command == EC_CMD_REBOOT_EC) msleep(EC_REBOOT_DELAY_MS); return ret; }
/** * cros_ec_spi_receive_response - Receive a response from the EC. * * This function has two phases: reading the preamble bytes (since if we read * data from the EC before it is ready to send, we just get preamble) and * reading the actual message. * * The received data is placed into ec_dev->din. * * @ec_dev: ChromeOS EC device * @need_len: Number of message bytes we need to read */ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev, int need_len) { u8 *ptr, *end; int ret; unsigned long deadline; int todo; BUG_ON(EC_MSG_PREAMBLE_COUNT > ec_dev->din_size); /* Receive data until we see the header byte */ deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS); while (true) { unsigned long start_jiffies = jiffies; ret = receive_n_bytes(ec_dev, ec_dev->din, EC_MSG_PREAMBLE_COUNT); if (ret < 0) return ret; ptr = ec_dev->din; for (end = ptr + EC_MSG_PREAMBLE_COUNT; ptr != end; ptr++) { if (*ptr == EC_SPI_FRAME_START) { dev_dbg(ec_dev->dev, "msg found at %zd\n", ptr - ec_dev->din); break; } } if (ptr != end) break; /* * Use the time at the start of the loop as a timeout. This * gives us one last shot at getting the transfer and is useful * in case we got context switched out for a while. */ if (time_after(start_jiffies, deadline)) { dev_warn(ec_dev->dev, "EC failed to respond in time\n"); return -ETIMEDOUT; } } /* * ptr now points to the header byte. Copy any valid data to the * start of our buffer */ todo = end - ++ptr; BUG_ON(todo < 0 || todo > ec_dev->din_size); todo = min(todo, need_len); memmove(ec_dev->din, ptr, todo); ptr = ec_dev->din + todo; dev_dbg(ec_dev->dev, "need %d, got %d bytes from preamble\n", need_len, todo); need_len -= todo; /* Receive data until we have it all */ while (need_len > 0) { /* * We can't support transfers larger than the SPI FIFO size * unless we have DMA. We don't have DMA on the ISP SPI ports * for Exynos. We need a way of asking SPI driver for * maximum-supported transfer size. */ todo = min(need_len, 256); dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%zd\n", todo, need_len, ptr - ec_dev->din); ret = receive_n_bytes(ec_dev, ptr, todo); if (ret < 0) return ret; debug_packet(ec_dev->dev, "interim", ptr, todo); ptr += todo; need_len -= todo; } dev_dbg(ec_dev->dev, "loop done, ptr=%zd\n", ptr - ec_dev->din); return 0; }
/** * cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply * * @ec_dev: ChromeOS EC device * @ec_msg: Message to transfer */ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev, struct cros_ec_msg *ec_msg) { struct cros_ec_spi *ec_spi = ec_dev->priv; struct spi_transfer trans; struct spi_message msg; int i, len; u8 *ptr; int sum; int ret = 0, final_ret; struct timespec ts; len = cros_ec_prepare_tx(ec_dev, ec_msg); dev_dbg(ec_dev->dev, "prepared, len=%d\n", len); /* If it's too soon to do another transaction, wait */ if (ec_spi->last_transfer_ns) { struct timespec ts; unsigned long delay; /* The delay completed so far */ ktime_get_ts(&ts); delay = timespec_to_ns(&ts) - ec_spi->last_transfer_ns; if (delay < EC_SPI_RECOVERY_TIME_NS) ndelay(delay); } /* Transmit phase - send our message */ debug_packet(ec_dev->dev, "out", ec_dev->dout, len); memset(&trans, '\0', sizeof(trans)); trans.tx_buf = ec_dev->dout; trans.len = len; trans.cs_change = 1; spi_message_init(&msg); spi_message_add_tail(&trans, &msg); ret = spi_sync(ec_spi->spi, &msg); /* Get the response */ if (!ret) { ret = cros_ec_spi_receive_response(ec_dev, ec_msg->in_len + EC_MSG_TX_PROTO_BYTES); } else { dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); } /* turn off CS */ spi_message_init(&msg); final_ret = spi_sync(ec_spi->spi, &msg); ktime_get_ts(&ts); ec_spi->last_transfer_ns = timespec_to_ns(&ts); if (!ret) ret = final_ret; if (ret < 0) { dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret); return ret; } /* check response error code */ ptr = ec_dev->din; if (ptr[0]) { dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n", ec_msg->cmd, ptr[0]); debug_packet(ec_dev->dev, "in_err", ptr, len); return -EINVAL; } len = ptr[1]; sum = ptr[0] + ptr[1]; if (len > ec_msg->in_len) { dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)", len, ec_msg->in_len); return -ENOSPC; } /* copy response packet payload and compute checksum */ for (i = 0; i < len; i++) { sum += ptr[i + 2]; if (ec_msg->in_len) ec_msg->in_buf[i] = ptr[i + 2]; } sum &= 0xff; debug_packet(ec_dev->dev, "in", ptr, len + 3); if (sum != ptr[len + 2]) { dev_err(ec_dev->dev, "bad packet checksum, expected %02x, got %02x\n", sum, ptr[len + 2]); return -EBADMSG; } return 0; }
static int sendrecv_eap(RADIUS_PACKET *rep) { RADIUS_PACKET *req = NULL; VALUE_PAIR *vp, *vpnext; int tried_eap_md5 = 0; /* * Keep a copy of the the User-Password attribute. */ if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue)); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue)); /* * Otherwise keep a copy of the CHAP-Password attribute. */ } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue)); } else { *password = '******'; } again: rep->id++; /* * if there are EAP types, encode them into an EAP-Message * */ map_eap_methods(rep); /* * Fix up Digest-Attributes issues */ for (vp = rep->vps; vp != NULL; vp = vp->next) { switch (vp->da->attribute) { default: break; case PW_DIGEST_REALM: case PW_DIGEST_NONCE: case PW_DIGEST_METHOD: case PW_DIGEST_URI: case PW_DIGEST_QOP: case PW_DIGEST_ALGORITHM: case PW_DIGEST_BODY_DIGEST: case PW_DIGEST_CNONCE: case PW_DIGEST_NONCE_COUNT: case PW_DIGEST_USER_NAME: /* overlapping! */ memmove(&vp->vp_strvalue[2], &vp->vp_octets[0], vp->length); vp->vp_octets[0] = vp->da->attribute - PW_DIGEST_REALM + 1; vp->length += 2; vp->vp_octets[1] = vp->length; vp->da->attribute = PW_DIGEST_ATTRIBUTES; break; } } /* * If we've already sent a packet, free up the old * one, and ensure that the next packet has a unique * ID and authentication vector. */ if (rep->data) { talloc_free(rep->data); rep->data = NULL; } fr_md5_calc(rep->vector, rep->vector, sizeof(rep->vector)); if (*password != '\0') { if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); rad_chap_encode(rep, vp->vp_octets, rep->id, vp); vp->length = 17; } } /* there WAS a password */ /* send the response, wait for the next request */ send_packet(rep, &req); /* okay got back the packet, go and decode the EAP-Message. */ unmap_eap_methods(req); debug_packet(req, R_RECV); /* now look for the code type. */ for (vp = req->vps; vp != NULL; vp = vpnext) { vpnext = vp->next; switch (vp->da->attribute) { default: break; case ATTRIBUTE_EAP_BASE+PW_EAP_MD5: if(respond_eap_md5(req, rep) && tried_eap_md5 < 3) { tried_eap_md5++; goto again; } break; case ATTRIBUTE_EAP_BASE+PW_EAP_SIM: if(respond_eap_sim(req, rep)) { goto again; } break; } } return 1; }
void debug_reply_packet(RADIUS_PACKET *packet) { debug_packet(packet,R_RECV); }
/*Note: * We just support EAP proxy. * rad_send_eap_response * send a EAP response to radius server */ int rad_send_eap_response(RADIUS_PACKET* rep,const char* secret,const char* pwd) { VALUE_PAIR* vp; int rc; int old_debug_flag; vp = NULL; rc = 0; old_debug_flag = 0; /* * if there are EAP types, encode them into an EAP-Message * */ map_eap_types(rep); /* * Fix up Digest-Attributes issues */ for (vp = rep->vps; vp != NULL; vp = vp->next) { switch (vp->attribute) { default: break; case PW_DIGEST_REALM: case PW_DIGEST_NONCE: case PW_DIGEST_METHOD: case PW_DIGEST_URI: case PW_DIGEST_QOP: case PW_DIGEST_ALGORITHM: case PW_DIGEST_BODY_DIGEST: case PW_DIGEST_CNONCE: case PW_DIGEST_NONCE_COUNT: case PW_DIGEST_USER_NAME: /* overlapping! */ memmove(&vp->vp_strvalue[2], &vp->vp_octets[0], vp->length); vp->vp_octets[0] = vp->attribute - PW_DIGEST_REALM + 1; vp->length += 2; vp->vp_octets[1] = vp->length; vp->attribute = PW_DIGEST_ATTRIBUTES; break; } } fr_md5_calc(rep->vector, rep->vector, sizeof(rep->vector)); if ((pwd != NULL) && (*pwd != '\0')) { if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD)) != NULL) { strncpy((char *)vp->vp_strvalue, pwd, sizeof(vp->vp_strvalue) - 1); vp->length = strlen(pwd); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD)) != NULL) { strncpy((char *)vp->vp_strvalue, pwd, sizeof(vp->vp_strvalue) - 1); vp->length = strlen(pwd); } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD)) != NULL) { strncpy((char *)vp->vp_strvalue, pwd, sizeof(vp->vp_strvalue) - 1); vp->length = strlen(pwd); rad_chap_encode(rep, vp->vp_octets, rep->id, vp); vp->length = 17; } } /* there WAS a password */ /* send the response*/ if(fr_debug_flag) { debug_packet(rep,R_SENT); old_debug_flag = fr_debug_flag; fr_debug_flag = 0; /*just turn off the debug-flag to avoid rad_send debug out agin*/ } if(rad_send(rep,NULL,secret) < 0) rc = -1; else rc = 0; if(old_debug_flag) fr_debug_flag = old_debug_flag; return rc; }
void debug_request_packet(RADIUS_PACKET *packet) { debug_packet(packet,R_SENT); }