📄 rlm_fastusers.c
字号:
int userfound = 0; /* * Now we have to make sure it's the right user by * comparing the check pairs */ while((cur) && (!userfound)) { if((strcmp(cur->name, username)==0) && paircmp(request, request->packet->vps, cur->check, &request->reply->vps) == 0) { /* * Usercollide means we have to compare check pairs * AND the password */ if(mainconfig.do_usercollide) { if((userfound = fastuser_passcheck(request, cur, username))==0) { cur = cur->next; } } else { userfound = 1; DEBUG2(" fastusers: Matched %s at %d", cur->name, cur->lineno); } } else { cur = cur->next; } } if(cur) { return cur; } return (PAIR_LIST *)0;}/* * Generate and log statistics about our hash table */static void fastuser_tablestats(PAIR_LIST **hashtable, int size) { int i, count; int countarray[256]; int toomany=0; PAIR_LIST *cur; memset(countarray, 0, sizeof(countarray)); for(i=0; i<size; i++) { count = 0; for(cur=hashtable[i]; cur; cur=cur->next) { count++; } if(count<256) { countarray[count]++; } else { toomany++; } } for(i=0; i<256; i++) if(countarray[i]) { radlog(L_INFO, "rlm_fastusers: Hash buckets with %d users: %d", i, countarray[i]); } if(toomany) { radlog(L_INFO, "rlm_fastusers: Hash buckets with more than 256: %d", toomany); }}static int fastuser_passcheck(REQUEST *request, PAIR_LIST *user, const char *name UNUSED){ int found=0; VALUE_PAIR *check_save; /* * We check for REJECT specially here or a REJECT * user will never match */ check_save = pairfind(user->check, PW_AUTHTYPE); if((check_save) && check_save->lvalue == PW_AUTHTYPE_REJECT) { DEBUG2(" fastusers(uc): User '%s' line %d is Auth-Type Reject, but usercollide match", user->name, user->lineno); return 1; } /* Save the orginal config items */ check_save = request->config_items; request->config_items = NULL; DEBUG2(" fastusers(uc): Checking %s at %d", user->name, user->lineno); /* Copy this users check pairs to the request */ request->config_items = paircopy(user->check); /* Check the req to see if we matched */ if(rad_check_password(request)==0) { DEBUG2(" fastusers(uc): Matched %s at %d", user->name, user->lineno); found = 1; } /* Restore check items */ pairfree(&request->config_items); request->config_items = check_save; return found;}/* * (Re-)read the "users" file into memory. */static int fastuser_instantiate(CONF_SECTION *conf, void **instance){ struct fastuser_instance *inst=0; inst = rad_malloc(sizeof *inst); if (!inst) return -1; memset(inst, 0, sizeof(*inst)); if (cf_section_parse(conf, inst, module_config) < 0) { free(inst); return -1; } inst->next_reload = time(NULL) + inst->hash_reload; inst->hashtable = NULL; inst->lastusersload = 0; inst->lastacctusersload = 0; if(fastuser_buildhash(inst) < 0) { radlog(L_ERR, "rlm_fastusers: error building user hash. aborting"); return -1; } /* * Need code here to read acct_users file */ *instance = inst; return 0;}/* * Find the named user in the database. Create the * set of attribute-value pairs to check and reply with * for this user from the database. The main code only * needs to check the password, the rest is done here. */static int fastuser_authorize(void *instance, REQUEST *request){ VALUE_PAIR *namepair; VALUE_PAIR *check_tmp; VALUE_PAIR *reply_tmp; PAIR_LIST *user; PAIR_LIST *curdefault; const char *name; int userfound=0; int defaultfound=0; int hashidx=0; struct fastuser_instance *inst = instance; /* * Do we need to reload the cache? * Really we should spawn a thread to do this */ if((inst->hash_reload) && (request->timestamp > inst->next_reload)) { inst->next_reload = request->timestamp + inst->hash_reload; radlog(L_INFO, "rlm_fastusers: Reloading fastusers hash"); if(fastuser_buildhash(inst) < 0) { radlog(L_ERR, "rlm_fastusers: error building user hash. aborting"); return RLM_MODULE_FAIL; } } /* * Grab the canonical user name. */ namepair = request->username; name = namepair ? (char *) namepair->strvalue : "NONE"; /* * Find the entry for the user. */ hashidx = fastuser_hash(name, inst->hashsize); user = inst->hashtable[hashidx]; if((user=fastuser_find(request, user, name))!=NULL) { userfound = 1; } /* * If there's no lastdefault and we * don't fallthrough, just copy the * pairs for this user and return */ if((user) && (userfound) && (user->lastdefault == NULL)) { DEBUG2("rlm_fastusers: user found before DEFAULT"); check_tmp = paircopy(user->check); pairmove(&request->config_items, &check_tmp); pairfree(&check_tmp); reply_tmp = paircopy(user->reply); pairmove(&request->reply->vps, &reply_tmp); pairfree(&reply_tmp); if(!fallthrough(user->reply)) { pairdelete(&request->reply->vps, PW_FALL_THROUGH); return(rad_check_return(user->check)); } else { user=user->next; user=fastuser_find(request, user, name); } } /* * When we get here, we've either found * the user or not, but to preserve order * we start at the top of the default * list and work our way thru * When we get to the user's 'lastdefault' * we check to see if we should stop * and return */ DEBUG2("rlm_fastusers: checking defaults"); curdefault = inst->defaults; while(curdefault) { if(paircmp(request, request->packet->vps, curdefault->check, &request->reply->vps) == 0) { DEBUG2(" fastusers: Matched %s at %d", curdefault->name, curdefault->lineno); defaultfound = 1; check_tmp = paircopy(curdefault->check); pairmove(&request->config_items, &check_tmp); pairfree(&check_tmp); reply_tmp = paircopy(curdefault->reply); pairmove(&request->reply->vps, &reply_tmp); pairfree(&reply_tmp); /* * There's no fallthru on this default which * is *before* we find the user in the file, * so we know it's safe to quit here */ if (!fallthrough(curdefault->reply)) break; } /* * If we found the user, we want to stop * processing once we get to 'lastdefault' * This way we can process this user's entry * in the order it was found in the file */ while((userfound && (user) && (curdefault == user->lastdefault))) { DEBUG2(" fastusers: found lastdefault at line %d", curdefault->lineno); check_tmp = paircopy(user->check); pairmove(&request->config_items, &check_tmp); pairfree(&check_tmp); reply_tmp = paircopy(user->reply); pairmove(&request->reply->vps, &reply_tmp); pairfree(&reply_tmp); if(!fallthrough(user->reply)) { pairdelete(&request->reply->vps, PW_FALL_THROUGH); return(rad_check_return(user->check)); } /* * Find next occurence of THIS user in * the users file */ user=user->next; user=fastuser_find(request, user, name); } curdefault = curdefault->next; } if(userfound || defaultfound) { pairdelete(&request->reply->vps, PW_FALL_THROUGH); return(rad_check_return(request->config_items)); } else { DEBUG2("rlm_fastusers: user not found"); return RLM_MODULE_NOTFOUND; }}/* * Authentication - unused. */static int fastuser_authenticate(void *instance, REQUEST *request){ instance = instance; request = request; return RLM_MODULE_OK;}/* * Pre-Accounting - read the acct_users file for check_items and * config_items. Reply items are Not Recommended(TM) in acct_users, * except for Fallthrough, which should work * * This function is mostly a copy of file_authorize */static int fastuser_preacct(void *instance, REQUEST *request){ VALUE_PAIR *namepair; const char *name; VALUE_PAIR *request_pairs; VALUE_PAIR **config_pairs; VALUE_PAIR *reply_pairs = NULL; VALUE_PAIR *check_tmp; VALUE_PAIR *reply_tmp; PAIR_LIST *pl = NULL; int found = 0; struct fastuser_instance *inst = instance; namepair = request->username; name = namepair ? (char *) namepair->strvalue : "NONE"; request_pairs = request->packet->vps; config_pairs = &request->config_items; /* * Find the entry for the user. */ for (pl = inst->acctusers; pl; pl = pl->next) { if (strcmp(name, pl->name) && strcmp(pl->name, "DEFAULT")) continue; if (paircmp(request, request_pairs, pl->check, &reply_pairs) == 0) { DEBUG2(" acct_users: Matched %s at %d", pl->name, pl->lineno); found = 1; check_tmp = paircopy(pl->check); reply_tmp = paircopy(pl->reply); pairmove(&reply_pairs, &reply_tmp); pairmove(config_pairs, &check_tmp); pairfree(&reply_tmp); pairfree(&check_tmp); /* should be NULL */ /* * Fallthrough? */ if (!fallthrough(pl->reply)) break; } } /* * See if we succeeded. */ if (!found) return RLM_MODULE_NOOP; /* on to the next module */ /* * FIXME: log a warning if there are any reply items other than * Fallthrough */ pairfree(&reply_pairs); /* Don't need these */ return RLM_MODULE_OK;}/* * Clean up. */static int fastuser_detach(void *instance){ struct fastuser_instance *inst = instance; int hashindex; PAIR_LIST *cur; /* Free hash table */ for(hashindex=0; hashindex<inst->hashsize; hashindex++) { if(inst->hashtable[hashindex]) { cur = inst->hashtable[hashindex]; pairlist_free(&cur); } } free(inst->compat_mode); free(inst->hashtable); pairlist_free(&inst->defaults); pairlist_free(&inst->acctusers); free(inst->usersfile); free(inst->acctusersfile); free(inst); return 0;}/* * This function is unused */static int fastuser_accounting(void *instance UNUSED, REQUEST *request UNUSED){ /* * FIXME: should re rather return RLM_MODULE_NOOP here? */ return RLM_MODULE_FAIL;}/* globally exported name */module_t rlm_fastusers = { "fastusers", 0, /* type: reserved */ NULL, /* initialization */ fastuser_instantiate, /* instantiation */ { fastuser_authenticate, /* authentication */ fastuser_authorize, /* authorization */ fastuser_preacct, /* preaccounting */ fastuser_accounting, /* accounting */ NULL, /* checksimul */ NULL, /* pre-proxy */ NULL, /* post-proxy */ NULL /* post-auth */ }, fastuser_detach, /* detach */ NULL /* destroy */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -