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

📄 x99_sync.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 2 页
字号:
unsignedx99_get_last_auth_pos(const char *syncdir, const char *username){    int 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, NULL, NULL, &pos);    x99_release_sd_lock(lock);    return rc ? 0 : pos;}/* * Record the last auth window position (for ewindow2). */intx99_set_last_auth_pos(const char *syncdir, const char *username, unsigned pos){    int rc;    char *lock;    char challenge[MAX_CHALLENGE_LEN + 1];    int failcount;    time_t last_auth;    if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	return -1;    rc = x99_get_sd(syncdir, username, challenge, &failcount, &last_auth, NULL);    if (rc == 0)	rc = x99_set_sd(syncdir, username, challenge, failcount, last_auth,			pos);    x99_release_sd_lock(lock);    return rc;}/* * Return the failed login count for a user. * Returns 0 on success, non-zero otherwise. */static intx99_get_failcount(const char *syncdir, const char *username, int *failcount){    int rc;    char *lock;    if ((lock = x99_acquire_sd_lock(syncdir, username)) == NULL)	return -1;    rc = x99_get_sd(syncdir, username, NULL, failcount, NULL, NULL);    x99_release_sd_lock(lock);    return rc;}/* * Sync data is kept in a flat file[s], only because it's easy to implement. * It might be worth looking at Berkeley DB, but the flat file implementation * gives maximal concurrency with minimal complexity.  Performance will be * better on filesystems like ext2fs, ffs w/ soft updates, etc, due to * the large number of ephemeral dot-files created/destroyed for locking. * * One file per user is created, and we typically expect that each thread * is handling a different user (even if a user is authenticating to * multiple NASs/ports, he can't really authenticate simultaneously to * each -- unless it's an attack), so this should give us maximal * concurrency. * * The file format is 'version:user:challenge:key:failures:last_auth:'. * Version is there to provide easy forward compatibility.  The trailing * colon is there for the same reason.  Future versions must add data to * the end.  The current version is 1. * * For performance enhancements, it might be more worthwhile to look at * caching the inst->pwdfile data.  Users who are disabled should also * be cached somehow, to reduce the impact of possible attacks. *//* * x99_acquire_sd_lock() returns NULL on failure, or a char * * which must be passed to x99_release_sd_lock() later. */static char *x99_acquire_sd_lock(const char *syncdir, const char *username){    char *lockfile;    int i, fd = -1;    struct stat st;    /* Verify permissions first. */    if (stat(syncdir, &st) != 0) {	x99_log(X99_LOG_ERR, "syncdir %s error: %s",		syncdir, strerror(errno));	return NULL;    }    if (st.st_mode != (S_IFDIR|S_IRUSR|S_IWUSR|S_IXUSR)) {	x99_log(X99_LOG_ERR,		"x99_acquire_sd_lock: syncdir %s has loose permissions",		syncdir);	return NULL;    }    /* We use dotfile locking. */    lockfile = malloc(strlen(syncdir) + strlen(username) + 3);    if (!lockfile) {	x99_log(X99_LOG_CRIT, "x99_acquire_sd_lock: out of memory");	return NULL;    }    (void) sprintf(lockfile, "%s/.%s", syncdir, username);    /*     * Try to obtain exclusive access.  10 should be *plenty* of     * iterations, we don't expect concurrent accesses to the same file,     * and any accesses should be very quick.  This is broken over NFS,     * but you shouldn't have this data on NFS anyway.     */    for (i = 0; i < 10; ++i) {	if ((fd = open(lockfile, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) != -1) {	    break;	}	/* break stale locks (older than 60s) */	if (stat(lockfile, &st) == 0)	    if (st.st_ctime  < time(NULL) - 60)		(void) unlink(lockfile);	usleep(500000); /* 0.5 second */    }    if (fd == -1) {	x99_log(X99_LOG_ERR,		"x99_acquire_sd_lock: unable to acquire lock for [%s]",		username);	free(lockfile);	return NULL;    }    (void) close(fd);    return lockfile;}static voidx99_release_sd_lock(char *lockfile){    (void) unlink(lockfile);    free(lockfile);}/* * x99_get_sd() returns 0 on success, non-zero otherwise. * On successful returns, challenge, failures, last_auth, pos are filled in, * if non-NULL. * On unsuccessful returns, challenge, failures, last_auth, pos may be garbage. * challenge should be sized as indicated (if non-NULL). * The caller must have obtained an exclusive lock on the sync file. */static intx99_get_sd(const char *syncdir, const char *username,	   char challenge[MAX_CHALLENGE_LEN + 1], int *failures,	   time_t *last_auth, unsigned *pos){    char syncfile[PATH_MAX + 1];    FILE *fp;    char syncdata[BUFSIZ];    char *p, *q;    unsigned ver = UINT_MAX;    (void) snprintf(syncfile, PATH_MAX, "%s/%s",  syncdir, username);    syncfile[PATH_MAX] = '\0';    /* Open sync file. */    if ((fp = fopen(syncfile, "r")) == NULL) {	if (errno != ENOENT) {	    x99_log(X99_LOG_ERR, "x99_get_sd: unable to open sync file %s: %s",		    syncfile, strerror(errno));	    return -1;	}	/*	 * Sync file did not exist.  If we can create it, all is well.	 * Set the challenge to something "impossible".	 */	if (failures)	    *failures = 0;	return x99_set_sd(syncdir, username, "NEWSTATE", 0, 0, 0);    }    /* Read sync data. */    if ((fgets(syncdata, sizeof(syncdata), fp) == NULL) || !strlen(syncdata)) {	x99_log(X99_LOG_ERR, "x99_get_sd: unable to read sync data from %s: %s",		syncfile, strerror(errno));	(void) fclose(fp);	return -1;    }    (void) fclose(fp);    p = syncdata;    /* Now, parse the sync data. */    /* Get the version. */    if ((q = strchr(p, ':')) == NULL) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data for user %s", username);	return -1;    }    *q++ = '\0';    if ((sscanf(p, "%u", &ver) != 1) || (ver > 2)) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (version) for user %s",		username);	return -1;    }    p = q;    /* Sanity check the username. */    if ((q = strchr(p, ':')) == NULL) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (username) for user %s",		username);	return -1;    }    *q++ = '\0';    if (strcmp(p, username)) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (user mismatch) for user %s",		username);	return -1;    }    p = q;    /* Get challenge. */    if ((q = strchr(p, ':')) == NULL) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (challenge) for user %s",		username);	return -1;    }    *q++ = '\0';    if (strlen(p) > MAX_CHALLENGE_LEN) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (challenge length) for user %s",		username);	return -1;    }    if (challenge)	strcpy(challenge, p);    p = q;    /* Eat key. */    if ((p = strchr(p, ':')) == NULL) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (key) for user %s", username);	return -1;    }    p++;    /* Get failures. */    if ((q = strchr(p, ':')) == NULL) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (failures) for user %s",		username);	return -1;    }    *q++ = '\0';    if (failures && (sscanf(p, "%d", failures) != 1)) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (failures) for user %s",		username);	return -1;    }    p = q;    /* Get last_auth. */    if ((q = strchr(p, ':')) == NULL) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (last_auth) for user %s",		username);	return -1;    }    *q++ = '\0';    if (last_auth && (sscanf(p, "%ld", last_auth) != 1)) {	x99_log(X99_LOG_ERR,		"x99_get_sd: invalid sync data (last_auth) for user %s",		username);	return -1;    }    p = q;    /* Get last auth position. */    if (pos) {	if (ver == 1) {	    *pos = 0;	} else if (sscanf(p, "%u", pos) != 1) {	    x99_log(X99_LOG_ERR,		    "x99_get_sd: invalid sync data (win. pos) for user %s",		    username);	    return -1;	}    }    return 0;}/* * See x99_get_sd(). * The caller must have obtained an exclusive lock on the sync file. */static intx99_set_sd(const char *syncdir, const char *username, const char *challenge,	   int failures, time_t last_auth, unsigned pos){    char syncfile[PATH_MAX + 1];    FILE *fp;    (void) snprintf(syncfile, PATH_MAX, "%s/%s",  syncdir, username);    syncfile[PATH_MAX] = '\0';    if ((fp = fopen(syncfile, "w")) == NULL) {	x99_log(X99_LOG_ERR, "x99_set_sd: unable to open sync file %s: %s",		syncfile, strerror(errno));	return -1;    }    /* Write our (version 2) sync data. */    (void) fprintf(fp, "2:%s:%s:%s:%d:%ld:%u:\n", username, challenge, "",		   failures, last_auth, pos);    if (fclose(fp) != 0) {	x99_log(X99_LOG_ERR, "x99_set_sd: unable to write sync file %s: %s",		syncfile, strerror(errno));	return -1;    }    return 0;}

⌨️ 快捷键说明

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