Ejemplo n.º 1
0
/*
 *	Send one packet.
 */
static int send_one_packet(radclient_t *radclient)
{
	assert(radclient->done == 0);

	/*
	 *	Remember when we have to wake up, to re-send the
	 *	request, of we didn't receive a response.
	 */
	if ((sleep_time == -1) ||
	    (sleep_time > (int) timeout)) {
		sleep_time = (int) timeout;
	}

	/*
	 *	Haven't sent the packet yet.  Initialize it.
	 */
	if (radclient->request->id == -1) {
		int i, rcode;

		assert(radclient->reply == NULL);

		/*
		 *	Didn't find a free packet ID, we're not done,
		 *	we don't sleep, and we stop trying to process
		 *	this packet.
		 */
	retry:
		radclient->request->src_ipaddr.af = server_ipaddr.af;
		rcode = fr_packet_list_id_alloc(pl, ipproto,
						radclient->request, NULL);
		if (rcode < 0) {
			int mysockfd;

#ifdef WITH_TCP
			if (proto) {
				mysockfd = fr_tcp_client_socket(NULL,
								&server_ipaddr,
								server_port);
			} else
#endif
			mysockfd = fr_socket(&client_ipaddr, 0);
			if (!mysockfd) {
				fprintf(stderr, "radclient: Can't open new socket\n");
				exit(1);
			}
			if (!fr_packet_list_socket_add(pl, mysockfd, ipproto,
						       &server_ipaddr,
						       server_port, NULL)) {
				fprintf(stderr, "radclient: Can't add new socket\n");
				exit(1);
			}
			goto retry;
		}

		if (rcode == 0) {
			done = 0;
			sleep_time = 0;
			return 0;
		}

		assert(radclient->request->id != -1);
		assert(radclient->request->data == NULL);

		for (i = 0; i < 4; i++) {
			((uint32_t *) radclient->request->vector)[i] = fr_rand();
		}

		/*
		 *	Update the password, so it can be encrypted with the
		 *	new authentication vector.
		 */
		if (radclient->password[0] != '\0') {
			VALUE_PAIR *vp;

			if ((vp = pairfind(radclient->request->vps, PW_USER_PASSWORD, 0)) != NULL) {
				strlcpy(vp->vp_strvalue, radclient->password,
					sizeof(vp->vp_strvalue));
				vp->length = strlen(vp->vp_strvalue);

			} else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD, 0)) != NULL) {
				int already_hex = 0;

				/*
				 *	If it's 17 octets, it *might* be already encoded.
				 *	Or, it might just be a 17-character password (maybe UTF-8)
				 *	Check it for non-printable characters.  The odds of ALL
				 *	of the characters being 32..255 is (1-7/8)^17, or (1/8)^17,
				 *	or 1/(2^51), which is pretty much zero.
				 */
				if (vp->length == 17) {
					for (i = 0; i < 17; i++) {
						if (vp->vp_octets[i] < 32) {
							already_hex = 1;
							break;
						}
					}
				}

				/*
				 *	Allow the user to specify ASCII or hex CHAP-Password
				 */
				if (!already_hex) {
					strlcpy(vp->vp_strvalue, radclient->password,
						sizeof(vp->vp_strvalue));
					vp->length = strlen(vp->vp_strvalue);
					
					rad_chap_encode(radclient->request,
							vp->vp_octets,
							fr_rand() & 0xff, vp);
					vp->length = 17;
				}
			} else if (pairfind(radclient->request->vps, PW_MSCHAP_PASSWORD, 0) != NULL) {
				mschapv1_encode(&radclient->request->vps,
						radclient->password);
			} else if (fr_debug_flag) {
				printf("WARNING: No password in the request\n");
			}
		}

		radclient->timestamp = time(NULL);
		radclient->tries = 1;
		radclient->resend++;

		/*
		 *	Duplicate found.  Serious error!
		 */
		if (!fr_packet_list_insert(pl, &radclient->request)) {
			assert(0 == 1);
		}

#ifdef WITH_TCP
		/*
		 *	WTF?
		 */
		if (client_port == 0) {
			client_ipaddr = radclient->request->src_ipaddr;
			client_port = radclient->request->src_port;
		}
#endif

	} else {		/* radclient->request->id >= 0 */
		time_t now = time(NULL);

		/*
		 *	FIXME: Accounting packets are never retried!
		 *	The Acct-Delay-Time attribute is updated to
		 *	reflect the delay, and the packet is re-sent
		 *	from scratch!
		 */

		/*
		 *	Not time for a retry, do so.
		 */
		if ((now - radclient->timestamp) < timeout) {
			/*
			 *	When we walk over the tree sending
			 *	packets, we update the minimum time
			 *	required to sleep.
			 */
			if ((sleep_time == -1) ||
			    (sleep_time > (now - radclient->timestamp))) {
				sleep_time = now - radclient->timestamp;
			}
			return 0;
		}

		/*
		 *	We're not trying later, maybe the packet is done.
		 */
		if (radclient->tries == retries) {
			assert(radclient->request->id >= 0);

			/*
			 *	Delete the request from the tree of
			 *	outstanding requests.
			 */
			fr_packet_list_yank(pl, radclient->request);

			fprintf(stderr, "radclient: no response from server for ID %d socket %d\n", radclient->request->id, radclient->request->sockfd);
			deallocate_id(radclient);

			/*
			 *	Normally we mark it "done" when we've received
			 *	the response, but this is a special case.
			 */
			if (radclient->resend == resend_count) {
				radclient->done = 1;
			}
			totallost++;
			return -1;
		}

		/*
		 *	We are trying later.
		 */
		radclient->timestamp = now;
		radclient->tries++;
	}


	/*
	 *	Send the packet.
	 */
	if (rad_send(radclient->request, NULL, secret) < 0) {
		fprintf(stderr, "radclient: Failed to send packet for ID %d: %s\n",
			radclient->request->id, fr_strerror());
	}

	if (fr_debug_flag > 2) print_hex(radclient->request);

	return 0;
}
Ejemplo n.º 2
0
/*
 *	Send one packet.
 */
static int send_one_packet(rc_request_t *request)
{
	assert(request->done == false);

	/*
	 *	Remember when we have to wake up, to re-send the
	 *	request, of we didn't receive a reply.
	 */
	if ((sleep_time == -1) || (sleep_time > (int) timeout)) sleep_time = (int) timeout;

	/*
	 *	Haven't sent the packet yet.  Initialize it.
	 */
	if (request->packet->id == -1) {
		int i;
		bool rcode;

		assert(request->reply == NULL);

		/*
		 *	Didn't find a free packet ID, we're not done,
		 *	we don't sleep, and we stop trying to process
		 *	this packet.
		 */
	retry:
		request->packet->src_ipaddr.af = server_ipaddr.af;
		rcode = fr_packet_list_id_alloc(pl, ipproto, &request->packet, NULL);
		if (!rcode) {
			int mysockfd;

#ifdef WITH_TCP
			if (proto) {
				mysockfd = fr_socket_client_tcp(NULL,
								&request->packet->dst_ipaddr,
								request->packet->dst_port, false);
			} else
#endif
			mysockfd = fr_socket(&client_ipaddr, 0);
			if (mysockfd < 0) {
				ERROR("Failed opening socket");
				exit(1);
			}
			if (!fr_packet_list_socket_add(pl, mysockfd, ipproto,
						       &request->packet->dst_ipaddr,
						       request->packet->dst_port, NULL)) {
				ERROR("Can't add new socket");
				exit(1);
			}
			goto retry;
		}

		assert(request->packet->id != -1);
		assert(request->packet->data == NULL);

		for (i = 0; i < 4; i++) {
			((uint32_t *) request->packet->vector)[i] = fr_rand();
		}

		/*
		 *	Update the password, so it can be encrypted with the
		 *	new authentication vector.
		 */
		if (request->password) {
			VALUE_PAIR *vp;

			if ((vp = fr_pair_find_by_num(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
				fr_pair_value_strcpy(vp, request->password->vp_strvalue);

			} else if ((vp = fr_pair_find_by_num(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
				uint8_t buffer[17];

				rad_chap_encode(request->packet, buffer, fr_rand() & 0xff, request->password);
				fr_pair_value_memcpy(vp, buffer, 17);

			} else if (fr_pair_find_by_num(request->packet->vps, PW_MS_CHAP_PASSWORD, 0, TAG_ANY) != NULL) {
				mschapv1_encode(request->packet, &request->packet->vps, request->password->vp_strvalue);

			} else {
				DEBUG("WARNING: No password in the request");
			}
		}

		request->timestamp = time(NULL);
		request->tries = 1;
		request->resend++;

	} else {		/* request->packet->id >= 0 */
		time_t now = time(NULL);

		/*
		 *	FIXME: Accounting packets are never retried!
		 *	The Acct-Delay-Time attribute is updated to
		 *	reflect the delay, and the packet is re-sent
		 *	from scratch!
		 */

		/*
		 *	Not time for a retry, do so.
		 */
		if ((now - request->timestamp) < timeout) {
			/*
			 *	When we walk over the tree sending
			 *	packets, we update the minimum time
			 *	required to sleep.
			 */
			if ((sleep_time == -1) ||
			    (sleep_time > (now - request->timestamp))) {
				sleep_time = now - request->timestamp;
			}
			return 0;
		}

		/*
		 *	We're not trying later, maybe the packet is done.
		 */
		if (request->tries == retries) {
			assert(request->packet->id >= 0);

			/*
			 *	Delete the request from the tree of
			 *	outstanding requests.
			 */
			fr_packet_list_yank(pl, request->packet);

			REDEBUG("No reply from server for ID %d socket %d",
				request->packet->id, request->packet->sockfd);
			deallocate_id(request);

			/*
			 *	Normally we mark it "done" when we've received
			 *	the reply, but this is a special case.
			 */
			if (request->resend == resend_count) {
				request->done = true;
			}
			stats.lost++;
			return -1;
		}

		/*
		 *	We are trying later.
		 */
		request->timestamp = now;
		request->tries++;
	}

	/*
	 *	Send the packet.
	 */
	if (rad_send(request->packet, NULL, secret) < 0) {
		REDEBUG("Failed to send packet for ID %d", request->packet->id);
		deallocate_id(request);
		request->done = true;
		return -1;
	}

	fr_packet_header_print(fr_log_fp, request->packet, false);
	if (fr_debug_lvl > 0) vp_printlist(fr_log_fp, request->packet->vps);

	return 0;
}
Ejemplo n.º 3
0
/*
 *	Send one packet.
 */
static int send_one_packet(rc_request_t *request)
{
	assert(request->done == false);

	/*
	 *	Remember when we have to wake up, to re-send the
	 *	request, of we didn't receive a reply.
	 */
	if ((sleep_time == -1) || (sleep_time > (int) timeout)) {
		sleep_time = (int) timeout;
	}

	/*
	 *	Haven't sent the packet yet.  Initialize it.
	 */
	if (request->packet->id == -1) {
		int i;
		bool rcode;

		assert(request->reply == NULL);

		/*
		 *	Didn't find a free packet ID, we're not done,
		 *	we don't sleep, and we stop trying to process
		 *	this packet.
		 */
	retry:
		request->packet->src_ipaddr.af = server_ipaddr.af;
		rcode = fr_packet_list_id_alloc(pl, ipproto,
						&request->packet, NULL);
		if (!rcode) {
			int mysockfd;

#ifdef WITH_TCP
			if (proto) {
				mysockfd = fr_tcp_client_socket(NULL,
								&server_ipaddr,
								server_port);
			} else
#endif
			mysockfd = fr_socket(&client_ipaddr, 0);
			if (mysockfd < 0) {
				ERROR("Can't open new socket: %s", strerror(errno));
				exit(1);
			}
			if (!fr_packet_list_socket_add(pl, mysockfd, ipproto,
						       &server_ipaddr,
						       server_port, NULL)) {
				ERROR("Can't add new socket");
				exit(1);
			}
			goto retry;
		}

		assert(request->packet->id != -1);
		assert(request->packet->data == NULL);

		for (i = 0; i < 4; i++) {
			((uint32_t *) request->packet->vector)[i] = fr_rand();
		}

		/*
		 *	Update the password, so it can be encrypted with the
		 *	new authentication vector.
		 */
		if (request->password[0] != '\0') {
			VALUE_PAIR *vp;

			if ((vp = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
				pairstrcpy(vp, request->password);

			} else if ((vp = pairfind(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
				bool already_hex = false;

				/*
				 *	If it's 17 octets, it *might* be already encoded.
				 *	Or, it might just be a 17-character password (maybe UTF-8)
				 *	Check it for non-printable characters.  The odds of ALL
				 *	of the characters being 32..255 is (1-7/8)^17, or (1/8)^17,
				 *	or 1/(2^51), which is pretty much zero.
				 */
				if (vp->length == 17) {
					for (i = 0; i < 17; i++) {
						if (vp->vp_octets[i] < 32) {
							already_hex = true;
							break;
						}
					}
				}

				/*
				 *	Allow the user to specify ASCII or hex CHAP-Password
				 */
				if (!already_hex) {
					uint8_t *p;
					size_t len, len2;

					len = len2 = strlen(request->password);
					if (len2 < 17) len2 = 17;

					p = talloc_zero_array(vp, uint8_t, len2);

					memcpy(p, request->password, len);

					rad_chap_encode(request->packet,
							p,
							fr_rand() & 0xff, vp);
					vp->vp_octets = p;
					vp->length = 17;
				}
			} else if (pairfind(request->packet->vps, PW_MSCHAP_PASSWORD, 0, TAG_ANY) != NULL) {
				mschapv1_encode(request->packet,
						&request->packet->vps,
						request->password);
			} else {
				DEBUG("WARNING: No password in the request");
			}
		}

		request->timestamp = time(NULL);
		request->tries = 1;
		request->resend++;

#ifdef WITH_TCP
		/*
		 *	WTF?
		 */
		if (client_port == 0) {
			client_ipaddr = request->packet->src_ipaddr;
			client_port = request->packet->src_port;
		}
#endif

	} else {		/* request->packet->id >= 0 */
		time_t now = time(NULL);

		/*
		 *	FIXME: Accounting packets are never retried!
		 *	The Acct-Delay-Time attribute is updated to
		 *	reflect the delay, and the packet is re-sent
		 *	from scratch!
		 */

		/*
		 *	Not time for a retry, do so.
		 */
		if ((now - request->timestamp) < timeout) {
			/*
			 *	When we walk over the tree sending
			 *	packets, we update the minimum time
			 *	required to sleep.
			 */
			if ((sleep_time == -1) ||
			    (sleep_time > (now - request->timestamp))) {
				sleep_time = now - request->timestamp;
			}
			return 0;
		}

		/*
		 *	We're not trying later, maybe the packet is done.
		 */
		if (request->tries == retries) {
			assert(request->packet->id >= 0);

			/*
			 *	Delete the request from the tree of
			 *	outstanding requests.
			 */
			fr_packet_list_yank(pl, request->packet);

			REDEBUG("No reply from server for ID %d socket %d",
				request->packet->id, request->packet->sockfd);
			deallocate_id(request);

			/*
			 *	Normally we mark it "done" when we've received
			 *	the reply, but this is a special case.
			 */
			if (request->resend == resend_count) {
				request->done = true;
			}
			stats.lost++;
			return -1;
		}

		/*
		 *	We are trying later.
		 */
		request->timestamp = now;
		request->tries++;
	}

	/*
	 *	Send the packet.
	 */
	if (rad_send(request->packet, NULL, secret) < 0) {
		REDEBUG("Failed to send packet for ID %d", request->packet->id);
	}

	return 0;
}