/* * * RADIUS * Remote Authentication Dial In User Service * * * Livingston Enterprises, Inc. * 4464 Willow Road * Pleasanton, CA 94588 * * Copyright 1992-1996 Livingston Enterprises, Inc. All Rights Reserved. * * This software is provided under license from Livingston * Enterprises, Inc., the terms and conditions of which are set * forth in a Software License Agreement that is contained in an * End User Agreement contained in the product packaging, and * electronically on the Livingston ftp site. This software may * only be used in conjunction with Livingston (or Livingston * authorized) products. Livingston makes no warranties to any * licensee concerning the applicability of the software to * licensee's specific requirements or the suitability of the * software for any intended use. Licensee shall not remove, * modify or alter any copyright and/or other proprietary rights * notice and must faithfully reproduce all such notices on any * copies or modifications to this software that it makes. * * 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. * */ static char sccsid[] = "$Id: users.c,v 1.25 1997/05/22 03:21:56 cdr Exp $ Copyright 1992 Livingston Enterprises Inc"; #include #include #include #include #include #include #include #include #include #include #include #include #include "radius.h" #include "users.h" #define MAXBUF 1024 extern char *progname; extern int debug_flag; extern int errno; extern char *radius_dir; static void fieldcpy (); int userparse(); /************************************************************************* * * Function: user_open * * Purpose: open the users file * *************************************************************************/ struct FAB ufab; struct RAB urab; int rad_users_file; int user_tmr_ast (void) { DEBUG("user: set USERS. expiration flag\n"); return ( rad_users_file = 1); } $DESCRIPTOR(delta_dsc,"0 00:10:00.00"); long delta_bin [2] = {0,0}; int user_open (void) { long status; if ( !delta_bin[0] && !delta_bin[1] ) { status = sys$bintim(&delta_dsc,delta_bin); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); } status = sys$setimr (0,delta_bin,user_tmr_ast ,user_tmr_ast,0); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); rad_users_file = 0; ufab = cc$rms_fab; ufab.fab$b_fac = FAB$M_GET; ufab.fab$b_shr = FAB$M_SHRGET; ufab.fab$l_fna = RADIUS_USERS; ufab.fab$b_fns = strlen(RADIUS_USERS); ufab.fab$b_rat = FAB$C_STMLF; ufab.fab$v_upi = 1; ufab.fab$v_sqo = 1; urab = cc$rms_rab; urab.rab$l_fab = &ufab; status = sys$open(&ufab); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); urab.rab$b_mbc = 4; urab.rab$b_mbf = 64; status = sys$connect(&urab); if (!$VMS_STATUS_SUCCESS(status)) lib$signal(status); urab.rab$v_nlk = 1; return status; } /************************************************************************* * * Function: user_close * * Purpose: close the users file * *************************************************************************/ void user_close (void) { sys$disconnect(&urab); sys$close(&ufab); } #define FIND_MODE_NAME 0 #define FIND_MODE_REPLY 1 #define FIND_MODE_SKIP 2 #define FIND_MODE_FLUSH 3 /************************************************************************* * * Function: user_find * * Purpose: Find the named user in the database. Create the * set of attribute-value pairs to check and reply with * for this user from the database. * *************************************************************************/ int user_find ( char * req_name, char * auth_name, VALUE_PAIR ** check_pairs, VALUE_PAIR ** reply_pairs, int rewind_flag ) { long status; char buffer[MAXBUF]; char *ptr; int req_namelen; int mode; int user_auth_name(); VALUE_PAIR *check_first; VALUE_PAIR *reply_first; if ( !rewind_flag ) { if ( rad_users_file ) { DEBUG("user: USERS. is expired, reopen\n"); user_close(); user_open(); } else { status = sys$rewind(&urab); if ( !(1 & status) ) lib$signal(status,urab.rab$l_stv); } } /* * Check for valid input, zero length names not permitted */ mode = FIND_MODE_NAME; if ( !(req_namelen = strlen(req_name)) ) { log_err("user_find: zero length username rejected\n"); return(-1); } check_first = (VALUE_PAIR *)NULL; reply_first = (VALUE_PAIR *)NULL; urab.rab$l_ubf = buffer; urab.rab$w_usz = sizeof(buffer) - 1; while( 1 & ( status = sys$get(&urab)) ) { buffer[urab.rab$w_rsz] = '\0'; if(mode == FIND_MODE_NAME) { /* * Find the entry starting with the users name */ if((strncasecmp(buffer, req_name, req_namelen) == 0 && (buffer[req_namelen] == ' ' || buffer[req_namelen] == '\t')) || strncmp(buffer, "DEFAULT", 7) == 0) { if(strncasecmp(buffer, "DEFAULT", 7) == 0) { ptr = &buffer[7]; /* * advance pointer to next white space */ while (isspace(*ptr) == 0) { ptr++; } } else { ptr = &buffer[req_namelen]; } /* * Parse the check values */ if ( userparse(ptr, &check_first) ) { log_err("user_find: unable to parse check-items for user %s\n", req_name); pairfree(check_first); return(-1); } /* * set authentication name */ if ( user_auth_name( req_name,auth_name,check_first) ) { pairfree(check_first); check_first = (VALUE_PAIR *)NULL; continue; } mode = FIND_MODE_REPLY; } } else { if(*buffer == ' ' || *buffer == '\t') { /* * Parse the reply values */ if ( userparse(buffer, &reply_first) ) { log_err("user_find: unable to parse reply-items for user %s\n", req_name); pairfree(check_first); pairfree(reply_first); return(-1); } } else { /* We are done */ *check_pairs = check_first; *reply_pairs = reply_first; return(0); } } } if ( !(1 & status) && (status != RMS$_EOF) ) lib$signal(status,urab.rab$l_stv); /* Update the callers pointers */ if ( reply_first ) { *check_pairs = check_first; *reply_pairs = reply_first; return 0; } return -1; } /************************************************************************* * * Function: user_auth_name * * Purpose: Set authentication name, stripping pre/suffix * *************************************************************************/ int user_auth_name ( char * req_name, char * auth_name, VALUE_PAIR * check_first ) { VALUE_PAIR *fix; VALUE_PAIR *get_attribute(); int req_len; int len; req_len = strlen(req_name); if ((fix = get_attribute(check_first, PW_PREFIX)) != (VALUE_PAIR *)NULL) { len = strlen(fix->strvalue); if (req_len <= len || (strncmp(req_name, fix->strvalue, len) != 0)) { return(-1); } /* * strip prefix from request name */ req_name += len; req_len -= len; } if ((fix = get_attribute(check_first, PW_SUFFIX)) != (VALUE_PAIR *)NULL) { len = strlen(fix->strvalue); if (req_len <= len || (strncmp(&req_name[req_len - len], fix->strvalue, len) != 0)) { return(-1); } /* * strip suffix from request name */ req_len -= len; } strncpy(auth_name, req_name, req_len); auth_name[req_len] = '\0'; return(0); } #define PARSE_MODE_NAME 0 #define PARSE_MODE_EQUAL 1 #define PARSE_MODE_VALUE 2 #define PARSE_MODE_INVALID 3 /************************************************************************* * * Function: userparse * * Purpose: Parses the buffer to extract the attribute-value pairs. * *************************************************************************/ int userparse ( char * buffer, VALUE_PAIR ** first_pair ) { int mode; char attrstr[64]; char valstr[256]; DICT_ATTR *attr; DICT_ATTR *dict_attrfind(); DICT_VALUE *dval; DICT_VALUE *dict_valfind(); VALUE_PAIR *pair; VALUE_PAIR *link; UINT4 ipstr2long(); UINT4 get_ipaddr(); UINT4 user_gettime(); struct tm *tm; time_t timeval; mode = PARSE_MODE_NAME; while(*buffer != '\n' && *buffer != '\0') { if(*buffer == ' ' || *buffer == '\t' || *buffer == ',') { buffer++; continue; } switch(mode) { case PARSE_MODE_NAME: /* Attribute Name */ fieldcpy(attrstr, &buffer); if((attr = dict_attrfind(attrstr)) == (DICT_ATTR *)NULL) { return(-1); } mode = PARSE_MODE_EQUAL; break; case PARSE_MODE_EQUAL: /* Equal sign */ if(*buffer == '=') { mode = PARSE_MODE_VALUE; buffer++; } else { return(-1); } break; case PARSE_MODE_VALUE: /* Value */ fieldcpy(valstr, &buffer); if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == (VALUE_PAIR *)NULL) { log_err("userparse: system error: out of memory\n"); return(-1); } strcpy(pair->name, attr->name); pair->attribute = attr->value; pair->type = attr->type; switch(pair->type) { case PW_TYPE_STRING: strcpy(pair->strvalue, valstr); pair->lvalue = strlen(valstr); break; case PW_TYPE_INTEGER: if(isdigit(*valstr)) { pair->lvalue = atoi(valstr); } else if((dval = dict_valfind(valstr)) == (DICT_VALUE *)NULL) { free(pair); return(-1); } else { pair->lvalue = dval->value; } break; case PW_TYPE_IPADDR: pair->lvalue = get_ipaddr(valstr); break; case PW_TYPE_DATE: timeval = time(0); tm = localtime(&timeval); if (user_gettime(valstr, tm) < 0) { pair->lvalue = 0; log_err("invalid expiration format \"%s\" rejected\n",valstr); } else { pair->lvalue = (UINT4)mktime(tm); } break; default: free(pair); return(-1); } pair->next = (VALUE_PAIR *)NULL; if(*first_pair == (VALUE_PAIR *)NULL) { *first_pair = pair; } else { link = *first_pair; while(link->next != (VALUE_PAIR *)NULL) { link = link->next; } link->next = pair; } mode = PARSE_MODE_NAME; break; default: mode = PARSE_MODE_NAME; break; } } return(0); } /************************************************************************* * * Function: fieldcpy * * Purpose: Copy a data field from the buffer. Advance the buffer * past the data field. * *************************************************************************/ static void fieldcpy ( char * string, char ** uptr ) { char *ptr; ptr = *uptr; if(*ptr == '"') { ptr++; while(*ptr != '"' && *ptr != '\0' && *ptr != '\n') { *string++ = *ptr++; } *string = '\0'; if(*ptr == '"') { ptr++; } *uptr = ptr; return; } while(*ptr != ' ' && *ptr != '\t' && *ptr != '\0' && *ptr != '\n' && *ptr != '=' && *ptr != ',') { *string++ = *ptr++; } *string = '\0'; *uptr = ptr; return; } /************************************************************************* * * Function: user_prtime * * Purpose: Turns printable string into correct tm struct entries * *************************************************************************/ static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; UINT4 user_gettime(valstr, tm) char *valstr; struct tm *tm; { int i; int atoi(); /* Get the month */ for(i = 0;i < 12;i++) { if(strncmp(months[i], valstr, 3) == 0) { tm->tm_mon = i; i = 13; } } /* Get the Day */ tm->tm_mday = atoi(&valstr[4]); /* Now the year */ tm->tm_year = atoi(&valstr[7]) - 1900; /* Midnight */ tm->tm_sec = 0; tm->tm_min = 0; tm->tm_hour = 0; /* if date makes no sense return failure */ if (i == 12 || tm->tm_mday < 1 || tm->tm_mday > 31 || tm->tm_year < 70) { return(-1); } else { return(0); } }