📄 rlm_passwd.c
字号:
#include <stdio.h>#include <string.h>#include <stdlib.h>/*#include "autoconf.h"#include "libradius.h"*/#include "radiusd.h"#include "modules.h"struct mypasswd { struct mypasswd *next; char *listflag; char *field[0];};struct hashtable { int tablesize; int keyfield; int nfields; int islist; int ignorenis; char * filename; struct mypasswd **table; struct mypasswd *last_found; char buffer[1024]; FILE *fp; char *delimiter;};#ifdef TEST#define rad_malloc(s) malloc(s)void printpw(struct mypasswd *pw, int nfields){ int i; if (pw) { for( i = 0; i < nfields; i++ ) printf("%s:", pw->field[i]); printf("\n"); } else printf ("Not found\n"); fflush(stdout);}#endifstatic struct mypasswd * mypasswd_malloc(const char* buffer, int nfields, int* len){ struct mypasswd *t; /* reserve memory for (struct mypasswd) + listflag (nfields * sizeof (char*)) + ** fields (nfields * sizeof (char)) + strlen (inst->format) + 1 */ *len=sizeof (struct mypasswd) + nfields * sizeof (char*) + nfields * sizeof (char ) + strlen(buffer) + 1; t = (struct mypasswd *) rad_malloc(*len); if (t) memset(t, 0, *len); return (t);}static int string_to_entry(const char* string, int nfields, char delimiter, struct mypasswd *passwd, int bufferlen){ char *str; int len, i, fn=0; char *data_beg; len = strlen(string); if(!len) return 0; if (string[len-1] == '\n') len--; if(!len) return 0; if (string[len-1] == '\r') len--; if(!len) return 0; if (!len || !passwd || bufferlen < (len + nfields * sizeof (char*) + nfields * sizeof (char) + sizeof (struct mypasswd) + 1) ) return 0; passwd->next = NULL; data_beg=(char *)passwd + sizeof(struct mypasswd); str = data_beg + nfields * sizeof (char) + nfields * sizeof (char*); memcpy (str, string, len); str[len] = 0; passwd->field[fn++] = str; passwd->listflag = data_beg + nfields * sizeof (char *); for(i=0; i < len; i++){ if (str[i] == delimiter) { str[i] = 0; passwd->field[fn++] = str + i + 1; if (fn == nfields) break; } } for (; fn < nfields; fn++) passwd->field[fn] = NULL; return len + nfields * sizeof (char) + nfields * sizeof (char*) + sizeof (struct mypasswd) + 1;}static void destroy_password (struct mypasswd * pass){ struct mypasswd *p; while ((p=pass)!=NULL) { pass = pass->next; free(p); }}static unsigned int hash(const unsigned char * username, unsigned int tablesize){ int h=1; while (*username) { h = h * 7907 + *username++; } return h%tablesize;} static void release_hash_table(struct hashtable * ht){ int i; if (!ht) return; for (i=0; i<ht->tablesize; i++) if (ht->table[i]) destroy_password(ht->table[i]); if (ht->table) free(ht->table); if (ht->fp) fclose(ht->fp);}static void release_ht(struct hashtable * ht){ if (!ht) return; release_hash_table(ht); if (ht->filename) free(ht->filename); free(ht);}static struct hashtable * build_hash_table (const char * file, int nfields, int keyfield, int islist, int tablesize, int ignorenis, char * delimiter){#define passwd ((struct mypasswd *) ht->buffer) char buffer[1024]; struct hashtable* ht; int len; unsigned int h; struct mypasswd *hashentry, *hashentry1; char *list; char *nextlist=0; int i; ht = (struct hashtable *) rad_malloc(sizeof(struct hashtable)); if(!ht) { return NULL; } memset(ht, 0, sizeof(struct hashtable)); ht->filename = strdup(file); if(!ht->filename) { free(ht); return NULL; } ht->tablesize = tablesize; ht->nfields = nfields; ht->keyfield = keyfield; ht->islist = islist; ht->ignorenis = ignorenis; if (delimiter && *delimiter) ht->delimiter = delimiter; else ht->delimiter = ":"; if(!tablesize) return ht; if(!(ht->fp = fopen(file,"r"))) return NULL; memset(ht->buffer, 0, 1024); ht->table = (struct mypasswd **) rad_malloc (tablesize * sizeof(struct mypasswd *)); if (!ht->table) { /* * Unable allocate memory for hash table * Still work without it */ ht->tablesize = 0; return ht; } memset(ht->table, 0, tablesize * sizeof(struct mypasswd *)); while (fgets(buffer, 1024, ht->fp)) { if(*buffer && *buffer!='\n' && (!ignorenis || (*buffer != '+' && *buffer != '-')) ){ if(!(hashentry = mypasswd_malloc(buffer, nfields, &len))){ release_hash_table(ht); ht->tablesize = 0; return ht; } len = string_to_entry(buffer, nfields, *ht->delimiter, hashentry, len); if(!hashentry->field[keyfield] || *hashentry->field[keyfield] == '\0') { free(hashentry); continue; } if (islist) { list = hashentry->field[keyfield]; for (nextlist = list; *nextlist && *nextlist!=','; nextlist++); if (*nextlist) *nextlist++ = 0; else nextlist = 0; } h = hash(hashentry->field[keyfield], tablesize); hashentry->next = ht->table[h]; ht->table[h] = hashentry; if (islist) { for(list=nextlist; nextlist; list = nextlist){ for (nextlist = list; *nextlist && *nextlist!=','; nextlist++); if (*nextlist) *nextlist++ = 0; else nextlist = 0; if(!(hashentry1 = mypasswd_malloc("", nfields, &len))){ release_hash_table(ht); ht->tablesize = 0; return ht; } for (i=0; i<nfields; i++) hashentry1->field[i] = hashentry->field[i]; hashentry1->field[keyfield] = list; h = hash(list, tablesize); hashentry1->next = ht->table[h]; ht->table[h] = hashentry1; } } } } fclose(ht->fp); ht->fp = NULL; return ht;#undef passwd}static struct mypasswd * get_next(char *name, struct hashtable *ht){#define passwd ((struct mypasswd *) ht->buffer) struct mypasswd * hashentry; char buffer[1024]; int len; char *list, *nextlist; if (ht->tablesize > 0) { /* get saved address of next item to check from buffer */ hashentry = ht->last_found; for (; hashentry; hashentry = hashentry->next) { if (!strcmp(hashentry->field[ht->keyfield], name)) { /* save new address */ ht->last_found = hashentry->next; return hashentry; } } return NULL; } printf("try to find in file\n"); if (!ht->fp) return NULL; while (fgets(buffer, 1024,ht->fp)) { if(*buffer && *buffer!='\n' && (len = string_to_entry(buffer, ht->nfields, *ht->delimiter, passwd, sizeof(ht->buffer)-1)) && (!ht->ignorenis || (*buffer !='-' && *buffer != '+') ) ){ if(!ht->islist) { if(!strcmp(passwd->field[ht->keyfield], name)) return passwd; } else { for (list = passwd->field[ht->keyfield], nextlist = list; nextlist; list = nextlist) { for(nextlist = list; *nextlist && *nextlist!=','; nextlist++); if(!*nextlist)nextlist = 0; else *nextlist++ = 0; if(!strcmp(list, name)) return passwd; } } } } fclose(ht->fp); ht->fp = NULL; return NULL;#undef passwd}static struct mypasswd * get_pw_nam(char * name, struct hashtable* ht){ int h; struct mypasswd * hashentry; if (!ht || !name || *name == '\0') return NULL; ht->last_found = NULL; if (ht->tablesize > 0) { h = hash (name, ht->tablesize); for (hashentry = ht->table[h]; hashentry; hashentry = hashentry->next) if (!strcmp(hashentry->field[ht->keyfield], name)){ /* save address of next item to check into buffer */ ht->last_found=hashentry->next; return hashentry; } return NULL; } if (ht->fp) fclose(ht->fp); if (!(ht->fp=fopen(ht->filename, "r"))) return NULL; return get_next(name, ht);}#ifdef TEST#define MALLOC_CHECK_ 1int main(void){ struct hashtable *ht; char *buffer; struct mypasswd* pw; int i; ht = build_hash_table("/etc/group", 4, 3, 1, 100, 0, ":"); if(!ht) { printf("Hash table not built\n"); return -1; } for (i=0; i<ht->tablesize; i++) if (ht->table[i]) { printf("%d:\n", i); for(pw=ht->table[i]; pw; pw=pw->next) printpw(pw, 4); } while(fgets(buffer, 1024, stdin)){ buffer[strlen(buffer)-1] = 0; pw = get_pw_nam(buffer, ht); printpw(pw,4); while (pw = get_next(buffer, ht)) printpw(pw,4); } release_ht(ht);}#else /* TEST */struct passwd_instance { struct hashtable *ht; struct mypasswd *pwdfmt; char *filename; char *format; char *authtype; char * delimiter; int allowmultiple; int ignorenislike; int hashsize; int nfields; int keyfield; int listable; int keyattr; int keyattrtype;};static CONF_PARSER module_config[] = { { "filename", PW_TYPE_STRING_PTR, offsetof(struct passwd_instance, filename), NULL, NULL }, { "format", PW_TYPE_STRING_PTR, offsetof(struct passwd_instance, format), NULL, NULL }, { "authtype", PW_TYPE_STRING_PTR, offsetof(struct passwd_instance, authtype), NULL, NULL }, { "delimiter", PW_TYPE_STRING_PTR, offsetof(struct passwd_instance, delimiter), NULL, ":" }, { "ignorenislike", PW_TYPE_BOOLEAN, offsetof(struct passwd_instance, ignorenislike), NULL, "yes" }, { "allowmultiplekeys", PW_TYPE_BOOLEAN, offsetof(struct passwd_instance, allowmultiple), NULL, "no" }, { "hashsize", PW_TYPE_INTEGER, offsetof(struct passwd_instance, hashsize), NULL, "100" },};static int passwd_instantiate(CONF_SECTION *conf, void **instance){#define inst ((struct passwd_instance *)*instance) int nfields=0, keyfield=-1, listable=0; char *s; char *lf=NULL; /* destination list flags temporary */ int len; int i; DICT_ATTR * da; *instance = rad_malloc(sizeof(struct passwd_instance)); if ( !*instance) { radlog(L_ERR, "rlm_passwd: cann't alloc instance"); return -1; } memset(*instance, 0, sizeof(struct passwd_instance)); if (cf_section_parse(conf, inst, module_config) < 0) { free(inst); radlog(L_ERR, "rlm_passwd: cann't parse configuration"); return -1; } if(!inst->filename || *inst->filename == '\0' || !inst->format || *inst->format == '\0') { radlog(L_ERR, "rlm_passwd: cann't find passwd file and/or format in configuration"); return -1; } lf=strdup(inst->format); if ( lf == NULL) { radlog(L_ERR, "rlm_passwd: memory allocation failed for lf"); return -1; } memset(lf, 0, strlen(inst->format)); s = inst->format - 1; do { if(s == inst->format - 1 || *s == ':'){ if(*(s+1) == '*'){ keyfield = nfields; s++; } if(*(s+1) == ','){ listable = 1; s++; } if(*(s+1) == '='){ lf[nfields]=1; s++; } if(*(s+1) == '~'){ lf[nfields]=2; s++; } nfields++; } s++; }while(*s); if(keyfield < 0) { radlog(L_ERR, "rlm_passwd: no field market as key in format: %s", inst->format); return -1; } if (! (inst->ht = build_hash_table (inst->filename, nfields, keyfield, listable, inst->hashsize, inst->ignorenislike, inst->delimiter)) ){ radlog(L_ERR, "rlm_passwd: can't build hashtable from passwd file"); return -1; } if (! (inst->pwdfmt = mypasswd_malloc(inst->format, nfields, &len)) ){ radlog(L_ERR, "rlm_passwd: memory allocation failed"); release_ht(inst->ht); return -1; } if (!string_to_entry(inst->format, nfields, ':', inst->pwdfmt , len)) { radlog(L_ERR, "rlm_passwd: unable to convert format entry"); release_ht(inst->ht); return -1; } memcpy(inst->pwdfmt->listflag, lf, nfields); free(lf); for (i=0; i<nfields; i++) { if (*inst->pwdfmt->field[i] == '*') inst->pwdfmt->field[i]++; if (*inst->pwdfmt->field[i] == ',') inst->pwdfmt->field[i]++; if (*inst->pwdfmt->field[i] == '=') inst->pwdfmt->field[i]++; if (*inst->pwdfmt->field[i] == '~') inst->pwdfmt->field[i]++; } if (!*inst->pwdfmt->field[keyfield]) { radlog(L_ERR, "rlm_passwd: key field is empty"); release_ht(inst->ht); return -1; } if (! (da = dict_attrbyname (inst->pwdfmt->field[keyfield])) ) { radlog(L_ERR, "rlm_passwd: unable to resolve attribute: %s", inst->pwdfmt->field[keyfield]); release_ht(inst->ht); return -1; } inst->keyattr = da->attr; inst->keyattrtype = da->type; inst->nfields = nfields; inst->keyfield = keyfield; inst->listable = listable; radlog(L_INFO, "rlm_passwd: nfields: %d keyfield %d(%s) listable: %s", nfields, keyfield, inst->pwdfmt->field[keyfield], listable?"yes":"no"); return 0; #undef inst}static int passwd_detach (void *instance) {#define inst ((struct passwd_instance *)instance) if(inst->ht) release_ht(inst->ht); if (inst->filename != NULL) free(inst->filename); if (inst->format != NULL) free(inst->format); if (inst->authtype != NULL ) free(inst->authtype); if (inst->delimiter != NULL) free(inst->delimiter); free(instance); return 0;#undef inst}static void addresult (struct passwd_instance * inst, VALUE_PAIR ** vp, struct mypasswd * pw, char when, char *listname){ int i; VALUE_PAIR *newpair; for (i=0; i<inst->nfields; i++) { if (inst->pwdfmt->field[i] && *inst->pwdfmt->field[i] && pw->field[i] && i != inst->keyfield && inst->pwdfmt->listflag[i] == when) { if (! (newpair = pairmake (inst->pwdfmt->field[i], pw->field[i], T_OP_EQ))) { radlog(L_AUTH, "rlm_passwd: Unable to create %s: %s", inst->pwdfmt->field[i], pw->field[i]); return; } radlog(L_DBG, "rlm_passwd: Added %s: '%s' to %s ", inst->pwdfmt->field[i], pw->field[i], listname); pairadd (vp, newpair); } }}static int passwd_authorize(void *instance, REQUEST *request){#define inst ((struct passwd_instance *)instance) char * name; char buffer[1024]; VALUE_PAIR * key; struct mypasswd * pw; int found = 0; if(!request || !request->packet ||!request->packet->vps) return RLM_MODULE_INVALID; for (key = request->packet->vps; key && (key = pairfind (key, inst->keyattr)); key = key->next ){ switch (inst->keyattrtype) { case PW_TYPE_INTEGER: snprintf(buffer, 1024, "%u", key->lvalue); name = buffer; break; default: name = key->strvalue; } if (! (pw = get_pw_nam(name, inst->ht)) ) { continue; } do { addresult(inst, &request->config_items, pw, 0, "config_items"); addresult(inst, &request->reply->vps, pw, 1, "reply_items"); addresult(inst, &request->packet->vps, pw, 2, "request_items"); } while ( (pw = get_next(name, inst->ht)) ); found++; if (!inst->allowmultiple) break; } if(!found) { return RLM_MODULE_NOTFOUND; } if (inst->authtype && (key = pairmake ("Auth-Type", inst->authtype, T_OP_EQ))) { radlog(L_INFO, "rlm_passwd: Adding Auth-Type: %s", inst->authtype); pairadd (&request->config_items, key); } return RLM_MODULE_OK; #undef inst}module_t rlm_passwd = { "passwd", RLM_TYPE_THREAD_SAFE, /* type */ NULL, /* initialize */ passwd_instantiate, /* instantiation */ { NULL, /* authentication */ passwd_authorize, /* authorization */ NULL, /* pre-accounting */ NULL, /* accounting */ NULL, /* checksimul */ NULL, /* pre-proxy */ NULL, /* post-proxy */ NULL /* post-auth */ }, passwd_detach, /* detach */ NULL /* destroy */};#endif /* TEST */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -