6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2001 The FreeRADIUS server project
21 * Copyright 2001 Kostas Kalevras <kkalev@noc.ntua.gr>
23 * Nov 03 2001, Kostas Kalevras <kkalev@noc.ntua.gr>
24 * - Added authorize() function to set Auth-Type if Chap-Password exists
25 * - Added module messages when rejecting user
29 #include "libradius.h"
39 static const char rcsid[] = "$Id$";
41 static int chap_authorize(void *instance, REQUEST *request)
44 /* quiet the compiler */
48 if (!request->password || request->password->attribute != PW_CHAP_PASSWORD){
49 DEBUG("rlm_chap: Could not find proper Chap-Password attribute in request");
50 return RLM_MODULE_NOOP;
52 if (pairfind(request->config_items, PW_AUTHTYPE) == NULL){
53 DEBUG("rlm_chap: Adding Auth-Type = CHAP");
54 pairadd(&request->config_items, pairmake("Auth-Type", "CHAP", T_OP_EQ));
62 * Find the named user in this modules database. Create the set
63 * of attribute-value pairs to check and reply with for this user
64 * from the database. The authentication code only needs to check
65 * the password, the rest is done here.
67 static int chap_authenticate(void *instance, REQUEST *request)
69 VALUE_PAIR *passwd_item;
70 char pass_str[MAX_STRING_LEN];
71 VALUE_PAIR *module_fmsg_vp;
72 char module_fmsg[MAX_STRING_LEN];
74 /* quiet the compiler */
78 if(!request->username){
79 radlog(L_AUTH, "rlm_chap: Attribute \"User-Name\" is required for authentication.\n");
80 return RLM_MODULE_INVALID;
83 if (!request->password){
84 radlog(L_AUTH, "rlm_chap: Attribute \"CHAP-Password\" is required for authentication.");
85 return RLM_MODULE_INVALID;
88 if (request->password->attribute != PW_CHAP_PASSWORD) {
89 radlog(L_AUTH, "rlm_chap: Attribute \"CHAP-Password\" is required for authentication. Cannot use \"%s\".", request->password->name);
90 return RLM_MODULE_INVALID;
93 if (request->password->length == 0) {
94 radlog(L_ERR, "rlm_chap: empty password supplied");
95 return RLM_MODULE_INVALID;
98 DEBUG("rlm_chap: login attempt by \"%s\" with CHAP password %s",
99 request->username->strvalue, request->password->strvalue);
101 if ((passwd_item = pairfind(request->config_items, PW_PASSWORD)) == NULL){
102 DEBUG("rlm_chap: Could not find clear text password for user %s",request->username->strvalue);
103 snprintf(module_fmsg,sizeof(module_fmsg),"rlm_chap: Clear text password not available");
104 module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);
105 pairadd(&request->packet->vps, module_fmsg_vp);
106 return RLM_MODULE_INVALID;
109 DEBUG("rlm_chap: Using clear text password %s for user %s authentication.",
110 passwd_item->strvalue, request->username->strvalue);
112 rad_chap_encode(request->packet,pass_str,request->password->strvalue[0],passwd_item);
114 if (memcmp(pass_str+1,request->password->strvalue+1,CHAP_VALUE_LENGTH) != 0){
115 DEBUG("rlm_chap: Pasword check failed");
116 snprintf(module_fmsg,sizeof(module_fmsg),"rlm_chap: Wrong user password");
117 module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);
118 pairadd(&request->packet->vps, module_fmsg_vp);
119 return RLM_MODULE_REJECT;
122 DEBUG("rlm_chap: chap user %s authenticated succesfully",request->username->strvalue);
124 return RLM_MODULE_OK;
128 * The module name should be the only globally exported symbol.
129 * That is, everything else should be 'static'.
131 * If the module needs to temporarily modify it's instantiation
132 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
133 * The server will then take care of ensuring that the module
134 * is single-threaded.
136 module_t rlm_chap = {
139 NULL, /* initialization */
140 NULL, /* instantiation */
142 chap_authenticate, /* authentication */
143 chap_authorize, /* authorization */
144 NULL, /* preaccounting */
145 NULL, /* accounting */
146 NULL, /* checksimul */
147 NULL, /* pre-proxy */
148 NULL, /* post-proxy */