📄 authenticate.c
字号:
/* * Copyright [C] The Regents of the University of Michigan and Merit Network, * Inc. 1992, 1993, 1994, 1995, 1996, 1997, 1998 All Rights Reserved * * Permission to use, copy, and modify this software and its documentation * for any purpose and without fee is hereby granted, provided: * * 1) that the above copyright notice and this permission notice appear in all * copies of the software and derivative works or modified versions thereof, * * 2) that both the copyright notice and this permission and disclaimer notice * appear in all supporting documentation, and * * 3) that all derivative works made from this material are returned to the * Regents of the University of Michigan and Merit Network, Inc. with * permission to copy, to display, to distribute, and to make derivative * works from the provided material in whole or in part for any purpose. * * Users of this code are requested to notify Merit Network, Inc. of such use * by sending email to aaa-admin@merit.edu * * Please also use aaa-admin@merit.edu to inform Merit Network, Inc of any * derivative works. * * Distribution of this software or derivative works or the associated * documentation is not allowed without an additional license. * * Licenses for other uses are available on an individually negotiated * basis. Contact aaa-license@merit.edu for more information. * * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE * UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the * University of Michigan and Merit Network, Inc. shall not be liable for any * special, indirect, incidental or consequential damages with respect to any * claim by Licensee or any third party arising from use of the software. * * Merit AAA Server Support * Merit Network, Inc. * 4251 Plymouth Road, Suite C. * Ann Arbor, Michigan, USA 48105-2785 * * attn: John Vollbrecht * voice: 734-764-9430 * fax: 734-647-3185 * email: aaa-admin@merit.edu * *//* * * Public entry points in this file: * * check_request * get_deny_message * */static char rcsid[] = "$Id: authenticate.c,v 1.1.1.1 2001/08/10 20:49:27 bonze Exp $";#include <sys/types.h>#include <sys/param.h>#ifdef sys5#include <sys/sysmacros.h>#endif /* sys5 */#ifdef OSF#include <sys/security.h>#include <prot.h>#endif /* OSF */#ifdef SIA#include <sia.h>#include <siad.h>#endif /* SIA */#include <sys/socket.h>#include <sys/time.h>#include <sys/file.h>#include <sys/wait.h>#include <net/if.h>#include <netinet/in.h>#include <stdio.h>#include <netdb.h>#include <errno.h>#include <signal.h>#include <memory.h>#include <syslog.h>#ifndef NOSHADOW#include <shadow.h>#endif /* NOSHADOW */#ifdef __hpuxtrust#include <hpsecurity.h>#endif /* __hpuxtrust */#define _XOPEN_SOURCE#include <unistd.h>#include "radius.h"extern char ourhostname[MAXHOSTNAMELEN];extern char default_radius_server[];extern int debug_flag;extern int token_caching_auth_type[];extern AATV *authtype_tv[];/************************************************************************* * * Function: check_request * * Purpose: Process check and deny items on a request. * * Returns: EV_ACK, EV_NAK, etc. * *************************************************************************/intcheck_request (authreq, list, sws)AUTH_REQ *authreq;VALUE_PAIR *list; /* Check against this list (if present) */int sws; /* 0 == do accept check, 1 == do deny check */{ int result = EV_ACK; /* Assume success. */ VALUE_PAIR *each; VALUE_PAIR *vp; char *why = (char *) NULL; char buffer[MAXPATHLEN]; /* For optional denial msg. */ static char *func = "check_request"; dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func)); if (authreq == (AUTH_REQ *) NULL) { logit (LOG_DAEMON, LOG_ERR, "%s: NULL authreq!", func); return EV_NAK; } /* If no list, find one. */ if (list == NULL_VP) { if ((sws & CHK_DENY) == CHK_DENY) { list = authreq->user_deny; } else { list = authreq->user_check; } } /* Short circut test. */ if (list == NULL_VP) { return EV_ACK; /* Nothing to check or deny, let it through */ } /* Check each check item in the list... */ for (each = list; (each != NULL_VP) && (result == EV_ACK); each = each->next) { /* Ignore (config) items. */ if ((each->ap->flags & ATTR_CONFIG) == ATTR_CONFIG) { continue; } /* * Just look for the matching attribute in the request. */ if ((vp = get_vp_vend (authreq->cur_request, each->attribute, each->ap->vendor_id)) != NULL_VP) { switch (each->ap->type) { case PW_TYPE_OCTETS: case PW_TYPE_TAG_STR: case PW_TYPE_STRING: if ((vp->lvalue == each->lvalue) && (memcmp (each->strvalue, vp->strvalue, each->lvalue) == 0)) { if ((sws & CHK_DENY) == CHK_DENY) { result = EV_NAK; why = buffer; sprintf (why, "Access not allowed, %s=%s", vp->ap->name, avpair_vtoa (vp, 0)); } } else { if ((sws & CHK_DENY) == 0) { result = EV_NAK; why = buffer; sprintf (why, "Access not allowed, %s=%s", vp->ap->name, avpair_vtoa (vp, 0)); } } break; case PW_TYPE_IPADDR: if ((each->strvalue != NULL) && (*each->strvalue != '\0')) { /* Resolve all DNS names */ if (find_host_by_name (&each->lvalue, each->strvalue) == 1) { why = buffer; sprintf (why, "Access temporarily not allowed, %s=%s", each->ap->name, each->strvalue); if ((sws & CHK_DENY) == CHK_DENY) { result = EV_NAK; } else { logit (LOG_AUTH, LOG_WARNING, "%s: request ignored - unresolved host '%s' in check item", func, each->strvalue); result = EV_ABORT; } break; /* switch() statement */ } } /***FALLTHROUGH****/ case PW_TYPE_SHORT: case PW_TYPE_OCTET: case PW_TYPE_TAG_INT: case PW_TYPE_INTEGER: if (each->lvalue == vp->lvalue) { if ((sws & CHK_DENY) == CHK_DENY) { result = EV_NAK; why = buffer; sprintf (why, "Access not allowed, %s=%s", vp->ap->name, avpair_vtoa (vp, 0)); } } else { if ((sws & CHK_DENY) == 0) { result = EV_NAK; why = buffer; sprintf (why, "Access not allowed, %s=%s", vp->ap->name, avpair_vtoa (vp, 0)); } } break; default: why = buffer; sprintf (why, "Configuration error, access not allowed, %s=%s", vp->ap->name, avpair_vtoa (vp, 0)); logit (LOG_DAEMON, LOG_ERR, "%s: Configuration error, %s bad type %d", func, each->ap->name, each->ap->type); result = EV_NAK; break; } } /* If a check item is not present, deny the request. */ else { if ((sws & CHK_DENY) == 0) { result = EV_NAK; why = buffer; sprintf (why, "Access not allowed, no %s", each->ap->name); } } /* If we are to check only one, do only one. */ if ((sws & CHK_ONCE) == CHK_ONCE) { break; } } /* end of "Check each check-item" */ /* * Explain why denial occured, allowing explanation to be configured. */ if ((result != EV_ACK) && (sws & CHK_MESSAGE) == CHK_MESSAGE) { reply_sprintf (0, authreq, get_deny_message (authreq, list, why)); } return result;} /* end of check_request () */static int chk_pass PROTO((AUTH_REQ *, int, char *));static AATV realm_aatv = DEF_AATV_DIRECT_TYPE("REALM", AA_REALM, chk_pass);AATVPTR rad_realm_aatv = & realm_aatv;/************************************************************************* * * Function: chk_pass * * Purpose: Check the users password against any server * *************************************************************************/static intchk_pass (authreq, value, af_param)AUTH_REQ *authreq;int value;char *af_param;{ int authprot; int type; VALUE_PAIR *vp; char *agent; char *realm; char *filter; char user_realm[AUTH_ID_LEN + 1]; static char *func = "chk_pass"; dprintf(1, (LOG_AUTH, LOG_DEBUG, "%s: entered", func)); if (get_vp (authreq->cur_request, PW_CHAP_PASSWORD)) { authprot = PW_PROTTYPE_CHAP; } else { authprot = PW_PROTTYPE_PW; } if ((vp = parse_realm (authreq)) == NULL_VP) { reply_sprintf (0, authreq, "Improper 'userid@realm' specification"); return EV_NAK; } strcpy (user_realm, vp->strvalue); if ((vp = get_vp_vend (authreq->cur_request, PW_USER_ID, VC_MERIT)) != NULL_VP) { if (strchr (vp->strvalue, '.') != (char *) NULL) { authprot = PW_PROTTYPE_HASDOT; } } if (user_realm[0] == '\0') /* user_realm is never NULL */ { if (find_auth_type ("", authprot, (char *) authreq->client->file_pfx, &type, &agent, &realm, &filter) != 0) { reply_sprintf (0, authreq, "Improper 'userid@realm' specification"); return EV_NAK; } } else /* Check for protected keyword realm value */ { if (strcasecmp (user_realm, DEFAULT_REALM) == 0 || strcasecmp (user_realm, NULL_REALM) == 0) { reply_sprintf (0, authreq, "Invalid authentication realm: '%s'", user_realm); return EV_NAK; } /* Try to match realm name in AUTHFILE */ if (find_auth_type (user_realm, authprot, (char *) authreq->client->file_pfx, &type, &agent, &realm, &filter) != 0) { /* If no match, try for DEFAULT entry */ if (find_auth_type (DEFAULT_REALM, authprot, (char *) authreq->client->file_pfx, &type, &agent, &realm, &filter) != 0) { /* No DEFAULT configured so give up */ reply_sprintf (0, authreq, "Invalid authentication realm: '%s'", user_realm); return EV_NAK; } } } authreq->realm_filter = filter; if (type == AA_REALM) /* Watch for misconfiguration */ { /* Can't have REALM auth type in authfile! */ logit (LOG_AUTH, LOG_ERR, "%s: Invalid Type '%d' in authfile", func, type); return EV_NAK; }#ifdef USR_CCA if (type == AA_LOCAL_VPN) { /* This is an error since all users belonging to a Local VPN must be defined in the local users file, and so this function must not be called in the first place */ vp = get_vp (authreq->cur_request, PW_USER_NAME); logit (LOG_AUTH, LOG_ERR, "%s: User %s of realm %s not defined", func, vp->strvalue, user_realm); return EV_NAK; }#endif /* USR_CCA */ return call_action (authtype_tv[type], authreq, 0, agent);} /* end of chk_pass () *//************************************************************************* * * Function: get_deny_message * * Purpose: Get the configured denial message, or a canned message. * *************************************************************************/char *get_deny_message (authreq, list, why)AUTH_REQ *authreq;VALUE_PAIR *list; /* Suggested list to try. */char *why; /* Suggested message, if CI_DENY_MESSAGE is "*" */{ VALUE_PAIR *vp; char *reason = "Access not allowed"; static char *func = "get_deny_message"; dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func)); /* * Find the deny message, first in the list... * then in the authreq somewhere... */ if ((vp = get_vp_ci (list, CI_DENY_MESSAGE, 0)) == NULL_VP) { if (authreq != (AUTH_REQ *) NULL) { if ((vp = get_vp_ci (authreq->user_check, CI_DENY_MESSAGE, 0)) == NULL_VP) { vp = get_vp_ci (authreq->user_deny, CI_DENY_MESSAGE, 0); } } } if (vp != NULL_VP) { reason = vp->strvalue; } /* * Special case: deny-message = "*" * * Allows message "access not allowed, xxx = value" */ if (strcmp (reason, "*") == 0) { if (why != (char *) NULL) { reason = why; } else { reason = "Access not allowed"; } } return reason;} /* end of get_deny_message () */static int rad_authenticate PROTO((AUTH_REQ *, int, char *));static AATV authen_aatv = DEF_AATV_DIRECT("AUTHENTICATE", rad_authenticate);AATVPTR rad_authen_aatv = & authen_aatv;/************************************************************************* * * Function: rad_authenticate * * Purpose: Process and reply to an authentication request * *************************************************************************/static intrad_authenticate (authreq, value, realm)AUTH_REQ *authreq;int value;char *realm;{#ifdef MERIT_LAS int cache_token;#endif /* MERIT_LAS */ int found_pw = 0; int i; int protocol; int result; int retval; VALUE_PAIR *auth_item; VALUE_PAIR *check_item; VALUE_PAIR *namepair; VALUE_PAIR *protpair; VALUE_PAIR *user_reply; VALUE_PAIR **prev_ptr; char *server_name = ""; char pwmsg[AUTH_PASS_LEN + 1];#ifdef USR_CCA /**** char res_assigned = FALSE; UINT4 nas = 0; UINT4 framed_ip = 0; UINT4 nas_port = 0; VALUE_PAIR *framed_ip_vp; VALUE_PAIR *nas_port_vp; VALUE_PAIR *nas_vp; ****/ VALUE_PAIR *term_act;#endif /* USR_CCA */ char *func = "rad_authenticate"; authreq->startlas = time (0); /* record time starting authentication */ dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func)); /* Get the username from the request */ if (((namepair = get_vp (authreq->cur_request, PW_USER_NAME)) == NULL_VP) || (strlen (namepair->strvalue) <= 0)) { logit (LOG_AUTH, LOG_ERR, "%s: from %s - No User Name", func, ip_hostname (authreq->ipaddr)); return EV_NAK; } protpair = get_vp (authreq->cur_request, PW_FRAMED_PROTOCOL); protocol = (protpair == NULL_VP) ? 0 : protpair->lvalue; if (authreq->user_check == NULL_VP) { /* Look in the database only if both lists are NULL. */ if ((retval = user_find ((char *) authreq->client->file_pfx, namepair->strvalue, protocol, &authreq->user_check, &authreq->user_deny, &user_reply, 0)) < 0) { logit (LOG_AUTH, LOG_ERR, "%s: from %s - Problem in user_find", func, ip_hostname (authreq->ipaddr)); return EV_NAK; } if (retval > 0) /* If no match, use DEFAULT entry */ { if (user_find ((char *) authreq->client->file_pfx, "DEFAULT", protocol, &authreq->user_check, &authreq->user_deny, &user_reply, 0) != 0) { logit (LOG_AUTH, LOG_ERR, "%s: from %s - Invalid/missing 'DEFAULT' entry", func, ip_hostname (authreq->ipaddr));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -