📄 auth.c
字号:
/* * auth.c User authentication. * * Version: $Id: auth.c,v 1.178 2008/04/18 09:29:49 aland Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2006 The FreeRADIUS server project * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl> * Copyright 2000 Jeff Carneal <jeff@apex.net> */#include <freeradius-devel/ident.h>RCSID("$Id: auth.c,v 1.178 2008/04/18 09:29:49 aland Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#include <freeradius-devel/rad_assert.h>#include <ctype.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){ VALUE_PAIR *cli; VALUE_PAIR *pair; int port = 0; if ((cli = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) == NULL) do_cli = 0; if ((pair = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL) port = pair->vp_integer; 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;}/* * Make sure user/pass are clean * and then log them */static int rad_authlog(const char *msg, REQUEST *request, int goodpass) { char clean_password[1024]; char clean_username[1024]; char buf[1024]; VALUE_PAIR *username = NULL; if (!request->root->log_auth) { return 0; } /* * Get the correct username based on the configured value */ if (log_stripped_names == 0) { username = pairfind(request->packet->vps, PW_USER_NAME); } else { username = request->username; } /* * Clean up the username */ if (username == NULL) { strcpy(clean_username, "<no User-Name attribute>"); } else { librad_safeprint((char *)username->vp_strvalue, username->length, clean_username, sizeof(clean_username)); } /* * Clean up the password */ if (request->root->log_auth_badpass || request->root->log_auth_goodpass) { if (!request->password) { VALUE_PAIR *auth_type; auth_type = pairfind(request->config_items, PW_AUTH_TYPE); if (auth_type && (auth_type->vp_strvalue[0] != '\0')) { snprintf(clean_password, sizeof(clean_password), "<via Auth-Type = %s>", auth_type->vp_strvalue); } else { strcpy(clean_password, "<no User-Password attribute>"); } } else if (pairfind(request->packet->vps, PW_CHAP_PASSWORD)) { strcpy(clean_password, "<CHAP-Password>"); } else { librad_safeprint((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, request->root->log_auth_goodpass ? "/" : "", request->root->log_auth_goodpass ? clean_password : "", auth_name(buf, sizeof(buf), request, 1)); } else { radlog(L_AUTH, "%s: [%s%s%s] (%s)", msg, clean_username, request->root->log_auth_badpass ? "/" : "", request->root->log_auth_badpass ? clean_password : "", auth_name(buf, sizeof(buf), request, 1)); } return 0;}/* * Check password. * * Returns: 0 OK * -1 Password fail * -2 Rejected (Auth-Type = Reject, send Port-Message back) * 1 End check & return, don't reply * * NOTE: NOT the same as the RLM_ values ! */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; uint8_t my_chap[MAX_STRING_LEN]; int auth_type = -1; int result; int auth_type_count = 0; result = 0; /* * Look for matching check items. We skip the whole lot * if the authentication type is PW_AUTHTYPE_ACCEPT or * 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->vp_integer; auth_type_count++; DEBUG2(" rad_check_password: Found Auth-Type %s", auth_type_pair->vp_strvalue); cur_config_item = auth_type_pair->next; if (auth_type == PW_AUTHTYPE_REJECT) { DEBUG2(" rad_check_password: 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->vp_strvalue); } /* * This means we have a proxy reply or an accept * and it wasn't rejected in the above loop. So * 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"); return 0; } password_pair = pairfind(request->config_items, PW_USER_PASSWORD); if (password_pair && pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) { pairdelete(&request->config_items, PW_USER_PASSWORD); password_pair = NULL; } if (password_pair) { DICT_ATTR *da; DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); DEBUG("!!! Replacing User-Password in config items with Cleartext-Password. !!!"); DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); DEBUG("!!! Please update your configuration so that the \"known good\" !!!"); DEBUG("!!! clear text password is in Cleartext-Password, and not in User-Password. !!!"); DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); password_pair->attribute = PW_CLEARTEXT_PASSWORD; da = dict_attrbyvalue(PW_CLEARTEXT_PASSWORD); if (!da) { radlog(L_ERR, "FATAL: You broke the dictionaries. Please use the default dictionaries!"); _exit(1); } password_pair->name = da->name; } /* * 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) { /* * 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_CLEARTEXT_PASSWORD); } if (auth_type < 0) { if (password_pair) { auth_type = PW_AUTHTYPE_LOCAL; } else { /* * The admin hasn't told us how to * authenticate the user, so we reject them! * * This is fail-safe. */ DEBUG2("auth: No authenticate method (Auth-Type) configuration found for the request: Rejecting the user"); return -2; } } switch(auth_type) { DICT_VALUE *dval; case PW_AUTHTYPE_CRYPT: /* * Find the password sent by the user. It * SHOULD be there, if it's not * authentication fails. */ auth_item = request->password; if (auth_item == NULL) { DEBUG2("auth: 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"); rad_authlog("Login incorrect " "(No Crypt-Password configured for the user)", request, 0); return -1; } 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); case 1: return -1; } break; case PW_AUTHTYPE_LOCAL: DEBUG2("auth: type Local"); /* * Find the password sent by the user. It * SHOULD be there, if it's not * authentication fails. */ auth_item = request->password; if (!auth_item) auth_item = pairfind(request->packet->vps, PW_CHAP_PASSWORD); if (!auth_item) { DEBUG2("auth: No User-Password or CHAP-Password attribute in the request"); return -1; } /* * Plain text password. */ if (password_pair == NULL) { DEBUG2("auth: No password configured for the user"); rad_authlog("Login incorrect " "(No password configured for the user)", request, 0); return -1; } /* * Local password is just plain text. */ if (auth_item->attribute == PW_USER_PASSWORD) { if (strcmp((char *)password_pair->vp_strvalue, (char *)auth_item->vp_strvalue) != 0) { DEBUG2("auth: user supplied User-Password does NOT match local User-Password"); return -1; } DEBUG2("auth: user supplied User-Password matches local User-Password"); break; } else if (auth_item->attribute != PW_CHAP_PASSWORD) { DEBUG2("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, my_chap, auth_item->vp_octets[0], password_pair); /* * Compare them */ 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"); return -1; } DEBUG2("auth: user supplied CHAP-Password matches local User-Password"); break; default: dval = dict_valbyattr(PW_AUTH_TYPE, auth_type); if (dval) { DEBUG2("auth: type \"%s\"", dval->name); } else { DEBUG2("auth: type UNKNOWN-%d", auth_type); } /* * See if there is a module that handles * this type, and turn the RLM_ return * status into the values as defined at * the top of this function. */ result = module_authenticate(auth_type, request); switch (result) { /* * An authentication module FAIL * return code, or any return code that * is not expected from authentication, * is the same as an explicit REJECT! */ case RLM_MODULE_FAIL: case RLM_MODULE_INVALID: 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: result = 0; break; case RLM_MODULE_HANDLED: result = 1; break; } break; } return result;}/* * Post-authentication step processes the response before it is * sent to the NAS. It can receive both Access-Accept and Access-Reject * replies. */int rad_postauth(REQUEST *request){ int result; int postauth_type = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -