1/***********************************************************************
2*
3* radius.c
4*
5* RADIUS plugin for pppd.  Performs PAP, CHAP, MS-CHAP, MS-CHAPv2
6* authentication using RADIUS.
7*
8* Copyright (C) 2002 Roaring Penguin Software Inc.
9*
10* Based on a patch for ipppd, which is:
11*    Copyright (C) 1996, Matjaz Godec <gody@elgo.si>
12*    Copyright (C) 1996, Lars Fenneberg <in5y050@public.uni-hamburg.de>
13*    Copyright (C) 1997, Miguel A.L. Paraz <map@iphil.net>
14*
15* Uses radiusclient library, which is:
16*    Copyright (C) 1995,1996,1997,1998 Lars Fenneberg <lf@elemental.net>
17*    Copyright (C) 2002 Roaring Penguin Software Inc.
18*
19* MPPE support is by Ralf Hofmann, <ralf.hofmann@elvido.net>, with
20* modification from Frank Cusack, <frank@google.com>.
21*
22* This plugin may be distributed according to the terms of the GNU
23* General Public License, version 2 or (at your option) any later version.
24*
25***********************************************************************/
26static char const RCSID[] =
27"$Id: radius.c,v 1.32 2008/05/26 09:18:08 paulus Exp $";
28
29#include "pppd.h"
30#include "chap-new.h"
31#ifdef CHAPMS
32#include "chap_ms.h"
33#ifdef MPPE
34#include "md5.h"
35#endif
36#endif
37#include "radiusclient.h"
38#include "fsm.h"
39#include "ipcp.h"
40#include <syslog.h>
41#include <sys/types.h>
42#include <sys/time.h>
43#include <string.h>
44#include <netinet/in.h>
45#include <stdlib.h>
46
47#define BUF_LEN 1024
48
49#define MD5_HASH_SIZE	16
50
51#define MSDNS 1
52
53static char *config_file = NULL;
54static int add_avp(char **);
55static struct avpopt {
56    char *vpstr;
57    struct avpopt *next;
58} *avpopt = NULL;
59static bool portnummap = 0;
60
61static option_t Options[] = {
62    { "radius-config-file", o_string, &config_file },
63    { "avpair", o_special, add_avp },
64    { "map-to-ttyname", o_bool, &portnummap,
65	"Set Radius NAS-Port attribute value via libradiusclient library", OPT_PRIO | 1 },
66    { "map-to-ifname", o_bool, &portnummap,
67	"Set Radius NAS-Port attribute to number as in interface name (Default)", OPT_PRIOSUB | 0 },
68    { NULL }
69};
70
71static int radius_secret_check(void);
72static int radius_pap_auth(char *user,
73			   char *passwd,
74			   char **msgp,
75			   struct wordlist **paddrs,
76			   struct wordlist **popts);
77static int radius_chap_verify(char *user, char *ourname, int id,
78			      struct chap_digest_type *digest,
79			      unsigned char *challenge,
80			      unsigned char *response,
81			      char *message, int message_space);
82
83static void radius_ip_up(void *opaque, int arg);
84static void radius_ip_down(void *opaque, int arg);
85static void make_username_realm(char *user);
86static int radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info,
87			    struct chap_digest_type *digest,
88			    unsigned char *challenge,
89			    char *message, int message_space);
90static void radius_choose_ip(u_int32_t *addrp);
91static int radius_init(char *msg);
92static int get_client_port(char *ifname);
93static int radius_allowed_address(u_int32_t addr);
94static void radius_acct_interim(void *);
95#ifdef MPPE
96static int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,
97			      unsigned char *);
98static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info);
99#endif
100
101#ifndef MAXSESSIONID
102#define MAXSESSIONID 32
103#endif
104
105#ifndef MAXCLASSLEN
106#define MAXCLASSLEN 500
107#endif
108
109struct radius_state {
110    int accounting_started;
111    int initialized;
112    int client_port;
113    int choose_ip;
114    int any_ip_addr_ok;
115    int done_chap_once;
116    u_int32_t ip_addr;
117    char user[MAXNAMELEN];
118    char config_file[MAXPATHLEN];
119    char session_id[MAXSESSIONID + 1];
120    time_t start_time;
121    int acct_interim_interval;
122    SERVER *authserver;		/* Authentication server to use */
123    SERVER *acctserver;		/* Accounting server to use */
124    int class_len;
125    char class[MAXCLASSLEN];
126    VALUE_PAIR *avp;	/* Additional (user supplied) vp's to send to server */
127};
128
129void (*radius_attributes_hook)(VALUE_PAIR *) = NULL;
130
131/* The pre_auth_hook MAY set authserver and acctserver if it wants.
132   In that case, they override the values in the radiusclient.conf file */
133void (*radius_pre_auth_hook)(char const *user,
134			     SERVER **authserver,
135			     SERVER **acctserver) = NULL;
136
137static struct radius_state rstate;
138
139char pppd_version[] = VERSION;
140
141/**********************************************************************
142* %FUNCTION: plugin_init
143* %ARGUMENTS:
144*  None
145* %RETURNS:
146*  Nothing
147* %DESCRIPTION:
148*  Initializes RADIUS plugin.
149***********************************************************************/
150void
151plugin_init(void)
152{
153    pap_check_hook = radius_secret_check;
154    pap_auth_hook = radius_pap_auth;
155
156    chap_check_hook = radius_secret_check;
157    chap_verify_hook = radius_chap_verify;
158
159    ip_choose_hook = radius_choose_ip;
160    allowed_address_hook = radius_allowed_address;
161
162    add_notifier(&ip_up_notifier, radius_ip_up, NULL);
163    add_notifier(&ip_down_notifier, radius_ip_down, NULL);
164
165    memset(&rstate, 0, sizeof(rstate));
166
167    strlcpy(rstate.config_file, "/etc/radiusclient/radiusclient.conf",
168	    sizeof(rstate.config_file));
169
170    add_options(Options);
171
172    info("RADIUS plugin initialized.");
173}
174
175/**********************************************************************
176* %FUNCTION: add_avp
177* %ARGUMENTS:
178*  argv -- the <attribute=value> pair to add
179* %RETURNS:
180*  1
181* %DESCRIPTION:
182*  Adds an av pair to be passed on to the RADIUS server on each request.
183***********************************************************************/
184static int
185add_avp(char **argv)
186{
187    struct avpopt *p = malloc(sizeof(struct avpopt));
188
189    /* Append to a list of vp's for later parsing */
190    p->vpstr = strdup(*argv);
191    p->next = avpopt;
192    avpopt = p;
193
194    return 1;
195}
196
197/**********************************************************************
198* %FUNCTION: radius_secret_check
199* %ARGUMENTS:
200*  None
201* %RETURNS:
202*  1 -- we are ALWAYS willing to supply a secret. :-)
203* %DESCRIPTION:
204* Tells pppd that we will try to authenticate the peer, and not to
205* worry about looking in /etc/ppp/*-secrets
206***********************************************************************/
207static int
208radius_secret_check(void)
209{
210    return 1;
211}
212
213/**********************************************************************
214* %FUNCTION: radius_choose_ip
215* %ARGUMENTS:
216*  addrp -- where to store the IP address
217* %RETURNS:
218*  Nothing
219* %DESCRIPTION:
220*  If RADIUS server has specified an IP address, it is stored in *addrp.
221***********************************************************************/
222static void
223radius_choose_ip(u_int32_t *addrp)
224{
225    if (rstate.choose_ip) {
226	*addrp = rstate.ip_addr;
227    }
228}
229
230/**********************************************************************
231* %FUNCTION: radius_pap_auth
232* %ARGUMENTS:
233*  user -- user-name of peer
234*  passwd -- password supplied by peer
235*  msgp -- Message which will be sent in PAP response
236*  paddrs -- set to a list of possible peer IP addresses
237*  popts -- set to a list of additional pppd options
238* %RETURNS:
239*  1 if we can authenticate, -1 if we cannot.
240* %DESCRIPTION:
241* Performs PAP authentication using RADIUS
242***********************************************************************/
243static int
244radius_pap_auth(char *user,
245		char *passwd,
246		char **msgp,
247		struct wordlist **paddrs,
248		struct wordlist **popts)
249{
250    VALUE_PAIR *send, *received;
251    UINT4 av_type;
252    int result;
253    static char radius_msg[BUF_LEN];
254
255    radius_msg[0] = 0;
256    *msgp = radius_msg;
257
258    if (radius_init(radius_msg) < 0) {
259	return 0;
260    }
261
262    /* Put user with potentially realm added in rstate.user */
263    make_username_realm(user);
264
265    if (radius_pre_auth_hook) {
266	radius_pre_auth_hook(rstate.user,
267			     &rstate.authserver,
268			     &rstate.acctserver);
269    }
270
271    send = NULL;
272    received = NULL;
273
274    /* Hack... the "port" is the ppp interface number.  Should really be
275       the tty */
276    rstate.client_port = get_client_port(portnummap ? devnam : ifname);
277
278    av_type = PW_FRAMED;
279    rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
280
281    av_type = PW_PPP;
282    rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
283
284    rc_avpair_add(&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE);
285    rc_avpair_add(&send, PW_USER_PASSWORD, passwd, 0, VENDOR_NONE);
286    if (*remote_number) {
287	rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0,
288		       VENDOR_NONE);
289    } else if (ipparam)
290	rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
291
292    /* Add user specified vp's */
293    if (rstate.avp)
294	rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
295
296    if (rstate.authserver) {
297	result = rc_auth_using_server(rstate.authserver,
298				      rstate.client_port, send,
299				      &received, radius_msg, NULL);
300    } else {
301	result = rc_auth(rstate.client_port, send, &received, radius_msg, NULL);
302    }
303
304    if (result == OK_RC) {
305	if (radius_setparams(received, radius_msg, NULL, NULL, NULL, NULL, 0) < 0) {
306	    result = ERROR_RC;
307	}
308    }
309
310    /* free value pairs */
311    rc_avpair_free(received);
312    rc_avpair_free(send);
313
314    return (result == OK_RC) ? 1 : 0;
315}
316
317/**********************************************************************
318* %FUNCTION: radius_chap_verify
319* %ARGUMENTS:
320*  user -- name of the peer
321*  ourname -- name for this machine
322*  id -- the ID byte in the challenge
323*  digest -- points to the structure representing the digest type
324*  challenge -- the challenge string we sent (length in first byte)
325*  response -- the response (hash) the peer sent back (length in 1st byte)
326*  message -- space for a message to be returned to the peer
327*  message_space -- number of bytes available at *message.
328* %RETURNS:
329*  1 if the response is good, 0 if it is bad
330* %DESCRIPTION:
331* Performs CHAP, MS-CHAP and MS-CHAPv2 authentication using RADIUS.
332***********************************************************************/
333static int
334radius_chap_verify(char *user, char *ourname, int id,
335		   struct chap_digest_type *digest,
336		   unsigned char *challenge, unsigned char *response,
337		   char *message, int message_space)
338{
339    VALUE_PAIR *send, *received;
340    UINT4 av_type;
341    static char radius_msg[BUF_LEN];
342    int result;
343    int challenge_len, response_len;
344    u_char cpassword[MAX_RESPONSE_LEN + 1];
345#ifdef MPPE
346    /* Need the RADIUS secret and Request Authenticator to decode MPPE */
347    REQUEST_INFO request_info, *req_info = &request_info;
348#else
349    REQUEST_INFO *req_info = NULL;
350#endif
351
352    challenge_len = *challenge++;
353    response_len = *response++;
354
355    radius_msg[0] = 0;
356
357    if (radius_init(radius_msg) < 0) {
358	error("%s", radius_msg);
359	return 0;
360    }
361
362    /* return error for types we can't handle */
363    if ((digest->code != CHAP_MD5)
364#ifdef CHAPMS
365	&& (digest->code != CHAP_MICROSOFT)
366	&& (digest->code != CHAP_MICROSOFT_V2)
367#endif
368	) {
369	error("RADIUS: Challenge type %u unsupported", digest->code);
370	return 0;
371    }
372
373    /* Put user with potentially realm added in rstate.user */
374    if (!rstate.done_chap_once) {
375	make_username_realm(user);
376	rstate.client_port = get_client_port (portnummap ? devnam : ifname);
377	if (radius_pre_auth_hook) {
378	    radius_pre_auth_hook(rstate.user,
379				 &rstate.authserver,
380				 &rstate.acctserver);
381	}
382    }
383
384    send = received = NULL;
385
386    av_type = PW_FRAMED;
387    rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
388
389    av_type = PW_PPP;
390    rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
391
392    rc_avpair_add (&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE);
393
394    /*
395     * add the challenge and response fields
396     */
397    switch (digest->code) {
398    case CHAP_MD5:
399	/* CHAP-Challenge and CHAP-Password */
400	if (response_len != MD5_HASH_SIZE)
401	    return 0;
402	cpassword[0] = id;
403	memcpy(&cpassword[1], response, MD5_HASH_SIZE);
404
405	rc_avpair_add(&send, PW_CHAP_CHALLENGE,
406		      challenge, challenge_len, VENDOR_NONE);
407	rc_avpair_add(&send, PW_CHAP_PASSWORD,
408		      cpassword, MD5_HASH_SIZE + 1, VENDOR_NONE);
409	break;
410
411#ifdef CHAPMS
412    case CHAP_MICROSOFT:
413    {
414	/* MS-CHAP-Challenge and MS-CHAP-Response */
415	u_char *p = cpassword;
416
417	if (response_len != MS_CHAP_RESPONSE_LEN)
418	    return 0;
419	*p++ = id;
420	/* The idiots use a different field order in RADIUS than PPP */
421	*p++ = response[MS_CHAP_USENT];
422	memcpy(p, response, MS_CHAP_LANMANRESP_LEN + MS_CHAP_NTRESP_LEN);
423
424	rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
425		      challenge, challenge_len, VENDOR_MICROSOFT);
426	rc_avpair_add(&send, PW_MS_CHAP_RESPONSE,
427		      cpassword, MS_CHAP_RESPONSE_LEN + 1, VENDOR_MICROSOFT);
428	break;
429    }
430
431    case CHAP_MICROSOFT_V2:
432    {
433	/* MS-CHAP-Challenge and MS-CHAP2-Response */
434	u_char *p = cpassword;
435
436	if (response_len != MS_CHAP2_RESPONSE_LEN)
437	    return 0;
438	*p++ = id;
439	/* The idiots use a different field order in RADIUS than PPP */
440	*p++ = response[MS_CHAP2_FLAGS];
441	memcpy(p, response, (MS_CHAP2_PEER_CHAL_LEN + MS_CHAP2_RESERVED_LEN
442			     + MS_CHAP2_NTRESP_LEN));
443
444	rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
445		      challenge, challenge_len, VENDOR_MICROSOFT);
446	rc_avpair_add(&send, PW_MS_CHAP2_RESPONSE,
447		      cpassword, MS_CHAP2_RESPONSE_LEN + 1, VENDOR_MICROSOFT);
448	break;
449    }
450#endif
451    }
452
453    if (*remote_number) {
454	rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0,
455		       VENDOR_NONE);
456    } else if (ipparam)
457	rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
458
459    /* Add user specified vp's */
460    if (rstate.avp)
461	rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
462
463    /*
464     * make authentication with RADIUS server
465     */
466
467    if (rstate.authserver) {
468	result = rc_auth_using_server(rstate.authserver,
469				      rstate.client_port, send,
470				      &received, radius_msg, req_info);
471    } else {
472	result = rc_auth(rstate.client_port, send, &received, radius_msg,
473			 req_info);
474    }
475
476    strlcpy(message, radius_msg, message_space);
477
478    if (result == OK_RC) {
479	if (!rstate.done_chap_once) {
480	    if (radius_setparams(received, radius_msg, req_info, digest,
481				 challenge, message, message_space) < 0) {
482		error("%s", radius_msg);
483		result = ERROR_RC;
484	    } else {
485		rstate.done_chap_once = 1;
486	    }
487	}
488    }
489
490    rc_avpair_free(received);
491    rc_avpair_free (send);
492    return (result == OK_RC);
493}
494
495/**********************************************************************
496* %FUNCTION: make_username_realm
497* %ARGUMENTS:
498*  user -- the user given to pppd
499* %RETURNS:
500*  Nothing
501* %DESCRIPTION:
502*  Copies user into rstate.user.  If it lacks a realm (no "@domain" part),
503* then the default realm from the radiusclient config file is added.
504***********************************************************************/
505static void
506make_username_realm(char *user)
507{
508    char *default_realm;
509
510    if ( user != NULL ) {
511	strlcpy(rstate.user, user, sizeof(rstate.user));
512    }  else {
513	rstate.user[0] = 0;
514    }
515
516    default_realm = rc_conf_str("default_realm");
517
518    if (!strchr(rstate.user, '@') &&
519	default_realm &&
520	(*default_realm != '\0')) {
521	strlcat(rstate.user, "@", sizeof(rstate.user));
522	strlcat(rstate.user, default_realm, sizeof(rstate.user));
523    }
524}
525
526/**********************************************************************
527* %FUNCTION: radius_setparams
528* %ARGUMENTS:
529*  vp -- received value-pairs
530*  msg -- buffer in which to place error message.  Holds up to BUF_LEN chars
531* %RETURNS:
532*  >= 0 on success; -1 on failure
533* %DESCRIPTION:
534*  Parses attributes sent by RADIUS server and sets them in pppd.
535***********************************************************************/
536static int
537radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info,
538		 struct chap_digest_type *digest, unsigned char *challenge,
539		 char *message, int message_space)
540{
541    u_int32_t remote;
542    int ms_chap2_success = 0;
543#ifdef MPPE
544    int mppe_enc_keys = 0;	/* whether or not these were received */
545    int mppe_enc_policy = 0;
546    int mppe_enc_types = 0;
547#endif
548#ifdef MSDNS
549    ipcp_options *wo = &ipcp_wantoptions[0];
550    ipcp_options *ao = &ipcp_allowoptions[0];
551    int got_msdns_1 = 0;
552    int got_msdns_2 = 0;
553    int got_wins_1 = 0;
554    int got_wins_2 = 0;
555#endif
556
557    /* Send RADIUS attributes to anyone else who might be interested */
558    if (radius_attributes_hook) {
559	(*radius_attributes_hook)(vp);
560    }
561
562    /*
563     * service type (if not framed then quit),
564     * new IP address (RADIUS can define static IP for some users),
565     */
566
567    while (vp) {
568	if (vp->vendorcode == VENDOR_NONE) {
569	    switch (vp->attribute) {
570	    case PW_SERVICE_TYPE:
571		/* check for service type       */
572		/* if not FRAMED then exit      */
573		if (vp->lvalue != PW_FRAMED) {
574		    slprintf(msg, BUF_LEN, "RADIUS: wrong service type %ld for %s",
575			     vp->lvalue, rstate.user);
576		    return -1;
577		}
578		break;
579
580	    case PW_FRAMED_PROTOCOL:
581		/* check for framed protocol type       */
582		/* if not PPP then also exit            */
583		if (vp->lvalue != PW_PPP) {
584		    slprintf(msg, BUF_LEN, "RADIUS: wrong framed protocol %ld for %s",
585			     vp->lvalue, rstate.user);
586		    return -1;
587		}
588		break;
589
590	    case PW_SESSION_TIMEOUT:
591		/* Session timeout */
592		maxconnect = vp->lvalue;
593		break;
594           case PW_FILTER_ID:
595               /* packet filter, will be handled via ip-(up|down) script */
596               script_setenv("RADIUS_FILTER_ID", vp->strvalue, 1);
597               break;
598           case PW_FRAMED_ROUTE:
599               /* route, will be handled via ip-(up|down) script */
600               script_setenv("RADIUS_FRAMED_ROUTE", vp->strvalue, 1);
601               break;
602           case PW_IDLE_TIMEOUT:
603               /* idle parameter */
604               idle_time_limit = vp->lvalue;
605               break;
606#ifdef MAXOCTETS
607	    case PW_SESSION_OCTETS_LIMIT:
608		/* Session traffic limit */
609		maxoctets = vp->lvalue;
610		break;
611	    case PW_OCTETS_DIRECTION:
612		/* Session traffic limit direction check */
613		maxoctets_dir = ( vp->lvalue > 4 ) ? 0 : vp->lvalue ;
614		break;
615#endif
616	    case PW_ACCT_INTERIM_INTERVAL:
617		/* Send accounting updates every few seconds */
618		rstate.acct_interim_interval = vp->lvalue;
619		/* RFC says it MUST NOT be less than 60 seconds */
620		/* We use "0" to signify not sending updates */
621		if (rstate.acct_interim_interval &&
622		    rstate.acct_interim_interval < 60) {
623		    rstate.acct_interim_interval = 60;
624		}
625		break;
626	    case PW_FRAMED_IP_ADDRESS:
627		/* seting up remote IP addresses */
628		remote = vp->lvalue;
629		if (remote == 0xffffffff) {
630		    /* 0xffffffff means user should be allowed to select one */
631		    rstate.any_ip_addr_ok = 1;
632		} else if (remote != 0xfffffffe) {
633		    /* 0xfffffffe means NAS should select an ip address */
634		    remote = htonl(vp->lvalue);
635		    if (bad_ip_adrs (remote)) {
636			slprintf(msg, BUF_LEN, "RADIUS: bad remote IP address %I for %s",
637				 remote, rstate.user);
638			return -1;
639		    }
640		    rstate.choose_ip = 1;
641		    rstate.ip_addr = remote;
642		}
643		break;
644            case PW_NAS_IP_ADDRESS:
645                wo->ouraddr = htonl(vp->lvalue);
646                break;
647	    case PW_CLASS:
648		/* Save Class attribute to pass it in accounting request */
649		if (vp->lvalue <= MAXCLASSLEN) {
650		    rstate.class_len=vp->lvalue;
651		    memcpy(rstate.class, vp->strvalue, rstate.class_len);
652		} /* else too big for our buffer - ignore it */
653		break;
654	    }
655
656
657	} else if (vp->vendorcode == VENDOR_MICROSOFT) {
658#ifdef CHAPMS
659	    switch (vp->attribute) {
660	    case PW_MS_CHAP2_SUCCESS:
661		if ((vp->lvalue != 43) || strncmp(vp->strvalue + 1, "S=", 2)) {
662		    slprintf(msg,BUF_LEN,"RADIUS: bad MS-CHAP2-Success packet");
663		    return -1;
664		}
665		if (message != NULL)
666		    strlcpy(message, vp->strvalue + 1, message_space);
667		ms_chap2_success = 1;
668		break;
669
670#ifdef MPPE
671	    case PW_MS_CHAP_MPPE_KEYS:
672		if (radius_setmppekeys(vp, req_info, challenge) < 0) {
673		    slprintf(msg, BUF_LEN,
674			     "RADIUS: bad MS-CHAP-MPPE-Keys attribute");
675		    return -1;
676		}
677		mppe_enc_keys = 1;
678		break;
679
680	    case PW_MS_MPPE_SEND_KEY:
681	    case PW_MS_MPPE_RECV_KEY:
682		if (radius_setmppekeys2(vp, req_info) < 0) {
683		    slprintf(msg, BUF_LEN,
684			     "RADIUS: bad MS-MPPE-%s-Key attribute",
685			     (vp->attribute == PW_MS_MPPE_SEND_KEY)?
686			     "Send": "Recv");
687		    return -1;
688		}
689		mppe_enc_keys = 1;
690		break;
691
692	    case PW_MS_MPPE_ENCRYPTION_POLICY:
693		mppe_enc_policy = vp->lvalue;	/* save for later */
694		break;
695
696	    case PW_MS_MPPE_ENCRYPTION_TYPES:
697		mppe_enc_types = vp->lvalue;	/* save for later */
698		break;
699
700#endif /* MPPE */
701#ifdef MSDNS
702	    case PW_MS_PRIMARY_DNS_SERVER:
703		ao->dnsaddr[0] = htonl(vp->lvalue);
704		got_msdns_1 = 1;
705		if (!got_msdns_2)
706		    ao->dnsaddr[1] = ao->dnsaddr[0];
707		break;
708	    case PW_MS_SECONDARY_DNS_SERVER:
709		ao->dnsaddr[1] = htonl(vp->lvalue);
710		got_msdns_2 = 1;
711		if (!got_msdns_1)
712		    ao->dnsaddr[0] = ao->dnsaddr[1];
713		break;
714	    case PW_MS_PRIMARY_NBNS_SERVER:
715		ao->winsaddr[0] = htonl(vp->lvalue);
716		got_wins_1 = 1;
717		if (!got_wins_2)
718		    ao->winsaddr[1] = ao->winsaddr[0];
719		break;
720	    case PW_MS_SECONDARY_NBNS_SERVER:
721		ao->winsaddr[1] = htonl(vp->lvalue);
722		got_wins_2 = 1;
723		if (!got_wins_1)
724		    ao->winsaddr[0] = ao->winsaddr[1];
725		break;
726#endif /* MSDNS */
727	    }
728#endif /* CHAPMS */
729	}
730	vp = vp->next;
731    }
732
733    /* Require a valid MS-CHAP2-SUCCESS for MS-CHAPv2 auth */
734    if (digest && (digest->code == CHAP_MICROSOFT_V2) && !ms_chap2_success)
735	return -1;
736
737#ifdef MPPE
738    /*
739     * Require both policy and key attributes to indicate a valid key.
740     * Note that if the policy value was '0' we don't set the key!
741     */
742    if (mppe_enc_policy && mppe_enc_keys) {
743	mppe_keys_set = 1;
744	/* Set/modify allowed encryption types. */
745	if (mppe_enc_types)
746	    set_mppe_enc_types(mppe_enc_policy, mppe_enc_types);
747    }
748#endif
749
750    return 0;
751}
752
753#ifdef MPPE
754/**********************************************************************
755* %FUNCTION: radius_setmppekeys
756* %ARGUMENTS:
757*  vp -- value pair holding MS-CHAP-MPPE-KEYS attribute
758*  req_info -- radius request information used for encryption
759* %RETURNS:
760*  >= 0 on success; -1 on failure
761* %DESCRIPTION:
762*  Decrypt the "key" provided by the RADIUS server for MPPE encryption.
763*  See RFC 2548.
764***********************************************************************/
765static int
766radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,
767		   unsigned char *challenge)
768{
769    int i;
770    MD5_CTX Context;
771    u_char  plain[32];
772    u_char  buf[16];
773
774    if (vp->lvalue != 32) {
775	error("RADIUS: Incorrect attribute length (%d) for MS-CHAP-MPPE-Keys",
776	      vp->lvalue);
777	return -1;
778    }
779
780    memcpy(plain, vp->strvalue, sizeof(plain));
781
782    MD5_Init(&Context);
783    MD5_Update(&Context, req_info->secret, strlen(req_info->secret));
784    MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN);
785    MD5_Final(buf, &Context);
786
787    for (i = 0; i < 16; i++)
788	plain[i] ^= buf[i];
789
790    MD5_Init(&Context);
791    MD5_Update(&Context, req_info->secret, strlen(req_info->secret));
792    MD5_Update(&Context, vp->strvalue, 16);
793    MD5_Final(buf, &Context);
794
795    for(i = 0; i < 16; i++)
796	plain[i + 16] ^= buf[i];
797
798    /*
799     * Annoying.  The "key" returned is just the NTPasswordHashHash, which
800     * the NAS (us) doesn't need; we only need the start key.  So we have
801     * to generate the start key, sigh.  NB: We do not support the LM-Key.
802     */
803    mppe_set_keys(challenge, &plain[8]);
804
805    return 0;
806}
807
808/**********************************************************************
809* %FUNCTION: radius_setmppekeys2
810* %ARGUMENTS:
811*  vp -- value pair holding MS-MPPE-SEND-KEY or MS-MPPE-RECV-KEY attribute
812*  req_info -- radius request information used for encryption
813* %RETURNS:
814*  >= 0 on success; -1 on failure
815* %DESCRIPTION:
816*  Decrypt the key provided by the RADIUS server for MPPE encryption.
817*  See RFC 2548.
818***********************************************************************/
819static int
820radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info)
821{
822    int i;
823    MD5_CTX Context;
824    u_char  *salt = vp->strvalue;
825    u_char  *crypt = vp->strvalue + 2;
826    u_char  plain[32];
827    u_char  buf[MD5_HASH_SIZE];
828    char    *type = "Send";
829
830    if (vp->attribute == PW_MS_MPPE_RECV_KEY)
831	type = "Recv";
832
833    if (vp->lvalue != 34) {
834	error("RADIUS: Incorrect attribute length (%d) for MS-MPPE-%s-Key",
835	      vp->lvalue, type);
836	return -1;
837    }
838
839    if ((salt[0] & 0x80) == 0) {
840	error("RADIUS: Illegal salt value for MS-MPPE-%s-Key attribute", type);
841	return -1;
842    }
843
844    memcpy(plain, crypt, 32);
845
846    MD5_Init(&Context);
847    MD5_Update(&Context, req_info->secret, strlen(req_info->secret));
848    MD5_Update(&Context, req_info->request_vector, AUTH_VECTOR_LEN);
849    MD5_Update(&Context, salt, 2);
850    MD5_Final(buf, &Context);
851
852    for (i = 0; i < 16; i++)
853	plain[i] ^= buf[i];
854
855    if (plain[0] != sizeof(mppe_send_key) /* 16 */) {
856	error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute",
857	      (int) plain[0], type);
858	return -1;
859    }
860
861    MD5_Init(&Context);
862    MD5_Update(&Context, req_info->secret, strlen(req_info->secret));
863    MD5_Update(&Context, crypt, 16);
864    MD5_Final(buf, &Context);
865
866    plain[16] ^= buf[0]; /* only need the first byte */
867
868    if (vp->attribute == PW_MS_MPPE_SEND_KEY)
869	memcpy(mppe_send_key, plain + 1, 16);
870    else
871	memcpy(mppe_recv_key, plain + 1, 16);
872
873    return 0;
874}
875#endif /* MPPE */
876
877/**********************************************************************
878* %FUNCTION: radius_acct_start
879* %ARGUMENTS:
880*  None
881* %RETURNS:
882*  Nothing
883* %DESCRIPTION:
884*  Sends a "start" accounting message to the RADIUS server.
885***********************************************************************/
886static void
887radius_acct_start(void)
888{
889    UINT4 av_type;
890    int result;
891    VALUE_PAIR *send = NULL;
892    ipcp_options *ho = &ipcp_hisoptions[0];
893    u_int32_t hisaddr;
894
895    if (!rstate.initialized) {
896	return;
897    }
898
899    rstate.start_time = time(NULL);
900
901    strncpy(rstate.session_id, rc_mksid(), sizeof(rstate.session_id));
902
903    rc_avpair_add(&send, PW_ACCT_SESSION_ID,
904		   rstate.session_id, 0, VENDOR_NONE);
905    rc_avpair_add(&send, PW_USER_NAME,
906		   rstate.user, 0, VENDOR_NONE);
907
908    if (rstate.class_len > 0)
909	rc_avpair_add(&send, PW_CLASS,
910		      rstate.class, rstate.class_len, VENDOR_NONE);
911
912    av_type = PW_STATUS_START;
913    rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
914
915    av_type = PW_FRAMED;
916    rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
917
918    av_type = PW_PPP;
919    rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
920
921    if (*remote_number) {
922	rc_avpair_add(&send, PW_CALLING_STATION_ID,
923		       remote_number, 0, VENDOR_NONE);
924    } else if (ipparam)
925	rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
926
927    av_type = PW_RADIUS;
928    rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE);
929
930
931    av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) );
932    rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);
933
934    hisaddr = ho->hisaddr;
935    av_type = htonl(hisaddr);
936    rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
937
938    /* Add user specified vp's */
939    if (rstate.avp)
940	rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
941
942    if (rstate.acctserver) {
943	result = rc_acct_using_server(rstate.acctserver,
944				      rstate.client_port, send);
945    } else {
946	result = rc_acct(rstate.client_port, send);
947    }
948
949    rc_avpair_free(send);
950
951    if (result != OK_RC) {
952	/* RADIUS server could be down so make this a warning */
953	syslog(LOG_WARNING,
954		"Accounting START failed for %s", rstate.user);
955    } else {
956	rstate.accounting_started = 1;
957	/* Kick off periodic accounting reports */
958	if (rstate.acct_interim_interval) {
959	    TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval);
960	}
961    }
962}
963
964/**********************************************************************
965* %FUNCTION: radius_acct_stop
966* %ARGUMENTS:
967*  None
968* %RETURNS:
969*  Nothing
970* %DESCRIPTION:
971*  Sends a "stop" accounting message to the RADIUS server.
972***********************************************************************/
973static void
974radius_acct_stop(void)
975{
976    UINT4 av_type;
977    VALUE_PAIR *send = NULL;
978    ipcp_options *ho = &ipcp_hisoptions[0];
979    u_int32_t hisaddr;
980    int result;
981
982    if (!rstate.initialized) {
983	return;
984    }
985
986    if (!rstate.accounting_started) {
987	return;
988    }
989
990    if (rstate.acct_interim_interval)
991	UNTIMEOUT(radius_acct_interim, NULL);
992
993    rstate.accounting_started = 0;
994    rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id,
995		   0, VENDOR_NONE);
996
997    rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE);
998
999    av_type = PW_STATUS_STOP;
1000    rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
1001
1002    av_type = PW_FRAMED;
1003    rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
1004
1005    av_type = PW_PPP;
1006    rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
1007
1008    av_type = PW_RADIUS;
1009    rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE);
1010
1011
1012    if (link_stats_valid) {
1013	av_type = link_connect_time;
1014	rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE);
1015
1016	av_type = link_stats.bytes_out;
1017	rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1018
1019	av_type = link_stats.bytes_in;
1020	rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1021
1022	av_type = link_stats.pkts_out;
1023	rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1024
1025	av_type = link_stats.pkts_in;
1026	rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1027    }
1028
1029    if (*remote_number) {
1030	rc_avpair_add(&send, PW_CALLING_STATION_ID,
1031		       remote_number, 0, VENDOR_NONE);
1032    } else if (ipparam)
1033	rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
1034
1035    av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) );
1036    rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);
1037
1038    av_type = PW_NAS_ERROR;
1039    switch( status ) {
1040	case EXIT_OK:
1041	case EXIT_USER_REQUEST:
1042	    av_type = PW_USER_REQUEST;
1043	    break;
1044
1045	case EXIT_HANGUP:
1046	case EXIT_PEER_DEAD:
1047	case EXIT_CONNECT_FAILED:
1048	    av_type = PW_LOST_CARRIER;
1049	    break;
1050
1051	case EXIT_INIT_FAILED:
1052	case EXIT_OPEN_FAILED:
1053	case EXIT_LOCK_FAILED:
1054	case EXIT_PTYCMD_FAILED:
1055	    av_type = PW_PORT_ERROR;
1056	    break;
1057
1058	case EXIT_PEER_AUTH_FAILED:
1059	case EXIT_AUTH_TOPEER_FAILED:
1060	case EXIT_NEGOTIATION_FAILED:
1061	case EXIT_CNID_AUTH_FAILED:
1062	    av_type = PW_SERVICE_UNAVAILABLE;
1063	    break;
1064
1065	case EXIT_IDLE_TIMEOUT:
1066	    av_type = PW_ACCT_IDLE_TIMEOUT;
1067	    break;
1068
1069	case EXIT_CALLBACK:
1070	    av_type = PW_CALLBACK;
1071	    break;
1072
1073	case EXIT_CONNECT_TIME:
1074	    av_type = PW_ACCT_SESSION_TIMEOUT;
1075	    break;
1076
1077#ifdef MAXOCTETS
1078	case EXIT_TRAFFIC_LIMIT:
1079	    av_type = PW_NAS_REQUEST;
1080	    break;
1081#endif
1082
1083	default:
1084	    av_type = PW_NAS_ERROR;
1085	    break;
1086    }
1087    rc_avpair_add(&send, PW_ACCT_TERMINATE_CAUSE, &av_type, 0, VENDOR_NONE);
1088
1089    hisaddr = ho->hisaddr;
1090    av_type = htonl(hisaddr);
1091    rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
1092
1093    /* Add user specified vp's */
1094    if (rstate.avp)
1095	rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
1096
1097    if (rstate.acctserver) {
1098	result = rc_acct_using_server(rstate.acctserver,
1099				      rstate.client_port, send);
1100    } else {
1101	result = rc_acct(rstate.client_port, send);
1102    }
1103
1104    if (result != OK_RC) {
1105	/* RADIUS server could be down so make this a warning */
1106	syslog(LOG_WARNING,
1107		"Accounting STOP failed for %s", rstate.user);
1108    }
1109    rc_avpair_free(send);
1110}
1111
1112/**********************************************************************
1113* %FUNCTION: radius_acct_interim
1114* %ARGUMENTS:
1115*  None
1116* %RETURNS:
1117*  Nothing
1118* %DESCRIPTION:
1119*  Sends an interim accounting message to the RADIUS server
1120***********************************************************************/
1121static void
1122radius_acct_interim(void *ignored)
1123{
1124    UINT4 av_type;
1125    VALUE_PAIR *send = NULL;
1126    ipcp_options *ho = &ipcp_hisoptions[0];
1127    u_int32_t hisaddr;
1128    int result;
1129
1130    if (!rstate.initialized) {
1131	return;
1132    }
1133
1134    if (!rstate.accounting_started) {
1135	return;
1136    }
1137
1138    rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id,
1139		   0, VENDOR_NONE);
1140
1141    rc_avpair_add(&send, PW_USER_NAME, rstate.user, 0, VENDOR_NONE);
1142
1143    av_type = PW_STATUS_ALIVE;
1144    rc_avpair_add(&send, PW_ACCT_STATUS_TYPE, &av_type, 0, VENDOR_NONE);
1145
1146    av_type = PW_FRAMED;
1147    rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);
1148
1149    av_type = PW_PPP;
1150    rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);
1151
1152    av_type = PW_RADIUS;
1153    rc_avpair_add(&send, PW_ACCT_AUTHENTIC, &av_type, 0, VENDOR_NONE);
1154
1155    /* Update link stats */
1156    update_link_stats(0);
1157
1158    if (link_stats_valid) {
1159	link_stats_valid = 0; /* Force later code to update */
1160
1161	av_type = link_connect_time;
1162	rc_avpair_add(&send, PW_ACCT_SESSION_TIME, &av_type, 0, VENDOR_NONE);
1163
1164	av_type = link_stats.bytes_out;
1165	rc_avpair_add(&send, PW_ACCT_OUTPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1166
1167	av_type = link_stats.bytes_in;
1168	rc_avpair_add(&send, PW_ACCT_INPUT_OCTETS, &av_type, 0, VENDOR_NONE);
1169
1170	av_type = link_stats.pkts_out;
1171	rc_avpair_add(&send, PW_ACCT_OUTPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1172
1173	av_type = link_stats.pkts_in;
1174	rc_avpair_add(&send, PW_ACCT_INPUT_PACKETS, &av_type, 0, VENDOR_NONE);
1175    }
1176
1177    if (*remote_number) {
1178	rc_avpair_add(&send, PW_CALLING_STATION_ID,
1179		       remote_number, 0, VENDOR_NONE);
1180    } else if (ipparam)
1181	rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);
1182
1183    av_type = ( using_pty ? PW_VIRTUAL : ( sync_serial ? PW_SYNC : PW_ASYNC ) );
1184    rc_avpair_add(&send, PW_NAS_PORT_TYPE, &av_type, 0, VENDOR_NONE);
1185
1186    hisaddr = ho->hisaddr;
1187    av_type = htonl(hisaddr);
1188    rc_avpair_add(&send, PW_FRAMED_IP_ADDRESS , &av_type , 0, VENDOR_NONE);
1189
1190    /* Add user specified vp's */
1191    if (rstate.avp)
1192	rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));
1193
1194    if (rstate.acctserver) {
1195	result = rc_acct_using_server(rstate.acctserver,
1196				      rstate.client_port, send);
1197    } else {
1198	result = rc_acct(rstate.client_port, send);
1199    }
1200
1201    if (result != OK_RC) {
1202	/* RADIUS server could be down so make this a warning */
1203	syslog(LOG_WARNING,
1204		"Interim accounting failed for %s", rstate.user);
1205    }
1206    rc_avpair_free(send);
1207
1208    /* Schedule another one */
1209    TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval);
1210}
1211
1212/**********************************************************************
1213* %FUNCTION: radius_ip_up
1214* %ARGUMENTS:
1215*  opaque -- ignored
1216*  arg -- ignored
1217* %RETURNS:
1218*  Nothing
1219* %DESCRIPTION:
1220*  Called when IPCP is up.  We'll do a start-accounting record.
1221***********************************************************************/
1222static void
1223radius_ip_up(void *opaque, int arg)
1224{
1225    radius_acct_start();
1226}
1227
1228/**********************************************************************
1229* %FUNCTION: radius_ip_down
1230* %ARGUMENTS:
1231*  opaque -- ignored
1232*  arg -- ignored
1233* %RETURNS:
1234*  Nothing
1235* %DESCRIPTION:
1236*  Called when IPCP is down.  We'll do a stop-accounting record.
1237***********************************************************************/
1238static void
1239radius_ip_down(void *opaque, int arg)
1240{
1241    radius_acct_stop();
1242}
1243
1244/**********************************************************************
1245* %FUNCTION: radius_init
1246* %ARGUMENTS:
1247*  msg -- buffer of size BUF_LEN for error message
1248* %RETURNS:
1249*  negative on failure; non-negative on success
1250* %DESCRIPTION:
1251*  Initializes radiusclient library
1252***********************************************************************/
1253static int
1254radius_init(char *msg)
1255{
1256    if (rstate.initialized) {
1257	return 0;
1258    }
1259
1260    if (config_file && *config_file) {
1261	strlcpy(rstate.config_file, config_file, MAXPATHLEN-1);
1262    }
1263
1264    rstate.initialized = 1;
1265
1266    if (rc_read_config(rstate.config_file) != 0) {
1267	slprintf(msg, BUF_LEN, "RADIUS: Can't read config file %s",
1268		 rstate.config_file);
1269	return -1;
1270    }
1271
1272    if (rc_read_dictionary(rc_conf_str("dictionary")) != 0) {
1273	slprintf(msg, BUF_LEN, "RADIUS: Can't read dictionary file %s",
1274		 rc_conf_str("dictionary"));
1275	return -1;
1276    }
1277
1278    if (rc_read_mapfile(rc_conf_str("mapfile")) != 0)	{
1279	slprintf(msg, BUF_LEN, "RADIUS: Can't read map file %s",
1280		 rc_conf_str("mapfile"));
1281	return -1;
1282    }
1283
1284    /* Add av pairs saved during option parsing */
1285    while (avpopt) {
1286	struct avpopt *n = avpopt->next;
1287
1288	rc_avpair_parse(avpopt->vpstr, &rstate.avp);
1289	free(avpopt->vpstr);
1290	free(avpopt);
1291	avpopt = n;
1292    }
1293    return 0;
1294}
1295
1296/**********************************************************************
1297* %FUNCTION: get_client_port
1298* %ARGUMENTS:
1299*  ifname -- PPP interface name (e.g. "ppp7")
1300* %RETURNS:
1301*  The NAS port number (e.g. 7)
1302* %DESCRIPTION:
1303*  Extracts the port number from the interface name
1304***********************************************************************/
1305static int
1306get_client_port(char *ifname)
1307{
1308    int port;
1309    if (sscanf(ifname, "ppp%d", &port) == 1) {
1310	return port;
1311    }
1312    return rc_map2id(ifname);
1313}
1314
1315/**********************************************************************
1316* %FUNCTION: radius_allowed_address
1317* %ARGUMENTS:
1318*  addr -- IP address
1319* %RETURNS:
1320*  1 if we're allowed to use that IP address; 0 if not; -1 if we do
1321*  not know.
1322***********************************************************************/
1323static int
1324radius_allowed_address(u_int32_t addr)
1325{
1326    ipcp_options *wo = &ipcp_wantoptions[0];
1327
1328    if (!rstate.choose_ip) {
1329	/* If RADIUS server said any address is OK, then fine... */
1330	if (rstate.any_ip_addr_ok) {
1331	    return 1;
1332	}
1333
1334	/* Sigh... if an address was supplied for remote host in pppd
1335	   options, it has to match that.  */
1336	if (wo->hisaddr != 0 && wo->hisaddr == addr) {
1337	    return 1;
1338	}
1339
1340	return 0;
1341    }
1342    if (addr == rstate.ip_addr) return 1;
1343    return 0;
1344}
1345
1346/* Useful for other plugins */
1347char *radius_logged_in_user(void)
1348{
1349    return rstate.user;
1350}
1351