⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extens.c

📁 This program is a RADIUS RFC-compliant daemon, which is derived from original Livingston Enterprise
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 1999-2004 Francesco P. Lovergine.  * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms stated in the LICENSE file which should be * enclosed with sources. */static char rcsid[] = "$Id: extens.c,v 1.9.2.3 2004/08/27 21:45:16 flovergine Exp $";#include	"yard.h"#include	"global.h"/* This structure is used for 3COM boxes */static int usr_speeds[53]={0, 300, 1200, 2400, 4800, 7200, 9600, 12000, 14400, 16800, 19200, 21600,28800, 38400, 57600, 115200, 288000, 751200, 120075, 24000, 26400, 31200,33600, 33333, 37333, 41333, 42666, 44000, 45333, 46666, 48000, 49333, 50666,52000, 53333, 54666, 56000, 57333, 64000, 25333, 26666, 28000, 29333, 30666,32000, 34666, 36000, 38666, 40000, 58666, 60000, 61333, 62666};/* * check_logins - see if maximum number of logins was not reached */int check_logins(char *user, const int max_logins){    char       	dbfile_name[PATH_MAX];    GDBM_FILE	dbf;    datum      	key, content;    user_entry	*ue;    struct tm	*time_info;    time_t     	crt_time = time(NULL);		    time_info = localtime(&crt_time);    snprintf(dbfile_name,sizeof(dbfile_name), "%s/%d/%s",	    radacct_dir,1900+time_info->tm_year,RADIUS_USER_STATS);    dbf = gdbm_open(dbfile_name,0,GDBM_READER,0600,NULL);    if (dbf == NULL) {	return 0;    }	    /* Build the key */    key.dptr = user;    key.dsize = strlen(user);    content = gdbm_fetch(dbf,key);    if (content.dptr == NULL) {	/* not here, at least one login is allowed */	gdbm_close(dbf);	return 0;    }    ue = (user_entry *)content.dptr;    if (ue->logins >= max_logins) {	gdbm_close(dbf);	if ( content.dptr!=NULL ) free( content.dptr );	return -2;    }    gdbm_close(dbf);    if ( content.dptr!=NULL ) free( content.dptr );    return 0;}/* * check_maxtime - see if maximum DAILY/MONTHLY/YEARLY online time is reached */int check_maxtime(char *user, const int hours, const int kind){    char       	dbfile_name[PATH_MAX];    GDBM_FILE	dbf;    datum      	key, content;    user_entry	*ue;    struct tm	*time_info;    UINT4	counter;    int		i,j;    time_t     	crt_time = time(NULL);	    time_info = localtime(&crt_time);    snprintf(dbfile_name, sizeof(dbfile_name), "%s/%d/%s",            radacct_dir,1900+time_info->tm_year,RADIUS_USER_STATS);    dbf = gdbm_open(dbfile_name,0,GDBM_READER,0600,NULL);    if (dbf == NULL) {	return 0;    }	    /* Build the key */    key.dptr = user;    key.dsize = strlen(user);    content = gdbm_fetch(dbf,key);    if (content.dptr == NULL) {	/* not here, login is allowed */	gdbm_close(dbf);	return 0;    }    ue = (user_entry *)content.dptr;    switch ( kind )      {      case DAY_LIMIT:        if (ue->day[time_info->tm_mon][time_info->tm_mday-1].on_line >= 	    hours*3600)           {	  gdbm_close(dbf);	  if ( content.dptr!=NULL ) free( content.dptr );	  return -2;	  }	break;      case MONTH_LIMIT:        for ( i=0, counter=0; i<time_info->tm_mday; i++ ) 	  counter += ue->day[time_info->tm_mon][i].on_line;	if ( counter >= hours*3600 )	  {	  gdbm_close(dbf);	  if ( content.dptr!=NULL ) free( content.dptr );	  return -2;	  }	break;      case YEAR_LIMIT:        for ( i=0, counter=0; i<=time_info->tm_mon; i++ )           for ( j=0; i<time_info->tm_mday; i++ ) 	    counter += ue->day[i][j].on_line;	if ( counter >= hours*3600 )	  {	  gdbm_close(dbf);	  if ( content.dptr!=NULL ) free( content.dptr );	  return -2;	  }	break;      default:        log_err("internal error: invalid kind of limit in a"	        "check_maxtime() call\n");        break;      }    gdbm_close(dbf);    if ( content.dptr!=NULL ) free( content.dptr );    return 0;}/* * clean_user_stats() * * initializes the user_stats database (clear the number of concurent logins) * to avoid starting a new radiusd server with invalid data * */ int clean_user_stats(void){    char            dbfile_name[PATH_MAX];    GDBM_FILE       dbf;    datum           key, content, nextkey;    struct tm       *time_info;    time_t          crt_time = time(NULL);	    time_info = localtime(&crt_time);    memset(dbfile_name, 0, PATH_MAX);    snprintf(dbfile_name, sizeof(dbfile_name), "%s/%d/%s",            radacct_dir,1900+time_info->tm_year,RADIUS_USER_STATS);    dbf = gdbm_open(dbfile_name,0,GDBM_WRITER|GDBM_SYNC,0600,NULL );    if (dbf == NULL) {	/* we couldn't open the databse. That's "okay" in this case... */	return 0;    }    key = gdbm_firstkey(dbf);    while (key.dptr != NULL) {	user_entry *p_ue;	int        retval;	content = gdbm_fetch(dbf, key);	if (content.dptr == NULL) {	    nextkey = gdbm_nextkey(dbf,key);	    free(key.dptr);	    key = nextkey;	    continue;	}	p_ue = (user_entry *)content.dptr;	p_ue->logins = 0;	content.dsize = sizeof(user_entry); /* rip off any port_entry */	/* update this modified entry */	retval = gdbm_store(dbf, key, content, GDBM_REPLACE);	if (retval != 0) {	    /* odd error updating the database */	    key.dptr[key.dsize] = '\0';	    log_err("could not reset user_stats entry for '%s'\n",		    (char *)key.dptr);	    gdbm_close(dbf);	    if (content.dptr != NULL) free(content.dptr);	    if (key.dptr != NULL) free(key.dptr);	    return -1;	}	/* update went okay */	if (content.dptr != NULL) free(content.dptr);	nextkey = gdbm_nextkey(dbf,key);	free(key.dptr);	key = nextkey;    }	    gdbm_close(dbf); /* close the database */    /* finished */    return 0;}/* * deny_user returns: * -2 if user is present in RADIUS_DIR/RADIUS_DENY * -3 if user is present in RADIUS_DIR/RADIUS_STOP * 1  if no such user (misa) * 0 if okay  * * allow_user returns: * -4 if user is NOT present in RADIUS_DIR/RADIUS_ALLOW * 0 if okay  *//*	Function: listed_on_file()	Purpose: it matches a user against many matching criteria:		GROUP: the user belongs to a certain group 		SHELL: the user has a certain shell		GECOS: the user has a Gecos field which _contains_ a		       certain string		USER: the user has a specific name.	Notes: string match is case-sensitive. Maybe a regex-match	       could be interesting. A value of ANY match any user.	Francesco Lovergine <f.lovergine@iesi.ba.cnr.it>*/static int listed_on_file(const char *filename, const char *username){    FILE *fp;    char buffer[1024];    char value[1024];    static char special[]="ANY";    if ((fp=fopen(filename, "r")) != NULL) {        while (fgets(buffer, sizeof(buffer), fp) != NULL) {            if ( strlen(buffer)==0 || buffer[0] == '\n' || 	         buffer[0] == '#' || buffer[0] == ';' ) continue;	    else	    if ( sscanf(buffer,"USER: %s",value ) == 1 )	      {              if (strcmp(value,special)==0 || 	          strcmp(username,value) == 0) { fclose(fp); return -1; }	      }	    else	    if ( sscanf(buffer,"GROUP: %s",value ) == 1 )	      {              if (strcmp(value,special)==0 || 	          unix_group(username,value)) { fclose(fp); return -1; }	      }	    else	    if ( sscanf(buffer,"GECOS: %s",value ) == 1 )	      {	      if (strcmp(value,special)==0 ||	          (strlen(value) && strstr(unix_gecos(username),value)!=NULL) )	        {		fclose(fp); return -1;		}	      }	    else	    if ( sscanf(buffer,"SHELL: %s",value ) == 1 )	      {	      if (strcmp(value,special)==0 ||	           (strlen(value) && strcmp(unix_shell(username),value)==0))	        {		fclose(fp); return -1;		}	      }	    else	      log_err("warning: syntax error in file '%s', line '%s' ignored",	               filename,buffer);	}    fclose(fp);    }    return 0;}/* * The actual function is quite simple ... */int deny_user(const char *username){    char file_name[PATH_MAX];    char buffer[1024];    if (!username || (strlen(username) >= sizeof(buffer))) {	/* well, an error, but for this function purpose 	 * should respond with okay... I hate this... */	return 0;    }    /* first try to open RADIUS_DIR/RADIUS_DENY */    snprintf(file_name, sizeof(file_name), "%s/%s", radius_dir, RADIUS_DENY);    if (listed_on_file(file_name, username) < 0)	return -2;    snprintf(file_name, sizeof(file_name), "%s/%s", radius_dir, RADIUS_STOP);    if (listed_on_file(file_name, username) < 0)	return -3;    return 0;}int allow_user(const char *username){    char file_name[PATH_MAX];    char buffer[1024];    if (!username || (strlen(username) >= sizeof(buffer))) {	return -4;    }    snprintf(file_name,sizeof(file_name),"%s/%s", radius_dir, RADIUS_ALLOW);    if (listed_on_file(file_name, username) < 0) return 0;    return -4;}/* * Builds a radlast structure from an AUTHREQ_HDR packet */static int build_radlast_from_authreq(radlast *rl, AUTH_REQ *authreq){    int		status_type = 0;    time_t	crt_time;    VALUE_PAIR	*pair;    int		vj = 0;        crt_time = time(NULL);    if (!rl || !authreq || !authreq->request)	return -1;    pair = authreq->request;    memset(rl, 0, sizeof(radlast));    rl->ut_time = crt_time;    while (pair != (VALUE_PAIR *)NULL) {	switch (pair->attribute) {	    case PW_ACCT_STATUS_TYPE:		status_type = pair->lvalue;		break;	    case PW_USER_NAME:		strncpy(rl->login, (char *)pair->strvalue, sizeof(rl->login));		break;	    case PW_CLIENT_PORT_ID:		rl->ent.port = pair->lvalue;		break;	    case PW_FRAMED_ADDRESS:	    case PW_LOGIN_HOST:		rl->client_ip = pair->lvalue;		break;	    case PW_ACCT_SESSION_TIME:		rl->length = pair->lvalue;		rl->ut_time -= pair->lvalue;		break;	    case PW_ACCT_INPUT_OCTETS:		rl->inb = pair->lvalue;		break;	    case PW_ACCT_OUTPUT_OCTETS:		rl->outb = pair->lvalue;		break;	    case PW_CLIENT_ID:		rl->nas_ip = pair->lvalue;		break;	    case PW_NAS_PORT_TYPE:		rl->ent.port_type = pair->lvalue;		break;	    case PW_LOGIN_SERVICE:		switch ((int)(pair->lvalue)) {		    case PW_TELNET:			rl->ent.proto = P_TELNET;			break;		    case PW_RLOGIN:			rl->ent.proto = P_RLOGIN;			break;		    case PW_TCP_CLEAR:			rl->ent.proto = P_TCP_CLEAR;			break;		    case PW_PORTMASTER:			rl->ent.proto = P_PORTMASTER;			break;		    default:			rl->ent.proto = P_LOGIN_UNK;		}		break;	    case PW_FRAMED_PROTOCOL:		switch ((int)(pair->lvalue)) {		    case PW_PPP:			rl->ent.proto = P_PPP;			break;		    case PW_SLIP:			rl->ent.proto = P_SLIP;			break;		    default:			rl->ent.proto = P_FRAMED_UNK;		}		break;	    case PW_ACCT_DELAY_TIME:		rl->ut_time -= pair->lvalue;		break;		    case PW_FRAMED_COMPRESSION:		vj++;		break;	    case PW_ACCT_TERMINATE_CAUSE:		rl->ent.term_cause = pair->lvalue;		break;	    case PW_ACCT_CALLED_STATION_ID:		strncpy(rl->calledid,(char*)pair->strvalue,		        sizeof(rl->calledid));	        break;	    case PW_ACCT_CALLING_STATION_ID:		strncpy(rl->callingid,(char*)pair->strvalue,		        sizeof(rl->callingid));	        break;	    /* Next attributes are VSAs */	    case PW_ACCT_ASCEND_DATA_RATE:		rl->rxrate = pair->lvalue;	        break;	    case PW_ACCT_ASCEND_XMIT_RATE:		rl->txrate = pair->lvalue;	        break;	    case PW_CONNECT_INFO_OLD:	        rl->txrate = (UINT4)atol(pair->strvalue);		rl->rxrate = rl->txrate;	        break;	    case PW_ACCT_USR_CONNECT_SPEED:		rl->rxrate = rl->txrate = usr_speeds[pair->lvalue%54 - 1];		break;	    case PW_CONNECT_INFO:	        sscanf(pair->strvalue,"%d/%d%*s",&rl->txrate,&rl->rxrate);	        break;	};	pair = pair->next;    };	    if ((rl->ent.proto == P_SLIP) && vj) rl->ent.proto = P_CSLIP;    return status_type;}/* * Updates the user entry from the user_stats databse (add one more login

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -