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

📄 extens.c

📁 This program is a RADIUS RFC-compliant daemon, which is derived from original Livingston Enterprise
💻 C
📖 第 1 页 / 共 4 页
字号:
 * or clear out an entry... */static int update_db_record(int action, datum *content, radlast *rl,int month, int day){	    void *data;    int datasize;    user_entry 	*tmp = (user_entry *)(content->dptr);    port_entry 	*tpe;		    /* update fields */    tmp->day[month][day].on_line += rl->length;    tmp->day[month][day].input_octets += rl->inb;    tmp->day[month][day].output_octets += rl->outb;    /* now it is time to check if this is a start or stop */    if (action == PW_STATUS_START) {	tmp->day[month][day].nr_logins++;	tmp->logins++;	/* okay, start a new one ... */	datasize = content->dsize + sizeof(port_entry);	data = (void *) malloc(datasize);	if (data==NULL) {	    /* malloc error */	    log_err("could not malloc for handling user acct\n");	    content->dptr = NULL;	    return -1;	}	/* we have the required memory */	memcpy(data,content->dptr,content->dsize); /* paste the original data */	tpe = (port_entry *)((char *)data + content->dsize);	/* store the new entry */	tpe->time = rl->ut_time;	tpe->client_ip = rl->client_ip;	tpe->port_type = rl->ent.port_type;	tpe->port_number = rl->ent.port;	tpe->nas_ip = rl->nas_ip;	tpe->proto = rl->ent.proto;    } else {	/* this is a stop record */	int port_found = 0;	/* now it is ugly ... */	datasize = sizeof(user_entry); /* do not attemp to take more */	data = (void *)malloc(content->dsize); /* make enough room */	if (data==NULL) {	    /* malloc error */	    log_err("could not malloc for handling user acct\n");	    content->dptr = NULL;	    return -1;	}	/* memory is okay */	if (content->dsize > sizeof(user_entry)) {	    /* do we have any port entry to rip off ? */	    int ports_copied = 0;	    int nr_port_entry = 0;			    port_entry *dptr = (port_entry *)((char*)data+sizeof(user_entry));	    /* go to first port entry */	    tpe = (port_entry *)((char *)(content->dptr) + sizeof(user_entry));	    /* be super-safe */	    nr_port_entry = (content->dsize-sizeof(user_entry))/sizeof(port_entry);	    if (nr_port_entry*sizeof(port_entry)+sizeof(user_entry) != content->dsize) {		/* somehow we've managed to break the port entries, we		 * don't have a valid number of entries		 */		log_err("ERROR: database is inconsistent for user '%s'."		        " Cleaned up.\n",rl->login);		/* clean up the mess */		tmp->logins = 0;	    } else {		/* we have a valid number of port entries, 		 * now just in case tmp->logins have a different opinion ...		 */		if (tmp->logins != nr_port_entry)		    log_err("ERROR: database not okay for '%s': velived %d"		            "logins, have only %d\n",			    rl->login, tmp->logins, nr_port_entry);		tmp->logins = nr_port_entry;	    }	    while (ports_copied < tmp->logins) {		/* is this the port we are looking for ? */		if ((tpe->nas_ip!=rl->nas_ip) || 		    (tpe->port_type != rl->ent.port_type) ||		    (tpe->port_number != rl->ent.port) || port_found) {		    /* not our port */		    memcpy((void *)dptr, (void *)tpe, sizeof(port_entry));		    dptr++;		    datasize += sizeof(port_entry);		} else		    /* port found */		    port_found++;		/* skip the current port */		tpe++;		/* count any port as a copied one */		ports_copied++;	    }	}	if (port_found) tmp->logins--;	/* all done */	memcpy(data, content->dptr, sizeof(user_entry)); /* paste orig. data */    }    /* Now no matter what *data contains our data, with a size of datasize */    if ( content->dptr != NULL ) free(content->dptr);    content->dsize = datasize;    content->dptr = (char*)data;    return 0;}/* * inserts a new entry for the username in the user_stats database */static int insert_db_record(int action,datum *content,radlast *rl,int month,int day){    user_entry *tmp;    content->dsize = sizeof(user_entry);    if (action == PW_STATUS_START) content->dsize += sizeof(port_entry);    tmp = (user_entry *)malloc(content->dsize);    if (tmp == NULL) {	log_err("insert_db_record(): malloc error!\n");	content->dptr = NULL;	return -2;    }    /* init things */    memset((char *)tmp, 0, sizeof(user_entry));    tmp->day[month][day].on_line += rl->length;    tmp->day[month][day].input_octets += rl->inb;    tmp->day[month][day].output_octets += rl->outb;    if (action == PW_STATUS_START) {	port_entry *tpe;	tmp->logins = 1;	tmp->day[month][day].nr_logins = 1;	/* get the port_entry pointer */	tpe = (port_entry *)((char *)tmp + sizeof(user_entry));	tpe->time = rl->ut_time;	tpe->client_ip = rl->client_ip;	tpe->port_type = rl->ent.port_type;	tpe->port_number = rl->ent.port;	tpe->nas_ip = rl->nas_ip;	tpe->proto = rl->ent.proto;    }    content->dptr = (char *)tmp;    return 0;}/* * Updates the radlast logs... */extern int sockfd;extern int acctfd;static int update_radlast(radlast *rl){    pid_t 	child_pid;        struct tm   *time_info;    {	time_t crt_time = time(NULL);	time_info = localtime(&crt_time);    }    /* fork a child to handle this job */    child_pid = fork();    if (child_pid < 0) {	log_err("severe: Cannot fork() to writte radlast information\n");	return -1;    }    if (child_pid > 0)	/* in the parent all is okay */	return 0;        /* now in the child context do the lastlog update */    if (child_pid == 0) {	FILE   *fp;	char   log_file[PATH_MAX];	/* first close the acct and sock fd, we don't listen here */	close(acctfd); acctfd = -1;	close(sockfd); sockfd = -1;	memset(log_file, 0, sizeof(log_file));	snprintf(log_file, sizeof(log_file), "%s/%d/%s-%02d", radacct_dir, 	        1900+time_info->tm_year,		RADIUS_LAST, 		time_info->tm_mon+1);	/* extra safety never hurts */	umask(0027);	/* now we should be safe */	if ((fp = fopen(log_file, "a")) != NULL) {	    if (fwrite(rl, sizeof(radlast), 1, fp) < 1)		log_err("Could not write lastlog info for %s to %s\n",			rl->login, log_file);	    else fclose(fp);	} else log_err("Cannot open lastlog file '%s' for logging\n",log_file);	exit(0);    }    return 0;}/* * * Function: update_user_status * * Given an acct packet, it updates the internal databse structure to be in * sync with the reality... *			--cristiang */int update_user_status(AUTH_REQ *authreq){    GDBM_FILE 	dbf;    int 	retval;    datum 	key, content;    int 	flag = GDBM_INSERT;    char 	dbfile_name[PATH_MAX];    radlast	rl;    int		action;    struct tm	*time_info;        if (!authreq || !authreq->request)	return -1;    /* Now build the radlast packet ... */    action = build_radlast_from_authreq(&rl, authreq);    if (!strlen(rl.login))	return -1;    if ((action != PW_STATUS_STOP) && (action != PW_STATUS_START))	return -1;    time_info = localtime(&rl.ut_time); /* Use start session time */    debug("acct: %s user='%s', port=%d, time=%d, input=%d, output=%d\n",	  (action==PW_STATUS_START)?"start":"stop",	  rl.login, rl.ent.port, rl.length, rl.inb, rl.outb);    /* Prepare the DB filename... */    snprintf(dbfile_name,sizeof(dbfile_name),"%s/%d",radacct_dir,1900+time_info->tm_year);    mkdir(dbfile_name,0755);    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_WRCREAT|GDBM_SYNC,0600,NULL );    if (dbf == NULL) {	log_err("Could not open database %s for updating user stats",		dbfile_name);	return -1;    }    /* Build the key */    key.dptr = rl.login;    key.dsize = strlen(rl.login);    /* Search for a previous entry */    content = gdbm_fetch(dbf, key);    if (content.dptr != NULL) {	/*  found */	retval = update_db_record(action, &content, &rl, 	                          time_info->tm_mon,time_info->tm_mday-1 );	if (retval < 0) {	    gdbm_close(dbf);	    if (content.dptr != NULL) free(content.dptr);	    return retval;	}	flag = GDBM_REPLACE;    } else {	/* key not found, insert new */	retval = insert_db_record(action, &content, &rl,	                          time_info->tm_mon,time_info->tm_mday-1 );	if (retval < 0) {	    gdbm_close(dbf);	    if (content.dptr != NULL) free(content.dptr);	    return retval;	}	flag = GDBM_INSERT;    }	    retval = gdbm_store(dbf, key, content, flag);    gdbm_close(dbf);    if (content.dptr != NULL) free(content.dptr);    if (retval != 0) {	log_err("acct: could not store entry for '%s' (session %s)\n",		rl.login, (action==PW_STATUS_START)?"start":"stop");	return -2;    }    if (action == PW_STATUS_STOP) retval = update_radlast(&rl);    return retval;}/* * shadow_expire - checks if an account is expired according to *		   the shadow aging fields */#if defined(SHADOW_EXPIRATION) && defined(SHADOW)#ifndef DAY#define	DAY	(3600*24)#endifint shadow_expired(const char *user){    struct spwd *spw;    int crt_day = time(NULL)/DAY; /* today date */    int expire;	    if ((user == NULL) || !strlen(user)) {	/* invalid call to this function */	debug("shadow_expired: called with null argument\n");	/* but the account is not expired... */	return 0;    }    debug("shadow_expired: checking shadow expiration for user '%s'\n", user);	    setspent();    spw = getspnam(user);    if (spw == NULL) {	/* Oops, sorry, all missing accounts are not expired :-) */	endspent();	return 0;    }    if ((spw->sp_expire > 0) && (spw->sp_expire < crt_day)) {	/* Expired */	endspent();	return -1;    }    if (spw->sp_lstchg == 0) {	/* expired by root */	endspent();	return -1;    }    if ((spw->sp_max <= 0) || (spw->sp_max == 99999)) {	/* password never expires */	endspent();	return 0;    }    if (spw->sp_lstchg + spw->sp_max + spw->sp_inact < crt_day) {	/* password expired - password aged */	endspent();	return -1;    }    /* be nice and also report when password is due to expire */    expire = spw->sp_lstchg + spw->sp_max + spw->sp_inact - crt_day;    if ((expire >= 0) && (expire <= spw->sp_warn)) {	/* warn the looser */	endspent();	return expire;    }    endspent();    return 0;}#endif	#if defined(PAM) && defined(HAVE_LIBPAM)/* local variables */static const char *PAM_username;static const char *PAM_password;/* *     Function: PAM_conv *     Purpose: Dialogue between RADIUS and PAM modules. */static int PAM_conv_acct(int num_msg, const struct pam_message **msg,struct pam_response **resp, void *appdata_ptr){    int count = 0, replies = 0;    struct pam_response *reply = NULL;    int size = sizeof(struct pam_response);    #define GET_MEM \    if (reply) realloc(reply, size); \    else reply = malloc(size); \    if (!reply) return PAM_CONV_ERR; \    size += sizeof(struct pam_response);#define COPY_STRING(s) (s) ? strdup(s) : NULL					     for (count = 0; count < num_msg; count++) {	switch (msg[count]->msg_style) {	    case PAM_PROMPT_ECHO_ON:		GET_MEM;		reply[replies].resp_retcode = PAM_SUCCESS;		reply[replies++].resp = COPY_STRING(PAM_username);		/* PAM frees resp */		break;	    case PAM_PROMPT_ECHO_OFF:		GET_MEM;		reply[replies].resp_retcode = PAM_SUCCESS;		reply[replies++].resp = COPY_STRING(PAM_password);		/* PAM frees resp */		break;	    case PAM_TEXT_INFO:		/* ignore it... */		break;	    case PAM_ERROR_MSG:	    default:		/* Must be an error of some sort... */		free (reply);		return PAM_CONV_ERR;	}    }    if (reply)	*resp = reply;    return PAM_SUCCESS;}static struct pam_conv conv_acct = {    (int (*)())PAM_conv_acct,    NULL};/* *     Function: unix_pam *     Purpose: Check the users password against the standard UNIX *              password table + PAM. */int unix_pam(const char *name, const char *passwd, const char *pamauth){    pam_handle_t *pamh=NULL;    int retval;        PAM_username = name;    PAM_password = passwd;	         debug("unix_PAM: using pamauth string <%s> for pam.conf lookup\n", pamauth);        retval = pam_start(pamauth, name, &conv_acct, &pamh);    if (retval == PAM_SUCCESS) {	debug("unix_PAM: function pam_start succeeded for <%s>\n", name);	retval = pam_authenticate(pamh, 0);    }

⌨️ 快捷键说明

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