Back to index

nagios-plugins  1.4.16
check_radius.c
Go to the documentation of this file.
00001 /*
00002  *
00003  *     RADIUS
00004  *     Remote Authentication Dial In User Service
00005  *
00006  *
00007  *     Livingston Enterprises, Inc.
00008  *     6920 Koll Center Parkway
00009  *     Pleasanton, CA   94566
00010  *
00011  *     Copyright 1992 Livingston Enterprises, Inc.
00012  *
00013  *     Permission to use, copy, modify, and distribute this software for any
00014  *     purpose and without fee is hereby granted, provided that this
00015  *     copyright and permission notice appear on all copies and supporting
00016  *     documentation, the name of Livingston Enterprises, Inc. not be used
00017  *     in advertising or publicity pertaining to distribution of the
00018  *     program without specific prior permission, and notice be given
00019  *     in supporting documentation that copying and distribution is by
00020  *     permission of Livingston Enterprises, Inc.   
00021  *
00022  *     Livingston Enterprises, Inc. makes no representations about
00023  *     the suitability of this software for any purpose.  It is
00024  *     provided "as is" without express or implied warranty.
00025  *
00026  */
00027 
00028 /*
00029  * Converted to check_radius module for Netsaint by Adam Jacob
00030  * adam@cybertrails.com
00031  *
00032  */
00033 
00034 char radtest_sccsid[] =
00035 "@(#)radpass.c       1.5 Copyright 1992 Livingston Enterprises Inc\n"
00036 "@(#)radtest.c       1.3 Copyright 1999 Cistron Internet Services B.V.";
00037 
00038 #include      <sys/types.h>
00039 #include      <sys/socket.h>
00040 #include      <sys/time.h>
00041 #include      <netinet/in.h>
00042 
00043 #include      <stdio.h>
00044 #include      <unistd.h>
00045 #include      <netdb.h>
00046 #include      <pwd.h>
00047 #include      <stdlib.h>
00048 #include      <errno.h>
00049 
00050 #include      "radiusd.h"
00051 #include      "conf.h"
00052 
00053 #define MAXPWNAM     32
00054 #define MAXPASS             16
00055 
00056 #define TEST_VENDOR  1
00057 #define TEST_USR     1
00058 
00059 int           i_send_buffer[2048];
00060 int           i_recv_buffer[2048];
00061 char          *send_buffer = (char *)i_send_buffer;
00062 char          *recv_buffer = (char *)i_recv_buffer;
00063 
00064 char          *progname;
00065 int           sockfd;
00066 char          vector[AUTH_VECTOR_LEN];
00067 char          *secretkey;
00068 
00069 char          *radius_dir = RADIUS_DIR;
00070 char          *radlog_dir = NULL;
00071 int           debug_flag = 0;
00072 
00073 /*
00074  *     Receive UDP client requests, build an authorization request
00075  *     structure, and attach attribute-value pairs contained in
00076  *     the request to the new structure.
00077  */
00078 static AUTH_REQ      *test_radrecv(UINT4 host, u_short udp_port,
00079                      char *buffer, int length)
00080 {
00081        u_char        *ptr;
00082        AUTH_HDR      *auth;
00083        int           totallen;
00084        int           attribute;
00085        int           attrlen;
00086        DICT_ATTR     *attr;
00087        UINT4         lvalue;
00088        VALUE_PAIR    *first_pair;
00089        VALUE_PAIR    *prev;
00090        VALUE_PAIR    *pair;
00091        AUTH_REQ      *authreq;
00092 
00093        /*
00094         *     Pre-allocate the new request data structure
00095         */
00096 
00097        if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) ==
00098                                           (AUTH_REQ *)NULL) {
00099               fprintf(stderr, "%s: no memory\n", progname);
00100               exit(1);
00101        }
00102 
00103        auth = (AUTH_HDR *)buffer;
00104        totallen = ntohs(auth->length);
00105 
00106        printf("radrecv: Reply from host %lx code=%d, id=%d, length=%d. ",
00107                             (u_long)host, auth->code, auth->id, totallen);
00108 
00109        /*
00110         *     Fill header fields
00111         */
00112        authreq->ipaddr = host;
00113        authreq->udp_port = udp_port;
00114        authreq->id = auth->id;
00115        authreq->code = auth->code;
00116        memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN);
00117 
00118        /*
00119         *     Extract attribute-value pairs
00120         */
00121        ptr = (u_char *)auth->data;
00122        length -= AUTH_HDR_LEN;
00123        first_pair = (VALUE_PAIR *)NULL;
00124        prev = (VALUE_PAIR *)NULL;
00125 
00126        while(length > 0) {
00127 
00128               attribute = *ptr++;
00129               attrlen = *ptr++;
00130               if(attrlen < 2) {
00131                      length = 0;
00132                      continue;
00133               }
00134               attrlen -= 2;
00135               if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) {
00136                      printf("Received unknown attribute %d. ", attribute);
00137               }
00138               else if ( attrlen >= AUTH_STRING_LEN ) {
00139                      printf("attribute %d too long, %d >= %d. ", attribute,
00140                             attrlen, AUTH_STRING_LEN);
00141               }
00142               else {
00143                      if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) ==
00144                                           (VALUE_PAIR *)NULL) {
00145                             fprintf(stderr, "%s: no memory\n",
00146                                           progname);
00147                             exit(1);
00148                      }
00149                      /* Same size */
00150                      strcpy(pair->name, attr->name);
00151                      pair->attribute = attr->value;
00152                      pair->type = attr->type;
00153                      pair->next = (VALUE_PAIR *)NULL;
00154 
00155                      switch(attr->type) {
00156 
00157                      case PW_TYPE_STRING:
00158                             memcpy(pair->strvalue, ptr, attrlen);
00159                             pair->strvalue[attrlen] = '\0';
00160                             pair->length = attrlen;
00161                             if(first_pair == (VALUE_PAIR *)NULL) {
00162                                    first_pair = pair;
00163                             }
00164                             else {
00165                                    prev->next = pair;
00166                             }
00167                             prev = pair;
00168                             break;
00169                      
00170                      case PW_TYPE_INTEGER:
00171                      case PW_TYPE_IPADDR:
00172                             memcpy(&lvalue, ptr, sizeof(UINT4));
00173                             pair->lvalue = ntohl(lvalue);
00174                             if(first_pair == (VALUE_PAIR *)NULL) {
00175                                    first_pair = pair;
00176                             }
00177                             else {
00178                                    prev->next = pair;
00179                             }
00180                             prev = pair;
00181                             break;
00182                      
00183                      default:
00184                             printf("    %s (Unknown Type %d). ", attr->name,attr->type);
00185                             free(pair);
00186                             break;
00187                      }
00188 
00189               }
00190               ptr += attrlen;
00191               length -= attrlen + 2;
00192        }
00193        authreq->request = first_pair;
00194        return(authreq);
00195 }
00196 
00197 
00198 /*
00199  *     Receive and print the result.
00200  */
00201 int result_recv(UINT4 host, u_short udp_port, char *buffer, int length)
00202 {
00203        AUTH_HDR      *auth;
00204        int           totallen;
00205        char          reply_digest[AUTH_VECTOR_LEN];
00206        char          calc_digest[AUTH_VECTOR_LEN];
00207        int           secretlen;
00208        AUTH_REQ      *authreq;
00209        VALUE_PAIR    *req;
00210 
00211        auth = (AUTH_HDR *)buffer;
00212        totallen = ntohs(auth->length);
00213 
00214        if(totallen != length) {
00215               printf("Received invalid reply length from server (want %d/ got %d)\n", totallen, length);
00216               exit(1);
00217        }
00218 
00219        /* Verify the reply digest */
00220        memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN);
00221        memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
00222        secretlen = strlen(secretkey);
00223        memcpy(buffer + length, secretkey, secretlen);
00224        md5_calc(calc_digest, (char *)auth, length + secretlen);
00225 
00226        if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) {
00227               printf("Warning: Received invalid reply digest from server. ");
00228        }
00229 
00230        authreq = test_radrecv(host, udp_port, buffer, length);
00231 
00232        req = authreq->request;
00233 
00234        while(req) {
00235               printf("    ");
00236               fprint_attr_val(stdout, req);
00237               printf(". ");
00238               req = req->next;
00239        }
00240        if(auth->code != PW_AUTHENTICATION_ACK) {
00241               printf("Access denied. ");
00242               return 1;
00243        }
00244        return 0;
00245 }
00246 
00247 
00248 
00249 
00250 /*
00251  *     Print usage message and exit.
00252  */
00253 void usage(void)
00254 {
00255        fprintf(stderr, "Usage: %s username passwd servername nas_port_id secretkey [ppphint] [nasname]\n",
00256               progname);
00257        exit(1);
00258 }
00259 
00260 
00261 /*
00262  *     Generate a random vector.
00263  */
00264 static void random_vector(char *vector)
00265 {
00266        int    randno;
00267        int    i;
00268 
00269        srand(time(0));
00270        for(i = 0;i < AUTH_VECTOR_LEN;) {
00271               randno = rand();
00272               memcpy(vector, &randno, sizeof(int));
00273               vector += sizeof(int);
00274               i += sizeof(int);
00275        }
00276 }
00277 
00278 
00279 int main(int argc, char **argv)
00280 {
00281        int                  salen;
00282        int                  result;
00283        struct sockaddr      salocal;
00284        struct sockaddr      saremote;
00285        struct sockaddr_in   *sin;
00286        struct servent              *svp;
00287        struct timeval              tv;
00288        fd_set               readfds;
00289         u_short                 svc_port;
00290        AUTH_HDR             *auth;
00291        char                 *username;
00292        char                 *passwd;
00293        char                 *server;
00294        char                 passbuf[AUTH_PASS_LEN];
00295        char                 md5buf[256];
00296        char                 nasname[256];
00297        UINT4                nas_ipaddr;
00298        UINT4                auth_ipaddr;
00299        UINT4                ui;
00300        u_short                     local_port;
00301        u_short                     total_length;
00302        int                  portno;
00303        int                  ppphint = 0;
00304        char                 *ptr;
00305        int                  length;
00306        int                  secretlen;
00307        int                  i;
00308        int                  bogus_packet = 0;
00309        int                  result_code;
00310 
00311        progname = argv[0];
00312 
00313        if (argv[1] && strcmp(argv[1], "-b") == 0) {
00314               argv++;
00315               argc--;
00316               bogus_packet = 1;
00317        }
00318 
00319        if (argc < 6 || argc > 8) {
00320               usage();
00321        }
00322        username  = argv[1];
00323        passwd    = argv[2];
00324        server    = argv[3];
00325        secretkey = argv[5];
00326        ptr = argv[4];
00327        if (*ptr == 's' || *ptr == 'S') ptr++;
00328        portno = atoi(ptr);
00329        if (argc > 6) ppphint = atoi(argv[6]);
00330 
00331        if (argc > 7)
00332               strNcpy(nasname, argv[7], sizeof(nasname));
00333        else
00334               gethostname(nasname, sizeof(nasname));
00335        nas_ipaddr = get_ipaddr(nasname);
00336 
00337        dict_init(NULL);
00338 
00339        /*
00340         *     Open a connection to the server.
00341         */
00342        svp = getservbyname ("radius", "udp");
00343        if (svp == (struct servent *) 0)
00344               svc_port = PW_AUTH_UDP_PORT;
00345        else
00346               svc_port = ntohs((u_short) svp->s_port);
00347 
00348        /* Get the IP address of the authentication server */
00349        if((auth_ipaddr = get_ipaddr(server)) == 0) {
00350               fprintf(stderr, "Couldn't find host %s\n", server);
00351               exit(1);
00352        }
00353 
00354        sockfd = socket (AF_INET, SOCK_DGRAM, 0);
00355        if (sockfd < 0) {
00356               perror ("socket");
00357               exit(1);
00358        }
00359 
00360        sin = (struct sockaddr_in *) &salocal;
00361         memset (sin, 0, sizeof (salocal));
00362        sin->sin_family = AF_INET;
00363        sin->sin_addr.s_addr = INADDR_ANY;
00364 
00365        local_port = 1025;
00366        do {
00367               local_port++;
00368               sin->sin_port = htons((u_short)local_port);
00369        } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) &&
00370                                           local_port < 64000);
00371        if (local_port >= 64000) {
00372               close(sockfd);
00373               perror ("bind");
00374               exit(1);
00375        }
00376 
00377        /*
00378         *     Build an authentication request
00379         */
00380        auth = (AUTH_HDR *)send_buffer;
00381        auth->code = PW_AUTHENTICATION_REQUEST;
00382        auth->id = getpid() % 256;
00383        random_vector(vector);
00384        memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
00385        total_length = AUTH_HDR_LEN;
00386        ptr = auth->data;
00387 
00388        /*
00389         *     User Name
00390         */
00391        *ptr++ = PW_USER_NAME;
00392        length = strlen(username);
00393        if(length > MAXPWNAM) {
00394               length = MAXPWNAM;
00395        }
00396        *ptr++ = length + 2;
00397        memcpy(ptr, username, length);
00398        ptr += length;
00399        total_length += length + 2;
00400 
00401        /*
00402         *     Password
00403         */
00404        *ptr++ = PW_PASSWORD;
00405        *ptr++ = AUTH_PASS_LEN + 2;
00406 
00407        length = strlen(passwd);
00408        if(length > MAXPASS) {
00409               length = MAXPASS;
00410        }
00411        memset(passbuf, 0, AUTH_PASS_LEN);
00412        memcpy(passbuf, passwd, length);
00413 
00414        /* Calculate the MD5 Digest */
00415        secretlen = strlen(secretkey);
00416        strNcpy(md5buf, secretkey, sizeof(md5buf));
00417        memcpy(md5buf + secretlen, auth->vector, AUTH_VECTOR_LEN);
00418        md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN);
00419 
00420        /* Xor the password into the MD5 digest */
00421        for(i = 0;i < AUTH_PASS_LEN;i++) {
00422               *ptr++ ^= passbuf[i];
00423        }
00424        total_length += AUTH_PASS_LEN + 2;
00425 
00426        *ptr++ = PW_NAS_PORT_ID;
00427        *ptr++ = 6;
00428        ui = htonl(portno);
00429        memcpy(ptr, &ui, sizeof(UINT4));
00430        ptr += 4;
00431        total_length += 6;
00432 
00433 #if TEST_VENDOR
00434        *ptr++ = PW_VENDOR_SPECIFIC;
00435        *ptr++ = 18;
00436        ui = htonl(307); /* livingston */
00437        memcpy(ptr, &ui, sizeof(UINT4));
00438        ptr += 4;
00439 
00440        *ptr++ = 2; /* LE-Terminate-Detail */
00441        *ptr++ = 6; /* len */
00442        strcpy(ptr, "test");
00443        ptr += 4;
00444 
00445        *ptr++ = 3; /* LE-Advice-of-Charge */
00446        *ptr++ = 6; /* len */
00447        strcpy(ptr, "TiNC");
00448        ptr += 4;
00449 
00450        total_length += 18;
00451 #endif
00452 
00453 #if TEST_USR
00454        *ptr++ = PW_VENDOR_SPECIFIC;
00455        *ptr++ = 14;
00456        ui = htonl(429); /* USR */
00457        memcpy(ptr, &ui, sizeof(UINT4));
00458        ptr += 4;
00459        ui = htonl(0x9823); /* Terminal-Type */
00460        memcpy(ptr, &ui, sizeof(UINT4));
00461        ptr += 4;
00462        strcpy(ptr, "test");
00463        ptr += 4;
00464        total_length += 14;
00465 #endif
00466 
00467        *ptr++ = PW_NAS_IP_ADDRESS;
00468        *ptr++ = 6;
00469        ui = htonl(nas_ipaddr);
00470        memcpy(ptr, &ui, sizeof(UINT4));
00471        ptr += 4;
00472        total_length += 6;
00473 
00474        /*
00475         *     We might need to add a PPP hint.
00476         */
00477        if (ppphint) {
00478               *ptr++ = PW_FRAMED_PROTOCOL;
00479               *ptr++ = 6;
00480               ui = htonl(PW_PPP);
00481               memcpy(ptr, &ui, sizeof(UINT4));
00482               ptr += 4;
00483               total_length += 6;
00484        }
00485 
00486        if (bogus_packet) {
00487               *ptr++ = PW_FILTER_ID;
00488               length = 4096;
00489               *ptr++ = length + 2;
00490               for(i = 0; i < 4096; i++)
00491                      *ptr++ = 'A';
00492               ptr += length;
00493               total_length += length + 2;
00494        }
00495 
00496        auth->length = htons(total_length);
00497 
00498        /*
00499         *     Send the request we've built.
00500         */
00501        sin = (struct sockaddr_in *) &saremote;
00502         memset (sin, 0, sizeof (saremote));
00503        sin->sin_family = AF_INET;
00504        sin->sin_addr.s_addr = htonl(auth_ipaddr);
00505        sin->sin_port = htons(svc_port);
00506 
00507        printf("Sending request. ");
00508        for (i = 0; i < 10; i++) {
00509               if (i > 0) printf("%i, ", i);
00510               sendto(sockfd, (char *)auth, total_length, 0,
00511                      &saremote, sizeof(struct sockaddr_in));
00512 
00513               tv.tv_sec = 3;
00514               tv.tv_usec = 0;
00515               FD_ZERO(&readfds);
00516               FD_SET(sockfd, &readfds);
00517               if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0)
00518                      continue;
00519               salen = sizeof (saremote);
00520               result = recvfrom (sockfd, recv_buffer, sizeof(i_recv_buffer),
00521                      0, &saremote, &salen);
00522               if (result >= 0)
00523                      break;
00524               sleep(tv.tv_sec);
00525        }
00526        if (result > 0 && i < 10) {
00527               result_code = result_recv(sin->sin_addr.s_addr, sin->sin_port, recv_buffer, result);
00528               exit(result_code);
00529        }
00530        printf("No answer.\n");
00531        close(sockfd);
00532        exit(2);
00533 }