--- ./include/radiusclient.h.orig Fri Feb 26 02:59:44 1999 +++ ./include/radiusclient.h Fri Feb 26 06:17:10 1999 @@ -149,10 +149,11 @@ #define PW_FRAMED_APPLETALK_LINK 37 /* integer */ #define PW_FRAMED_APPLETALK_NETWORK 38 /* integer */ #define PW_FRAMED_APPLETALK_ZONE 39 /* string */ -#define PW_CHAP_CHALLENGE 60 /* string */ -#define PW_NAS_PORT_TYPE 61 /* integer */ -#define PW_PORT_LIMIT 62 /* integer */ -#define PW_LOGIN_LAT_PORT 63 /* string */ +#define PW_CHAP_CHALLENGE 60 /* string */ +#define PW_NAS_PORT_TYPE 61 /* integer */ +#define PW_PORT_LIMIT 62 /* integer */ +#define PW_LOGIN_LAT_PORT 63 /* string */ +#define PW_CONNECT_INFO 77 /* string */ /* Accounting */ @@ -275,6 +276,10 @@ #define PW_LOCAL 2 #define PW_REMOTE 3 +#ifdef ATTRIB_NMC +#define VENDORPEC_USR 429 +#endif + /* Server data structures */ typedef struct dict_attr @@ -293,6 +298,13 @@ struct dict_value *next; } DICT_VALUE; +typedef struct dict_vendor { + char vendorname[32]; + int vendorpec; + int vendorcode; + struct dict_vendor *next; +} DICT_VENDOR; + typedef struct value_pair { char name[NAME_LENGTH + 1]; @@ -390,7 +402,11 @@ DICT_ATTR *rc_dict_getattr __P((int)); DICT_ATTR *rc_dict_findattr __P((char *)); DICT_VALUE *rc_dict_findval __P((char *)); -DICT_VALUE * rc_dict_getval __P((UINT4, char *)); +DICT_VALUE *rc_dict_getval __P((UINT4, char *)); +DICT_VENDOR *rc_dict_findvendor __P((char *)); +DICT_VENDOR *rc_dict_getvendor __P((int)); +DICT_VENDOR *rc_dict_attrvendor __P((int)); +#define VENDOR_SPECIFIC(attr) ((attr) & 0xffff) /* ip_util.c */ --- ./lib/config.c.orig Tue Feb 10 18:29:37 1998 +++ ./lib/config.c Fri Feb 26 06:48:47 1999 @@ -274,7 +274,7 @@ if (option != NULL) { return (char *)option->val; } else { - rc_log(LOG_CRIT, "rc_conf_str: unkown config option requested: %s", optname); + rc_log(LOG_CRIT, "rc_conf_str: unknown config option requested: %s", optname); abort(); } } @@ -286,9 +286,9 @@ option = find_option(optname, OT_INT|OT_AUO); if (option != NULL) { - return *((int *)option->val); + return (option->val != NULL ? *((int *)option->val) : -1); } else { - rc_log(LOG_CRIT, "rc_conf_int: unkown config option requested: %s", optname); + rc_log(LOG_CRIT, "rc_conf_int: unknown config option requested: %s", optname); abort(); } } @@ -302,7 +302,7 @@ if (option != NULL) { return (SERVER *)option->val; } else { - rc_log(LOG_CRIT, "rc_conf_srv: unkown config option requested: %s", optname); + rc_log(LOG_CRIT, "rc_conf_srv: unknown config option requested: %s", optname); abort(); } } --- ./lib/buildreq.c.orig Fri Dec 11 16:24:08 1998 +++ ./lib/buildreq.c Fri Feb 26 06:55:25 1999 @@ -262,10 +262,12 @@ */ dtime = 0; - if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0)) == NULL) + start_time = time(NULL); + if ((adt_vp = rc_avpair_get(data.send_pairs, PW_ACCT_DELAY_TIME)) != NULL) + start_time -= (time_t) adt_vp->lvalue; + else if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0)) == NULL) return (ERROR_RC); - start_time = time(NULL); result = ERROR_RC; for(i=0; (imax) && (result != OK_RC) && (result != BADRESP_RC) ; i++) --- ./lib/avpair.c.orig Fri Dec 26 04:27:48 1997 +++ ./lib/avpair.c Fri Feb 26 07:11:28 1999 @@ -161,6 +161,8 @@ VALUE_PAIR *pair; unsigned char hex[3]; /* For hex string conversion. */ char buffer[256]; + UINT4 vendorpec; + DICT_VENDOR *vendor; /* * Extract attribute-value pairs @@ -178,6 +180,33 @@ { rc_log(LOG_ERR, "rc_avpair_gen: received attribute with invalid length"); break; + } + + /* + * FIXME: + * For now we ignore the length in the vendor-specific + * part, and assume only one entry. + */ + if (attribute == PW_VENDOR_SPECIFIC && attrlen > 6) { + vendorpec = ntohl (*(UINT4 *) ptr); + if ((vendor = rc_dict_getvendor (vendorpec)) != NULL) { + ptr += 4; +#ifdef ATTRIB_NMC + if (vendorpec == VENDORPEC_USR) { + attribute = (ntohl(*(UINT4 *)ptr) & + 0xFFFF) | vendor->vendorcode; + ptr += 4; + attrlen -= 8; + length -= 8; + } else +#endif + { + attribute = *ptr | vendor->vendorcode; + ptr += 2; + attrlen -= 6; + length -= 6; + } + } } if ((attr = rc_dict_getattr (attribute)) == (DICT_ATTR *) NULL) --- ./lib/dict.c.orig Fri Dec 26 04:27:50 1997 +++ ./lib/dict.c Fri Feb 26 07:08:23 1999 @@ -20,6 +20,37 @@ static DICT_ATTR *dictionary_attributes; static DICT_VALUE *dictionary_values; +static DICT_VENDOR *dictionary_vendors; +#ifdef ATTRIB_NMC +static int vendor_usr_seen = 0; +#endif + +/* + * Add vendor to the list. + */ +static int rc_addvendor (char *name, int value) +{ + DICT_VENDOR *vval; + static int vendorno = 1; + + if ((vval = (DICT_VENDOR *) malloc (sizeof(DICT_VENDOR))) == NULL) { + rc_log(LOG_CRIT, "rc_addvendor: out of memory"); + return (-1); + } + strcpy (vval->vendorname, name); + vval->vendorpec = value; + vval->vendorcode = vendorno++ << 16; + + /* Insert at front. */ + vval->next = dictionary_vendors; + dictionary_vendors = vval; + +#ifdef ATTRIB_NMC + if (value == VENDORPEC_USR) + vendor_usr_seen = 1; +#endif + return 0; +} /* * Function: rc_read_dictionary @@ -44,6 +75,11 @@ char buffer[256]; int value; int type; + DICT_VENDOR *vendor; + char vendorstr[64]; +#ifdef ATTRIB_NMC + int not_nmc; +#endif if ((dictfd = fopen (filename, "r")) == (FILE *) NULL) { @@ -63,18 +99,34 @@ continue; } +#ifdef ATTRIB_NMC + not_nmc = 1; + if (strncmp (buffer, "ATTRIBUTE", 9) == 0 || + (not_nmc = strncmp(buffer, "ATTRIB_NMC", 10)) == 0) +#else if (strncmp (buffer, "ATTRIBUTE", 9) == 0) +#endif { /* Read the ATTRIBUTE line */ - if (sscanf (buffer, "%s%s%s%s", dummystr, namestr, - valstr, typestr) != 4) + vendor = NULL; + vendorstr[0] = 0; + if (sscanf (buffer, "%s%s%s%s%s", dummystr, namestr, + valstr, typestr, vendorstr) < 4) { rc_log(LOG_ERR, "rc_read_dictionary: invalid attribute on line %d of dictionary %s", line_no, filename); return (-1); } +#ifdef ATTRIB_NMC + if (!not_nmc && vendorstr[0] == 0) { + if (!vendor_usr_seen && rc_addvendor ("USR", VENDORPEC_USR) < 0) + return -1; + strcpy(vendorstr, "USR"); + } +#endif + /* * Validate all entries */ @@ -92,7 +144,7 @@ line_no, filename); return (-1); } - value = atoi (valstr); + value = strtol (valstr, NULL, 0); if (strcmp (typestr, "string") == 0) { @@ -118,6 +170,14 @@ return (-1); } + if (vendorstr[0] && + (vendor = rc_dict_findvendor (vendorstr)) == NULL) { + rc_log(LOG_ERR, + "rc_read_dictionary: unknown vendor %s on line %d of dictionary", + vendorstr, line_no); + return (-1); + } + /* Create a new attribute for the list */ if ((attr = (DICT_ATTR *) malloc (sizeof (DICT_ATTR))) @@ -129,6 +189,8 @@ strcpy (attr->name, namestr); attr->value = value; attr->type = type; + if (vendor != NULL) + attr->value |= vendor->vendorcode; /* Insert it into the list */ attr->next = dictionary_attributes; @@ -172,7 +234,7 @@ line_no, filename); return (-1); } - value = atoi (valstr); + value = strtol (valstr, NULL, 0); /* Create a new VALUE entry for the list */ if ((dval = @@ -190,6 +252,37 @@ dval->next = dictionary_values; dictionary_values = dval; } + else if (strncmp (buffer, "VENDOR", 6) == 0) { + + /* Read the VENDOR line */ + if (sscanf (buffer, "%s%s%s", dummystr, attrstr, valstr) != 3) { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid vendor entry on line %d of dictionary", + line_no); + return (-1); + } + + /* + * Validate all entries + */ + if (strlen (attrstr) > 31) { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid vendor name length on line %d of dictionary", + line_no); + return (-1); + } + + if (!isdigit (*valstr)) { + rc_log(LOG_ERR, + "rc_read_dictionary: invalid vendor code on line %d of dictionary", + line_no); + return (-1); + } + + /* Create a new VENDOR entry for the list */ + if (rc_addvendor (attrstr, strtol (valstr, NULL, 0)) < 0) + return (-1); + } } fclose (dictfd); return (0); @@ -292,3 +385,51 @@ } return ((DICT_VALUE *) NULL); } + +/* + * Return the full vendor structure based on its PEC + * (Private Enterprise Code). + */ +DICT_VENDOR * rc_dict_getvendor (int pec) +{ + DICT_VENDOR *v; + + for (v = dictionary_vendors; v; v = v->next) + if (v->vendorpec == pec) + break; + + return v; +} + +/* + * Return the full vendor structure based on vendor name. + */ +DICT_VENDOR * rc_dict_findvendor (char *vendorname) +{ + DICT_VENDOR *v; + + for (v = dictionary_vendors; v; v = v->next) + if (strcasecmp(v->vendorname, vendorname) == 0) + break; + + return v; +} + +/* + * Return the full vendor structure for given attribute + * based on attribute id number. + */ +DICT_VENDOR * rc_dict_attrvendor (int attribute) +{ + DICT_VENDOR *v; + int code; + + if ((code = attribute & ~0xffff) == 0) + return NULL; + + for (v = dictionary_vendors; v; v = v->next) + if (v->vendorcode == code) + break; + + return v; +} --- ./lib/sendserver.c.orig Sun Jan 17 00:54:44 1999 +++ ./lib/sendserver.c Mon Mar 15 23:51:09 1999 @@ -163,7 +163,7 @@ struct sockaddr salocal; struct sockaddr saremote; struct sockaddr_in *sin; - struct timeval authtime; + struct timeval authtime, authstart; fd_set readfds; AUTH_HDR *auth, *recv_auth; UINT4 auth_ipaddr; @@ -264,18 +264,34 @@ sendto (sockfd, (char *) auth, (unsigned int) total_length, (int) 0, (struct sockaddr *) sin, sizeof (struct sockaddr_in)); - authtime.tv_usec = 0L; - authtime.tv_sec = (long) data->timeout; - FD_ZERO (&readfds); - FD_SET (sockfd, &readfds); - if (select (sockfd + 1, &readfds, NULL, NULL, &authtime) < 0) - { - if (errno == EINTR) - continue; - rc_log(LOG_ERR, "rc_send_server: select: %s", strerror(errno)); - memset (secret, '\0', sizeof (secret)); - close (sockfd); - return (ERROR_RC); + authstart.tv_sec = 0; + for (;;) { + if (authstart.tv_sec == 0) { + gettimeofday(&authstart, NULL); + authtime.tv_usec = 0; + authtime.tv_sec = (long) data->timeout; + } else { + gettimeofday(&authtime, NULL); + authtime.tv_usec = authstart.tv_usec - authtime.tv_usec; + authtime.tv_sec = (long) data->timeout + + authstart.tv_sec - authtime.tv_sec; + if (authtime.tv_usec < 0) { + authtime.tv_usec += 1000000; + authtime.tv_sec -= 1; + } + if (authtime.tv_sec < 0) + break; + } + FD_ZERO (&readfds); + FD_SET (sockfd, &readfds); + if (select (sockfd + 1, &readfds, NULL, NULL, &authtime) >= 0) + break; + if (errno != EINTR) { + rc_log(LOG_ERR, "rc_send_server: select: %s", strerror(errno)); + memset (secret, '\0', sizeof (secret)); + close (sockfd); + return (ERROR_RC); + } } if (FD_ISSET (sockfd, &readfds)) break; --- ./src/radexample.c.orig Wed Jan 6 04:20:09 1999 +++ ./src/radexample.c Fri Feb 26 06:47:16 1999 @@ -26,10 +26,13 @@ int result; char username[128]; char passwd[AUTH_PASS_LEN + 1]; - VALUE_PAIR *send, *received; + VALUE_PAIR *send, *received, *vp; UINT4 service; char msg[4096], username_realm[256]; char *default_realm = rc_conf_str("default_realm"); + DICT_VALUE *val; + DICT_VENDOR *ven; + struct in_addr addr; pname = (pname = strrchr(argv[0],'/'))?pname+1:argv[0]; @@ -88,6 +91,36 @@ { fprintf(stderr, "\"%s\" RADIUS Authentication failure (RC=%i)\n", username, result); } - + + for (vp = received; vp; vp = vp->next) + { + if ((ven = rc_dict_attrvendor(vp->attribute)) != NULL) + printf("Vendor-Specific: Vendor = %s, ", ven->vendorname); + printf("%s = ", vp->name); + + switch (vp->type) + { + case PW_TYPE_STRING: + printf("%s\n", vp->strvalue); + break; + case PW_TYPE_INTEGER: + val = rc_dict_getval(vp->lvalue, vp->name); + if (val != NULL) + printf("%s\n", val->name); + else + printf("%ld\n", vp->lvalue); + break; + case PW_TYPE_IPADDR: + addr.s_addr = htonl(vp->lvalue); + printf("%s\n", inet_ntoa(addr)); + break; + case PW_TYPE_DATE: + printf("%s\n", ctime((time_t *) &vp->lvalue)); + break; + default: + printf("unknown type\n"); + } + } + return result; } --- ./configure.in.orig Thu Jan 7 04:51:05 1999 +++ ./configure.in Fri Feb 26 03:47:26 1999 @@ -175,6 +175,24 @@ ] ) +dnl ATTRIB_NMC +AC_MSG_CHECKING(whether to add support for USR Vendor-Specific attributes) +AC_ARG_ENABLE(vendor-usr, +[ --disable-vendor-usr Do not include support for USR specific attributes], +[ + if test $enableval = "yes" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(ATTRIB_NMC) + else + AC_MSG_RESULT(no) + fi +], +[ + AC_MSG_RESULT(yes) + AC_DEFINE(ATTRIB_NMC) +] +) + AC_SUBST(RC_SECURE_PATH) AC_SUBST(RC_LOG_FACILITY) --- ./acconfig.h.orig Wed Jan 14 18:16:24 1998 +++ ./acconfig.h Fri Feb 26 03:32:50 1999 @@ -32,5 +32,8 @@ /* SCP support */ #undef SCP +/* ATTRIB_NMC support */ +#undef ATTRIB_NMC + /* package version */ #undef VERSION