Add more NULL's to module data structures, in preparation for
[freeradius.git] / src / modules / rlm_chap / rlm_chap.c
1 /*
2  * rlm_chap.c
3  *
4  * Version:  $Id$
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 2001  The FreeRADIUS server project
21  * Copyright 2001  Kostas Kalevras <kkalev@noc.ntua.gr>
22  *
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
26  */
27
28 #include "autoconf.h"
29 #include "libradius.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "radiusd.h"
36 #include "modules.h"
37 #include "conffile.h"
38
39 static const char rcsid[] = "$Id$";
40
41 static int chap_authorize(void *instance, REQUEST *request)
42 {
43         
44         /* quiet the compiler */
45         instance = instance;
46         request = request;
47
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;
51         }
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));
55         }
56
57         return RLM_MODULE_OK;
58 }
59         
60
61 /*
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.
66  */
67 static int chap_authenticate(void *instance, REQUEST *request)
68 {
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];
73
74         /* quiet the compiler */
75         instance = instance;
76         request = request;
77
78         if(!request->username){
79                 radlog(L_AUTH, "rlm_chap: Attribute \"User-Name\" is required for authentication.\n");
80                 return RLM_MODULE_INVALID;
81         }
82
83         if (!request->password){
84                 radlog(L_AUTH, "rlm_chap: Attribute \"CHAP-Password\" is required for authentication.");
85                 return RLM_MODULE_INVALID;
86         }
87
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;
91         }
92
93         if (request->password->length == 0) {
94                 radlog(L_ERR, "rlm_chap: empty password supplied");
95                 return RLM_MODULE_INVALID;
96         }
97
98         DEBUG("rlm_chap: login attempt by \"%s\" with CHAP password %s", 
99                 request->username->strvalue, request->password->strvalue);
100
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;
107         }
108
109         DEBUG("rlm_chap: Using clear text password %s for user %s authentication.",
110               passwd_item->strvalue, request->username->strvalue);
111         
112         rad_chap_encode(request->packet,pass_str,request->password->strvalue[0],passwd_item);
113         
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;
120         }
121
122         DEBUG("rlm_chap: chap user %s authenticated succesfully",request->username->strvalue);
123
124         return RLM_MODULE_OK;
125 }
126
127 /*
128  *      The module name should be the only globally exported symbol.
129  *      That is, everything else should be 'static'.
130  *
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.
135  */
136 module_t rlm_chap = {
137         "CHAP", 
138         0,                              /* type */
139         NULL,                           /* initialization */
140         NULL,                           /* instantiation */
141         {
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 */
149                 NULL                    /* post-auth */
150         },
151         NULL,                           /* detach */
152         NULL,                           /* destroy */
153 };