Logo Search packages:      
Sourcecode: nagios-plugins version File versions  Download package

check_radius.c

/*
 *
 *    RADIUS
 *    Remote Authentication Dial In User Service
 *
 *
 *    Livingston Enterprises, Inc.
 *    6920 Koll Center Parkway
 *    Pleasanton, CA   94566
 *
 *    Copyright 1992 Livingston Enterprises, Inc.
 *
 *    Permission to use, copy, modify, and distribute this software for any
 *    purpose and without fee is hereby granted, provided that this
 *    copyright and permission notice appear on all copies and supporting
 *    documentation, the name of Livingston Enterprises, Inc. not be used
 *    in advertising or publicity pertaining to distribution of the
 *    program without specific prior permission, and notice be given
 *    in supporting documentation that copying and distribution is by
 *    permission of Livingston Enterprises, Inc.   
 *
 *    Livingston Enterprises, Inc. makes no representations about
 *    the suitability of this software for any purpose.  It is
 *    provided "as is" without express or implied warranty.
 *
 */

/*
 * Converted to check_radius module for Netsaint by Adam Jacob
 * adam@cybertrails.com
 *
 */

char radtest_sccsid[] =
"@(#)radpass.c    1.5 Copyright 1992 Livingston Enterprises Inc\n"
"@(#)radtest.c    1.3 Copyright 1999 Cistron Internet Services B.V.";

#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"

#define MAXPWNAM  32
#define MAXPASS         16

#define TEST_VENDOR     1
#define TEST_USR  1

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;

/*
 *    Receive UDP client requests, build an authorization request
 *    structure, and attach attribute-value pairs contained in
 *    the request to the new structure.
 */
static AUTH_REQ   *test_radrecv(UINT4 host, u_short udp_port,
                  char *buffer, int length)
{
      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. ",
                        (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. ", attribute);
            }
            else if ( attrlen >= AUTH_STRING_LEN ) {
                  printf("attribute %d too long, %d >= %d. ", 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). ", attr->name,attr->type);
                        free(pair);
                        break;
                  }

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


/*
 *    Receive and print the result.
 */
int result_recv(UINT4 host, u_short udp_port, char *buffer, int length)
{
      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. ");
      }

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

      req = authreq->request;

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




/*
 *    Print usage message and exit.
 */
void usage(void)
{
      fprintf(stderr, "Usage: %s username passwd servername nas_port_id secretkey [ppphint] [nasname]\n",
            progname);
      exit(1);
}


/*
 *    Generate a random vector.
 */
static void random_vector(char *vector)
{
      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);
      }
}


int main(int argc, char **argv)
{
      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;
      int               result_code;

      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. ");
      for (i = 0; i < 10; i++) {
            if (i > 0) printf("%i, ", i);
            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_code = result_recv(sin->sin_addr.s_addr, sin->sin_port, recv_buffer, result);
            exit(result_code);
      }
      printf("No answer.\n");
      close(sockfd);
      exit(2);
}

Generated by  Doxygen 1.6.0   Back to index