diff -urN freeradius-0.8.1/src/modules/rlm_skunk/Makefile freeradius-0.8.1-skunk/src/modules/rlm_skunk/Makefile --- freeradius-0.8.1/src/modules/rlm_skunk/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ freeradius-0.8.1-skunk/src/modules/rlm_skunk/Makefile 2003-06-19 15:35:09.000000000 +0100 @@ -0,0 +1,4 @@ +TARGET = rlm_skunk +SRCS = rlm_skunk.c skunk.c + +include ../rules.mak diff -urN freeradius-0.8.1/src/modules/rlm_skunk/rlm_skunk.c freeradius-0.8.1-skunk/src/modules/rlm_skunk/rlm_skunk.c --- freeradius-0.8.1/src/modules/rlm_skunk/rlm_skunk.c 1970-01-01 01:00:00.000000000 +0100 +++ freeradius-0.8.1-skunk/src/modules/rlm_skunk/rlm_skunk.c 2003-06-19 16:00:15.000000000 +0100 @@ -0,0 +1,164 @@ +/* + * 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 (c) 2003 Gianni Tedesco + */ + +#include "autoconf.h" +#include "libradius.h" + +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_SYSLOG_H +#include +#endif + +#include "radiusd.h" +#include "modules.h" +#include "skunk.h" + +typedef struct rlm_skunk_t { + struct skunk_db *db; + struct rec res; + char *file; +} rlm_skunk_t; + +static CONF_PARSER module_config[] = { + { "file", PW_TYPE_STRING_PTR, offsetof(rlm_skunk_t,file), + NULL, "userdb.sdb" }, + { NULL, -1, 0, NULL, NULL } +}; + +/* + * (Re-)read radiusd.conf into memory. + */ +static int skunk_instantiate(CONF_SECTION *conf, void **instance) +{ + rlm_skunk_t *data; + int fd; + + data = rad_malloc(sizeof(*data)); + + if (cf_section_parse(conf, data, module_config) < 0) { + goto err; + } + + fd = open(data->file, O_RDONLY); + if ( fd < 0 ) { + radlog(L_ERR|L_CONS, "rlm_skunk: %s: open: %s", + data->file, strerror(errno)); + goto err; + } + + data->db = skunk_open(fd); + if ( data->db == NULL ) { + radlog(L_ERR|L_CONS, "rlm_skunk: %s: skunk_open: %s", + data->file, errno ? strerror(errno) : "unknown error"); + goto err_close; + } + + /* NOTE: FD is closed now */ + + skunk_set_result(data->db, &data->res); + + *instance = data; + return 0; + +err_close: + close(fd); +err: + free(data); + return -1; +} + +/* + * Clean up. + */ +static int skunk_detach(void *instance) +{ + rlm_skunk_t *data = instance; + + if (data->file) + free(data->file); + if (data->db) + skunk_close(data->db); + free(data); + return 0; +} + +/* translate between function declarations */ +static int skunk_auth(void *instance, REQUEST *request) +{ + rlm_skunk_t *data = instance; + + if (!request->username) { + radlog(L_AUTH, "rlm_skunk: Attribute \"User-Name\" is required for authentication."); + return RLM_MODULE_INVALID; + } + + if (!request->password) { + radlog(L_AUTH, "rlm_skunk: Attribute \"User-Password\" is required for authentication."); + return RLM_MODULE_INVALID; + } + + if (request->password->attribute != PW_PASSWORD) { + radlog(L_AUTH, "rlm_skunk: Attribute \"User-Password\" is required for authentication. " + "Cannot use \"%s\".", request->password->name); + return RLM_MODULE_INVALID; + } + + /* Lookup the username */ + if ( skunk_select(data->db, + request->username->strvalue, + strlen(request->username->strvalue)) <= 0 ) + return RLM_MODULE_REJECT; + + /* Check if the password length is the same as our password */ + if ( strlen(request->password->strvalue) != data->res.val_len ) + return RLM_MODULE_REJECT; + + /* Make sure the password match */ + if ( memcpy(request->password->strvalue, data->res.val, data->res.val_len) ) + return RLM_MODULE_REJECT; + + /* YAY, its a good guy!! */ + return RLM_MODULE_OK; +} + +module_t rlm_skunk = { + "Pam", + RLM_TYPE_THREAD_SAFE, /* Should be OK ;) */ + NULL, /* initialize */ + skunk_instantiate, /* instantiation */ + { + skunk_auth, /* authenticate */ + NULL, /* authorize */ + NULL, /* pre-accounting */ + NULL, /* accounting */ + NULL, /* checksimul */ + NULL, /* pre-proxy */ + NULL, /* post-proxy */ + NULL /* post-auth */ + }, + skunk_detach, /* detach */ + NULL, /* destroy */ +}; + diff -urN freeradius-0.8.1/src/modules/rlm_skunk/skunk.c freeradius-0.8.1-skunk/src/modules/rlm_skunk/skunk.c --- freeradius-0.8.1/src/modules/rlm_skunk/skunk.c 1970-01-01 01:00:00.000000000 +0100 +++ freeradius-0.8.1-skunk/src/modules/rlm_skunk/skunk.c 2003-06-19 15:36:48.000000000 +0100 @@ -0,0 +1,109 @@ +/* + * This file is part of SkunkDB + * Copyright (c) 2002 Gianni Tedesco + * Released under the terms of the GNU GPL version 2 + * + * TODO + * o Support cursors. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "skunk.h" + +/* Map in the database */ +struct skunk_db *skunk_open(int fd) +{ + struct skunk_db *d; + struct stat st; + + if ( fstat(fd, &st) ) + return NULL; + + if ( st.st_size < SKUNK_HASHSZ * + sizeof(struct skunk_table) ) + return NULL; + + if ( !(d=calloc(1, sizeof(*d))) ) + return NULL; + + if ( (d->map=mmap(NULL, st.st_size, PROT_READ, + MAP_SHARED, fd, 0))==MAP_FAILED ) { + free(d); + return NULL; + } + + d->maplen=st.st_size; + d->end=d->map + st.st_size; + + /* Closing the file does not unmap it, we + * just close it to save resources, heh */ + close(fd); + + return d; +} + +/* Grab the first matching record from the database */ +int skunk_select(struct skunk_db *d, char *key, size_t klen) +{ + struct skunk_table *t; + struct skunk_bucket *b; + skunk_ofs_t i, dist=0; + skunk_hash_t h; + + if ( !klen ) + return -1; + + h=skunk_hash(key, klen); + + t=((struct skunk_table *)d->map) + (h % SKUNK_HASHSZ); + + if ( !t->ofs || !t->len ) + return 0; + + if ( t->ofs > d->maplen ) + return -1; + + i=(h ^ klen) % t->len; + for(;;) { + b=((struct skunk_bucket *)(d->map+t->ofs)) + i; + + if ( (char *)b > d->end ) + return -1; + + if ( b->hash == h && b->klen == klen ) { + char *record=(char *)(d->map + b->ofs); + + if ( b->ofs + b->klen + b->vlen > d->maplen ) + goto not_this; + + if ( memcmp(record, key, klen) != 0 ) + goto not_this; + + d->result->key=record; + d->result->val=record+b->klen; + d->result->key_len=b->klen; + d->result->val_len=b->vlen; + return 1; + } +not_this: + if ( ++dist>t->len ) + break; + + i=(i+1) % t->len; + } + return 0; +} + +/* Close the database */ +void skunk_close(struct skunk_db *d) +{ + munmap(d->map, d->maplen); + free(d); +} diff -urN freeradius-0.8.1/src/modules/rlm_skunk/skunk.h freeradius-0.8.1-skunk/src/modules/rlm_skunk/skunk.h --- freeradius-0.8.1/src/modules/rlm_skunk/skunk.h 1970-01-01 01:00:00.000000000 +0100 +++ freeradius-0.8.1-skunk/src/modules/rlm_skunk/skunk.h 2003-06-19 15:37:18.000000000 +0100 @@ -0,0 +1,103 @@ +/* + * This file is part of SkunkDB + * Copyright (c) 2002 Gianni Tedesco + * Released under the terms of the GNU GPL version 2 +*/ +#ifndef __SKUNK_HEADER_INCLUDED__ +#define __SKUNK_HEADER_INCLUDED__ + +#define SKUNK_HASHSZ 2048UL + +typedef u_int32_t skunk_ofs_t; + +/* Hash size */ +#ifdef SKUNK_HASH_64 +typedef u_int64_t skunk_hash_t; +#define FNV_PRIME 1099511628211ULL +#define FNV_OFFSET 14695981039346656037ULL +#else +typedef u_int32_t skunk_hash_t; +#define FNV_PRIME 16777619UL +#define FNV_OFFSET 2166136261UL +#endif + +/* Generic record structure */ +struct rec { + char *key, *val; + size_t key_len, val_len; +}; + +/* Database creation structures */ +struct skunk_rec { + struct skunk_rec *next; + size_t key_len, val_len; + void *key, *val; + skunk_hash_t hash; +}; + +struct skunk_head { + size_t count; + struct skunk_rec *list; +}; + +#if 0 +struct skunk_make { + int fd; + struct mpool rec; + struct skunk_head head[SKUNK_HASHSZ]; +}; +#endif + +/* Database query structures */ +struct skunk_db { + char *map; + char *end; + size_t maplen; + struct rec *result; +}; + +/* These are our two on-disk structures */ +struct skunk_table{ + skunk_ofs_t ofs; + skunk_ofs_t len; +}; + +struct skunk_bucket { + skunk_hash_t hash; + skunk_ofs_t ofs; + skunk_ofs_t klen; + skunk_ofs_t vlen; +}; + +/* Database creation API */ +#if 0 +struct skunk_make *skunk_new_db(int); +int skunk_insert(struct skunk_make *, char *, size_t, char *, size_t); +int skunk_commit(struct skunk_make *); +int skunk_abort(struct skunk_make *); +#endif + +/* Database query API */ +struct skunk_db *skunk_open(int); +int skunk_select(struct skunk_db *, char *, size_t); +void skunk_close(struct skunk_db *); + +static inline +void skunk_set_result(struct skunk_db *d, struct rec *r) +{ + d->result=r; +} + +/* Fowler/Noll/Vo hash + * Its fast to compute, its obvious code, it performs well... */ +static inline skunk_hash_t skunk_hash(char *data, size_t len) +{ + skunk_hash_t h=FNV_OFFSET; + + while(len--) + h = (h*FNV_PRIME) ^ *data++; + + return h; +} + +#endif /* __SKUNK_HEADER_INCLUDED__ */ diff -urN freeradius-0.8.1/src/modules/stable freeradius-0.8.1-skunk/src/modules/stable --- freeradius-0.8.1/src/modules/stable 2002-11-01 16:16:51.000000000 +0000 +++ freeradius-0.8.1-skunk/src/modules/stable 2003-06-19 15:00:31.000000000 +0100 @@ -22,3 +22,4 @@ rlm_sql rlm_unix rlm_x99_token +rlm_skunk