Back to index

nagios-plugins  1.4.16
dict.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 char dict_sccsid[] =
00029 "@(#)dict.c   1.5 Copyright 1992 Livingston Enterprises Inc\n"
00030 "@(#)dict.c   2.2 Copyright 1998 Cistron Internet Services B.V.";
00031 
00032 #include      <stdio.h>
00033 #include      <stdlib.h>
00034 #include      <sys/types.h>
00035 #include      <pwd.h>
00036 #include      <ctype.h>
00037 
00038 #include      "radiusd.h"
00039 
00040 static DICT_ATTR     *dictionary_attributes;
00041 static DICT_VALUE    *dictionary_values;
00042 static DICT_VENDOR   *dictionary_vendors;
00043 
00044 static int           vendorno = 1;
00045 
00046 #ifdef NOCASE
00047 #define DICT_STRCMP strcasecmp
00048 #else
00049 #define DICT_STRCMP strcmp
00050 #endif
00051 
00052 /*
00053  *     Free the dictionary_attributes and dictionary_values lists.
00054  */
00055 static void dict_free(void)
00056 {
00057        DICT_ATTR     *dattr, *anext;
00058        DICT_VALUE    *dval, *vnext;
00059        DICT_VENDOR   *dvend, *enext;
00060 
00061        for (dattr = dictionary_attributes; dattr; dattr = anext) {
00062               anext = dattr->next;
00063               free(dattr);
00064        }
00065        for (dval = dictionary_values; dval; dval = vnext) {
00066               vnext = dval->next;
00067               free(dval);
00068        }
00069        for (dvend = dictionary_vendors; dvend; dvend = enext) {
00070               enext = dvend->next;
00071               free(dvend);
00072        }
00073        dictionary_attributes = NULL;
00074        dictionary_values = NULL;
00075        dictionary_vendors = NULL;
00076        vendorno = 1;
00077 }
00078 
00079 /*
00080  *     Add vendor to the list.
00081  */
00082 static int addvendor(char *name, int value)
00083 {
00084        DICT_VENDOR *vval;
00085 
00086        if ((vval =(DICT_VENDOR *)malloc(sizeof(DICT_VENDOR))) ==
00087            (DICT_VENDOR *)NULL) {
00088               log(L_ERR|L_CONS, "dict_init: out of memory");
00089               return(-1);
00090        }
00091        strNcpy(vval->vendorname, name, sizeof(vval->vendorname));
00092        vval->vendorpec  = value;
00093        vval->vendorcode = vendorno++;
00094 
00095        /* Insert at front. */
00096        vval->next = dictionary_vendors;
00097        dictionary_vendors = vval;
00098 
00099        return 0;
00100 }
00101 
00102 /*
00103  *     Initialize the dictionary.  Read all ATTRIBUTES into
00104  *      the dictionary_attributes list.  Read all VALUES into
00105  *      the dictionary_values list.
00106  */
00107 int
00108 dict_init(char *fn)
00109 {
00110        FILE   *dictfd;
00111        char   dummystr[64];
00112        char   namestr[64];
00113        char   valstr[64];
00114        char   attrstr[64];
00115        char   typestr[64];
00116        char   vendorstr[64];
00117        int    line_no;
00118        DICT_ATTR     *attr;
00119        DICT_VALUE    *dval;
00120        DICT_VENDOR   *v;
00121        char   buffer[256];
00122        int    value;
00123        int    type;
00124        int    vendor;
00125        int    is_attrib;
00126 #ifdef ATTRIB_NMC
00127        int    vendor_usr_seen = 0;
00128        int    is_nmc = 0;
00129 #endif
00130 
00131        if (fn == NULL) dict_free();
00132 
00133        if (fn) {
00134               if (fn[0] == '/')
00135                      strNcpy(buffer, fn, sizeof(buffer));
00136               else
00137                      sprintf(buffer, "%.127s/%.127s", radius_dir, fn);
00138        } else
00139               sprintf(buffer, "%.200s/%.50s", radius_dir, RADIUS_DICTIONARY);
00140 
00141        if((dictfd = fopen(buffer, "r")) == (FILE *)NULL) {
00142               log(L_CONS|L_ERR, "dict_init: Couldn't open dictionary: %s",
00143                      buffer);
00144               return(-1);
00145        }
00146 
00147        line_no = 0;
00148        while(fgets(buffer, sizeof(buffer), dictfd) != (char *)NULL) {
00149               line_no++;
00150               
00151               /* Skip empty space */
00152               if(*buffer == '#' || *buffer == '\0' || *buffer == '\n') {
00153                      continue;
00154               }
00155 
00156               if (strncasecmp(buffer, "$INCLUDE", 8) == 0) {
00157 
00158                      /* Read the $INCLUDE line */
00159                      if(sscanf(buffer, "%63s%63s", dummystr, valstr) != 2) {
00160                             log(L_ERR,
00161                      "%s: Invalid filename on line %d of dictionary\n",
00162                                    progname, line_no);
00163                             return(-1);
00164                      }
00165                      if (dict_init(valstr) < 0)
00166                             return -1;
00167                      continue;
00168               }
00169 
00170               is_attrib = 0;
00171               if (strncmp(buffer, "ATTRIBUTE", 9) == 0)
00172                      is_attrib = 1;
00173 #ifdef ATTRIB_NMC
00174               is_nmc = 0;
00175               if (strncmp(buffer, "ATTRIB_NMC", 10) == 0)
00176                      is_attrib = is_nmc = 1;
00177 #endif
00178               if (is_attrib) {
00179                      /* Read the ATTRIBUTE line */
00180                      vendor = 0;
00181                      vendorstr[0] = 0;
00182                      if(sscanf(buffer, "%63s%63s%63s%63s%63s", dummystr,
00183                             namestr, valstr, typestr, vendorstr) < 4) {
00184                             log(L_ERR,
00185                      "%s: Invalid attribute on line %d of dictionary\n",
00186                                    progname, line_no);
00187                             return(-1);
00188                      }
00189 
00190 #ifdef ATTRIB_NMC
00191                      /*
00192                       *     Convert ATTRIB_NMC into our format.
00193                       *     We might need to add USR to the list of
00194                       *     vendors first.
00195                       */
00196                      if (is_nmc && vendorstr[0] == 0) {
00197                             if (!vendor_usr_seen) {
00198                                    if (addvendor("USR", VENDORPEC_USR) < 0)
00199                                           return -1;
00200                                    vendor_usr_seen = 1;
00201                             }
00202                             strcpy(vendorstr, "USR");
00203                      }
00204 #endif
00205 
00206                      /*
00207                       * Validate all entries
00208                       */
00209                      if(strlen(namestr) > 31) {
00210                             log(L_ERR|L_CONS,
00211               "dict_init: Invalid name length on line %d of dictionary",
00212                                    line_no);
00213                             return(-1);
00214                      }
00215 
00216                      if(!isdigit(*valstr)) {
00217                             log(L_ERR|L_CONS,
00218                      "dict_init: Invalid value on line %d of dictionary",
00219                                    line_no);
00220                             return(-1);
00221                      }
00222                      if (valstr[0] != '0')
00223                             value = atoi(valstr);
00224                      else
00225                             sscanf(valstr, "%i", &value);
00226 
00227                      if(strcmp(typestr, "string") == 0) {
00228                             type = PW_TYPE_STRING;
00229                      }
00230                      else if(strcmp(typestr, "integer") == 0) {
00231                             type = PW_TYPE_INTEGER;
00232                      }
00233                      else if(strcmp(typestr, "ipaddr") == 0) {
00234                             type = PW_TYPE_IPADDR;
00235                      }
00236                      else if(strcmp(typestr, "date") == 0) {
00237                             type = PW_TYPE_DATE;
00238                      }
00239                      else {
00240                             log(L_ERR|L_CONS,
00241                      "dict_init: Invalid type on line %d of dictionary",
00242                                    line_no);
00243                             return(-1);
00244                      }
00245 
00246                      for (v = dictionary_vendors; v; v = v->next) {
00247                             if (strcmp(vendorstr, v->vendorname) == 0)
00248                                    vendor = v->vendorcode;
00249                      }
00250                      if (vendorstr[0] && !vendor) {
00251                             log(L_ERR|L_CONS,
00252                      "dict_init: unknown vendor %s on line %d of dictionary",
00253                             vendorstr, line_no);
00254                             return -1;
00255                      }
00256 
00257 #ifdef COMPAT_1543
00258                      /*
00259                       *     Convert old values 221,1036-1039 to the new
00260                       *     ones, in case the dictionary is still the
00261                       *     one from 1.5.4.3
00262                       *
00263                       *     XXX - this is a HACK !!
00264                       */
00265                      switch (value) {
00266                             case 221:
00267                                    value = PW_HUNTGROUP_NAME;
00268                                    break;
00269                             case 1036:
00270                                    value = PW_FALL_THROUGH;
00271                                    break;
00272                             case 1037:
00273                                    value = PW_ADD_PORT_TO_IP_ADDRESS;
00274                                    break;
00275                             case 1038:
00276                                    value = PW_EXEC_PROGRAM;
00277                                    break;
00278                             case 1039:
00279                                    value = PW_EXEC_PROGRAM_WAIT;
00280                                    break;
00281                      }
00282 #endif
00283                      /* Create a new attribute for the list */
00284                      if((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) ==
00285                                    (DICT_ATTR *)NULL) {
00286                             log(L_ERR|L_CONS, "dict_init: out of memory");
00287                             return(-1);
00288                      }
00289                      strNcpy(attr->name, namestr, sizeof(attr->name));
00290                      attr->value = value;
00291                      attr->type = type;
00292                      if (vendor)
00293                             attr->value |= (vendor << 16);
00294 
00295                      /*
00296                       *     Add to the front of the list, so that
00297                       *     values at the end of the file override
00298                       *     those in the begin.
00299                       */
00300                      attr->next = dictionary_attributes;
00301                      dictionary_attributes = attr;
00302 
00303               }
00304               else if (strncmp(buffer, "VALUE", 5) == 0) {
00305 
00306                      /* Read the VALUE line */
00307                      if(sscanf(buffer, "%63s%63s%63s%63s", dummystr, attrstr,
00308                                           namestr, valstr) != 4) {
00309                             log(L_ERR|L_CONS,
00310               "dict_init: Invalid value entry on line %d of dictionary",
00311                                    line_no);
00312                             return(-1);
00313                      }
00314 
00315                      /*
00316                       * Validate all entries
00317                       */
00318                      if(strlen(attrstr) > 31) {
00319                             log(L_ERR|L_CONS,
00320               "dict_init: Invalid attribute length on line %d of dictionary",
00321                                    line_no);
00322                             return(-1);
00323                      }
00324 
00325                      if(strlen(namestr) > 31) {
00326                             log(L_ERR|L_CONS,
00327               "dict_init: Invalid name length on line %d of dictionary",
00328                                    line_no);
00329                             return(-1);
00330                      }
00331 
00332                      if(!isdigit(*valstr)) {
00333                             log(L_ERR|L_CONS,
00334                      "dict_init: Invalid value on line %d of dictionary",
00335                                    line_no);
00336                             return(-1);
00337                      }
00338                      value = atoi(valstr);
00339 
00340                      /* Create a new VALUE entry for the list */
00341                      if((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) ==
00342                                    (DICT_VALUE *)NULL) {
00343                             log(L_ERR|L_CONS, "dict_init: out of memory");
00344                             return(-1);
00345                      }
00346                      strNcpy(dval->attrname, attrstr, sizeof(dval->attrname));
00347                      strNcpy(dval->name, namestr, sizeof(dval->name));
00348                      dval->value = value;
00349 
00350                      /* Insert at front. */
00351                      dval->next = dictionary_values;
00352                      dictionary_values = dval;
00353               }
00354               else if(strncmp(buffer, "VENDOR", 6) == 0) {
00355 
00356                      /* Read the VENDOR line */
00357                      if(sscanf(buffer, "%63s%63s%63s", dummystr, attrstr,
00358                                           valstr) != 3) {
00359                             log(L_ERR|L_CONS,
00360               "dict_init: Invalid vendor entry on line %d of dictionary",
00361                                    line_no);
00362                             return(-1);
00363                      }
00364 
00365                      /*
00366                       * Validate all entries
00367                       */
00368                      if(strlen(attrstr) > 31) {
00369                             log(L_ERR|L_CONS,
00370               "dict_init: Invalid attribute length on line %d of dictionary",
00371                                    line_no);
00372                             return(-1);
00373                      }
00374 
00375                      if(!isdigit(*valstr)) {
00376                             log(L_ERR|L_CONS,
00377                      "dict_init: Invalid value on line %d of dictionary",
00378                                    line_no);
00379                             return(-1);
00380                      }
00381                      value = atoi(valstr);
00382 
00383                      /* Create a new VENDOR entry for the list */
00384                      if (addvendor(attrstr, value) < 0)
00385                             return -1;
00386 #ifdef ATTRIB_NMC
00387                      if (value == VENDORPEC_USR)
00388                             vendor_usr_seen = 1;
00389 #endif
00390               }
00391        }
00392        fclose(dictfd);
00393        return(0);
00394 }
00395 
00396 /*************************************************************************
00397  *
00398  *     Function: dict_attrget
00399  *
00400  *     Purpose: Return the full attribute structure based on the
00401  *             attribute id number.
00402  *
00403  *************************************************************************/
00404 
00405 DICT_ATTR     *
00406 dict_attrget(attribute)
00407 int    attribute;
00408 {
00409        DICT_ATTR     *attr;
00410 
00411        attr = dictionary_attributes;
00412        while(attr != (DICT_ATTR *)NULL) {
00413               if(attr->value == attribute) {
00414                      return(attr);
00415               }
00416               attr = attr->next;
00417        }
00418        return((DICT_ATTR *)NULL);
00419 }
00420 
00421 /*************************************************************************
00422  *
00423  *     Function: dict_attrfind
00424  *
00425  *     Purpose: Return the full attribute structure based on the
00426  *             attribute name.
00427  *
00428  *************************************************************************/
00429 
00430 DICT_ATTR     *
00431 dict_attrfind(attrname)
00432 char   *attrname;
00433 {
00434        DICT_ATTR     *attr;
00435 
00436        attr = dictionary_attributes;
00437        while(attr != (DICT_ATTR *)NULL) {
00438               if(DICT_STRCMP(attr->name, attrname) == 0) {
00439                      return(attr);
00440               }
00441               attr = attr->next;
00442        }
00443        return((DICT_ATTR *)NULL);
00444 }
00445 
00446 /*************************************************************************
00447  *
00448  *     Function: dict_valfind
00449  *
00450  *     Purpose: Return the full value structure based on the
00451  *             value name.
00452  *
00453  *************************************************************************/
00454 
00455 DICT_VALUE    *
00456 dict_valfind(valname)
00457 char   *valname;
00458 {
00459        DICT_VALUE    *val;
00460 
00461        val = dictionary_values;
00462        while(val != (DICT_VALUE *)NULL) {
00463               if(DICT_STRCMP(val->name, valname) == 0) {
00464                      return(val);
00465               }
00466               val = val->next;
00467        }
00468        return((DICT_VALUE *)NULL);
00469 }
00470 
00471 /*************************************************************************
00472  *
00473  *     Function: dict_valget
00474  *
00475  *     Purpose: Return the full value structure based on the
00476  *             actual value and the associated attribute name.
00477  *
00478  *************************************************************************/
00479 
00480 DICT_VALUE    *
00481 dict_valget(value, attrname)
00482 UINT4  value;
00483 char   *attrname;
00484 {
00485        DICT_VALUE    *val;
00486 
00487        val = dictionary_values;
00488        while(val != (DICT_VALUE *)NULL) {
00489               if(DICT_STRCMP(val->attrname, attrname) == 0 &&
00490                                           val->value == value) {
00491                      return(val);
00492               }
00493               val = val->next;
00494        }
00495        return((DICT_VALUE *)NULL);
00496 }
00497 
00498 /*
00499  *     Get the PEC (Private Enterprise Code) of the vendor
00500  *     based on it's internal number.
00501  */
00502 int dict_vendorpec(int code)
00503 {
00504        DICT_VENDOR   *v;
00505 
00506        for (v = dictionary_vendors; v; v = v->next)
00507               if (v->vendorcode == code)
00508                      break;
00509 
00510        return v ? v->vendorpec : 0;
00511 }
00512 
00513 /*
00514  *     Get the internal code of the vendor based on its PEC.
00515  */
00516 int dict_vendorcode(int pec)
00517 {
00518        DICT_VENDOR   *v;
00519 
00520        for (v = dictionary_vendors; v; v = v->next)
00521               if (v->vendorpec == pec)
00522                      break;
00523 
00524        return v ? v->vendorcode : 0;
00525 }
00526