4 /*#include "autoconf.h"
5 #include "libradius.h"*/
11 struct mypasswd *next;
23 struct mypasswd **table;
31 void printpw(struct mypasswd *pw, int nfields){
34 for( i = 0; i < nfields; i++ ) printf("%s:", pw->field[i]);
37 else printf ("Not found\n");
42 static int string_to_entry(const char* string, int nfields, char delimiter,
43 struct mypasswd *passwd, int bufferlen)
51 if (string[len-1] == '\n') len--;
53 if (string[len-1] == '\r') len--;
55 if (!len || !passwd || bufferlen < (len + nfields * sizeof (char*) + sizeof (struct mypasswd) + 1) ) return 0;
57 str = passwd->data + nfields * sizeof (char *);
58 memcpy (str, string, len);
60 passwd->field[fn++] = str;
61 for(i=0; i < len; i++){
62 if (str[i] == delimiter) {
64 passwd->field[fn++] = str + i + 1;
65 if (fn == nfields) break;
68 for (; fn < nfields; fn++) passwd->field[fn] = NULL;
72 return len + nfields * sizeof (char*) + sizeof (struct mypasswd) + 1;
76 static void destroy_password (struct mypasswd * pass)
79 if(pass->next)destroy_password(pass->next);
84 static unsigned int hash(const unsigned char * username, unsigned int tablesize)
88 h = h * 7907 + *username++;
93 static void release_hash_table(struct hashtable * ht){
97 for (i=0; i<ht->tablesize; i++)
99 destroy_password(ht->table[i]);
100 if (ht->table) free(ht->table);
101 if (ht->filename) free(ht->filename);
102 if (ht->fp) fclose(ht->fp);
106 static struct hashtable * build_hash_table (const char * file, int nfields,
107 int keyfield, int islist, int tablesize, int ignorenis, char * delimiter)
109 #define passwd ((struct mypasswd *) ht->buffer)
111 struct hashtable* ht;
114 struct mypasswd *hashentry, *hashentry1;
119 ht = (struct hashtable *) malloc(sizeof(struct hashtable));
123 ht->filename = strdup(file);
128 ht->tablesize = tablesize;
129 ht->nfields = nfields;
130 ht->keyfield = keyfield;
132 ht->ignorenis = ignorenis;
133 if (delimiter && *delimiter) ht->delimiter = delimiter;
134 else ht->delimiter = ":";
135 if(!tablesize) return ht;
136 if(!(ht->fp = fopen(file,"r"))) return NULL;
137 memset(ht->buffer, 0, 1024);
138 ht->table = (struct mypasswd **) malloc (tablesize * sizeof(struct mypasswd *));
141 * Unable allocate memory for hash table
142 * Still work without it
147 while (fgets(buffer, 1024, ht->fp)) {
148 if(*buffer && *buffer!='\n' && (!ignorenis || (*buffer != '+' && *buffer != '-')) ){
149 len = strlen(buffer) + nfields * sizeof (char *) + sizeof (struct mypasswd) + 1;
150 if(!(hashentry = (struct mypasswd *) malloc(len))){
151 release_hash_table(ht);
155 len = string_to_entry(buffer, nfields, *ht->delimiter, hashentry, len);
156 if(!hashentry->field[keyfield] || *hashentry->field[keyfield] == '\0') {
162 list = hashentry->field[keyfield];
163 for (nextlist = list; *nextlist && *nextlist!=','; nextlist++);
164 if (*nextlist) *nextlist++ = 0;
167 h = hash(hashentry->field[keyfield], tablesize);
168 hashentry->next = ht->table[h];
169 ht->table[h] = hashentry;
171 for(list=nextlist; nextlist; list = nextlist){
172 for (nextlist = list; *nextlist && *nextlist!=','; nextlist++);
173 if (*nextlist) *nextlist++ = 0;
175 if(!(hashentry1 = (struct mypasswd *) malloc(sizeof(struct mypasswd) + nfields * sizeof(char *)))){
176 release_hash_table(ht);
180 for (i=0; i<nfields; i++) hashentry1->field[i] = hashentry->field[i];
181 hashentry1->field[keyfield] = list;
182 h = hash(list, tablesize);
183 hashentry1->next = ht->table[h];
184 ht->table[h] = hashentry1;
195 static struct mypasswd * get_next(char *name, struct hashtable *ht)
197 #define passwd ((struct mypasswd *) ht->buffer)
198 struct mypasswd * hashentry;
201 char *list, *nextlist;
203 if (ht->tablesize > 0) {
204 /* get saved address of next item to check from buffer */
205 memcpy(&hashentry, ht->buffer, sizeof(hashentry));
206 for (; hashentry; hashentry = hashentry->next) {
207 if (!strcmp(hashentry->field[ht->keyfield], name)) {
208 /* save new address */
209 memcpy(ht->buffer, &hashentry->next, sizeof(hashentry));
213 memset(ht->buffer, 0, sizeof(hashentry));
216 if (!ht->fp) return NULL;
217 while (fgets(buffer, 1024,ht->fp)) {
218 if(*buffer && *buffer!='\n' && (len = string_to_entry(buffer, ht->nfields, *ht->delimiter, passwd, 1024)) &&
219 (!ht->ignorenis || (*buffer !='-' && *buffer != '+') ) ){
221 if(!strcmp(passwd->field[ht->keyfield], name))
225 for (list = passwd->field[ht->keyfield], nextlist = list; nextlist; list = nextlist) {
226 for(nextlist = list; *nextlist && *nextlist!=','; nextlist++);
227 if(!*nextlist)nextlist = 0;
228 else *nextlist++ = 0;
229 if(!strcmp(list, name)) return passwd;
241 static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht)
244 struct mypasswd * hashentry;
246 if (!ht || !name || *name == '\0') return NULL;
247 if (ht->tablesize > 0) {
248 h = hash (name, ht->tablesize);
249 for (hashentry = ht->table[h]; hashentry; hashentry = hashentry->next)
250 if (!strcmp(hashentry->field[ht->keyfield], name)){
251 /* save address of next item to check into buffer */
252 memcpy(ht->buffer, &hashentry->next, sizeof(hashentry));
255 memset(ht->buffer, 0, sizeof(hashentry));
258 if (ht->fp) fclose(ht->fp);
259 if (!(ht->fp=fopen(ht->filename, "r"))) return NULL;
260 return get_next(name, ht);
266 struct hashtable *ht;
271 ht = build_hash_table("/etc/group", 4, 3, 1, 100, 0);
273 printf("Hash table not built\n");
277 for (i=0; i<ht->tablesize; i++) if (ht->table[i]) {
279 for(pw=ht->table[i]; pw; pw=pw->next) printpw(pw, 4);
281 while(fgets(buffer, 1024, stdin)){
282 buffer[strlen(buffer)-1] = 0;
283 pw = get_pw_nam(buffer, ht);
285 while (pw = get_next(buffer, ht))printpw(pw,4);
290 struct passwd_instance {
291 struct hashtable *ht;
292 struct mypasswd *pwdfmt;
307 static CONF_PARSER module_config[] = {
308 { "filename", PW_TYPE_STRING_PTR,
309 offsetof(struct passwd_instance, filename), NULL, NULL },
310 { "format", PW_TYPE_STRING_PTR,
311 offsetof(struct passwd_instance, format), NULL, NULL },
312 { "authtype", PW_TYPE_STRING_PTR,
313 offsetof(struct passwd_instance, authtype), NULL, NULL },
314 { "delimiter", PW_TYPE_STRING_PTR,
315 offsetof(struct passwd_instance, delimiter), NULL, ":" },
316 { "ignorenislike", PW_TYPE_BOOLEAN,
317 offsetof(struct passwd_instance, ignorenislike), NULL, "yes" },
318 { "allowmultiplekeys", PW_TYPE_BOOLEAN,
319 offsetof(struct passwd_instance, ignorenislike), NULL, "no" },
320 { "hashsize", PW_TYPE_INTEGER,
321 offsetof(struct passwd_instance, hashsize), NULL, "100" },
323 { NULL, -1, 0, NULL, NULL } /* end the list */
326 static int passwd_instantiate(CONF_SECTION *conf, void **instance)
328 #define inst ((struct passwd_instance *)*instance)
329 int nfields=0, keyfield=-1, listable=0;
334 *instance = rad_malloc(sizeof(struct passwd_instance));
335 if (cf_section_parse(conf, inst, module_config) < 0) {
337 radlog(L_ERR, "rlm_passwd: cann't parse configuration");
340 if(!inst->filename || *inst->filename == '\0' || !inst->format || *inst->format == '\0') {
341 radlog(L_ERR, "rlm_passwd: cann't find passwd file and/or format in configuration");
344 s = inst->format - 1;
346 if(s == inst->format - 1 || *s == ':'){
358 radlog(L_ERR, "rlm_passwd: no field market as key in format: %s", inst->format);
361 if (! (inst->ht = build_hash_table (inst->filename, nfields, keyfield, listable, inst->hashsize, inst->ignorenislike, inst->delimiter)) ){
362 radlog(L_ERR, "rlm_passwd: can't build hashtable from passwd file");
365 len = strlen (inst->format)+ nfields * sizeof (char*) + sizeof (struct mypasswd) + 1;
366 if (! (inst->pwdfmt = (struct mypasswd *)rad_malloc(len)) ){
367 radlog(L_ERR, "rlm_passwd: memory allocation failed");
368 release_hash_table(inst->ht);
371 if (!string_to_entry(inst->format, nfields, ':', inst->pwdfmt , len)) {
372 radlog(L_ERR, "rlm_passwd: unable to convert format entry");
373 release_hash_table(inst->ht);
376 if (*inst->pwdfmt->field[keyfield] == '*') inst->pwdfmt->field[keyfield]++;
377 if (*inst->pwdfmt->field[keyfield] == ',') inst->pwdfmt->field[keyfield]++;
378 if (!*inst->pwdfmt->field[keyfield]) {
379 radlog(L_ERR, "rlm_passwd: key field is empty");
380 release_hash_table(inst->ht);
383 if (! (da = dict_attrbyname (inst->pwdfmt->field[keyfield])) ) {
384 radlog(L_ERR, "rlm_passwd: unable to resolve attribute: %s", inst->pwdfmt->field[keyfield]);
385 release_hash_table(inst->ht);
388 inst->keyattr = da->attr;
389 inst->keyattrtype = da->type;
390 inst->nfields = nfields;
391 inst->keyfield = keyfield;
392 inst->listable = listable;
393 radlog(L_INFO, "rlm_passwd: nfields: %d keyfield %d(%s) listable: %s", nfields, keyfield, inst->pwdfmt->field[keyfield], listable?"yes":"no");
399 static int passwd_detach (void *instance) {
400 #define inst ((struct passwd_instance *)instance)
401 if(inst->ht) release_hash_table(inst->ht);
407 static void addresult (struct passwd_instance * inst, VALUE_PAIR ** vp, struct mypasswd * pw)
412 for (i=0; i<inst->nfields; i++) {
413 if (inst->pwdfmt->field[i] && *inst->pwdfmt->field[i] && pw->field[i] && i != inst->keyfield) {
414 if (! (newpair = pairmake (inst->pwdfmt->field[i], pw->field[i], T_OP_EQ))) {
415 radlog(L_AUTH, "rlm_passwd: Unable to create %s: %s", inst->pwdfmt->field[i], pw->field[i]);
418 radlog(L_INFO, "rlm_passwd: Added %s: %s", inst->pwdfmt->field[i], pw->field[i]);
419 pairadd (vp, newpair);
424 static int passwd_authorize(void *instance, REQUEST *request)
426 #define inst ((struct passwd_instance *)instance)
430 struct mypasswd * pw;
433 if(!request || !request->packet ||!request->packet->vps)
434 return RLM_MODULE_INVALID;
435 for (key = request->packet->vps;
436 key && (key = pairfind (key, inst->keyattr));
438 switch (inst->keyattrtype) {
439 case PW_TYPE_INTEGER:
440 snprintf(buffer, 1024, "%u", key->lvalue);
444 name = key->strvalue;
446 if (! (pw = get_pw_nam(name, inst->ht)) ) {
450 addresult(inst, &request->config_items, pw);
451 } while ( (pw = get_next(name, inst->ht)) );
453 if (!inst->allowmultiple) break;
456 return RLM_MODULE_NOTFOUND;
458 if (inst->authtype && (key = pairmake ("Auth-Type", inst->authtype, T_OP_EQ))) {
459 radlog(L_INFO, "rlm_passwd: Adding Auth-Type: %s", inst->authtype);
460 pairadd (&request->config_items, key);
462 return RLM_MODULE_OK;
467 module_t rlm_passwd = {
469 RLM_TYPE_THREAD_SAFE, /* type */
470 NULL, /* initialize */
471 passwd_instantiate, /* instantiation */
473 NULL, /* authentication */
474 passwd_authorize, /* authorization */
475 NULL, /* pre-accounting */
476 NULL, /* accounting */
477 NULL, /* checksimul */
478 NULL, /* pre-proxy */
479 NULL, /* post-proxy */
482 passwd_detach, /* detach */