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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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
28 #include <freeradius-devel/autoconf.h>
34 #include <freeradius-devel/radiusd.h>
35 #include <freeradius-devel/modules.h>
37 static const char rcsid[] = "$Id$";
39 static int chap_authorize(void *instance, REQUEST *request)
42 /* quiet the compiler */
46 if (!request->password ||
47 request->password->attribute != PW_CHAP_PASSWORD) {
48 return RLM_MODULE_NOOP;
51 if (pairfind(request->config_items, PW_AUTHTYPE) != NULL) {
52 DEBUG2(" rlm_chap: WARNING: Auth-Type already set. Not setting to CHAP");
53 return RLM_MODULE_NOOP;
56 DEBUG(" rlm_chap: Setting 'Auth-Type := CHAP'");
57 pairadd(&request->config_items,
58 pairmake("Auth-Type", "CHAP", T_OP_EQ));
64 * Find the named user in this modules database. Create the set
65 * of attribute-value pairs to check and reply with for this user
66 * from the database. The authentication code only needs to check
67 * the password, the rest is done here.
69 static int chap_authenticate(void *instance, REQUEST *request)
71 VALUE_PAIR *passwd_item;
72 uint8_t pass_str[MAX_STRING_LEN];
73 VALUE_PAIR *module_fmsg_vp;
74 char module_fmsg[MAX_STRING_LEN];
76 /* quiet the compiler */
80 if (!request->username) {
81 radlog(L_AUTH, "rlm_chap: Attribute \"User-Name\" is required for authentication.\n");
82 return RLM_MODULE_INVALID;
85 if (!request->password) {
86 radlog(L_AUTH, "rlm_chap: Attribute \"CHAP-Password\" is required for authentication.");
87 return RLM_MODULE_INVALID;
90 if (request->password->attribute != PW_CHAP_PASSWORD) {
91 radlog(L_AUTH, "rlm_chap: Attribute \"CHAP-Password\" is required for authentication. Cannot use \"%s\".", request->password->name);
92 return RLM_MODULE_INVALID;
95 if (request->password->length == 0) {
96 radlog(L_ERR, "rlm_chap: empty password supplied");
97 return RLM_MODULE_INVALID;
100 if (request->password->length != CHAP_VALUE_LENGTH + 1) {
101 radlog(L_ERR, "rlm_chap: password supplied has wrong length");
102 return RLM_MODULE_INVALID;
106 * Don't print out the CHAP password here. It's binary crap.
108 DEBUG(" rlm_chap: login attempt by \"%s\" with CHAP password",
109 request->username->vp_strvalue);
111 if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) == NULL){
112 DEBUG(" rlm_chap: Cleartext-Password is required for authentication");
113 snprintf(module_fmsg, sizeof(module_fmsg),
114 "rlm_chap: Clear text password not available");
115 module_fmsg_vp = pairmake("Module-Failure-Message",
116 module_fmsg, T_OP_EQ);
117 pairadd(&request->packet->vps, module_fmsg_vp);
118 return RLM_MODULE_INVALID;
121 DEBUG(" rlm_chap: Using clear text password %s for user %s authentication.",
122 passwd_item->vp_strvalue, request->username->vp_strvalue);
124 rad_chap_encode(request->packet,pass_str,
125 request->password->vp_octets[0],passwd_item);
127 if (memcmp(pass_str + 1, request->password->vp_octets + 1,
128 CHAP_VALUE_LENGTH) != 0){
129 DEBUG(" rlm_chap: Pasword check failed");
130 snprintf(module_fmsg, sizeof(module_fmsg),
131 "rlm_chap: Wrong user password");
132 module_fmsg_vp = pairmake("Module-Failure-Message",
133 module_fmsg, T_OP_EQ);
134 pairadd(&request->packet->vps, module_fmsg_vp);
135 return RLM_MODULE_REJECT;
138 DEBUG(" rlm_chap: chap user %s authenticated succesfully",
139 request->username->vp_strvalue);
141 return RLM_MODULE_OK;
145 * The module name should be the only globally exported symbol.
146 * That is, everything else should be 'static'.
148 * If the module needs to temporarily modify it's instantiation
149 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
150 * The server will then take care of ensuring that the module
151 * is single-threaded.
153 module_t rlm_chap = {
157 NULL, /* instantiation */
160 chap_authenticate, /* authentication */
161 chap_authorize, /* authorization */
162 NULL, /* preaccounting */
163 NULL, /* accounting */
164 NULL, /* checksimul */
165 NULL, /* pre-proxy */
166 NULL, /* post-proxy */