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

📄 extens.c

📁 This program is a RADIUS RFC-compliant daemon, which is derived from original Livingston Enterprise
💻 C
📖 第 1 页 / 共 4 页
字号:
    if (retval == PAM_SUCCESS) {	debug("unix_PAM: function pam_authenticate succeeded for <%s>\n", name);	retval = pam_acct_mgmt(pamh, 0);    }    /* do not remove block braces, it could break things due to debug     * macro */        if (retval == PAM_SUCCESS) {	debug("unix_PAM: function pam_acct_mgmt succeeded for <%s>\n", name);    }    else {	debug("unix_PAM: PAM FAILED for <%s> failed\n", name);    }    if (pam_end(pamh, retval) != PAM_SUCCESS) {	pamh = NULL;	log_err("ERROR!!!: PAM failed to release authenticator items");    }    return (retval == PAM_SUCCESS)?0:-1;}/* *     Function: PAM_conv_session *     Purpose: A dummy conversation function between the radiusd and the *              session modules. */static int PAM_conv_session(int num_msg, const struct pam_message **msg,struct pam_response **resp, void *appdata_ptr){    /* this one should never be called; use appdata_ptr instead */    return PAM_CONV_ERR;}    /* * We use this structure to pass the network packet pairs to * the session module(s) */static struct pam_conv conv_session = {    (int (*)())PAM_conv_session,	    NULL	};/* * This is to save the handle of the PAM session betwenn incantations... */static pam_handle_t *PAM_handle = NULL;/* *     Function: pam_session *     Purpose: This is called when we are using PAM to inform the PAM *              library about the new sessions being open or closed by *		the NASes. */void pam_session(AUTH_REQ *authreq){    char		*username = NULL;    VALUE_PAIR		*pair;    int 		retval;    pam_handle_t	*pamh = NULL;    int			type=0;        /* First, get some important data: username and the type of the packet */    pair = authreq->request;    while (pair != (VALUE_PAIR *)NULL) {	switch (pair->attribute) {	    case PW_USER_NAME:		username = pair->strvalue;		break;	    case PW_ACCT_STATUS_TYPE:		type = pair->lvalue;		break;	}	pair = pair->next;    }    /* To do:     * -we should maybe look at the NAS ip and set the     *  PAM_RHOST item too. But for now it is not critical,     *	and I am lazy..     *		--cristiang     */    if ((username == NULL) || !type)	/* nothing to do */	return;    /* initialize the conv_session struct */    conv_session.appdata_ptr = authreq->request;    /* we avoid to open to many sessions with pam_start because of the     * overhead induced by this call. On a busy accounting server,     * this is critical. We open just one session and reuse it later...     */    if (PAM_handle == (pam_handle_t *)NULL) {	/* we need to open a new session */	debug("about to init PAM session call for %s\n", username);    	retval = pam_start(RADIUS_PAM_SERVICE, username, &conv_session, &pamh);	if (retval != PAM_SUCCESS) {#if !defined(OLD_PAM)	    log_err("cannot initialize PAM session for %s (%s)\n",		    username, pam_strerror(PAM_handle, retval));#else	    log_err("cannot initialize PAM session for %s (%s)\n",		    username, pam_strerror(retval));#endif 	    return;	} else	    /* opened successfuly - save it for later use... */	    PAM_handle = pamh;    } else {	/* we have already an open session - use that... */	pamh = PAM_handle;	/* and update the username */	retval = pam_set_item(pamh, PAM_USER, username);	if (retval != PAM_SUCCESS) {#if !defined(OLD_PAM) /* The new pam libraries have 2 params for pam_strerr - misa*/	    log_err("can not set username (%s) for acct packet: %s\n",		  username, pam_strerror(PAM_handle, retval));#else	    log_err("can not set username (%s) for acct packet: %s\n",		  username, pam_strerror(retval));#endif /*OLD_PAM*/	    return;	}	/* and the conversation structure, to get appdata pointer	 * updated with the new pointer to the network packet...	 */	retval = pam_set_item(pamh, PAM_CONV, &conv_session);	if (retval != PAM_SUCCESS) {#if !defined(OLD_PAM) /* The new pam libraries have 2 params for pam_strerr - misa*/	    log_err("can not pass acct packet for %s: %s\n",		  username, pam_strerror(PAM_handle, retval));#else	    log_err("can not pass acct packet for %s: %s\n",		  username, pam_strerror(retval));#endif /*OLD_PAM*/	    return;	}    }    /* all good, now do we start or close a session ? */    if (type == PW_STATUS_START) {	/* start session */	debug("opening session for user %s\n", username);		retval = pam_open_session(pamh, 0);	if (retval != PAM_SUCCESS) {#if !defined(OLD_PAM) /* The new pam libraries have 2 params for pam_strerr - misa*/	    log_err("could not start session for user %s (%s)\n",		    username, pam_strerror(PAM_handle, retval));#else	    log_err("could not start session for user %s (%s)\n",		    username, pam_strerror(retval));#endif /*OLD_PAM*/	    return;	}    }    if (type == PW_STATUS_STOP) {		/* close session */	debug("closing session for user %s\n", username);	retval = pam_close_session(pamh, 0);	if (retval != PAM_SUCCESS) {#if !defined(OLD_PAM) /* The new pam libraries have 2 params for pam_strerr - misa*/	    log_err("could not close session for user %s (%s)\n",		    username, pam_strerror(PAM_handle, retval));#else	    log_err("could not close session for user %s (%s)\n",		    username, pam_strerror(retval));#endif /*OLD_PAM*/	    return;	}    }    /* we don't call pam_end because this code is not supposed to die()...     * <sigh!> --cristiang     */    return;}#else #if defined(PAM) && !defined(HAVE_LIBPAM)#error "PAM development library missed. Check your configuration."#endif#endif /* PAM *//* * SOME BASIC PACKET QUEUE MANAGEMENT STUFF * * Idea: eliminate the duplicate acct packets problem and sort out the *	out-of-order packets to get better accounting */static acct_packet *root_acct_packet = NULL;static int acct_queue_entries = 0;static acct_packet *in_acct_queue(acct_packet *packet, int type){    acct_packet *this;    this = root_acct_packet;    while (this != (acct_packet *)NULL) {	if (	    (this->port == packet->port) &&	    (this->nas_ip == packet->nas_ip) &&	    !strncmp(this->username, packet->username, sizeof(packet->username)) &&	    !strncmp(this->sessionid, packet->sessionid, sizeof(packet->sessionid)) &&	    (this->type & type)	    )	    return this;	this = this->next;    }    return (acct_packet *)NULL;}/* * Adds a pack to the queue */static int add_acct_queue(acct_packet *packet){    acct_packet *this, *temp;    this = root_acct_packet;    temp = in_acct_queue(packet, packet->type);    if (temp != (acct_packet *)NULL)	return 0;    temp = in_acct_queue(packet, PW_STATUS_STOP | PW_STATUS_START);    if (temp != (acct_packet *)NULL) {	temp->type |= packet->type;	return 1;    }    temp = (acct_packet *)NULL;    while (this != (acct_packet *)NULL) {	temp = this;	this = this->next;    }    this = (acct_packet *)malloc(sizeof(acct_packet));    if (this == (acct_packet *)NULL) {	log_err("MEMORY ERROR !!! Can not alloc memory for acct packet %s (user %s)",		packet->sessionid, packet->username);	return 0;    }    if (temp == (acct_packet *)NULL)	temp = this;    else {	temp->next = this;	temp = this;    }    temp->next = (acct_packet *)NULL;    /* one more entry */    acct_queue_entries++;    /* root list empty */    if (root_acct_packet == (acct_packet *)NULL)	root_acct_packet = temp;    /* copy over */    memcpy(temp, packet, sizeof(acct_packet));    return 1;}/* * Removes a packet from the queue */static int remove_acct_queue(acct_packet *packet){    acct_packet	*temp, *temp1;            temp = in_acct_queue(packet, PW_STATUS_START | PW_STATUS_STOP);    if (temp == (acct_packet *)NULL)	return 0;    if (temp->type != (PW_STATUS_START | PW_STATUS_STOP))	return 0;    if (temp == root_acct_packet) {	/* oops. the root is here ... */	root_acct_packet = root_acct_packet->next;    } else {	temp1 = root_acct_packet;	while (temp1->next != temp)	    temp1 = temp1->next;	temp1->next = temp->next;    };    free(temp);    acct_queue_entries--;    return 1;}/* * Delete the oldest pair of (start,stop) packets from the queue * to make room for more */static int cleanup_acct_queue(void){    acct_packet *temp;    temp = root_acct_packet;    while (temp != (acct_packet*)NULL) {	if (temp->type == (PW_STATUS_START | PW_STATUS_STOP))	    return remove_acct_queue(temp);	temp = temp->next;    }    return 1;}/* * Returns > 0 if the packet passed is valid, 0 otherwise * A valid packet is: * - a new one (we haven't seen it before) * - a stop packet * - a start packet which is not out of order (we haven't seen *	the corresponsing packet for it yet */int validate_acct_packet(AUTH_REQ *authreq){    acct_packet packet;    VALUE_PAIR	*pair;    /* Some run-time debugging */    if (acct_queue_entries > 2*MAX_ACCT_QUEUE) {	log_debug("WARNING: acct queue is large: %d entries, max %d\n",		  acct_queue_entries, MAX_ACCT_QUEUE);	log_debug("possible unreliable communication with term servers ?\n");    }          pair = authreq->request;    memset(&packet, 0, sizeof(acct_packet));    while (pair != (VALUE_PAIR *)NULL) {	switch (pair->attribute) {	    case PW_ACCT_STATUS_TYPE:		packet.type = pair->lvalue;		break;	    case PW_USER_NAME:		strncpy(packet.username, (char *)pair->strvalue, sizeof(packet.username));		break;	    case PW_CLIENT_PORT_ID:		packet.port = pair->lvalue;		break;	    case PW_CLIENT_ID:		packet.nas_ip = pair->lvalue;		break;	    case PW_ACCT_SESSION_ID:		strncpy(packet.sessionid, (char *)pair->strvalue, sizeof(packet.sessionid));		break;	};	pair = pair->next;    };    /* we have a complete packet ... */    if (in_acct_queue(&packet, packet.type) != (acct_packet *)NULL)	return 0;    if (packet.type == PW_STATUS_START) {	if (!add_acct_queue(&packet))	    log_err("ERROR!!!: could not add acct packet to queue (%s/%s)",		    packet.sessionid, packet.username);	if (in_acct_queue(&packet, PW_STATUS_STOP) != (acct_packet *)NULL)	   return 0;    } else if (packet.type == PW_STATUS_STOP) {	if (!add_acct_queue(&packet))	    log_err("ERROR!!!: could not add acct packet to queue (%s/%s)",		    packet.sessionid, packet.username);	if (in_acct_queue(&packet, PW_STATUS_START) != (acct_packet *)NULL)	    if (acct_queue_entries > MAX_ACCT_QUEUE)		if (!cleanup_acct_queue())		    log_err("ERROR!!!: could not cleanup the acct packet queue!");    } else	return 0;    return 1;}/* * MD5 crypt() support for systems using both DES and MD5 */static unsigned char itoa64[] =		/* 0 ... 63 => ascii - 64 */	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";static void to64(char *s, unsigned long v, int n){    while (--n >= 0) {	*s++ = itoa64[v&0x3f];	v >>= 6;    }}/* * UNIX password * * Use MD5 for what it is best at... */char * crypt_md5(const char *pw, const char *salt){    const char *magic = "$1$";    /* This string is magic for this algorithm.  Having     * it this way, we can get get better later on */    static char passwd[120], *p;    static const char *sp,*ep;    unsigned char	final[16];    int sl,pl,i,j;    MD5_CTX	ctx,ctx1;    unsigned long l;    /* Refine the Salt first */    sp = salt;    /* If it starts with the magic string, then skip that */    if(!strncmp(sp,magic,strlen(magic)))	sp += strlen(magic);    /* It stops at the first '$', max 8 chars */    for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)	continue;    /* get the length of the true salt */    sl = ep - sp;    MD5Init(&ctx);    /* The password first, since that is what is most unknown */    MD5Update(&ctx, (unsigned const char *)pw, strlen(pw));    /* Then our magic string */    MD5Update(&ctx, (unsigned const char *)magic,strlen(magic));    /* Then the raw salt */    MD5Update(&ctx, (unsigned const char *)sp, sl);    /* Then just as many characters of the MD5(pw,salt,pw) */    MD5Init(&ctx1);    MD5Update(&ctx1, (unsigned const char *)pw, strlen(pw));    MD5Update(&ctx1, (unsigned const char *)sp, sl);    MD5Update(&ctx1, (unsigned const char *)pw, strlen(pw));    MD5Final(final,&ctx1);    for(pl = strlen(pw); pl > 0; pl -= 16)	MD5Update(&ctx, (unsigned const char *)final,pl>16 ? 16 : pl);    /* Don't leave anything around in vm they could use. */    memset(final,0,sizeof final);    /* Then something really weird... */    for (j=0,i = strlen(pw); i ; i >>= 1)	if(i&1)	    MD5Update(&ctx, (unsigned const char *)final+j, 1);	else	    MD5Update(&ctx, (unsigned const char *)pw+j, 1);    /* Now make the output string */    strcpy(passwd,magic);    strncat(passwd,sp,sl);    strcat(passwd,"$");    MD5Final(final,&ctx);    /*     * and now, just to make sure things don't run too fast     * On a 60 Mhz Pentium this takes 34 msec, so you would     * need 30 seconds to build a 1000 entry dictionary...     */

⌨️ 快捷键说明

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