X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmain%2Fauth.c;h=054511421610b5848edca5ab1a3737dd7d8027b1;hb=e4d2860552e745ba785ee8716b918b288b6194a6;hp=58c92dbb37f230dead82651000609b0744eadcbe;hpb=f8eac0d9735be5f0b8d7a13e6c984e05bc8c835c;p=freeradius.git diff --git a/src/main/auth.c b/src/main/auth.c index 58c92db..0545114 100644 --- a/src/main/auth.c +++ b/src/main/auth.c @@ -15,103 +15,62 @@ * * 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * - * Copyright 2000 The FreeRADIUS server project + * Copyright 2000,2006 The FreeRADIUS server project * Copyright 2000 Miquel van Smoorenburg * Copyright 2000 Jeff Carneal */ -static const char rcsid[] = "$Id$"; +#include +RCSID("$Id$") -#include "autoconf.h" -#include "libradius.h" +#include +#include +#include -#include -#include #include -#ifdef HAVE_NETINET_IN_H -# include -#endif - -#include "radiusd.h" -#include "modules.h" - /* * Return a short string showing the terminal server, port * and calling station ID. */ -char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli) { +char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli) +{ VALUE_PAIR *cli; VALUE_PAIR *pair; int port = 0; - if ((cli = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) == NULL) + if ((cli = pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0)) == NULL) do_cli = 0; - if ((pair = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL) - port = pair->lvalue; + if ((pair = pairfind(request->packet->vps, PW_NAS_PORT, 0)) != NULL) + port = pair->vp_integer; - snprintf(buf, buflen, "from client %.128s port %u%s%.128s", - client_name(request->packet->src_ipaddr), port, - (do_cli ? " cli " : ""), (do_cli ? (char *)cli->strvalue : "")); + snprintf(buf, buflen, "from client %.128s port %u%s%.128s%s", + request->client->shortname, port, + (do_cli ? " cli " : ""), (do_cli ? (char *)cli->vp_strvalue : ""), + (request->packet->dst_port == 0) ? " via TLS tunnel" : ""); return buf; } -/* - * Check if account has expired, and if user may login now. - */ -static int check_expiration(REQUEST *request) -{ - int result; - VALUE_PAIR *check_item = request->config_items; - - result = 0; - while (result == 0 && check_item != NULL) { - - /* - * Check expiration date if we are doing password aging. - */ - if (check_item->attribute == PW_EXPIRATION) { - /* - * Has this user's password expired? - * - * If so, remove ALL reply attributes, - * and add our own Reply-Message, saying - * why they're being rejected. - */ - if (check_item->lvalue < (unsigned) time(NULL)) { - VALUE_PAIR *vp; - - result = -1; - vp = pairmake("Reply-Message", - "Password Has Expired\r\n", - T_OP_ADD); - pairfree(&request->reply->vps); - request->reply->vps = vp; - break; - } - } - check_item = check_item->next; - } - return result; -} - /* * Make sure user/pass are clean * and then log them */ -static int rad_authlog(const char *msg, REQUEST *request, int goodpass) { - +static int rad_authlog(const char *msg, REQUEST *request, int goodpass) +{ + int logit; + const char *extra_msg = NULL; char clean_password[1024]; char clean_username[1024]; char buf[1024]; + char extra[1024]; VALUE_PAIR *username = NULL; - if (!mainconfig.log_auth) { + if (!request->root->log_auth) { return 0; } @@ -119,7 +78,7 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) { * Get the correct username based on the configured value */ if (log_stripped_names == 0) { - username = pairfind(request->packet->vps, PW_USER_NAME); + username = pairfind(request->packet->vps, PW_USER_NAME, 0); } else { username = request->username; } @@ -130,7 +89,7 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) { if (username == NULL) { strcpy(clean_username, ""); } else { - librad_safeprint((char *)username->strvalue, + fr_print_string((char *)username->vp_strvalue, username->length, clean_username, sizeof(clean_username)); } @@ -138,34 +97,52 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) { /* * Clean up the password */ - if (mainconfig.log_auth_badpass || mainconfig.log_auth_goodpass) { + if (request->root->log_auth_badpass || request->root->log_auth_goodpass) { if (!request->password) { - strcpy(clean_password, ""); - } else if (request->password->attribute == PW_CHAP_PASSWORD) { + VALUE_PAIR *auth_type; + + auth_type = pairfind(request->config_items, + PW_AUTH_TYPE, 0); + if (auth_type && (auth_type->vp_strvalue[0] != '\0')) { + snprintf(clean_password, sizeof(clean_password), + "", + auth_type->vp_strvalue); + } else { + strcpy(clean_password, ""); + } + } else if (pairfind(request->packet->vps, PW_CHAP_PASSWORD, 0)) { strcpy(clean_password, ""); } else { - librad_safeprint((char *)request->password->strvalue, + fr_print_string((char *)request->password->vp_strvalue, request->password->length, clean_password, sizeof(clean_password)); } } if (goodpass) { - radlog(L_AUTH, "%s: [%s%s%s] (%s)", - msg, - clean_username, - mainconfig.log_auth_goodpass ? "/" : "", - mainconfig.log_auth_goodpass ? clean_password : "", - auth_name(buf, sizeof(buf), request, 1)); + logit = request->root->log_auth_goodpass; + extra_msg = request->root->auth_goodpass_msg; + } else { + logit = request->root->log_auth_badpass; + extra_msg = request->root->auth_badpass_msg; + } + + if (extra_msg) { + extra[0] = ' '; + radius_xlat(extra + 1, sizeof(extra) - 1, extra_msg, request, + NULL); } else { - radlog(L_AUTH, "%s: [%s%s%s] (%s)", - msg, - clean_username, - mainconfig.log_auth_badpass ? "/" : "", - mainconfig.log_auth_badpass ? clean_password : "", - auth_name(buf, sizeof(buf), request, 1)); + *extra = '\0'; } + radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)%s", + msg, + clean_username, + logit ? "/" : "", + logit ? clean_password : "", + auth_name(buf, sizeof(buf), request, 1), + extra); + return 0; } @@ -179,13 +156,13 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) { * * NOTE: NOT the same as the RLM_ values ! */ -int rad_check_password(REQUEST *request) +static int rad_check_password(REQUEST *request) { VALUE_PAIR *auth_type_pair; VALUE_PAIR *cur_config_item; VALUE_PAIR *password_pair; VALUE_PAIR *auth_item; - char string[MAX_STRING_LEN]; + uint8_t my_chap[MAX_STRING_LEN]; int auth_type = -1; int result; int auth_type_count = 0; @@ -197,23 +174,26 @@ int rad_check_password(REQUEST *request) * PW_AUTHTYPE_REJECT. */ cur_config_item = request->config_items; - while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE))) != NULL) { - auth_type = auth_type_pair->lvalue; + while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE, 0))) != NULL) { + DICT_VALUE *dv; + auth_type = auth_type_pair->vp_integer; auth_type_count++; + dv = dict_valbyattr(auth_type_pair->attribute, + auth_type_pair->vp_integer, 0); - DEBUG2(" rad_check_password: Found Auth-Type %s", - auth_type_pair->strvalue); + RDEBUG2("Found Auth-Type = %s", + (dv != NULL) ? dv->name : "?"); cur_config_item = auth_type_pair->next; if (auth_type == PW_AUTHTYPE_REJECT) { - DEBUG2(" rad_check_password: Auth-Type = Reject, rejecting user"); + RDEBUG2("Auth-Type = Reject, rejecting user"); return -2; } } if (( auth_type_count > 1) && (debug_flag)) { - radlog(L_ERR, "Warning: Found %d auth-types on request for user '%s'", - auth_type_count, request->username->strvalue); + radlog_request(L_ERR, 0, request, "Warning: Found %d auth-types on request for user '%s'", + auth_type_count, request->username->vp_strvalue); } /* @@ -222,22 +202,55 @@ int rad_check_password(REQUEST *request) * that means it is accepted and we do no further * authentication */ - if ((auth_type == PW_AUTHTYPE_ACCEPT) || (request->proxy)) { - DEBUG2(" rad_check_password: Auth-Type = Accept, accepting the user"); + if ((auth_type == PW_AUTHTYPE_ACCEPT) +#ifdef WITH_PROXY + || (request->proxy) +#endif + ) { + RDEBUG2("Auth-Type = Accept, accepting the user"); return 0; } + password_pair = pairfind(request->config_items, PW_USER_PASSWORD, 0); + if (password_pair && + pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0)) { + pairdelete(&request->config_items, PW_USER_PASSWORD, 0); + password_pair = NULL; + } + + if (password_pair) { + DICT_ATTR *da; + + RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + RDEBUG("!!! Replacing User-Password in config items with Cleartext-Password. !!!"); + RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + RDEBUG("!!! Please update your configuration so that the \"known good\" !!!"); + RDEBUG("!!! clear text password is in Cleartext-Password, and not in User-Password. !!!"); + RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + password_pair->attribute = PW_CLEARTEXT_PASSWORD; + da = dict_attrbyvalue(PW_CLEARTEXT_PASSWORD, 0); + if (!da) { + radlog_request(L_ERR, 0, request, "FATAL: You broke the dictionaries. Please use the default dictionaries!"); + _exit(1); + } + + password_pair->name = da->name; + } + /* - * Find the password from the users file. + * Find the "known good" password. + * + * FIXME: We should get rid of these hacks, and replace + * them with a module. */ - if ((password_pair = pairfind(request->config_items, PW_CRYPT_PASSWORD)) != NULL) { + if ((password_pair = pairfind(request->config_items, PW_CRYPT_PASSWORD, 0)) != NULL) { /* * Re-write Auth-Type, but ONLY if it isn't already * set. */ if (auth_type == -1) auth_type = PW_AUTHTYPE_CRYPT; } else { - password_pair = pairfind(request->config_items, PW_PASSWORD); + password_pair = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0); } if (auth_type < 0) { @@ -250,13 +263,16 @@ int rad_check_password(REQUEST *request) * * This is fail-safe. */ - DEBUG2("auth: No authenticate method (Auth-Type) configuration found for the request: Rejecting the user"); + RDEBUG2("ERROR: No authenticate method (Auth-Type) found for the request: Rejecting the user"); return -2; } } switch(auth_type) { case PW_AUTHTYPE_CRYPT: + RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Crypt'"); + RDEBUG2("WARNING: Use the PAP module instead."); + /* * Find the password sent by the user. It * SHOULD be there, if it's not @@ -264,20 +280,19 @@ int rad_check_password(REQUEST *request) */ auth_item = request->password; if (auth_item == NULL) { - DEBUG2("auth: No User-Password or CHAP-Password attribute in the request"); + RDEBUG2("No User-Password or CHAP-Password attribute in the request"); return -1; } - DEBUG2("auth: type Crypt"); if (password_pair == NULL) { - DEBUG2("No Crypt-Password configured for the user"); + RDEBUG2("No Crypt-Password configured for the user"); rad_authlog("Login incorrect " "(No Crypt-Password configured for the user)", request, 0); return -1; } - switch (lrad_crypt_check((char *)auth_item->strvalue, - (char *)password_pair->strvalue)) { + switch (fr_crypt_check((char *)auth_item->vp_strvalue, + (char *)password_pair->vp_strvalue)) { case -1: rad_authlog("Login incorrect " "(system failed to supply an encrypted password for comparison)", request, 0); @@ -286,7 +301,8 @@ int rad_check_password(REQUEST *request) } break; case PW_AUTHTYPE_LOCAL: - DEBUG2("auth: type Local"); + RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Local'"); + RDEBUG2("WARNING: Use the PAP or CHAP modules instead."); /* * Find the password sent by the user. It @@ -294,8 +310,12 @@ int rad_check_password(REQUEST *request) * authentication fails. */ auth_item = request->password; - if (auth_item == NULL) { - DEBUG2("auth: No User-Password or CHAP-Password attribute in the request"); + if (!auth_item) + auth_item = pairfind(request->packet->vps, + PW_CHAP_PASSWORD, 0); + if (!auth_item) { + RDEBUG2("No User-Password or CHAP-Password attribute in the request."); + RDEBUG2("Cannot perform authentication."); return -1; } @@ -303,7 +323,8 @@ int rad_check_password(REQUEST *request) * Plain text password. */ if (password_pair == NULL) { - DEBUG2("auth: No password configured for the user"); + RDEBUG2("No \"known good\" password was configured for the user."); + RDEBUG2("As a result, we cannot authenticate the user."); rad_authlog("Login incorrect " "(No password configured for the user)", request, 0); return -1; @@ -312,38 +333,36 @@ int rad_check_password(REQUEST *request) /* * Local password is just plain text. */ - if (auth_item->attribute == PW_PASSWORD) { - if (strcmp((char *)password_pair->strvalue, - (char *)auth_item->strvalue) != 0) { - DEBUG2("auth: user supplied User-Password does NOT match local User-Password"); + if (auth_item->attribute == PW_USER_PASSWORD) { + if (strcmp((char *)password_pair->vp_strvalue, + (char *)auth_item->vp_strvalue) != 0) { + RDEBUG2("User-Password in the request does NOT match \"known good\" password."); return -1; } - DEBUG2("auth: user supplied User-Password matches local User-Password"); + RDEBUG2("User-Password in the request is correct."); break; } else if (auth_item->attribute != PW_CHAP_PASSWORD) { - DEBUG2("The user did not supply a User-Password or a CHAP-Password attribute"); + RDEBUG2("The user did not supply a User-Password or a CHAP-Password attribute"); rad_authlog("Login incorrect " "(no User-Password or CHAP-Password attribute)", request, 0); return -1; } - rad_chap_encode(request->packet, string, - auth_item->strvalue[0], password_pair); + rad_chap_encode(request->packet, my_chap, + auth_item->vp_octets[0], password_pair); /* * Compare them */ - if (memcmp(string + 1, auth_item->strvalue + 1, + if (memcmp(my_chap + 1, auth_item->vp_strvalue + 1, CHAP_VALUE_LENGTH) != 0) { - DEBUG2("auth: user supplied CHAP-Password does NOT match local User-Password"); + RDEBUG2("CHAP-Password is incorrect."); return -1; } - DEBUG2("auth: user supplied CHAP-Password matches local User-Password"); + RDEBUG2("CHAP-Password is correct."); break; default: - DEBUG2("auth: type \"%s\"", - dict_valbyattr(PW_AUTH_TYPE, auth_type)->name); /* * See if there is a module that handles * this type, and turn the RLM_ return @@ -359,12 +378,13 @@ int rad_check_password(REQUEST *request) * is the same as an explicit REJECT! */ case RLM_MODULE_FAIL: - case RLM_MODULE_REJECT: - case RLM_MODULE_USERLOCK: case RLM_MODULE_INVALID: - case RLM_MODULE_NOTFOUND: case RLM_MODULE_NOOP: + case RLM_MODULE_NOTFOUND: + case RLM_MODULE_REJECT: case RLM_MODULE_UPDATED: + case RLM_MODULE_USERLOCK: + default: result = -1; break; case RLM_MODULE_OK: @@ -389,65 +409,44 @@ int rad_postauth(REQUEST *request) { int result; int postauth_type = 0; - VALUE_PAIR *postauth_type_item = NULL; + VALUE_PAIR *vp; /* * Do post-authentication calls. ignoring the return code. */ - postauth_type_item = pairfind(request->config_items, PW_POST_AUTH_TYPE); - if (postauth_type_item) - postauth_type = postauth_type_item->lvalue; + vp = pairfind(request->config_items, PW_POST_AUTH_TYPE, 0); + if (vp) { + RDEBUG2("Using Post-Auth-Type %s", vp->vp_strvalue); + postauth_type = vp->vp_integer; + } result = module_post_auth(postauth_type, request); switch (result) { - default: - break; - - /* - * The module failed, or said to reject the user: Do so. - */ - case RLM_MODULE_FAIL: - case RLM_MODULE_REJECT: - case RLM_MODULE_USERLOCK: - case RLM_MODULE_INVALID: - request->reply->code = PW_AUTHENTICATION_REJECT; - result = RLM_MODULE_REJECT; - break; - - /* - * The module had a number of OK return codes. - */ - case RLM_MODULE_NOTFOUND: - case RLM_MODULE_NOOP: - case RLM_MODULE_UPDATED: - case RLM_MODULE_OK: - case RLM_MODULE_HANDLED: - result = RLM_MODULE_OK; - break; - } - return result; -} - -/* - * Before sending an Access-Reject, call the modules in the - * Post-Auth-Type REJECT stanza. - */ -static int rad_postauth_reject(REQUEST *request) -{ - int result; - VALUE_PAIR *tmp; - DICT_VALUE *dval; - - dval = dict_valbyname(PW_POST_AUTH_TYPE, "REJECT"); - if (dval) { - /* Overwrite the Post-Auth-Type with the value REJECT */ - pairdelete(&request->config_items, PW_POST_AUTH_TYPE); - tmp = paircreate(PW_POST_AUTH_TYPE, PW_TYPE_INTEGER); - tmp->lvalue = dval->value; - pairadd(&request->config_items, tmp); - result = rad_postauth(request); - } else { - /* No REJECT stanza */ - result = RLM_MODULE_OK; + /* + * The module failed, or said to reject the user: Do so. + */ + case RLM_MODULE_FAIL: + case RLM_MODULE_INVALID: + case RLM_MODULE_REJECT: + case RLM_MODULE_USERLOCK: + default: + request->reply->code = PW_AUTHENTICATION_REJECT; + result = RLM_MODULE_REJECT; + break; + /* + * The module handled the request, cancel the reply. + */ + case RLM_MODULE_HANDLED: + /* FIXME */ + break; + /* + * The module had a number of OK return codes. + */ + case RLM_MODULE_NOOP: + case RLM_MODULE_NOTFOUND: + case RLM_MODULE_OK: + case RLM_MODULE_UPDATED: + result = RLM_MODULE_OK; + break; } return result; } @@ -461,75 +460,64 @@ static int rad_postauth_reject(REQUEST *request) int rad_authenticate(REQUEST *request) { VALUE_PAIR *namepair; +#ifdef WITH_SESSION_MGMT VALUE_PAIR *check_item; - VALUE_PAIR *reply_item; - VALUE_PAIR *auth_item; +#endif + VALUE_PAIR *auth_item = NULL; VALUE_PAIR *module_msg; VALUE_PAIR *tmp = NULL; - int result, r; - char umsg[MAX_STRING_LEN + 1]; - const char *user_msg = NULL; + int result; const char *password; - char *exec_program; - int exec_wait; - int seen_callback_id; - char buf[1024], logstr[1024]; char autz_retry = 0; int autz_type = 0; password = ""; +#ifdef WITH_PROXY /* - * 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 this request got proxied to another server, we need + * to check whether it authenticated the request or not. */ - 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); - } - + if (request->proxy_reply) { + switch (request->proxy_reply->code) { /* - * Challenges are punted back to the NAS - * without any further processing. + * Reply of ACCEPT means accept, thus set Auth-Type + * accordingly. */ - if (request->proxy_reply->code == PW_ACCESS_CHALLENGE) { - request->reply->code = PW_ACCESS_CHALLENGE; - return RLM_MODULE_HANDLED; - } + case PW_AUTHENTICATION_ACK: + tmp = radius_paircreate(request, + &request->config_items, + PW_AUTH_TYPE, 0, PW_TYPE_INTEGER); + if (tmp) tmp->vp_integer = PW_AUTHTYPE_ACCEPT; + goto authenticate; /* - * Reply of ACCEPT means accept, ALL other - * replies mean reject. This is fail-safe. + * Challenges are punted back to the NAS without any + * further processing. */ - if (request->proxy_reply->code == PW_AUTHENTICATION_ACK) - tmp->lvalue = PW_AUTHTYPE_ACCEPT; - else - tmp->lvalue = PW_AUTHTYPE_REJECT; - pairadd(&request->config_items, tmp); - + case PW_ACCESS_CHALLENGE: + request->reply->code = PW_ACCESS_CHALLENGE; + return RLM_MODULE_OK; /* - * 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 + * ALL other replies mean reject. (this is fail-safe) + * + * Do NOT do any authorization or authentication. They + * are 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); + case PW_AUTHENTICATION_REJECT: + rad_authlog("Login incorrect (Home Server says so)", + request, 0); request->reply->code = PW_AUTHENTICATION_REJECT; - rad_postauth_reject(request); + return RLM_MODULE_REJECT; + + default: + rad_authlog("Login incorrect (Home Server failed to respond)", + request, 0); return RLM_MODULE_REJECT; } } +#endif /* * Get the username from the request. @@ -544,7 +532,7 @@ int rad_authenticate(REQUEST *request) */ if (!request->password) { request->password = pairfind(request->packet->vps, - PW_PASSWORD); + PW_USER_PASSWORD, 0); } /* @@ -552,14 +540,14 @@ int rad_authenticate(REQUEST *request) */ auth_item = request->password; if (auth_item) { - password = (const char *)auth_item->strvalue; + password = (const char *)auth_item->vp_strvalue; } else { /* * Maybe there's a CHAP-Password? */ if ((auth_item = pairfind(request->packet->vps, - PW_CHAP_PASSWORD)) != NULL) { + PW_CHAP_PASSWORD, 0)) != NULL) { password = ""; } else { @@ -575,30 +563,37 @@ int rad_authenticate(REQUEST *request) * 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) { + result = module_authorize(autz_type, request); + switch (result) { + case RLM_MODULE_NOOP: + case RLM_MODULE_NOTFOUND: + case RLM_MODULE_OK: + case RLM_MODULE_UPDATED: + break; + case RLM_MODULE_HANDLED: + return result; + case RLM_MODULE_FAIL: + case RLM_MODULE_INVALID: + case RLM_MODULE_REJECT: + case RLM_MODULE_USERLOCK: + default: if ((module_msg = pairfind(request->packet->vps, - PW_MODULE_FAILURE_MESSAGE)) != NULL){ - char msg[MAX_STRING_LEN+16]; + PW_MODULE_FAILURE_MESSAGE, 0)) != NULL) { + char msg[MAX_STRING_LEN + 16]; snprintf(msg, sizeof(msg), "Invalid user (%s)", - module_msg->strvalue); + module_msg->vp_strvalue); rad_authlog(msg,request,0); } else { rad_authlog("Invalid user", request, 0); } request->reply->code = PW_AUTHENTICATION_REJECT; - } - return r; + return result; } - 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; + if (!autz_retry) { + tmp = pairfind(request->config_items, PW_AUTZ_TYPE, 0); + if (tmp) { + RDEBUG2("Using Autz-Type %s", tmp->vp_strvalue); + autz_type = tmp->vp_integer; autz_retry = 1; goto autz_redo; } @@ -610,26 +605,41 @@ autz_redo: * 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)) { + if ( +#ifdef WITH_PROXY + (request->proxy == NULL) && +#endif + ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM, 0)) != NULL)) { REALM *realm; + realm = realm_find2(tmp->vp_strvalue); + /* - * Catch users who set Proxy-To-Realm to a LOCAL - * realm (sigh). + * Don't authenticate, as the request is going to + * be proxied. */ - realm = realm_find(tmp->strvalue, 0); - if (realm && (realm->ipaddr == 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. - */ + if (realm && realm->auth_pool) { return RLM_MODULE_OK; } + + /* + * Catch users who set Proxy-To-Realm to a LOCAL + * realm (sigh). But don't complain if it is + * *the* LOCAL realm. + */ + if (realm &&(strcmp(realm->name, "LOCAL") != 0)) { + RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm! Cancelling proxy request.", realm->name); + } + + if (!realm) { + RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but the realm does not exist! Cancelling invalid proxy request.", tmp->vp_strvalue); + } } +#ifdef WITH_PROXY + authenticate: +#endif + /* * Perhaps there is a Stripped-User-Name now. */ @@ -639,8 +649,6 @@ autz_redo: * Validate the user */ do { - if ((result = check_expiration(request)) < 0) - break; result = rad_check_password(request); if (result > 0) { /* don't reply! */ @@ -656,14 +664,14 @@ autz_redo: * wants to send back. */ if (result < 0) { - DEBUG2("auth: Failed to validate the user."); + RDEBUG2("Failed to authenticate the user."); request->reply->code = PW_AUTHENTICATION_REJECT; - if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE)) != NULL){ + if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE, 0)) != NULL){ char msg[MAX_STRING_LEN+19]; snprintf(msg, sizeof(msg), "Login incorrect (%s)", - module_msg->strvalue); + module_msg->vp_strvalue); rad_authlog(msg, request, 0); } else { rad_authlog("Login incorrect", request, 0); @@ -671,10 +679,10 @@ autz_redo: /* double check: maybe the secret is wrong? */ if ((debug_flag > 1) && (auth_item != NULL) && - (auth_item->attribute == PW_PASSWORD)) { - u_char *p; + (auth_item->attribute == PW_USER_PASSWORD)) { + char *p; - p = auth_item->strvalue; + p = auth_item->vp_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!"); @@ -685,38 +693,43 @@ autz_redo: } } +#ifdef WITH_SESSION_MGMT 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; + (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE, 0)) != NULL) { + int r, session_type = 0; + char logstr[1024]; + char umsg[MAX_STRING_LEN + 1]; + const char *user_msg = NULL; + + tmp = pairfind(request->config_items, PW_SESSION_TYPE, 0); + if (tmp) { + RDEBUG2("Using Session-Type %s", tmp->vp_strvalue); + session_type = tmp->vp_integer; + } /* * 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) { + (r = module_checksimul(session_type, request, check_item->vp_integer)) != 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"); + if ((port_limit = pairfind(request->reply->vps, PW_PORT_LIMIT, 0)) != NULL && + port_limit->vp_integer > check_item->vp_integer){ + RDEBUG2("MPP is OK"); mpp_ok = 1; } } if (!mpp_ok){ - if (check_item->lvalue > 1) { + if (check_item->vp_integer > 1) { snprintf(umsg, sizeof(umsg), "\r\nYou are already logged in %d times - access denied\r\n\n", - (int)check_item->lvalue); + (int)check_item->vp_integer); user_msg = umsg; } else { user_msg = "\r\nYou are already logged in - access denied\r\n\n"; @@ -729,11 +742,12 @@ autz_redo: * Remove ALL reply attributes. */ pairfree(&request->reply->vps); - tmp = pairmake("Reply-Message", user_msg, T_OP_SET); - request->reply->vps = tmp; + radius_pairmake(request, &request->reply->vps, + "Reply-Message", + user_msg, T_OP_SET); snprintf(logstr, sizeof(logstr), "Multiple logins (max %d) %s", - check_item->lvalue, + check_item->vp_integer, r == 2 ? "[MPP attempt]" : ""); rad_authlog(logstr, request, 1); @@ -741,90 +755,22 @@ autz_redo: } } } - - if (result >= 0 && - (check_item = pairfind(request->config_items, PW_LOGIN_TIME)) != NULL) { - - /* - * Authentication is OK. Now see if this - * user may login at this time of the day. - */ - r = timestr_match((char *)check_item->strvalue, - request->timestamp); - - if (r == 0) { /* unlimited */ - /* - * Do nothing: login-time is OK. - */ - - /* - * Session-Timeout needs to be at least - * 60 seconds, some terminal servers - * ignore smaller values. - */ - } else if (r < 60) { - /* - * User called outside allowed time interval. - */ - result = -1; - user_msg = "You are calling outside your allowed timespan\r\n"; - - request->reply->code = PW_AUTHENTICATION_REJECT; - pairfree(&request->reply->vps); - - tmp = pairmake("Reply-Message", user_msg, T_OP_SET); - request->reply->vps = tmp; - - snprintf(logstr, sizeof(logstr), "Outside allowed timespan (time allowed %s)", - check_item->strvalue); - rad_authlog(logstr, request, 1); - - } else if (r > 0) { - - /* - * User is allowed, but set Session-Timeout. - */ - if ((reply_item = pairfind(request->reply->vps, - PW_SESSION_TIMEOUT)) != NULL) { - if (reply_item->lvalue > (unsigned) r) - reply_item->lvalue = r; - } else { - if ((reply_item = paircreate( - PW_SESSION_TIMEOUT, - PW_TYPE_INTEGER)) == NULL) { - radlog(L_ERR|L_CONS, "no memory"); - exit(1); - } - reply_item->lvalue = r; - pairadd(&request->reply->vps, reply_item); - } - } - } +#endif /* * 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 = "CHAP-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) && + PW_FRAMED_IP_ADDRESS, 0)) != NULL) && (tmp->flags.addport != 0)) { VALUE_PAIR *vpPortId; @@ -832,130 +778,14 @@ autz_redo: * 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); + PW_NAS_PORT, 0)) != NULL) { + unsigned long tvalue = ntohl(tmp->vp_integer); + tmp->vp_integer = htonl(tvalue + vpPortId->vp_integer); tmp->flags.addport = 0; - ip_ntoa(tmp->strvalue, tmp->lvalue); + ip_ntoa(tmp->vp_strvalue, tmp->vp_integer); } 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); - } - } - - /* - * See if we need to execute a program. - * FIXME: somehow cache this info, and only execute the - * program when we receive an Accounting-START packet. - * Only at that time we know dynamic IP etc. - */ - exec_program = NULL; - exec_wait = 0; - if ((auth_item = pairfind(request->reply->vps, PW_EXEC_PROGRAM)) != NULL) { - exec_wait = 0; - exec_program = strdup((char *)auth_item->strvalue); - pairdelete(&request->reply->vps, PW_EXEC_PROGRAM); - } - if ((auth_item = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) { - exec_wait = 1; - exec_program = strdup((char *)auth_item->strvalue); - pairdelete(&request->reply->vps, PW_EXEC_PROGRAM_WAIT); - } - - /* - * Hack - allow % expansion in certain value strings. - * This is nice for certain Exec-Program programs. - */ - seen_callback_id = 0; - if ((auth_item = pairfind(request->reply->vps, PW_CALLBACK_ID)) != NULL) { - seen_callback_id = 1; - radius_xlat(buf, sizeof(auth_item->strvalue), - (char *)auth_item->strvalue, request, NULL); - strNcpy((char *)auth_item->strvalue, buf, - sizeof(auth_item->strvalue)); - auth_item->length = strlen((char *)auth_item->strvalue); - } - - - /* - * If we want to exec a program, but wait for it, - * do it first before sending the reply. - */ - if (exec_program && exec_wait) { - r = radius_exec_program(exec_program, request, - exec_wait, - umsg, sizeof(umsg), - request->packet->vps, &tmp); - free(exec_program); - exec_program = NULL; - - /* - * Always add the value-pairs to the reply. - */ - pairmove(&request->reply->vps, &tmp); - pairfree(&tmp); - - if (r != 0) { - /* - * Error. radius_exec_program() returns -1 on - * fork/exec errors, or >0 if the exec'ed program - * had a non-zero exit status. - */ - if (umsg[0] == '\0') { - user_msg = "\r\nAccess denied (external check failed)."; - } else { - user_msg = &umsg[0]; - } - - request->reply->code = PW_AUTHENTICATION_REJECT; - tmp = pairmake("Reply-Message", user_msg, T_OP_SET); - - pairadd(&request->reply->vps, tmp); - rad_authlog("Login incorrect (external check failed)", - request, 0); - - rad_postauth_reject(request); - - return RLM_MODULE_REJECT; - } - } - - /* - * Delete "normal" A/V pairs when using callback. - * - * FIXME: This is stupid. The portmaster should accept - * these settings instead of insisting on using a - * dialout location. - * - * FIXME2: Move this into the above exec thingy? - * (if you knew how I use the exec_wait, you'd understand). - */ - if (seen_callback_id) { - pairdelete(&request->reply->vps, PW_FRAMED_PROTOCOL); - pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS); - pairdelete(&request->reply->vps, PW_FRAMED_IP_NETMASK); - pairdelete(&request->reply->vps, PW_FRAMED_ROUTE); - pairdelete(&request->reply->vps, PW_FRAMED_MTU); - pairdelete(&request->reply->vps, PW_FRAMED_COMPRESSION); - pairdelete(&request->reply->vps, PW_FILTER_ID); - pairdelete(&request->reply->vps, PW_PORT_LIMIT); - pairdelete(&request->reply->vps, PW_CALLBACK_NUMBER); - } - - /* - * Filter (possibly multiple) Reply-Message attributes - * through radius_xlat, modifying them in place. - */ - if (user_msg == NULL) { - reply_item = pairfind(request->reply->vps, PW_REPLY_MESSAGE); - while (reply_item) { - radius_xlat(buf, sizeof(reply_item->strvalue), - (char *)reply_item->strvalue, request, NULL); - strNcpy((char *)reply_item->strvalue, buf, - sizeof(reply_item->strvalue)); - reply_item->length = strlen((char *)reply_item->strvalue); - user_msg = NULL; - reply_item = pairfind(reply_item->next, PW_REPLY_MESSAGE); + RDEBUG2("WARNING: No NAS-Port attribute in request. CANNOT return a Framed-IP-Address + NAS-Port.\n"); + pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS, 0); } } @@ -966,27 +796,19 @@ autz_redo: if (request->reply->code == 0) request->reply->code = PW_AUTHENTICATION_ACK; - if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE)) != NULL){ + if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE, 0)) != NULL){ char msg[MAX_STRING_LEN+12]; snprintf(msg, sizeof(msg), "Login OK (%s)", - module_msg->strvalue); + module_msg->vp_strvalue); rad_authlog(msg, request, 1); } else { rad_authlog("Login OK", request, 1); } - if (exec_program && !exec_wait) { - /* - * No need to check the exit status here. - */ - radius_exec_program(exec_program, request, exec_wait, - NULL, 0, request->packet->vps, NULL); - } - - if (exec_program) - free(exec_program); - + /* + * Run the modules in the 'post-auth' section. + */ result = rad_postauth(request); return result;