Back to index

nagios-plugins  1.4.16
Defines | Functions | Variables
radtest.c File Reference
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <pwd.h>
#include <stdlib.h>
#include <errno.h>
#include "radiusd.h"
#include "conf.h"

Go to the source code of this file.

Defines

#define MAXPWNAM   32
#define MAXPASS   16
#define TEST_VENDOR   1
#define TEST_USR   1

Functions

static AUTH_REQtest_radrecv (UINT4 host, u_short udp_port, char *buffer, int length)
int result_recv (UINT4 host, u_short udp_port, char *buffer, int length)
void usage (void)
static void random_vector (char *vector)
int main (int argc, char **argv)

Variables

char radtest_sccsid [] = "@(#)radtest.c 1.3 Copyright 1999 Cistron Internet Services B.V."
int i_send_buffer [2048]
int i_recv_buffer [2048]
char * send_buffer = (char *)i_send_buffer
char * recv_buffer = (char *)i_recv_buffer
char * progname
int sockfd
char vector [AUTH_VECTOR_LEN]
char * secretkey
char * radius_dir = RADIUS_DIR
char * radlog_dir = NULL
int debug_flag = 0

Define Documentation

#define MAXPASS   16

Definition at line 48 of file radtest.c.

#define MAXPWNAM   32

Definition at line 47 of file radtest.c.

#define TEST_USR   1

Definition at line 51 of file radtest.c.

#define TEST_VENDOR   1

Definition at line 50 of file radtest.c.


Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 273 of file radtest.c.

{
       int                  salen;
       int                  result;
       struct sockaddr      salocal;
       struct sockaddr      saremote;
       struct sockaddr_in   *sin;
       struct servent              *svp;
       struct timeval              tv;
       fd_set               readfds;
        u_short                 svc_port;
       AUTH_HDR             *auth;
       char                 *username;
       char                 *passwd;
       char                 *server;
       char                 passbuf[AUTH_PASS_LEN];
       char                 md5buf[256];
       char                 nasname[256];
       UINT4                nas_ipaddr;
       UINT4                auth_ipaddr;
       UINT4                ui;
       u_short                     local_port;
       u_short                     total_length;
       int                  portno;
       int                  ppphint = 0;
       char                 *ptr;
       int                  length;
       int                  secretlen;
       int                  i;
       int                  bogus_packet = 0;

       progname = argv[0];

       if (argv[1] && strcmp(argv[1], "-b") == 0) {
              argv++;
              argc--;
              bogus_packet = 1;
       }

       if (argc < 6 || argc > 8) {
              usage();
       }
       username  = argv[1];
       passwd    = argv[2];
       server    = argv[3];
       secretkey = argv[5];
       ptr = argv[4];
       if (*ptr == 's' || *ptr == 'S') ptr++;
       portno = atoi(ptr);
       if (argc > 6) ppphint = atoi(argv[6]);

       if (argc > 7)
              strNcpy(nasname, argv[7], sizeof(nasname));
       else
              gethostname(nasname, sizeof(nasname));
       nas_ipaddr = get_ipaddr(nasname);

       dict_init(NULL);

       /*
        *     Open a connection to the server.
        */
       svp = getservbyname ("radius", "udp");
       if (svp == (struct servent *) 0)
              svc_port = PW_AUTH_UDP_PORT;
       else
              svc_port = ntohs((u_short) svp->s_port);

       /* Get the IP address of the authentication server */
       if((auth_ipaddr = get_ipaddr(server)) == 0) {
              fprintf(stderr, "Couldn't find host %s\n", server);
              exit(1);
       }

       sockfd = socket (AF_INET, SOCK_DGRAM, 0);
       if (sockfd < 0) {
              perror ("socket");
              exit(1);
       }

       sin = (struct sockaddr_in *) &salocal;
        memset (sin, 0, sizeof (salocal));
       sin->sin_family = AF_INET;
       sin->sin_addr.s_addr = INADDR_ANY;

       local_port = 1025;
       do {
              local_port++;
              sin->sin_port = htons((u_short)local_port);
       } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) &&
                                          local_port < 64000);
       if (local_port >= 64000) {
              close(sockfd);
              perror ("bind");
              exit(1);
       }

       /*
        *     Build an authentication request
        */
       auth = (AUTH_HDR *)send_buffer;
       auth->code = PW_AUTHENTICATION_REQUEST;
       auth->id = getpid() % 256;
       random_vector(vector);
       memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
       total_length = AUTH_HDR_LEN;
       ptr = auth->data;

       /*
        *     User Name
        */
       *ptr++ = PW_USER_NAME;
       length = strlen(username);
       if(length > MAXPWNAM) {
              length = MAXPWNAM;
       }
       *ptr++ = length + 2;
       memcpy(ptr, username, length);
       ptr += length;
       total_length += length + 2;

       /*
        *     Password
        */
       *ptr++ = PW_PASSWORD;
       *ptr++ = AUTH_PASS_LEN + 2;

       length = strlen(passwd);
       if(length > MAXPASS) {
              length = MAXPASS;
       }
       memset(passbuf, 0, AUTH_PASS_LEN);
       memcpy(passbuf, passwd, length);

       /* Calculate the MD5 Digest */
       secretlen = strlen(secretkey);
       strNcpy(md5buf, secretkey, sizeof(md5buf));
       memcpy(md5buf + secretlen, auth->vector, AUTH_VECTOR_LEN);
       md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN);

       /* Xor the password into the MD5 digest */
       for(i = 0;i < AUTH_PASS_LEN;i++) {
              *ptr++ ^= passbuf[i];
       }
       total_length += AUTH_PASS_LEN + 2;

       *ptr++ = PW_NAS_PORT_ID;
       *ptr++ = 6;
       ui = htonl(portno);
       memcpy(ptr, &ui, sizeof(UINT4));
       ptr += 4;
       total_length += 6;

#if TEST_VENDOR
       *ptr++ = PW_VENDOR_SPECIFIC;
       *ptr++ = 18;
       ui = htonl(307); /* livingston */
       memcpy(ptr, &ui, sizeof(UINT4));
       ptr += 4;

       *ptr++ = 2; /* LE-Terminate-Detail */
       *ptr++ = 6; /* len */
       strcpy(ptr, "test");
       ptr += 4;

       *ptr++ = 3; /* LE-Advice-of-Charge */
       *ptr++ = 6; /* len */
       strcpy(ptr, "TiNC");
       ptr += 4;

       total_length += 18;
#endif

#if TEST_USR
       *ptr++ = PW_VENDOR_SPECIFIC;
       *ptr++ = 14;
       ui = htonl(429); /* USR */
       memcpy(ptr, &ui, sizeof(UINT4));
       ptr += 4;
       ui = htonl(0x9823); /* Terminal-Type */
       memcpy(ptr, &ui, sizeof(UINT4));
       ptr += 4;
       strcpy(ptr, "test");
       ptr += 4;
       total_length += 14;
#endif

       *ptr++ = PW_NAS_IP_ADDRESS;
       *ptr++ = 6;
       ui = htonl(nas_ipaddr);
       memcpy(ptr, &ui, sizeof(UINT4));
       ptr += 4;
       total_length += 6;

       /*
        *     We might need to add a PPP hint.
        */
       if (ppphint) {
              *ptr++ = PW_FRAMED_PROTOCOL;
              *ptr++ = 6;
              ui = htonl(PW_PPP);
              memcpy(ptr, &ui, sizeof(UINT4));
              ptr += 4;
              total_length += 6;
       }

       if (bogus_packet) {
              *ptr++ = PW_FILTER_ID;
              length = 4096;
              *ptr++ = length + 2;
              for(i = 0; i < 4096; i++)
                     *ptr++ = 'A';
              ptr += length;
              total_length += length + 2;
       }

       auth->length = htons(total_length);

       /*
        *     Send the request we've built.
        */
       sin = (struct sockaddr_in *) &saremote;
        memset (sin, 0, sizeof (saremote));
       sin->sin_family = AF_INET;
       sin->sin_addr.s_addr = htonl(auth_ipaddr);
       sin->sin_port = htons(svc_port);

       printf("Sending request.\n");
       for (i = 0; i < 10; i++) {
              if (i > 0) printf("Re-sending request.\n");
              sendto(sockfd, (char *)auth, total_length, 0,
                     &saremote, sizeof(struct sockaddr_in));

              tv.tv_sec = 3;
              tv.tv_usec = 0;
              FD_ZERO(&readfds);
              FD_SET(sockfd, &readfds);
              if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0)
                     continue;
              salen = sizeof (saremote);
              result = recvfrom (sockfd, recv_buffer, sizeof(i_recv_buffer),
                     0, &saremote, &salen);
              if (result >= 0)
                     break;
              sleep(tv.tv_sec);
       }
       if (result > 0 && i < 10) {
              result_recv(sin->sin_addr.s_addr,
                                   sin->sin_port, recv_buffer, result);
              exit(0);
       }
       printf("No answer.\n");
       close(sockfd);
       exit(1);
}

Here is the call graph for this function:

static void random_vector ( char *  vector) [static]

Definition at line 258 of file radtest.c.

{
       int    randno;
       int    i;

       srand(time(0));
       for(i = 0;i < AUTH_VECTOR_LEN;) {
              randno = rand();
              memcpy(vector, &randno, sizeof(int));
              vector += sizeof(int);
              i += sizeof(int);
       }
}

Here is the caller graph for this function:

int result_recv ( UINT4  host,
u_short  udp_port,
char *  buffer,
int  length 
)

Definition at line 195 of file radtest.c.

{
       AUTH_HDR      *auth;
       int           totallen;
       char          reply_digest[AUTH_VECTOR_LEN];
       char          calc_digest[AUTH_VECTOR_LEN];
       int           secretlen;
       AUTH_REQ      *authreq;
       VALUE_PAIR    *req;

       auth = (AUTH_HDR *)buffer;
       totallen = ntohs(auth->length);

       if(totallen != length) {
              printf("Received invalid reply length from server (want %d/ got %d)\n", totallen, length);
              exit(1);
       }

       /* Verify the reply digest */
       memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN);
       memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
       secretlen = strlen(secretkey);
       memcpy(buffer + length, secretkey, secretlen);
       md5_calc(calc_digest, (char *)auth, length + secretlen);

       if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) {
              printf("Warning: Received invalid reply digest from server\n");
       }

       authreq = test_radrecv(host, udp_port, buffer, length);

       req = authreq->request;

       while(req) {
              printf("    ");
              fprint_attr_val(stdout, req);
              printf("\n");
              req = req->next;
       }
       if(auth->code != PW_AUTHENTICATION_ACK) {
              printf("Access denied.\n");
              return -1;
       }
       return 0;
}

Here is the call graph for this function:

static AUTH_REQ* test_radrecv ( UINT4  host,
u_short  udp_port,
char *  buffer,
int  length 
) [static]

Definition at line 72 of file radtest.c.

{
       u_char        *ptr;
       AUTH_HDR      *auth;
       int           totallen;
       int           attribute;
       int           attrlen;
       DICT_ATTR     *attr;
       UINT4         lvalue;
       VALUE_PAIR    *first_pair;
       VALUE_PAIR    *prev;
       VALUE_PAIR    *pair;
       AUTH_REQ      *authreq;

       /*
        *     Pre-allocate the new request data structure
        */

       if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) ==
                                          (AUTH_REQ *)NULL) {
              fprintf(stderr, "%s: no memory\n", progname);
              exit(1);
       }

       auth = (AUTH_HDR *)buffer;
       totallen = ntohs(auth->length);

       printf("radrecv: Reply from host %lx code=%d, id=%d, length=%d\n",
                            (u_long)host, auth->code, auth->id, totallen);

       /*
        *     Fill header fields
        */
       authreq->ipaddr = host;
       authreq->udp_port = udp_port;
       authreq->id = auth->id;
       authreq->code = auth->code;
       memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);

       /*
        *     Extract attribute-value pairs
        */
       ptr = (u_char *)auth->data;
       length -= AUTH_HDR_LEN;
       first_pair = (VALUE_PAIR *)NULL;
       prev = (VALUE_PAIR *)NULL;

       while(length > 0) {

              attribute = *ptr++;
              attrlen = *ptr++;
              if(attrlen < 2) {
                     length = 0;
                     continue;
              }
              attrlen -= 2;
              if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {
                     printf("Received unknown attribute %d\n", attribute);
              }
              else if ( attrlen >= AUTH_STRING_LEN ) {
                     printf("attribute %d too long, %d >= %d\n", attribute,
                            attrlen, AUTH_STRING_LEN);
              }
              else {
                     if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
                                          (VALUE_PAIR *)NULL) {
                            fprintf(stderr, "%s: no memory\n",
                                          progname);
                            exit(1);
                     }
                     /* Same size */
                     strcpy(pair->name, attr->name);
                     pair->attribute = attr->value;
                     pair->type = attr->type;
                     pair->next = (VALUE_PAIR *)NULL;

                     switch(attr->type) {

                     case PW_TYPE_STRING:
                            memcpy(pair->strvalue, ptr, attrlen);
                            pair->strvalue[attrlen] = '\0';
                            pair->length = attrlen;
                            if(first_pair == (VALUE_PAIR *)NULL) {
                                   first_pair = pair;
                            }
                            else {
                                   prev->next = pair;
                            }
                            prev = pair;
                            break;
                     
                     case PW_TYPE_INTEGER:
                     case PW_TYPE_IPADDR:
                            memcpy(&lvalue, ptr, sizeof(UINT4));
                            pair->lvalue = ntohl(lvalue);
                            if(first_pair == (VALUE_PAIR *)NULL) {
                                   first_pair = pair;
                            }
                            else {
                                   prev->next = pair;
                            }
                            prev = pair;
                            break;
                     
                     default:
                            printf("    %s (Unknown Type %d)\n", attr->name,attr->type);
                            free(pair);
                            break;
                     }

              }
              ptr += attrlen;
              length -= attrlen + 2;
       }
       authreq->request = first_pair;
       return(authreq);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void usage ( void  )

Definition at line 247 of file radtest.c.

{
       fprintf(stderr, "Usage: %s username passwd servername nas_port_id secretkey [ppphint] [nasname]\n",
              progname);
       exit(1);
}

Variable Documentation

int debug_flag = 0

Definition at line 65 of file radtest.c.

int i_recv_buffer[2048]

Definition at line 54 of file radtest.c.

int i_send_buffer[2048]

Definition at line 53 of file radtest.c.

char* progname

Definition at line 58 of file radtest.c.

Definition at line 63 of file radtest.c.

char* radlog_dir = NULL

Definition at line 64 of file radtest.c.

char radtest_sccsid[] = "@(#)radtest.c 1.3 Copyright 1999 Cistron Internet Services B.V."

Definition at line 28 of file radtest.c.

char* recv_buffer = (char *)i_recv_buffer

Definition at line 56 of file radtest.c.

char* secretkey

Definition at line 61 of file radtest.c.

char* send_buffer = (char *)i_send_buffer

Definition at line 55 of file radtest.c.

int sockfd

Definition at line 59 of file radtest.c.

Definition at line 60 of file radtest.c.