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

📄 x99_sync.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * x99_sync.c * $Id: x99_sync.c,v 1.16 2003/01/10 07:04:08 fcusack Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2001,2002  Google, Inc. */#ifdef FREERADIUS#include "radiusd.h"#endif#include "x99.h"#include "x99_sync.h"#include <errno.h>#include <limits.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <openssl/des.h> /* des_cblock */static const char rcsid[] = "$Id: x99_sync.c,v 1.16 2003/01/10 07:04:08 fcusack Exp $";/* * Sync data fields changed slightly between v1 and v2, and were renamed. * These routines, however, retain the v1 names.  The name:field mapping is: *       *_last_auth: last_auth_t	last authentication time *       *_failcount: last_auth_s	number of consecutive auth failures *   *_last_auth_pos: last_auth_p	window pos. of last auth (not in v1) *//* * Get sync data for a given user. * Returns 0 on success, non-zero otherwise. * *  syncdir:  duh * username:  duh * card_id:   duh * ewin:      event window position (0 == now) * twin:      time window position (0 == now) (NOT IMPLEMENTED) * challenge: On successful return it will be filled in with the challenge *            expected for the given window slot.  On unsuccesful return, *            challenge may be overwritten and contain garbage. *            If ewin == 0, the stored "ewin 0" value is returned. *            If ewin > 0 and challenge points to a non-empty string, it *               will be taken as the challenge for (ewin - 1).  That is, *               ewin will not be used to calculate the next challenge; *               instead the passed in challenge is run through the sync *               calculation once to arrive at the next challenge.  This *               speeds things up since we don't have to iterate ewin times. *            If ewin > 0 and challenge points to an empty string, the *               stored "ewin 0" challenge value is run through the sync *               calculation ewin times. * keyblock:  Similar to challenge.  It may be updated for key changing *            sync modes. (NOT IMPLEMENTED) */intx99_get_sync_data(const char *syncdir, const char *username,		  uint32_t card_id, int ewin, int twin,		  char challenge[MAX_CHALLENGE_LEN + 1], des_cblock keyblock){    /* ARGSUSED */    des_cblock output;    int i, rc = -1;    char *lock;    if (ewin == 0) {	if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	    return -1;	rc = x99_get_sd(syncdir, username, challenge, NULL, NULL, NULL);	x99_release_sd_lock(lock);	return rc;    } else if (challenge[0]) {	ewin = 1; /* only iterate once */    } else {	/* The hard way.  Get the zeroeth challenge. */	rc = x99_get_sync_data(syncdir, username, card_id, 0, twin,			       challenge, keyblock);	if (rc)	    return rc;    }    while (ewin--) {	if (card_id & X99_CF_CRYPTOCARD) {	    if ((rc = x99_mac(challenge, output, keyblock)) == 0) {		for (i = 0; i < 8; ++i) {		    output[i] &= 0x0f;		    if (output[i] > 9)			output[i] -= 10;		    output[i] |= 0x30;		}		(void) memcpy(challenge, output, 8);		challenge[8] = '\0';	    } else {		break;	    }	} else {	    /* No other vendors implemented yet. */	    rc = -1;	    break;	}    }    return rc;}/* * Set sync data for a given user. * Returns 0 on success, non-zero otherwise. * Side effects: * - Resets failure count to 0 on successful return. * - Sets last auth time to "now" on successful return. * - Sets last auth window position to 0. * Because of the failure count reset, this should only be called for/after * successful authentications. * * username:  duh * challenge: The challenge to be stored. * keyblock:  The key to be stored.  This is for sync modes in which the *            key changes for successive challenges. (NOT IMPLEMENTED) */intx99_set_sync_data(const char *syncdir, const char *username,		  const char *challenge, const des_cblock keyblock){    /* ARGSUSED */    int rc;    char *lock;    if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	return -1;    rc = x99_set_sd(syncdir, username, challenge, 0, time(NULL), 0);    x99_release_sd_lock(lock);    return rc;}/* * Return the last time the user authenticated. * Returns 0 on success, non-zero otherwise. */intx99_get_last_auth(const char *syncdir, const char *username, time_t *last_auth){    int rc;    char *lock;    if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	return -1;    rc = x99_get_sd(syncdir, username, NULL, NULL, last_auth, NULL);    x99_release_sd_lock(lock);    return rc;}/* * Set the last auth time for a user to "now". * Returns 0 on success, non-zero otherwise. * Note that x99_set_sync_data() also resets the auth time. * This function is no longer called, (the failcount() routines do this work), * but I'm saving it here for reference. */intx99_upd_last_auth(const char *syncdir, const char *username){    int failcount, rc;    char *lock;    char challenge[MAX_CHALLENGE_LEN + 1];    unsigned pos;    if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	return -1;    rc = x99_get_sd(syncdir, username, challenge, &failcount, NULL, &pos);    if (rc == 0)	rc = x99_set_sd(syncdir, username, challenge, failcount, time(NULL),			pos);    x99_release_sd_lock(lock);    return rc;}/* * Atomically increment a user's failed login count. * Also updates last_auth. */intx99_incr_failcount(const char *syncdir, const char *username){    int failcount, rc;    char *lock;    char challenge[MAX_CHALLENGE_LEN + 1];    unsigned pos;    if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	return -1;    /* Get current value. */    rc = x99_get_sd(syncdir, username, challenge, &failcount, NULL, &pos);    if (rc == 0) {	/* Increment. */	if (++failcount == INT_MAX)	    failcount--;	rc = x99_set_sd(syncdir, username, challenge, failcount, time(NULL),			pos);    }    x99_release_sd_lock(lock);    return rc;}/* * Reset failure count to 0.  Also updates last_auth and resets pos. * Returns 0 on success, non-zero otherwise. * This is almost just like x99_incr_failcount(). * x99_set_sync_data() resets the failcount also, but that's because * we keep the failcount and other sync data together; we don't want * to necessarily make that visible to our callers (x99_rlm.c). */intx99_reset_failcount(const char *syncdir, const char *username){    int rc;    char *lock;    char challenge[MAX_CHALLENGE_LEN + 1];    if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	return -1;    rc = x99_get_sd(syncdir, username, challenge, NULL, NULL, NULL);    if (rc == 0)	rc = x99_set_sd(syncdir, username, challenge, 0, time(NULL), 0);    x99_release_sd_lock(lock);    return rc;}/* * checks the failure counter. * returns 0 if the user is allowed to authenticate, < 0 otherwise: *   FAIL_ERR if the user is failed due to internal error, *   FAIL_HARD if the user is failed "hard", *   FAIL_SOFT if the user is failed "soft". * caller does not need to log failures, we do it (in order to be specific). */intx99_check_failcount(const char *username, const x99_token_t *inst){    time_t last_auth;    int failcount;    if (x99_get_last_auth(inst->syncdir, username, &last_auth) != 0) {	x99_log(X99_LOG_ERR,		"auth: unable to get last auth time for [%s]", username);	return FAIL_ERR;    }    if (x99_get_failcount(inst->syncdir, username, &failcount) != 0) {	x99_log(X99_LOG_ERR,		"auth: unable to get failure count for [%s]", username);	return FAIL_ERR;    }    /* Check against hardfail setting. */    if (inst->hardfail && failcount >= inst->hardfail) {	x99_log(X99_LOG_AUTH,		"auth: %d/%d failed/max authentications for [%s]",		failcount, inst->hardfail, username);	if (x99_incr_failcount(inst->syncdir, username) != 0) {	    x99_log(X99_LOG_ERR,		    "auth: unable to increment failure count for "		    "locked out user [%s]", username);	}	return FAIL_HARD;    }    /* Check against softfail setting. */    if (inst->softfail && failcount >= inst->softfail) {	time_t when;	int fcount;	/*	 * Determine the next time this user can authenticate.	 *	 * Once we hit softfail, we introduce a 1m delay before the user	 * can authenticate.  For each successive failed authentication,	 * we double the delay time, up to a max of 32 minutes.  While in	 * the "delay mode" of operation, all authentication ATTEMPTS are	 * considered failures (we don't test if the password is correct).	 * Also, each attempt during the delay period restarts the clock.	 *	 * The advantage of a delay instead of a simple lockout is that an	 * attacker can't lock out a user as easily; the user need only wait	 * a bit before he can authenticate.	 */	fcount = failcount - inst->softfail;	when = last_auth + (fcount > 5 ? 32 * 60 : (1 << fcount) * 60);	if (time(NULL) < when) {	    x99_log(X99_LOG_AUTH,		    "auth: user [%s] auth too soon while delayed, "		    "%d/%d failed/softfail authentications",		    username, failcount, inst->softfail);	    if (x99_incr_failcount(inst->syncdir, username) != 0) {		x99_log(X99_LOG_ERR,			"auth: unable to increment failure count for "			"delayed user [%s]", username);	    }	    return FAIL_SOFT;	}    }    return 0;}/* * Get the last auth window position for ewindow2. * Returns 0 on failure (caller cannot distinguish between failure and * a 0 position). */

⌨️ 快捷键说明

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