/* * CoA realms via Operator-Name. Because the realm isn't in a * User-Name, concepts like "prefix" and "suffix' don't matter. */ static rlm_rcode_t realm_recv_coa(UNUSED void *instance, REQUEST *request) { VALUE_PAIR *vp; REALM *realm; if (pairfind(request->packet->vps, PW_REALM, 0, TAG_ANY) != NULL) { RDEBUG2("Request already proxied. Ignoring."); return RLM_MODULE_OK; } vp = pairfind(request->packet->vps, PW_OPERATOR_NAME, 0, TAG_ANY); if (!vp) return RLM_MODULE_NOOP; /* * Catch the case of broken dictionaries. */ if (vp->da->type != PW_TYPE_STRING) return RLM_MODULE_NOOP; /* * The string is too short. */ if (vp->length == 1) return RLM_MODULE_NOOP; /* * '1' means "the rest of the string is a realm" */ if (vp->vp_strvalue[0] != '1') return RLM_MODULE_NOOP; realm = realm_find(vp->vp_strvalue + 1); if (!realm) return RLM_MODULE_NOTFOUND; if (!realm->coa_pool) { RDEBUG2("CoA realm is LOCAL."); return RLM_MODULE_OK; } /* * Maybe add a Proxy-To-Realm attribute to the request. */ RDEBUG2("Preparing to proxy authentication request to realm \"%s\"\n", realm->name); pairmake_config("Proxy-To-Realm", realm->name, T_OP_EQ); return RLM_MODULE_UPDATED; /* try the next module */ }
/* * Internal function to cut down on duplicated code. * * Returns -1 on failure, 0 on no failure. returnrealm * is NULL on don't proxy, realm otherwise. */ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm) { char *namebuf; char *username; char const *realmname = NULL; char *ptr; VALUE_PAIR *vp; REALM *realm; struct realm_config_t *inst = instance; /* initiate returnrealm */ *returnrealm = NULL; /* * If the request has a proxy entry, then it's a proxy * reply, and we're walking through the module list again. * * In that case, don't bother trying to proxy the request * again. * * Also, if there's no User-Name attribute, we can't * proxy it, either. */ if ((!request->username) #ifdef WITH_PROXY || (request->proxy != NULL) #endif ) { RDEBUG2("Proxy reply, or no User-Name. Ignoring."); return RLM_MODULE_OK; } /* * Check for 'Realm' attribute. If it exists, then we've proxied * it already ( via another rlm_realm instance ) and should return. */ if (pairfind(request->packet->vps, PW_REALM, 0, TAG_ANY) != NULL ) { RDEBUG2("Request already proxied. Ignoring."); return RLM_MODULE_OK; } /* * We will be modifing this later, so we want our own copy * of it. */ namebuf = talloc_strdup(request, request->username->vp_strvalue); username = namebuf; switch(inst->format) { case REALM_FORMAT_SUFFIX: /* DEBUG2(" rlm_realm: Checking for suffix after \"%c\"", inst->delim[0]); */ ptr = strrchr(username, inst->delim[0]); if (ptr) { *ptr = '\0'; realmname = ptr + 1; } break; case REALM_FORMAT_PREFIX: /* DEBUG2(" rlm_realm: Checking for prefix before \"%c\"", inst->delim[0]); */ ptr = strchr(username, inst->delim[0]); if (ptr) { *ptr = '\0'; ptr++; realmname = username; username = ptr; } break; default: realmname = NULL; break; } /* * Print out excruciatingly descriptive debugging messages * for the people who find it too difficult to think about * what's going on. */ if (realmname) { RDEBUG2("Looking up realm \"%s\" for User-Name = \"%s\"", realmname, request->username->vp_strvalue); } else { if (inst->ignore_null ) { RDEBUG2("No '%c' in User-Name = \"%s\", skipping NULL due to config.", inst->delim[0], request->username->vp_strvalue); talloc_free(namebuf); return RLM_MODULE_NOOP; } RDEBUG2("No '%c' in User-Name = \"%s\", looking up realm NULL", inst->delim[0], request->username->vp_strvalue); } /* * Allow DEFAULT realms unless told not to. */ realm = realm_find(realmname); if (!realm) { RDEBUG2("No such realm \"%s\"", (!realmname) ? "NULL" : realmname); talloc_free(namebuf); return RLM_MODULE_NOOP; } if( inst->ignore_default && (strcmp(realm->name, "DEFAULT")) == 0) { RDEBUG2("Found DEFAULT, but skipping due to config."); talloc_free(namebuf); return RLM_MODULE_NOOP; } RDEBUG2("Found realm \"%s\"", realm->name); /* * If we've been told to strip the realm off, then do so. */ if (realm->striprealm) { /* * Create the Stripped-User-Name attribute, if it * doesn't exist. * */ if (request->username->da->attr != PW_STRIPPED_USER_NAME) { vp = radius_paircreate(request, &request->packet->vps, PW_STRIPPED_USER_NAME, 0); RDEBUG2("Adding Stripped-User-Name = \"%s\"", username); } else { vp = request->username; RDEBUG2("Setting Stripped-User-Name = \"%s\"", username); } pairstrcpy(vp, username); request->username = vp; } /* * Add the realm name to the request. * If the realm is a regex, the use the realm as entered * by the user. Otherwise, use the configured realm name, * as realm name comparison is case insensitive. We want * to use the configured name, rather than what the user * entered. */ if (realm->name[0] != '~') realmname = realm->name; pairmake_packet("Realm", realmname, T_OP_EQ); RDEBUG2("Adding Realm = \"%s\"", realmname); talloc_free(namebuf); realmname = username = NULL; /* * Figure out what to do with the request. */ switch (request->packet->code) { default: RDEBUG2("Unknown packet code %d\n", request->packet->code); return RLM_MODULE_OK; /* don't do anything */ /* * Perhaps accounting proxying was turned off. */ case PW_ACCOUNTING_REQUEST: if (!realm->acct_pool) { RDEBUG2("Accounting realm is LOCAL."); return RLM_MODULE_OK; } break; /* * Perhaps authentication proxying was turned off. */ case PW_AUTHENTICATION_REQUEST: if (!realm->auth_pool) { RDEBUG2("Authentication realm is LOCAL."); return RLM_MODULE_OK; } break; } #ifdef WITH_PROXY RDEBUG2("Proxying request from user %s to realm %s", request->username->vp_strvalue, realm->name); /* * Skip additional checks if it's not an accounting * request. */ if (request->packet->code != PW_ACCOUNTING_REQUEST) { *returnrealm = realm; return RLM_MODULE_UPDATED; } /* * FIXME: Each server should have a unique server key, * and put it in the accounting packet. Every server * should know about the keys, and NOT proxy requests to * a server with key X if the packet already contains key * X. */ /* * If this request has arrived from another freeradius server * that has already proxied the request, we don't need to do * it again. */ vp = pairfind(request->packet->vps, PW_FREERADIUS_PROXIED_TO, 0, TAG_ANY); if (vp && (request->packet->src_ipaddr.af == AF_INET)) { int i; fr_ipaddr_t my_ipaddr; my_ipaddr.af = AF_INET; my_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; /* * Loop over the home accounting servers for this * realm. If one of them has the same IP as the * FreeRADIUS-Proxied-To attribute, then the * packet has already been sent there. Don't * send it there again. */ for (i = 0; i < realm->acct_pool->num_home_servers; i++) { if (fr_ipaddr_cmp(&realm->acct_pool->servers[i]->ipaddr, &my_ipaddr) == 0) { RDEBUG2("Suppressing proxy due to FreeRADIUS-Proxied-To"); return RLM_MODULE_OK; } } /* * See detail_recv() in src/main/listen.c for the * additional checks. */ #ifdef WITH_DETAIL } else if ((request->listener->type == RAD_LISTEN_DETAIL) && !fr_inaddr_any(&request->packet->src_ipaddr)) { int i; /* * Loop over the home accounting servers for this * realm. If one of them has the same IP as the * FreeRADIUS-Proxied-To attribute, then the * packet has already been sent there. Don't * send it there again. */ for (i = 0; i < realm->acct_pool->num_home_servers; i++) { if ((fr_ipaddr_cmp(&realm->acct_pool->servers[i]->ipaddr, &request->packet->src_ipaddr) == 0) && (realm->acct_pool->servers[i]->port == request->packet->src_port)) { RDEBUG2("Suppressing proxy because packet was already sent to a server in that realm"); return RLM_MODULE_OK; } } #endif /* WITH_DETAIL */ } #endif /* WITH_PROXY */ /* * We got this far, which means we have a realm, set returnrealm */ *returnrealm = realm; return RLM_MODULE_UPDATED; }
/* * Process and reply to an authentication request * * The return value of this function isn't actually used right now, so * it's not entirely clear if it is returning the right things. --Pac. */ int rad_authenticate(REQUEST *request) { VALUE_PAIR *namepair; VALUE_PAIR *check_item; VALUE_PAIR *auth_item; VALUE_PAIR *module_msg; VALUE_PAIR *tmp = NULL; int result, r; char umsg[MAX_STRING_LEN + 1]; const char *user_msg = NULL; const char *password; char logstr[1024]; char autz_retry = 0; int autz_type = 0; password = ""; /* * If this request got proxied to another server, * AND it was an authentication request, then we need * to add an initial Auth-Type: Auth-Accept for success, * Auth-Reject for fail. We also need to add the reply * pairs from the server to the initial reply. * * Huh? If the request wasn't an authentication request, * WTF are we doing here? */ if ((request->proxy_reply) && (request->packet->code == PW_AUTHENTICATION_REQUEST)) { tmp = paircreate(PW_AUTH_TYPE, PW_TYPE_INTEGER); if (tmp == NULL) { radlog(L_ERR|L_CONS, "no memory"); exit(1); } /* * Challenges are punted back to the NAS * without any further processing. */ if (request->proxy_reply->code == PW_ACCESS_CHALLENGE) { request->reply->code = PW_ACCESS_CHALLENGE; return RLM_MODULE_HANDLED; } /* * Reply of ACCEPT means accept, ALL other * replies mean reject. This is fail-safe. */ if (request->proxy_reply->code == PW_AUTHENTICATION_ACK) tmp->lvalue = PW_AUTHTYPE_ACCEPT; else tmp->lvalue = PW_AUTHTYPE_REJECT; pairadd(&request->config_items, tmp); /* * If it's an Access-Reject, then do NOT do any * authorization or authentication. They're being * rejected, so we minimize the amount of work * done by the server, by rejecting them here. */ if ((request->proxy_reply->code != PW_AUTHENTICATION_ACK) && (request->proxy_reply->code != PW_ACCESS_CHALLENGE)) { rad_authlog("Login incorrect (Home Server says so)", request, 0); request->reply->code = PW_AUTHENTICATION_REJECT; rad_postauth_reject(request); return RLM_MODULE_REJECT; } } /* * Get the username from the request. * * Note that namepair MAY be NULL, in which case there * is no User-Name attribute in the request. */ namepair = request->username; /* * Look for, and cache, passwords. */ if (!request->password) { request->password = pairfind(request->packet->vps, PW_PASSWORD); } /* * Discover which password we want to use. */ auth_item = request->password; if (auth_item) { password = (const char *)auth_item->strvalue; } else { /* * Maybe there's a CHAP-Password? */ if ((auth_item = pairfind(request->packet->vps, PW_CHAP_PASSWORD)) != NULL) { password = "******"; } else { /* * No password we recognize. */ password = "******"; } } request->password = auth_item; /* * Get the user's authorization information from the database */ autz_redo: r = module_authorize(autz_type, request); if (r != RLM_MODULE_NOTFOUND && r != RLM_MODULE_NOOP && r != RLM_MODULE_OK && r != RLM_MODULE_UPDATED) { if (r != RLM_MODULE_FAIL && r != RLM_MODULE_HANDLED) { if ((module_msg = pairfind(request->packet->vps, PW_MODULE_FAILURE_MESSAGE)) != NULL){ char msg[MAX_STRING_LEN+16]; snprintf(msg, sizeof(msg), "Invalid user (%s)", module_msg->strvalue); rad_authlog(msg,request,0); } else { rad_authlog("Invalid user", request, 0); } request->reply->code = PW_AUTHENTICATION_REJECT; } return r; } if (!autz_retry){ VALUE_PAIR *autz_type_item = NULL; autz_type_item = pairfind(request->config_items, PW_AUTZ_TYPE); if (autz_type_item){ autz_type = autz_type_item->lvalue; autz_retry = 1; goto autz_redo; } } /* * If we haven't already proxied the packet, then check * to see if we should. Maybe one of the authorize * modules has decided that a proxy should be used. If * so, get out of here and send the packet. */ if ((request->proxy == NULL) && ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM)) != NULL)) { REALM *realm; /* * Catch users who set Proxy-To-Realm to a LOCAL * realm (sigh). */ realm = realm_find(tmp->strvalue, 0); rad_assert((realm == NULL) || (realm->ipaddr.af == AF_INET)); if (realm && (realm->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE))) { DEBUG2(" WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm! Cancelling invalid proxy request.", realm->realm); } else { /* * Don't authenticate, as the request is * proxied. */ return RLM_MODULE_OK; } } /* * Perhaps there is a Stripped-User-Name now. */ namepair = request->username; /* * Validate the user */ do { result = rad_check_password(request); if (result > 0) { /* don't reply! */ return RLM_MODULE_HANDLED; } } while(0); /* * Failed to validate the user. * * We PRESUME that the code which failed will clean up * request->reply->vps, to be ONLY the reply items it * wants to send back. */ if (result < 0) { DEBUG2("auth: Failed to validate the user."); request->reply->code = PW_AUTHENTICATION_REJECT; if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE)) != NULL){ char msg[MAX_STRING_LEN+19]; snprintf(msg, sizeof(msg), "Login incorrect (%s)", module_msg->strvalue); rad_authlog(msg, request, 0); } else { rad_authlog("Login incorrect", request, 0); } /* double check: maybe the secret is wrong? */ if ((debug_flag > 1) && (auth_item != NULL) && (auth_item->attribute == PW_PASSWORD)) { u_char *p; p = auth_item->strvalue; while (*p != '\0') { if (!isprint((int) *p)) { log_debug(" WARNING: Unprintable characters in the password.\n\t Double-check the shared secret on the server and the NAS!"); break; } p++; } } } if (result >= 0 && (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE)) != NULL) { VALUE_PAIR *session_type; int sess_type = 0; session_type = pairfind(request->config_items, PW_SESSION_TYPE); if (session_type) sess_type = session_type->lvalue; /* * User authenticated O.K. Now we have to check * for the Simultaneous-Use parameter. */ if (namepair && (r = module_checksimul(sess_type,request, check_item->lvalue)) != 0) { char mpp_ok = 0; if (r == 2){ /* Multilink attempt. Check if port-limit > simultaneous-use */ VALUE_PAIR *port_limit; if ((port_limit = pairfind(request->reply->vps, PW_PORT_LIMIT)) != NULL && port_limit->lvalue > check_item->lvalue){ DEBUG2("main auth: MPP is OK"); mpp_ok = 1; } } if (!mpp_ok){ if (check_item->lvalue > 1) { snprintf(umsg, sizeof(umsg), "\r\nYou are already logged in %d times - access denied\r\n\n", (int)check_item->lvalue); user_msg = umsg; } else { user_msg = "\r\nYou are already logged in - access denied\r\n\n"; } request->reply->code = PW_AUTHENTICATION_REJECT; /* * They're trying to log in too many times. * Remove ALL reply attributes. */ pairfree(&request->reply->vps); tmp = pairmake("Reply-Message", user_msg, T_OP_SET); request->reply->vps = tmp; snprintf(logstr, sizeof(logstr), "Multiple logins (max %d) %s", check_item->lvalue, r == 2 ? "[MPP attempt]" : ""); rad_authlog(logstr, request, 1); result = -1; } } } /* * Result should be >= 0 here - if not, it means the user * is rejected, so we just process post-auth and return. */ if (result < 0) { rad_postauth_reject(request); return RLM_MODULE_REJECT; } /* * We might need this later. The 'password' string * is NOT used anywhere below here, except for logging, * so it should be safe... */ if ((auth_item != NULL) && (auth_item->attribute == PW_CHAP_PASSWORD)) { password = "******"; } /* * Add the port number to the Framed-IP-Address if * vp->addport is set. */ if (((tmp = pairfind(request->reply->vps, PW_FRAMED_IP_ADDRESS)) != NULL) && (tmp->flags.addport != 0)) { VALUE_PAIR *vpPortId; /* * Find the NAS port ID. */ if ((vpPortId = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL) { unsigned long tvalue = ntohl(tmp->lvalue); tmp->lvalue = htonl(tvalue + vpPortId->lvalue); tmp->flags.addport = 0; ip_ntoa(tmp->strvalue, tmp->lvalue); } else { DEBUG2("WARNING: No NAS-Port attribute in request. CANNOT return a Framed-IP-Address + NAS-Port.\n"); pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS); } } /* * Set the reply to Access-Accept, if it hasn't already * been set to something. (i.e. Access-Challenge) */ if (request->reply->code == 0) request->reply->code = PW_AUTHENTICATION_ACK; if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE)) != NULL){ char msg[MAX_STRING_LEN+12]; snprintf(msg, sizeof(msg), "Login OK (%s)", module_msg->strvalue); rad_authlog(msg, request, 1); } else { rad_authlog("Login OK", request, 1); } /* * Run the modules in the 'post-auth' section. */ result = rad_postauth(request); return result; }
/* * Find the named realm in the database. Create the * set of attribute-value pairs to check and reply with * for this realm from the database. */ static int attr_filter_postproxy(void *instance, REQUEST *request) { struct attr_filter_instance *inst = instance; VALUE_PAIR *request_pairs; VALUE_PAIR **reply_items; VALUE_PAIR *reply_item; VALUE_PAIR *reply_tmp = NULL; VALUE_PAIR *check_item; PAIR_LIST *pl; int found = 0; int compare; int pass, fail; #ifdef HAVE_REGEX_H regex_t reg; #endif VALUE_PAIR *realmpair; REALM *realm; char *realmname; /* * It's not a proxy reply, so return NOOP */ if( request->proxy == NULL ) { return( RLM_MODULE_NOOP ); } request_pairs = request->packet->vps; reply_items = &request->proxy_reply->vps; /* * Get the realm. Can't use request->config_items as * that gets freed by rad_authenticate.... use the one * set in the original request vps */ realmpair = pairfind(request_pairs, PW_REALM); if(!realmpair) { /* Can't find a realm, so no filtering of attributes * or should we use a DEFAULT entry? * For now, just return NOTFOUND. (maybe NOOP?) */ return RLM_MODULE_NOTFOUND; } realmname = (char *) realmpair->strvalue; realm = realm_find(realmname, FALSE); /* * Find the attr_filter profile entry for the realm. */ for(pl = inst->attrs; pl; pl = pl->next) { /* * If the current entry is NOT a default, * AND the realm does NOT match the current entry, * then skip to the next entry. */ if ( (strcmp(pl->name, "DEFAULT") != 0) && (strcmp(realmname, pl->name) != 0) ) { continue; } DEBUG2(" attr_filter: Matched entry %s at line %d", pl->name, pl->lineno); found = 1; check_item = pl->check; while( check_item != NULL ) { /* * If it is a SET operator, add the attribute to * the reply list without checking reply_items. */ if( check_item->operator == T_OP_SET ) { mypairappend(check_item, &reply_tmp); } check_item = check_item->next; } /* while( check_item != NULL ) */ /* * Iterate through the reply items, * comparing each reply item to every rule, * then moving it to the reply_tmp list only if it matches all * rules for that attribute. * IE, Idle-Timeout is moved only if it matches * all rules that describe an Idle-Timeout. */ for( reply_item = *reply_items; reply_item != NULL; reply_item = reply_item->next ) { /* reset the pass,fail vars for each reply item */ pass = fail = 0; /* reset the check_item pointer to the beginning of the list */ check_item = pl->check; while( check_item != NULL ) { if(reply_item->attribute == check_item->attribute) { compare = simplepaircmp(request, reply_item, check_item); switch(check_item->operator) { case T_OP_SET: /* nothing to do for set */ break; case T_OP_EQ: default: radlog(L_ERR, "Invalid operator for item %s: " "reverting to '=='", check_item->name); case T_OP_CMP_TRUE: /* compare always == 0 */ case T_OP_CMP_FALSE: /* compare always == 1 */ case T_OP_CMP_EQ: if (compare == 0) { pass++; } else { fail++; } break; case T_OP_NE: if (compare != 0) { pass++; } else { fail++; } break; case T_OP_LT: if (compare < 0) { pass++; } else { fail++; } break; case T_OP_GT: if (compare > 0) { pass++; } else { fail++; } break; case T_OP_LE: if (compare <= 0) { pass++; } else { fail++; } break; case T_OP_GE: if (compare >= 0) { pass++; } else { fail++; } break; #ifdef HAVE_REGEX_H case T_OP_REG_EQ: regcomp(®, (char *)check_item->strvalue, 0); compare = regexec(®, (char *)reply_item->strvalue, 0, NULL, 0); regfree(®); if (compare == 0) { pass++; } else { fail++; } break; case T_OP_REG_NE: regcomp(®, (char *)check_item->strvalue, 0); compare = regexec(®, (char *)reply_item->strvalue, 0, NULL, 0); regfree(®); if (compare != 0) { pass++; } else { fail++; } break; #endif } /* switch( check_item->operator ) */ } /* if reply == check */ check_item = check_item->next; } /* while( check ) */ /* only move attribute if it passed all rules */ if (fail == 0 && pass > 0) { mypairappend( reply_item, &reply_tmp); } } /* for( reply ) */ /* If we shouldn't fall through, break */ if(!fallthrough(pl->check)) break; } pairfree(&request->proxy_reply->vps); request->proxy_reply->vps = reply_tmp; /* * See if we succeeded. If we didn't find the realm, * then exit from the module. */ if (!found) return RLM_MODULE_OK; /* * Remove server internal parameters. */ pairdelete(reply_items, PW_FALL_THROUGH); return RLM_MODULE_UPDATED; }
/* * Internal function to cut down on duplicated code. * * Returns -1 on failure, 0 on no failure. returnrealm * is NULL on don't proxy, realm otherwise. */ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm) { char namebuf[MAX_STRING_LEN]; char *username; char *realmname = NULL; char *ptr; VALUE_PAIR *vp; REALM *realm; struct realm_config_t *inst = instance; /* initiate returnrealm */ *returnrealm = NULL; /* * If the request has a proxy entry, then it's a proxy * reply, and we're walking through the module list again. * * In that case, don't bother trying to proxy the request * again. * * Also, if there's no User-Name attribute, we can't * proxy it, either. */ if ((request->proxy != NULL) || (request->username == NULL)) { DEBUG2(" rlm_realm: Proxy reply, or no User-Name. Ignoring."); return 0; } /* * Check for 'Realm' attribute. If it exists, then we've proxied * it already ( via another rlm_realm instance ) and should return. */ if ( (vp = pairfind(request->packet->vps, PW_REALM)) != NULL ) { DEBUG2(" rlm_realm: Request already proxied. Ignoring."); return 0; } /* * We will be modifing this later, so we want our own copy * of it. */ strNcpy(namebuf, (char *)request->username->strvalue, sizeof(namebuf)); username = namebuf; switch(inst->format) { case REALM_FORMAT_SUFFIX: /* DEBUG2(" rlm_realm: Checking for suffix after \"%c\"", inst->delim[0]); */ realmname = strrchr(username, inst->delim[0]); if (realmname) { *realmname = '\0'; realmname++; } break; case REALM_FORMAT_PREFIX: /* DEBUG2(" rlm_realm: Checking for prefix before \"%c\"", inst->delim[0]); */ ptr = strchr(username, inst->delim[0]); if (ptr) { *ptr = '\0'; ptr++; realmname = username; username = ptr; } break; default: realmname = NULL; break; } /* * Print out excruciatingly descriptive debugging messages * for the people who find it too difficult to think about * what's going on. */ if (realmname) { DEBUG2(" rlm_realm: Looking up realm \"%s\" for User-Name = \"%s\"", realmname, request->username->strvalue); } else { if( inst->ignore_null ) { DEBUG2(" rlm_realm: No '%c' in User-Name = \"%s\", skipping NULL due to config.", inst->delim[0], request->username->strvalue); return 0; } DEBUG2(" rlm_realm: No '%c' in User-Name = \"%s\", looking up realm NULL", inst->delim[0], request->username->strvalue); } /* * Allow DEFAULT realms unless told not to. */ realm = realm_find(realmname, (request->packet->code == PW_ACCOUNTING_REQUEST)); if (!realm) { DEBUG2(" rlm_realm: No such realm \"%s\"", (realmname == NULL) ? "NULL" : realmname); return 0; } if( inst->ignore_default && (strcmp(realm->realm, "DEFAULT")) == 0) { DEBUG2(" rlm_realm: Found DEFAULT, but skipping due to config."); return 0; } DEBUG2(" rlm_realm: Found realm \"%s\"", realm->realm); /* * If we've been told to strip the realm off, then do so. */ if (realm->striprealm) { /* * Create the Stripped-User-Name attribute, if it * doesn't exist. * */ if (request->username->attribute != PW_STRIPPED_USER_NAME) { vp = paircreate(PW_STRIPPED_USER_NAME, PW_TYPE_STRING); if (!vp) { radlog(L_ERR|L_CONS, "no memory"); return -1; } pairadd(&request->packet->vps, vp); DEBUG2(" rlm_realm: Adding Stripped-User-Name = \"%s\"", username); } else { vp = request->username; DEBUG2(" rlm_realm: Setting Stripped-User-Name = \"%s\"", username); } strcpy(vp->strvalue, username); vp->length = strlen((char *)vp->strvalue); request->username = vp; } DEBUG2(" rlm_realm: Proxying request from user %s to realm %s", username, realm->realm); /* * Add the realm name to the request. */ pairadd(&request->packet->vps, pairmake("Realm", realm->realm, T_OP_EQ)); DEBUG2(" rlm_realm: Adding Realm = \"%s\"", realm->realm); /* * Figure out what to do with the request. */ switch (request->packet->code) { default: DEBUG2(" rlm_realm: Unknown packet code %d\n", request->packet->code); return 0; /* don't do anything */ /* * Perhaps accounting proxying was turned off. */ case PW_ACCOUNTING_REQUEST: if (realm->acct_ipaddr == htonl(INADDR_NONE)) { DEBUG2(" rlm_realm: Accounting realm is LOCAL."); return 0; } if (realm->acct_port == 0) { DEBUG2(" rlm_realm: acct_port is not set. Proxy cancelled."); return 0; } break; /* * Perhaps authentication proxying was turned off. */ case PW_AUTHENTICATION_REQUEST: if (realm->ipaddr == htonl(INADDR_NONE)) { DEBUG2(" rlm_realm: Authentication realm is LOCAL."); return 0; } if (realm->auth_port == 0) { DEBUG2(" rlm_realm: auth_port is not set. Proxy cancelled."); return 0; } break; } /* * If this request has arrived from another freeradius server * that has already proxied the request, we don't need to do * it again. */ for (vp = request->packet->vps; vp; vp = vp->next) { if (vp->attribute == PW_FREERADIUS_PROXIED_TO) { if (request->packet->code == PW_AUTHENTICATION_REQUEST && vp->lvalue == realm->ipaddr) { DEBUG2(" rlm_realm: Request not proxied due to Freeradius-Proxied-To"); return 0; } if (request->packet->code == PW_ACCOUNTING_REQUEST && vp->lvalue == realm->acct_ipaddr) { DEBUG2(" rlm_realm: Request not proxied due to Freeradius-Proxied-To"); return 0; } } } /* * We got this far, which means we have a realm, set returnrealm */ *returnrealm = realm; return 0; }