2
2
* radclient.c General radius packet debug tool.
4
* Version: $Id: radclient.c,v 1.72.2.1 2004/06/02 15:31:53 aland Exp $
4
* Version: $Id: radclient.c,v 1.72.2.1.2.5 2006/05/16 18:26:08 aland Exp $
6
6
* This program is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
21
21
* Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
22
22
* Copyright 2000 Alan DeKok <aland@ox.org>
24
static const char rcsid[] = "$Id: radclient.c,v 1.72.2.1 2004/06/02 15:31:53 aland Exp $";
24
static const char rcsid[] = "$Id: radclient.c,v 1.72.2.1.2.5 2006/05/16 18:26:08 aland Exp $";
26
26
#include "autoconf.h"
27
#include "libradius.h"
30
29
#include <stdlib.h>
98
98
static radclient_t *radclient_tail = NULL;
101
static void usage(void)
101
static void NEVER_RETURNS usage(void)
103
103
fprintf(stderr, "Usage: radclient [options] server[:port] <command> [<secret>]\n");
105
fprintf(stderr, " <command> One of auth, acct, status, or disconnect.\n");
105
fprintf(stderr, " <command> One of auth, acct, status, coa, or disconnect.\n");
106
106
fprintf(stderr, " -c count Send each packet 'count' times.\n");
107
107
fprintf(stderr, " -d raddb Set dictionary directory.\n");
108
108
fprintf(stderr, " -f file Read packets from file, not stdin.\n");
109
fprintf(stderr, " -r retries If timeout, retry sending the packet 'retries' times.\n");
110
fprintf(stderr, " -t timeout Wait 'timeout' seconds before retrying (may be a floating point number).\n");
111
109
fprintf(stderr, " -i id Set request id to 'id'. Values may be 0..255\n");
112
fprintf(stderr, " -S file read secret from file, not command line.\n");
110
fprintf(stderr, " -n num Send N requests/s\n");
111
fprintf(stderr, " -p num Send 'num' packets from a file in parallel.\n");
113
112
fprintf(stderr, " -q Do not print anything out.\n");
113
fprintf(stderr, " -r retries If timeout, retry sending the packet 'retries' times.\n");
114
114
fprintf(stderr, " -s Print out summary information of auth results.\n");
115
fprintf(stderr, " -S file read secret from file, not command line.\n");
116
fprintf(stderr, " -t timeout Wait 'timeout' seconds before retrying (may be a floating point number).\n");
115
117
fprintf(stderr, " -v Show program version information.\n");
116
118
fprintf(stderr, " -x Debugging mode.\n");
189
191
radclient = malloc(sizeof(*radclient));
190
192
if (!radclient) {
191
perror("radclient: ");
193
perror("radclient: X");
192
194
return NULL; /* memory leak "start" */
194
196
memset(radclient, 0, sizeof(*radclient));
196
198
radclient->request = rad_alloc(1);
197
199
if (!radclient->request) {
198
librad_perror("radclient: ");
200
librad_perror("radclient: X");
199
201
radclient_free(radclient);
200
202
return NULL; /* memory leak "start" */
210
radclient->request->vps = readvp2(fp, &filedone, "radclient:");
212
radclient->request->vps = readvp2(fp, &filedone, "radclient: X");
211
213
if (!radclient->request->vps) {
212
214
radclient_free(radclient);
213
215
return start; /* done: return the list */
217
219
* Keep a copy of the the User-Password attribute.
219
221
if ((vp = pairfind(radclient->request->vps, PW_PASSWORD)) != NULL) {
220
strNcpy(radclient->password, (char *)vp->strvalue, sizeof(vp->strvalue));
222
strNcpy(radclient->password, (char *)vp->strvalue, sizeof(radclient->password));
222
224
* Otherwise keep a copy of the CHAP-Password attribute.
224
226
} else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
225
strNcpy(radclient->password, (char *)vp->strvalue, sizeof(vp->strvalue));
227
strNcpy(radclient->password, (char *)vp->strvalue, sizeof(radclient->password));
227
229
radclient->password[0] = '\0';
319
321
return strcmp((const char *) one, (const char *) two);
322
static int filename_walk(void *data)
324
static int filename_walk(void *context, void *data)
324
326
const char *filename = data;
325
327
radclient_t *radclient;
329
context = context; /* -Wunused */
328
332
* Initialize the request we're about
479
483
if ((vp = pairfind(radclient->request->vps, PW_PASSWORD)) != NULL) {
480
strNcpy((char *)vp->strvalue, radclient->password, strlen(radclient->password) + 1);
481
vp->length = strlen(radclient->password);
484
strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
485
vp->length = strlen(vp->strvalue);
483
487
} else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
484
strNcpy((char *)vp->strvalue, radclient->password, strlen(radclient->password) + 1);
485
vp->length = strlen(radclient->password);
488
strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
489
vp->length = strlen(vp->strvalue);
487
491
rad_chap_encode(radclient->request, (char *) vp->strvalue, radclient->request->id, vp);
566
570
* Send the packet.
568
rad_send(radclient->request, NULL, secret);
572
if (rad_send(radclient->request, NULL, secret) < 0) {
573
fprintf(stderr, "radclient: Failed to send packet for ID %d: %s\n",
574
radclient->request->id, librad_errstr);
633
641
* FIXME: Do stuff to process the reply.
643
if (rad_verify(reply, radclient->request, secret) != 0) {
644
librad_perror("rad_verify");
646
goto packet_done; /* shared secret is incorrect */
635
649
if (rad_decode(reply, radclient->request, secret) != 0) {
636
650
librad_perror("rad_decode");
652
goto packet_done; /* shared secret is incorrect */
641
655
/* libradius debug already prints out the value pairs for us */
703
while ((c = getopt(argc, argv, "c:d:f:hi:qst:r:S:xv")) != EOF) switch(c) {
720
while ((c = getopt(argc, argv, "c:d:f:hi:n:p:qr:sS:t:vx")) != EOF) switch(c) {
705
722
if (!isdigit((int) *optarg))
713
730
rbtree_insert(filename_tree, optarg);
733
if (!isdigit((int) *optarg))
735
last_used_id = atoi(optarg);
736
if ((last_used_id < 0) || (last_used_id > 255)) {
742
persec = atoi(optarg);
743
if (persec <= 0) usage();
747
parallel = atoi(optarg);
748
if (parallel <= 0) usage();
722
755
if (!isdigit((int) *optarg))
724
757
retries = atoi(optarg);
725
758
if ((retries == 0) || (retries > 1000)) usage();
728
if (!isdigit((int) *optarg))
730
last_used_id = atoi(optarg);
731
if ((last_used_id < 0) || (last_used_id > 255)) {
739
if (!isdigit((int) *optarg))
741
timeout = atof(optarg);
744
printf("radclient: $Id: radclient.c,v 1.72.2.1 2004/06/02 15:31:53 aland Exp $ built on " __DATE__ " at " __TIME__ "\n");
748
764
fp = fopen(optarg, "r");
815
843
if (server_port == 0) server_port = PW_AUTH_UDP_PORT;
816
844
packet_code = PW_AUTHENTICATION_REQUEST;
846
} else if (strcmp(argv[2], "challenge") == 0) {
847
if (server_port == 0) server_port = getport("radius");
848
if (server_port == 0) server_port = PW_AUTH_UDP_PORT;
849
packet_code = PW_ACCESS_CHALLENGE;
818
851
} else if (strcmp(argv[2], "acct") == 0) {
819
852
if (server_port == 0) server_port = getport("radacct");
820
853
if (server_port == 0) server_port = PW_ACCT_UDP_PORT;
830
863
if (server_port == 0) server_port = PW_POD_UDP_PORT;
831
864
packet_code = PW_DISCONNECT_REQUEST;
866
} else if (strcmp(argv[2], "coa") == 0) {
867
if (server_port == 0) server_port = PW_POD_UDP_PORT;
868
packet_code = PW_COA_REQUEST;
833
870
} else if (strcmp(argv[2], "auto") == 0) {
834
871
packet_code = -1;
866
903
* Walk over the list of filenames, creating the requests.
868
if (rbtree_walk(filename_tree, filename_walk, InOrder) != 0) {
905
if (rbtree_walk(filename_tree, InOrder, filename_walk, NULL) != 0) {
931
969
* Packets from multiple '-f' are sent
932
* in parallel. Packets from one file
933
* are sent in series.
972
* Packets from one file are sent in
973
* series, unless '-p' is specified, in
974
* which case N packets from each file
975
* are sent in parallel.
935
977
if (this->filename != filename) {
936
978
filename = this->filename;
939
986
* Send the current packet.
941
988
send_one_packet(this);
991
* Wait a little before sending
992
* the next packet, if told to.
998
* Don't sleep elsewhere.
1007
tv.tv_usec = 1000000/persec;
1011
* Sleep for milliseconds,
1014
* If we get an error or
1015
* a signal, treat it like
1018
select(0, NULL, NULL, NULL, &tv);
944
1022
* If we haven't sent this packet
945
1023
* often enough, we're not done,
946
1024
* and we shouldn't sleep.