/[radius]/radius/radiusd/radius.c
ViewVC logotype

Diff of /radius/radiusd/radius.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.41 by gray, Fri Dec 20 15:33:33 2002 UTC revision 1.42 by gray, Fri Apr 18 05:27:10 2003 UTC
# Line 1  Line 1 
1  /* This file is part of GNU RADIUS.  /* This file is part of GNU Radius.
2     Copyright (C) 2000, Sergey Poznyakoff     Copyright (C) 2000, 2002, 2003, Sergey Poznyakoff
3        
4     This program is free software; you can redistribute it and/or modify     GNU Radius is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.     (at your option) any later version.
8        
9     This program is distributed in the hope that it will be useful,     GNU Radius is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.     GNU General Public License for more details.
13        
14     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software Foundation,     along with GNU Radius; if not, write to the Free Software Foundation,
16     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17    
18  #define RADIUS_MODULE_RADIUS_C  #define RADIUS_MODULE_RADIUS_C
# Line 37  static char rcsid[] = Line 37  static char rcsid[] =
37            is used instead of the supplied arguments. */            is used instead of the supplied arguments. */
38    
39  void  void
40  rad_send_reply(code, radreq, reply_pairs, msg, fd)  radius_send_reply(int code, RADIUS_REQ *radreq,
41          int code;                    VALUE_PAIR *reply_pairs, char *msg, int fd)
         RADIUS_REQ *radreq;  
         VALUE_PAIR *reply_pairs;  
         char *msg;  
         int fd;  
42  {  {
43          if (radreq->reply_code == 0) {          if (radreq->reply_code == 0) {
44                  VALUE_PAIR *reply;                  VALUE_PAIR *reply;
# Line 81  rad_send_reply(code, radreq, reply_pairs Line 77  rad_send_reply(code, radreq, reply_pairs
77            state       -- Value of the State attribute.            state       -- Value of the State attribute.
78            fd          -- Socket descriptor. */            fd          -- Socket descriptor. */
79  void  void
80  send_challenge(radreq, msg, state, fd)  radius_send_challenge(RADIUS_REQ *radreq, char *msg, char *state, int fd)
         RADIUS_REQ *radreq;  
         char *msg;  
         char *state;  
         int fd;  
81  {  {
82          radreq->reply_pairs = NULL;          radreq->reply_pairs = NULL;
83          avl_move_attr(&radreq->reply_pairs, &radreq->request, DA_PROXY_STATE);          avl_move_attr(&radreq->reply_pairs, &radreq->request, DA_PROXY_STATE);
# Line 95  send_challenge(radreq, msg, state, fd) Line 87  send_challenge(radreq, msg, state, fd)
87  #endif  #endif
88    
89  /* Validates the requesting client NAS. */  /* Validates the requesting client NAS. */
90  int  static int
91  validate_client(radreq)  validate_client(RADIUS_REQ *radreq)
         RADIUS_REQ *radreq;  
92  {  {
93          CLIENT  *cl;          CLIENT  *cl;
94                    
# Line 114  validate_client(radreq) Line 105  validate_client(radreq)
105    
106  /* Validates the requesting NAS */  /* Validates the requesting NAS */
107  int  int
108  calc_acctdigest(radreq)  radius_verify_digest(REQUEST *req)
         RADIUS_REQ *radreq;  
109  {  {
110          int     secretlen;          RADIUS_REQ *radreq = req->data;
111            size_t len = req->rawsize;
112            int  secretlen;
113          char zero[AUTH_VECTOR_LEN];          char zero[AUTH_VECTOR_LEN];
114          u_char  *recvbuf;          u_char  *recvbuf;
         int     len = radreq->data_len;  
115          u_char digest[AUTH_VECTOR_LEN];          u_char digest[AUTH_VECTOR_LEN];
116    
117          secretlen = strlen(radreq->secret);          secretlen = strlen(radreq->secret);
118    
119          recvbuf = emalloc(len + secretlen);          recvbuf = emalloc(len + secretlen);
120          memcpy(recvbuf, radreq->data, len + secretlen);          memcpy(recvbuf, req->rawdata, len + secretlen);
121                    
122          /* Older clients have the authentication vector set to          /* Older clients have the authentication vector set to
123             all zeros. Return `1' in that case. */             all zeros. Return `1' in that case. */
# Line 147  calc_acctdigest(radreq) Line 138  calc_acctdigest(radreq)
138                            REQ_AUTH_BAD : REQ_AUTH_OK;                            REQ_AUTH_BAD : REQ_AUTH_OK;
139  }  }
140    
141    
142    /* *********************** Radius Protocol Support ************************* */
143    
144    int
145    radius_req_decode(struct sockaddr_in *sa,
146                      void *input, size_t inputsize, void **output)
147    {
148            RADIUS_REQ *radreq;
149    
150            radreq = rad_decode_pdu(ntohl(sa->sin_addr.s_addr),
151                                    ntohs(sa->sin_port),
152                                    input,
153                                    inputsize);
154            if (!radreq)
155                    return 1;
156            *output = radreq;
157            return 0;
158    }
159    
160    static VALUE_PAIR *
161    _extract_pairs(RADIUS_REQ *req, int prop)
162    {
163            static int attrlist[] = { DA_USER_PASSWORD, DA_CHAP_PASSWORD };
164            int i;
165            VALUE_PAIR *newlist = NULL;
166            VALUE_PAIR *pair;
167            char password[AUTH_STRING_LEN+1];
168    
169            for (pair = req->request; pair; pair = pair->next)
170                    for (i = 0; i < NITEMS(attrlist); i++) {
171                            if (pair->attribute == attrlist[i]
172                                && (pair->prop & prop))
173                                    break;
174                    }
175    
176            if (!pair)
177                    return NULL;
178    
179            newlist = avl_dup(req->request);
180            for (pair = newlist; pair; pair = pair->next)
181                    for (i = 0; i < NITEMS(attrlist); i++) {
182                            if (pair->attribute == attrlist[i]
183                                && (pair->prop & prop)) {
184                                    req_decrypt_password(password, req, pair);
185                                    string_free(pair->avp_strvalue);
186                                    pair->avp_strvalue = string_create(password);
187                                    pair->avp_strlength = strlen(pair->avp_strvalue);
188                            }
189                    }
190            return newlist;
191    }
192    
193    int
194    radius_req_cmp(void *adata, void *bdata)
195    {
196            RADIUS_REQ *a = adata;
197            RADIUS_REQ *b = bdata;
198            int prop = 0;
199            VALUE_PAIR *alist = NULL, *blist = NULL, *ap, *bp;
200            int rc;
201            NAS *nas;
202            
203            if (a->ipaddr != b->ipaddr || a->code != b->code)
204                    return 1;
205            
206            if (a->id == b->id
207                && memcmp(a->vector, b->vector, sizeof(a->vector)) == 0)
208                    return 0;
209    
210            if (nas = nas_request_to_nas(a))
211                    prop = envar_lookup_int(nas->args, "compare-atribute-flag", 0);
212    
213            if (!prop) {
214                    switch (a->code) {
215                    case RT_AUTHENTICATION_REQUEST:
216                    case RT_AUTHENTICATION_ACK:
217                    case RT_AUTHENTICATION_REJECT:
218                    case RT_ACCESS_CHALLENGE:
219                            prop = auth_comp_flag;
220                            break;
221                            
222                    case RT_ACCOUNTING_REQUEST:
223                    case RT_ACCOUNTING_RESPONSE:
224                    case RT_ACCOUNTING_STATUS:
225                    case RT_ACCOUNTING_MESSAGE:
226                            prop = acct_comp_flag;
227                            break;
228                    }
229            }
230    
231            if (prop == 0)
232                    return 1;
233    
234            prop |= AP_REQ_CMP;
235            alist = _extract_pairs(a, prop);
236            blist = _extract_pairs(b, prop);
237    
238            ap = alist ? alist : a->request;
239            bp = blist ? blist : b->request;
240            
241            rc = avl_cmp(ap, bp, prop) || avl_cmp(bp, ap, prop);
242    
243            avl_free(alist);
244            avl_free(blist);
245            return rc;
246    }
247    
248    void
249    radius_req_free(void *req)
250    {
251            debug(1,("enter: %p",req));
252            radreq_free((RADIUS_REQ *)req);
253            debug(1,("exit"));
254    }
255    
256    /*ARGSUSED*/
257    void
258    radius_req_drop(int type, void *data, void *orig_data,
259                    int fd, char *status_str)
260    {
261            RADIUS_REQ *radreq = data ? data : orig_data;
262            RADIUS_REQ *origreq = orig_data;
263            char buf[MAX_LONGNAME];
264    
265            radlog_req(L_NOTICE, radreq,
266                       "%s: %s", _("Dropping packet"),  status_str);
267    
268            switch (type) {
269            case R_AUTH:
270                    stat_inc(auth, radreq->ipaddr, num_dropped);
271                    break;
272            case R_ACCT:
273                    stat_inc(acct, radreq->ipaddr, num_dropped);
274            }
275    }
276    
277    void
278    radius_req_xmit(REQUEST *request)
279    {
280            RADIUS_REQ *req = request->data;
281    
282            if (request->code == 0) {
283                    radius_send_reply(0, req, NULL, NULL, request->fd);
284                    radlog_req(L_NOTICE, req, _("Retransmitting %s reply"),
285                               request_class[request->type].name);
286            } else {
287                    radius_req_drop(request->type, NULL, req, request->fd,
288                                    _("request failed"));
289            }
290    }
291    
292    int
293    radius_req_failure(int type, struct sockaddr_in *addr)
294    {
295            /*FIXME: should do:
296              stat_inc(acct or auth, ntohl(addr->sin_addr.s_addr), num_bad_req);*/
297            return 0;
298    }
299    
300    int
301    radius_respond(REQUEST *req)
302    {
303            int rc;
304            RADIUS_REQ *radreq = req->data;
305            
306            if (suspend_flag)
307                    return 1;
308            
309            if (validate_client(radreq)) {
310                    /*FIXME: update stats */
311                    return -1;
312            }
313    
314            /* Check if we support this request */
315            switch (radreq->code) {
316            case RT_AUTHENTICATION_REQUEST:
317                    stat_inc(auth, radreq->ipaddr, num_access_req);
318                    if (rad_auth_init(radreq, req->fd) < 0)
319                            return 1;
320                    /*FALLTHRU*/            
321            case RT_ACCOUNTING_REQUEST:
322                    if (avl_find(radreq->request, DA_USER_NAME) == NULL)
323                            break;
324                    if (proxy_send(radreq, req->fd) != 0) {
325                            req->type = R_PROXY;
326                            return 0;
327                    }
328                    break;
329                    
330            case RT_AUTHENTICATION_ACK:
331            case RT_AUTHENTICATION_REJECT:
332            case RT_ACCOUNTING_RESPONSE:
333            case RT_ACCESS_CHALLENGE:
334                    if (proxy_receive(radreq, req->fd) < 0) {
335                            return 1;
336                    }
337                    break;
338            }
339    
340            switch (radreq->code) {
341            case RT_AUTHENTICATION_REQUEST:
342                    rad_authenticate(radreq, req->fd);
343                    break;
344                    
345            case RT_ACCOUNTING_REQUEST:
346                    /* Check the request authenticator. */
347                    rc = radius_verify_digest(req);
348                    if (rc == REQ_AUTH_BAD)
349                            stat_inc(acct, radreq->ipaddr, num_bad_sign);
350                    rad_accounting(radreq, req->fd, rc);
351                    break;
352                    
353            default:
354                    stat_inc(acct, radreq->ipaddr, num_unknowntypes);
355                    radlog_req(L_NOTICE, radreq, _("unknown request code %d"),
356                               radreq->code);
357                    return -1;
358            }      
359            return 0;
360    }

Legend:
Removed from v.1.41  
changed lines
  Added in v.1.42

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26