summaryrefslogtreecommitdiff
path: root/usr.sbin/npppd
diff options
context:
space:
mode:
authorYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2011-07-06 20:52:29 +0000
committerYASUOKA Masahiko <yasuoka@cvs.openbsd.org>2011-07-06 20:52:29 +0000
commit71439565dc13acd0c12565c5ffe0070c15a31cb8 (patch)
tree17fd5e40db40780fd57bab6971fbf17c07e50f98 /usr.sbin/npppd
parentbc9b906bf38e2c685a6c283bb2b36af90689a981 (diff)
Add RADIUS accounting support and some authentication related changes:
- Add functions to radius+.c that are required to implement RADIUS accounting. - Send RADIUS Account-Start and Account-Stop messages with attributes that are defined by RFC 2866, 2868, 2869. - If any authentication realm is deleted from the configuration, npppd may exit by segmentation fault. - Delete radius_common.c, radius_common.h and eap.c because they are not used. - Retransmission and failover are reimplemented. - Cleanup
Diffstat (limited to 'usr.sbin/npppd')
-rw-r--r--usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt14
-rw-r--r--usr.sbin/npppd/npppd/Makefile8
-rw-r--r--usr.sbin/npppd/npppd/chap.c44
-rw-r--r--usr.sbin/npppd/npppd/eap.c971
-rw-r--r--usr.sbin/npppd/npppd/lcp.c46
-rw-r--r--usr.sbin/npppd/npppd/npppd.c37
-rw-r--r--usr.sbin/npppd/npppd/npppd.h13
-rw-r--r--usr.sbin/npppd/npppd/npppd_auth.c240
-rw-r--r--usr.sbin/npppd/npppd/npppd_auth.h7
-rw-r--r--usr.sbin/npppd/npppd/npppd_auth_local.h24
-rw-r--r--usr.sbin/npppd/npppd/npppd_local.h5
-rw-r--r--usr.sbin/npppd/npppd/npppd_radius.c435
-rw-r--r--usr.sbin/npppd/npppd/npppd_radius.h16
-rw-r--r--usr.sbin/npppd/npppd/pap.c35
-rw-r--r--usr.sbin/npppd/npppd/ppp.c72
-rw-r--r--usr.sbin/npppd/npppd/ppp.h11
-rw-r--r--usr.sbin/npppd/npppd/radius+.c86
-rw-r--r--usr.sbin/npppd/npppd/radius+.h11
-rw-r--r--usr.sbin/npppd/npppd/radius+_local.h6
-rw-r--r--usr.sbin/npppd/npppd/radius_common.c74
-rw-r--r--usr.sbin/npppd/npppd/radius_common.h42
-rw-r--r--usr.sbin/npppd/npppd/radius_req.c317
-rw-r--r--usr.sbin/npppd/npppd/radius_req.h43
-rw-r--r--usr.sbin/npppd/npppd/radiusconst.h127
24 files changed, 1307 insertions, 1377 deletions
diff --git a/usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt b/usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt
index 986dee38ebe..58ab59329a1 100644
--- a/usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt
+++ b/usr.sbin/npppd/HOWTO_PIPEX_NPPPD.txt
@@ -1,4 +1,4 @@
-$Id: HOWTO_PIPEX_NPPPD.txt,v 1.3 2010/09/26 06:54:44 yasuoka Exp $
+$Id: HOWTO_PIPEX_NPPPD.txt,v 1.4 2011/07/06 20:52:28 yasuoka Exp $
How to test npppd and pipex
---------------------------
@@ -88,7 +88,7 @@ How to test L2TP/IPsec
#
# Simplest npppd.conf sample
#
-# $Id: HOWTO_PIPEX_NPPPD.txt,v 1.3 2010/09/26 06:54:44 yasuoka Exp $
+# $Id: HOWTO_PIPEX_NPPPD.txt,v 1.4 2011/07/06 20:52:28 yasuoka Exp $
interface_list: tun0
interface.tun0.ip4addr: 10.0.0.1
@@ -97,11 +97,19 @@ interface.tun0.ip4addr: 10.0.0.1
pool.dyna_pool: 10.0.0.0/25
pool.pool: 10.0.0.128/25
-# Authentication
+# Local file authentication
auth.local.realm_list: local
auth.local.realm.acctlist: /etc/npppd/npppd-users.csv
realm.local.concentrate: tun0
+# RADIUS authentication / accounting
+#auth.radius.realm_list: radius
+#auth.radius.realm.server.address: 127.0.0.1:1812
+#auth.radius.realm.server.secret: hogehoge
+#auth.radius.realm.acct_server.address: 127.0.0.1:1813
+#auth.radius.realm.acct_server.secret: hogehoge
+#realm.radius.concentrate: tun0
+
lcp.mru: 1400
auth.method: mschapv2 chap
#auth.method: mschapv2 chap pap
diff --git a/usr.sbin/npppd/npppd/Makefile b/usr.sbin/npppd/npppd/Makefile
index cae2ef7f1f6..647cd0cf6cd 100644
--- a/usr.sbin/npppd/npppd/Makefile
+++ b/usr.sbin/npppd/npppd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.7 2010/09/23 01:45:10 jsg Exp $
+# $OpenBSD: Makefile,v 1.8 2011/07/06 20:52:28 yasuoka Exp $
NPPPD_COMMON_DIR= ${.CURDIR}/../common
@@ -7,12 +7,12 @@ NOMAN= noman
#MAN= npppd.8 npppd.conf.5 npppd-users.csv.5
CPPFLAGS+= -I${NPPPD_COMMON_DIR} -I${.CURDIR}
SRCS= ccp.c chap.c chap_ms.c fsm.c ipcp.c lcp.c
-SRCS+= mppe.c pap.c ppp.c radius_req.c
+SRCS+= mppe.c pap.c ppp.c
SRCS+= npppd.c npppd_config.c npppd_subr.c npppd_auth.c npppd_iface.c
SRCS+= config_helper.c slist.c hash.c properties.c rtev_common.c
SRCS+= rtev_libevent.c bytebuf.c debugutil.c csvreader.c net_utils.c
SRCS+= radish.c time_utils.c npppd_pool.c addr_range.c
-SRCS+= radius+.c
+SRCS+= radius+.c radius_req.c npppd_radius.c
SRCS+= recvfromto.c
SRCS+= privsep.c
#SRCS+= ipsec_util.c
@@ -32,8 +32,6 @@ CPPFLAGS+= -DUSE_NPPPD_PPPOE -I${.CURDIR}/../pppoe
SRCS+= pppoe_session.c pppoed.c
.PATH: ${.CURDIR}/../pppoe
-#SRCS+= eap.c radius_common.c
-
CPPFLAGS+= -D__COPYRIGHT\(x\)= -D__RCSID\(x\)=
CPPFLAGS+= -DUSE_NPPPD_MPPE
CPPFLAGS+= -DUSE_NPPPD_PIPEX
diff --git a/usr.sbin/npppd/npppd/chap.c b/usr.sbin/npppd/npppd/chap.c
index fdd9774f81f..bb6fd991ef3 100644
--- a/usr.sbin/npppd/npppd/chap.c
+++ b/usr.sbin/npppd/npppd/chap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: chap.c,v 1.4 2010/09/22 11:48:38 yasuoka Exp $ */
+/* $OpenBSD: chap.c,v 1.5 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -36,7 +36,7 @@
* </ul></p>
*/
/* RFC 1994, 2433 */
-/* $Id: chap.c,v 1.4 2010/09/22 11:48:38 yasuoka Exp $ */
+/* $Id: chap.c,v 1.5 2011/07/06 20:52:28 yasuoka Exp $ */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
@@ -49,6 +49,7 @@
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
+#include <errno.h>
#include <time.h>
#include <event.h>
#include <md5.h>
@@ -59,6 +60,7 @@
#ifdef USE_NPPPD_RADIUS
#include "radius_chap_const.h"
+#include "npppd_radius.h"
#endif
#include "npppd_defs.h"
@@ -118,7 +120,7 @@ static void mschapv2_send_error (chap *, int, int);
static void mschapv2_authenticate (chap *, int, char *, u_char *, int, u_char *);
#ifdef USE_NPPPD_RADIUS
static void chap_radius_authenticate (chap *, int, char *, u_char *, int, u_char *);
-static void chap_radius_response (void *, RADIUS_PACKET *, int);
+static void chap_radius_response (void *, RADIUS_PACKET *, int, RADIUS_REQUEST_CTX);
#endif
static char *strip_nt_domain (char *);
static void chap_log (chap *, uint32_t, const char *, ...) __printflike(3,4);
@@ -176,10 +178,10 @@ chap_start(chap *_this)
chap_log(_this, LOG_ALERT,
"Requested authentication type(0x%x) "
"is not supported.", _this->type);
- ppp_stop_ex(_this->ppp,
- "Authentication Required",
+ ppp_set_disconnect_cause(_this->ppp,
PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
PPP_PROTO_CHAP, 2 /* local */, NULL);
+ ppp_stop(_this->ppp, "Authentication Required");
return;
}
@@ -191,10 +193,10 @@ chap_start(chap *_this)
chap_log(_this, LOG_ALERT,
"mppe is required but try to start chap "
"type=0x%02x", _this->type);
- ppp_stop_ex(_this->ppp,
- "Authentication Required",
+ ppp_set_disconnect_cause(_this->ppp,
PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
PPP_PROTO_CHAP, 2 /* local */, NULL);
+ ppp_stop(_this->ppp, "Authentication Required");
return;
}
#endif
@@ -226,9 +228,10 @@ chap_start(chap *_this)
} else {
chap_log(_this, LOG_INFO,
"Client did't respond our challenage.");
- ppp_stop_ex(_this->ppp, "Authentication Required",
+ ppp_set_disconnect_cause(_this->ppp,
PPP_DISCON_AUTH_FSM_TIMEOUT,
PPP_PROTO_CHAP, 0, NULL);
+ ppp_stop(_this->ppp, "Authentication Required");
}
}
}
@@ -440,8 +443,9 @@ chap_response(chap *_this, int authok, u_char *pktp, int lpktp)
realm_name);
chap_stop(_this);
/* Stop the PPP if the authentication is failed. */
- ppp_stop_ex(_this->ppp, "Authentication Required",
+ ppp_set_disconnect_cause(_this->ppp,
PPP_DISCON_AUTH_FAILED, PPP_PROTO_CHAP, 1 /* peer */, NULL);
+ ppp_stop(_this->ppp, "Authentication Required");
} else {
strlcpy(_this->ppp->username, _this->name,
sizeof(_this->ppp->username));
@@ -746,7 +750,7 @@ chap_radius_authenticate(chap *_this, int id, char *username,
radpkt = NULL;
radctx = NULL;
- if ((rad_setting = npppd_get_radius_req_setting(_this->ppp->pppd,
+ if ((rad_setting = npppd_get_radius_auth_setting(_this->ppp->pppd,
_this->ppp)) == NULL) {
goto fail; /* no radius server */
}
@@ -835,7 +839,8 @@ fail:
}
static void
-chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags)
+chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
+ RADIUS_REQUEST_CTX reqctx)
{
int code, lrespkt;
const char *secret, *reason = "";
@@ -857,15 +862,12 @@ chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags)
+ HEADERLEN;
lrespkt = _this->ppp->mru - HEADERLEN;
if (pkt == NULL) {
- if (flags & RADIUS_REQUST_TIMEOUT) {
+ if (flags & RADIUS_REQUEST_TIMEOUT)
reason = "timeout";
- npppd_radius_server_failure_notify(_this->ppp->pppd,
- _this->ppp, radctx, "request timeout");
- } else {
+ else if (flags & RADIUS_REQUEST_ERROR)
+ reason = strerror(errno);
+ else
reason = "error";
- npppd_radius_server_failure_notify(_this->ppp->pppd,
- _this->ppp, radctx, "unknown error");
- }
goto auth_failed;
}
@@ -879,11 +881,9 @@ chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags)
reason="error";
goto auth_failed;
}
- if ((flags & RADIUS_REQUST_CHECK_AUTHENTICTOR_OK) == 0 &&
- (flags & RADIUS_REQUST_CHECK_AUTHENTICTOR_NO_CHECK) == 0) {
+ if ((flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK) == 0 &&
+ (flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK) == 0) {
reason="bad_authenticator";
- npppd_radius_server_failure_notify(_this->ppp->pppd, _this->ppp,
- radctx, "bad authenticator");
goto auth_failed;
}
/*
diff --git a/usr.sbin/npppd/npppd/eap.c b/usr.sbin/npppd/npppd/eap.c
index 1de8875d53f..e69de29bb2d 100644
--- a/usr.sbin/npppd/npppd/eap.c
+++ b/usr.sbin/npppd/npppd/eap.c
@@ -1,971 +0,0 @@
-/* $OpenBSD: eap.c,v 1.6 2011/01/20 23:12:33 jasper Exp $ */
-
-/*-
- * Copyright (c) 2009 Internet Initiative Japan Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/**@file
- * This file provides EAP(Extensible Authentication Protocols, RFC 3748)
- * handlers. This currently provides only EAP Pass-through Authenticator.
- * @see RFC3748
- * Extensible Authentication Protocols(EAP)
- * @see RFC3579
- * RADIUS (Remote Authentication Dial In User Service) Support For
- * Extensible Authentication Protocol (EAP). B. Aboba, P. Calhoun.
- */
-/* $Id: eap.c,v 1.6 2011/01/20 23:12:33 jasper Exp $ */
-
-/* FIXME: This must be rewritten. */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <net/if_dl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <time.h>
-#include <event.h>
-
-#ifdef USE_NPPPD_RADIUS
-#include <radius+.h>
-#include <radiusconst.h>
-#endif
-
-#include "debugutil.h"
-#ifdef USE_NPPPD_RADIUS
-#include "radius_chap_const.h"
-#endif
-#include "npppd_local.h"
-#include "chap_ms.h"
-
-/* initital state */
-#define EAP_STATE_INITIAL 1
-#define EAP_STATE_SEND_REQUEST_TO_PEER 2
-#define EAP_STATE_STOPPED 3
-
-#define EAP_HEADERLEN 4
-
-#define EAP_TIMEOUT_INIT 3 /* Initial retry internval */
-#define EAP_TIMEOUT_MAX 20 /* Maximum retry internval */
-#define EAP_RETRY 4 /* Number of retry */
-
-#define EAP_REQUEST 1
-#define EAP_RESPONSE 2
-#define EAP_SUCCESS 3
-#define EAP_FAILURE 4
-
-/* MprError.h */
-#define ERROR_AUTH_SERVER_TIMEOUT 930
-
-#define EAP_DEBUG
-#ifdef EAP_DEBUG
-#define EAP_DBG(x) eap_log x
-#define EAP_ASSERT(cond) \
- if (!(cond)) { \
- fprintf(stderr, \
- "\nASSERT(" #cond ") failed on %s() at %s:%d.\n"\
- , __func__, __FILE__, __LINE__); \
- abort(); \
- }
-#else
-#define EAP_ASSERT(cond)
-#define EAP_DBG(x)
-#endif
-
-#define TMPBUF 256
-#define IDENT_STRING "What your name?"
-#define TIMER_CBFUNC void(*)(void *)
-
-#define INIT_EAPID 1
-
-static void eap_restart(eap *_this);
-static void eap_forward_to_radius(eap *_this, u_int8_t *data, int datalen);
-static void eap_recv_from_radius(void *context, RADIUS_PACKET *pkt, int flags);
-static int eap_forward_to_peer(eap *_this, u_int8_t *data, int datalen, int type, u_int8_t id);
-static void eap_log(eap *_this, uint32_t prio, const char *fmt, ...) __printflike(3,4);
-#ifdef USE_NPPPD_MPPE
-static int get_mppe_keys(eap *_this, RADIUS_PACKET *pkt, const char *secret);
-#endif
-
-/** Initialize the EAP */
-void
-eap_init(eap *_this, npppd_ppp *ppp)
-{
- EAP_ASSERT(ppp != NULL);
- EAP_ASSERT(_this != NULL);
- /* initiallize */
- memset(_this, 0, sizeof(eap));
- _this->ntry = EAP_RETRY;
- _this->ppp = ppp;
- _this->state = EAP_STATE_INITIAL;
-}
-
-/** Start the EAP as a authenticator. Send a identity request */
-void
-eap_start(eap *_this)
-{
- u_int8_t *req,*req0;
- int len;
-
- EAP_ASSERT(_this != NULL);
- EAP_ASSERT(_this->ppp != NULL);
-
- /*
- * initialize for timeout callback
- */
- _this->name_len = 0;
- memset(_this->name, 0, sizeof(_this->name));
- _this->attr_state_len = 0;
- memset(_this->attr_state, 0, RADIUS_ATTR_STATE_LEN);
-
- if (_this->state == EAP_STATE_INITIAL ||
- _this->state == EAP_STATE_SEND_REQUEST_TO_PEER){
- if (_this->ntry > 0) {
- _this->ntry--;
-
- /* eap header
- * code: 1 (request) [1 byte]
- * ID: 0x01 (sequence) [1 byte]
- * length: ? [2 byte]
- */
-
- /*
- * type: Identity [1 byte]
- * data: data [ ? ]
- */
-
- req = ppp_packetbuf(_this->ppp, PPP_AUTH_EAP);
- req += PPP_HDRLEN;
- req0 = req;
-
- PUTCHAR(PPP_AUTH_EAP_IDENTITY, req);
- BCOPY(IDENT_STRING, req, (len = strlen(IDENT_STRING)));
- req += strlen(IDENT_STRING);
-
- if (_this->eapid == 0)
- _this->eapid = INIT_EAPID;
- else
- _this->eapid++;
-
- /*
- * send eap request
- */
- ppp_output(_this->ppp, PPP_PROTO_EAP, EAP_REQUEST,
- _this->eapid, req0, req - req0);
- _this->state = EAP_STATE_SEND_REQUEST_TO_PEER;
-
- TIMEOUT((TIMER_CBFUNC)eap_restart, _this,
- EAP_TIMEOUT_INIT);
- } else {
- eap_log(_this, LOG_NOTICE,
- "Client didn't respond our EAP request");
- eap_stop(_this);
- ppp_stop(_this->ppp, "Authentication Required");
- }
- }
-}
-
-void
-eap_restart(eap *_this) {
- if (_this == NULL) {
- log_printf(LOG_INFO, "Failed restart authentication, "
- "already peer session closed with eap");
- return;
- }
-
- eap_log(_this, LOG_INFO, "Retry authentication");
- _this->name_len = 0;
- _this->attr_state_len = 0;
- memset(_this->name, 0, sizeof(_this->name));
- memset(_this->attr_state, 0, sizeof(_this->attr_state));
- if (_this->radctx != NULL)
- radius_cancel_request(_this->radctx);
-
- eap_start(_this);
-}
-
-void
-eap_input(eap *_this, unsigned char *pktp, int len){
- u_int8_t *pkthp;
- int code, id, length, type;
-
- if (_this->state == EAP_STATE_INITIAL ||
- _this->state == EAP_STATE_STOPPED) {
- eap_log(_this, LOG_INFO, "Received eap packet. But eap is "
- "not started");
- return;
- }
- pkthp = pktp;
-
- UNTIMEOUT(eap_restart, _this);
-
- if(len < EAP_HEADERLEN + 1){
- /* discard */
- eap_log(_this, LOG_NOTICE, "Packet has unexpect length");
- return;
- }
-
- GETCHAR(code, pkthp);
- if (code == EAP_FAILURE) {
- /* discard */
- eap_log(_this, LOG_NOTICE,
- "Received unexpected packet from peer (code = %d)", code);
- return;
- }
-
- GETCHAR(id, pkthp);
- if (id != _this->eapid) {
- /* discard */
- eap_log(_this, LOG_NOTICE,
- "Not match EAP identifier (request = %d, response = %d)",
- _this->eapid, id);
- return;
- }
-
- /*
- * get user name from itentity response
- */
- GETSHORT(length, pkthp);
- GETCHAR(type, pkthp);
- if (type == PPP_AUTH_EAP_IDENTITY && _this->name_len == 0) {
- if (length != len) {
- /* discard */
- eap_log(_this, LOG_NOTICE,
- "Identity packet has Invalid length");
- return;
- } else {
- _this->name_len = length - ( EAP_HEADERLEN + 1 );
- if (_this->name_len <= MAX_USERNAME_LENGTH) {
- memcpy(_this->name, pkthp, _this->name_len);
- _this->name[_this->name_len] = '\0';
- } else {
- /* discard */
- _this->name_len = 0;
- eap_log(_this, LOG_ERR,
- "Identity name is too long");
- return;
- }
- }
- }
-
- if (type == PPP_AUTH_EAP_NAK){
- /*
- * Nak check
- */
- _this->flags |= PPP_EAP_FLAG_NAK_RESPONSE;
- eap_log(_this, LOG_DEBUG, "peer response is nak");
- }
-
- if(_this->name_len != 0){
- eap_forward_to_radius(_this, pktp, len);
- return;
- }
-
- /* unexpected process
- * discard
- */
- eap_log(_this, LOG_DEBUG,
- "receive eap length = %d, "
- "eap info: code = %d, id = %d, length = %d, type = %d, "
- "name length = %d",
- len, code, id, length, type, _this->name_len );
- eap_log(_this, LOG_NOTICE, "Received unexpected eap packet from peer");
- return;
-}
-
-static void
-eap_forward_to_radius(eap *_this, u_int8_t *data, int datalen)
-{
- RADIUS_REQUEST_CTX radctx;
- RADIUS_PACKET *radpkt = NULL;
- const char *secret;
- int secretlen;
- int rlength = datalen;
- radius_req_setting *rad_setting;
- int retry = 0;
- unsigned int timeout;
- char buf0[MAX_USERNAME_LENGTH];
-
- /*
- * FIXME: Whenever a radius packet is forwarded, is
- * FIXME: npppd_ppp_bind_realm() called?
- */
- if (npppd_ppp_bind_realm(_this->ppp->pppd, _this->ppp, _this->name, 1)
- != 0) {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR, "Not found realm");
- retry = 1;
- goto fail;
- }
-
- if (npppd_ppp_is_realm_radius(
- _this->ppp->pppd, _this->ppp) == 0) {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR, "Not found realm");
- retry = 1;
- goto fail;
- }
-
- if ((rad_setting = npppd_get_radius_req_setting(
- _this->ppp->pppd, _this->ppp)) == NULL) {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR, "Not found radius server setting");
- retry = 1;
- goto fail;
- }
-
- /*
- * make new request packet
- */
- if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST))
- == NULL){
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR, "Can't make new request packet");
- retry = 1;
- goto fail;
- }
-
- if (ppp_set_radius_attrs_for_authreq(_this->ppp, rad_setting, radpkt)
- != 0) {
- /*
- * internal error
- * retry
- */
- retry = 1;
- goto fail;
- }
-
- /* avoid EAP fragmentation */
- if (radius_put_uint32_attr(radpkt, RADIUS_TYPE_FRAMED_MTU,
- _this->ppp->mru) != 0) {
- /*
- * internal error
- * retry
- */
- retry = 1;
- goto fail;
- }
-
- /*
- * set user name attribute
- */
- if (_this->name_len != 0) {
- if (radius_put_string_attr(radpkt, RADIUS_TYPE_USER_NAME,
- npppd_ppp_get_username_for_auth(_this->ppp->pppd,
- _this->ppp, _this->name, buf0)) != 0) {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR,
- "Can't put attribute to radius packet. type = %d",
- RADIUS_TYPE_USER_NAME);
- retry = 1;
- goto fail;
- }
- } else {
- /*
- * none Identity
- * discard
- */
- eap_log(_this, LOG_NOTICE, "Identity name is not seted");
- goto fail;
- }
-
- /*
- * set state attribute
- */
- if (_this->attr_state_len != 0) {
- if (radius_put_raw_attr(radpkt,
- RADIUS_TYPE_STATE,
- _this->attr_state,
- _this->attr_state_len) != 0) {
- /*
- * internal error
- * discard
- */
- eap_log(_this, LOG_ERR,
- "Can't put attribute to radius packet. type = %d",
- RADIUS_TYPE_STATE);
- goto fail;
- }
- }
-
- /*
- * set EAP message attribute
- * radius packet has some eap message attribute
- */
- while (rlength > 0) {
- if (rlength > 253) {
- if (radius_put_raw_attr(radpkt,
- RADIUS_TYPE_EAP_MESSAGE,
- data+(datalen-rlength), 253) != 0) {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR,
- "Can't put attribute to radius packet. "
- "type = %d", RADIUS_TYPE_EAP_MESSAGE);
- retry = 1;
- goto fail;
- }
- rlength -= 253;
- } else {
- if (radius_put_raw_attr(radpkt,
- RADIUS_TYPE_EAP_MESSAGE,
- data+(datalen-rlength),
- rlength) != 0) {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR,
- "Can't put attribute to radius packet. "
- "type = %d", RADIUS_TYPE_EAP_MESSAGE);
- retry = 1;
- goto fail;
- }
- rlength -= rlength;
- }
- }
-
- /*
- * request cancel
- */
- if (_this->radctx != NULL)
- radius_cancel_request(_this->radctx);
-
- /*
- * prepare request
- */
- if (_this->session_timeout != 0)
-/*
- * FIXME: Is the timer other than authentication timeout timer really
- * FIXME: necessary?
- */
- timeout = _this->session_timeout/2;
- else
- timeout = _this->ppp->auth_timeout;
- if (radius_prepare(rad_setting, _this, &radctx,
- eap_recv_from_radius, timeout) != 0) {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_ERR, "Can't prepare to send access request "
- "packet to radius");
- if (!npppd_ppp_is_realm_ready(_this->ppp->pppd, _this->ppp)) {
- eap_log(_this, LOG_ERR,
- "radius server setting is not ready");
- }
- retry = 1;
- goto fail;
- }
- _this->radctx = radctx;
-
- /*
- * get secret password
- * for radius
- */
- secret = radius_get_server_secret(_this->radctx);
- secretlen = strlen(secret);
-
- /*
- * set message authenticator attribute
- */
- if (radius_put_message_authenticator(radpkt, secret) != 0) {
- eap_log(_this, LOG_ERR, "couldn't put message authentication "
- "attribute to radius packet");
- retry = 1;
- goto fail;
- }
-
- radius_get_authenticator(radpkt, _this->authenticator);
-
- /*
- * send request
- */
- radius_request(_this->radctx, radpkt);
- return;
-fail:
- /*
- * don't give peer user infomation
- */
- if (radpkt != NULL)
- radius_delete_packet(radpkt);
- eap_log(_this, LOG_NOTICE, "Can't forward packet to radius from peer");
- if (retry) {
- eap_restart(_this);
- }
- return;
-}
-
-static void
-eap_recv_from_radius(void *context, RADIUS_PACKET *pkt, int flags)
-{
- int code;
- eap *_this;
- int errorCode;
- int finish;
- int retry = 0;
- char *notify_reason = NULL;
- RADIUS_REQUEST_CTX radctx;
- u_char msgbuf[4096], *cp; /* FIXME: May be enough? */
- int len;
- u_int8_t attrlen = 0;
-
- u_int8_t eap_code = 0;
- u_int8_t eap_id = 0;
- size_t eap_length;
-
- const char *secret;
- int secretlen;
-
- EAP_ASSERT(context != NULL);
-
- _this = context;
- radctx = _this->radctx;
- errorCode = ERROR_AUTH_SERVER_TIMEOUT;
- _this->radctx = NULL;
-
- if (pkt == NULL) {
- if (flags & RADIUS_REQUST_TIMEOUT) {
- /*
- * timeout
- * retry
- */
- eap_log(_this, LOG_WARNING, "Timeout radius response");
- retry = 1;
- notify_reason = "timeout";
- } else {
- /*
- * internal error
- * retry
- */
- eap_log(_this, LOG_WARNING,
- "Internal error with radius packet");
- retry = 1;
- notify_reason = "intenal error";
- }
- goto auth_failed;
- }
-
- if(!(flags & RADIUS_REQUST_CHECK_AUTHENTICTOR_NO_CHECK) &&
- !(flags & RADIUS_REQUST_CHECK_AUTHENTICTOR_OK)){
- /* discard */
- eap_log(_this, LOG_WARNING, "Header has invalid authticator");
- notify_reason = "bad authenticator";
- retry = 1;
- goto auth_failed;
- }
-
- /*
- * get secret password from the radius request context
- */
- secret = radius_get_server_secret(radctx);
- secretlen = strlen(secret);
-
- /*
- * get radius code
- */
- code = radius_get_code(pkt);
- if (radius_check_message_authenticator(pkt, secret) != 0) {
- eap_log(_this, LOG_WARNING, "bad message authenticator.");
- goto auth_failed;
- } else {
- EAP_DBG((_this, LOG_INFO, "good message authenticator."));
- }
-
- /*
- * get first eap message and get length of eap message
- */
- if (radius_get_raw_attr(pkt, RADIUS_TYPE_EAP_MESSAGE, msgbuf, &attrlen)
- != 0) {
- /*
- * check reject
- */
- if ((_this->flags & PPP_EAP_FLAG_NAK_RESPONSE)
- && code == RADIUS_CODE_ACCESS_REJECT) {
- /*
- * nak and reject
- */
- eap_log(_this, LOG_NOTICE,
- "Authentication reject with nak");
- } else if (code == RADIUS_CODE_ACCESS_REJECT) {
- /*
- * reject
- */
- eap_log(_this, LOG_NOTICE, "Authentication reject");
- } else {
- /*
- * discard
- */
- eap_log(_this, LOG_WARNING, "Not found eap attribute");
- goto auth_failed;
- }
- eap_stop(_this);
- ppp_stop(_this->ppp, "Authentication reject");
- goto auth_failed;
- }
- if (attrlen < 4) {
- /*
- * discard
- */
- eap_log(_this, LOG_WARNING, "EAP message is too short");
- goto auth_failed;
- }
- cp = msgbuf;
- GETCHAR(eap_code, cp);
- GETCHAR(eap_id, cp);
- _this->eapid = eap_id;
- GETSHORT(eap_length, cp);
-
- /*
- * if challenge packet, try get state attribute
- */
- if (code == RADIUS_CODE_ACCESS_CHALLENGE) {
- _this->attr_state_len = RADIUS_ATTR_STATE_LEN;
- if (radius_get_raw_attr(pkt,
- RADIUS_TYPE_STATE,
- _this->attr_state,
- &(_this->attr_state_len)) != 0) {
- /* discard */
- eap_log(_this, LOG_ERR, "Not found state attribute");
- goto auth_failed;
- }
- if (_this->attr_state_len < 1) {
- /* discard */
- _this->attr_state_len = 0;
- eap_log(_this, LOG_WARNING,
- "State attribute has invalid length");
- goto auth_failed;
- }
- }
-
- /*
- * get session timeout field
- */
- if (radius_get_uint32_attr(pkt, RADIUS_TYPE_SESSION_TIMEOUT,
- &_this->session_timeout) == 0) {
- if (_this->session_timeout > EAP_TIMEOUT_MAX)
- _this->session_timeout = EAP_TIMEOUT_MAX;
- eap_log(_this, LOG_DEBUG, "Found session timeout attribute");
- }
-
- /*
- * get eap message attribute
- */
- if (radius_get_raw_attr_all(pkt, RADIUS_TYPE_EAP_MESSAGE,
- NULL, &len) != 0) {
- eap_log(_this, LOG_INFO, "Failed to get eap-message from the "
- "radius");
- retry = 1;
- goto auth_failed;
- }
-
- if (len != eap_length) {
- eap_log(_this, LOG_INFO, "Received a bad eap-message: "
- "length in the header is wrong.");
- retry = 1;
- goto auth_failed;
- }
- if (radius_get_raw_attr_all(pkt, RADIUS_TYPE_EAP_MESSAGE, msgbuf, &len)
- != 0) {
- eap_log(_this, LOG_INFO,
- "failed to get eap-message from the radius response.");
- retry = 1;
- goto auth_failed;
- }
-
- /*
- * forwarding validation
- * RFC 3579, RFC 3784
- *
- */
- finish = 0;
- switch (code) {
- case RADIUS_CODE_ACCESS_REQUEST:
- eap_log(_this, LOG_INFO,
- "Invalid radius code (access request) code=%d eap_code=%d",
- code, eap_code);
- goto auth_failed;
- break;
- case RADIUS_CODE_ACCESS_REJECT:
- switch (eap_code) {
- case EAP_REQUEST:
- eap_log(_this, LOG_INFO, "Abnormal reject");
- eap_stop(_this);
- ppp_stop(_this->ppp, "Authentication failed");
- finish = 1;
- break;
- case EAP_RESPONSE:
- eap_log(_this, LOG_INFO,
- "Unexpected eap code(access reject)");
- goto auth_failed;
- break;
- case EAP_FAILURE:
- eap_log(_this, LOG_INFO, "Eap failure");
- eap_stop(_this);
- finish = eap_forward_to_peer(_this,
- msgbuf+EAP_HEADERLEN, len-EAP_HEADERLEN,
- eap_code, eap_id);
- break;
- case EAP_SUCCESS:
- default:
- eap_log(_this, LOG_INFO,
- "Invalid combination code: radius code = %d and "
- "eap code = %d", code ,eap_code);
- goto auth_failed;
- break;
- }
- break;
- case RADIUS_CODE_ACCESS_ACCEPT:
- switch (eap_code) {
- case EAP_REQUEST:
- finish = eap_forward_to_peer(_this,
- msgbuf+EAP_HEADERLEN, len-EAP_HEADERLEN,
- eap_code, eap_id);
- break;
- case EAP_RESPONSE:
- eap_log(_this, LOG_INFO,
- "unexpected eap code(access accept)");
- goto auth_failed;
- break;
- case EAP_FAILURE:
- eap_log(_this, LOG_INFO,
- "Invalid combination code: radius code = %d and "
- "eap code = %d",
- code ,eap_code);
- goto auth_failed;
- break;
- case EAP_SUCCESS:
- ppp_process_radius_framed_ip(_this->ppp, pkt);
-#ifdef USE_NPPPD_MPPE
- if (get_mppe_keys(_this, pkt, secret)) {
- if (MPPE_REQUIRED(_this->ppp)) {
- eap_log(_this, LOG_ERR,
- "mppe is required but can't get "
- "mppe keys");
- eap_stop(_this);
- ppp_stop(_this->ppp, "can't get mppe "
- "attribute");
- } else {
- eap_log(_this, LOG_INFO,
- "can't get mppe keys, unuse "
- "encryption");
- }
- } else {
- eap_log(_this, LOG_DEBUG,
- "Found attribute of mppe keys");
- }
-
-#endif
- finish = eap_forward_to_peer(_this,
- msgbuf+EAP_HEADERLEN, len-EAP_HEADERLEN,
- eap_code, eap_id);
- break;
- default:
- eap_log(_this, LOG_INFO,
- "Invalid combination code: radius code = %d and "
- "eap code = %d", code ,eap_code);
- goto auth_failed;
- break;
- }
- break;
- case RADIUS_CODE_ACCESS_CHALLENGE:
- switch (eap_code) {
- case EAP_REQUEST:
- finish = eap_forward_to_peer(_this,
- msgbuf+EAP_HEADERLEN, len-EAP_HEADERLEN,
- eap_code, eap_id);
- break;
- case EAP_RESPONSE:
- eap_log(_this, LOG_INFO,
- "Unexpected eap code(access challenge)");
- goto auth_failed;
- break;
- case EAP_FAILURE:
- case EAP_SUCCESS:
- default:
- eap_log(_this, LOG_INFO,
- "Invalid combination code: radius code = %d and "
- "eap code = %d", code ,eap_code);
- goto auth_failed;
- break;
- }
- /* XXX TODO:not forward EAP-START */
- break;
- default:
- eap_log(_this, LOG_INFO,
- "Unknown radius code type code = %d and eap code = %d",
- code ,eap_code);
- goto auth_failed;
- break;
- }
-
- if(!finish) {
- if (_this->session_timeout != 0) {
- TIMEOUT((TIMER_CBFUNC)eap_restart, _this,
- _this->session_timeout/2);
- } else {
- TIMEOUT((TIMER_CBFUNC)eap_restart, _this,
- EAP_TIMEOUT_INIT);
- }
- }
- return;
-
-auth_failed:
- eap_log(_this, LOG_WARNING,
- "Can't forward packet to peer from radius");
- if (notify_reason != NULL) {
- npppd_radius_server_failure_notify(
- _this->ppp->pppd, _this->ppp, radctx, notify_reason);
- }
- if (retry) {
- eap_restart(_this);
- }
- return;
-}
-
-#ifdef USE_NPPPD_MPPE
-int
-get_mppe_keys(eap *_this, RADIUS_PACKET *pkt, const char *secret) {
- struct RADIUS_MPPE_KEY sendkey, recvkey;
- u_int8_t len;
-
- EAP_ASSERT(_this != NULL);
- EAP_ASSERT(_this->ppp != NULL);
-
-
- if (_this->ppp->mppe.enabled == 0) {
- return 1;
- }
- len = sizeof(sendkey);
- /* XXX: radius_get_vs_raw_attr doesn't read 'len' */
- if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT,
- RADIUS_VTYPE_MPPE_SEND_KEY, &sendkey, &len) != 0) {
- eap_log(_this, LOG_ERR, "no mppe_send_key");
- return 1;
- }
- len = sizeof(recvkey);
- /* XXX: radius_get_vs_raw_attr doesn't read 'len' */
- if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT,
- RADIUS_VTYPE_MPPE_RECV_KEY, &recvkey, &len) != 0) {
- eap_log(_this, LOG_ERR, "no mppe_recv_key");
- return 1;
- }
- mschap_radiuskey(_this->ppp->mppe.send.master_key,
- sendkey.salt, _this->authenticator, secret);
-
- mschap_radiuskey(_this->ppp->mppe.recv.master_key,
- recvkey.salt, _this->authenticator, secret);
-
- return 0;
-}
-#endif
-
-void
-eap_stop(eap *_this)
-{
- _this->state = EAP_STATE_STOPPED;
- UNTIMEOUT(eap_restart, _this);
- if (_this->radctx != NULL) {
- radius_cancel_request(_this->radctx);
- _this->radctx = NULL;
- }
-}
-
-static int
-eap_forward_to_peer(eap *_this, u_int8_t *data, int datalen, int type, u_int8_t id)
-{
- int finish = 0;
- EAP_ASSERT(_this != NULL);
- EAP_ASSERT(data != NULL);
-
- switch (type) {
- case EAP_REQUEST:
- ppp_output(_this->ppp, PPP_PROTO_EAP, EAP_REQUEST, id, data,
- datalen);
- break;
- case EAP_SUCCESS:
- ppp_output(_this->ppp, PPP_PROTO_EAP, EAP_SUCCESS, id, data,
- datalen);
- eap_log(_this, LOG_INFO, "Authentication succeeded");
- eap_stop(_this);
- memcpy(_this->ppp->username, _this->name, _this->name_len);
- ppp_auth_ok(_this->ppp);
- finish = 1;
- break;
- case EAP_FAILURE:
- ppp_output(_this->ppp, PPP_PROTO_EAP, EAP_FAILURE, id, data,
- datalen);
- eap_log(_this, LOG_INFO, "eap-failure has been received from the peer.");
- eap_log(_this, LOG_INFO, "Authentication failed");
- eap_stop(_this);
- ppp_stop(_this->ppp, "Authentication failed");
- finish = 1;
- break;
- default:
- break;
- }
- return finish;
-}
-
-/************************************************************************
- * Miscellaneous functions
- ************************************************************************/
-void
-eap_log(eap *_this, uint32_t prio, const char *fmt, ...)
-{
- char logbuf[BUFSIZ];
- va_list ap;
-
- EAP_ASSERT(_this != NULL);
- EAP_ASSERT(_this->ppp != NULL);
-
- va_start(ap, fmt);
- snprintf(logbuf, sizeof(logbuf), "ppp id=%u layer=eap %s",
- _this->ppp->id, fmt);
- vlog_printf(prio, logbuf, ap);
- va_end(ap);
-}
diff --git a/usr.sbin/npppd/npppd/lcp.c b/usr.sbin/npppd/npppd/lcp.c
index 44e5f57b47e..25cd8ecd1a6 100644
--- a/usr.sbin/npppd/npppd/lcp.c
+++ b/usr.sbin/npppd/npppd/lcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lcp.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: lcp.c,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* $Id: lcp.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $Id: lcp.c,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/**@file
* This file provides LCP related functions.
*<pre>
@@ -204,6 +204,10 @@ lcp_open(fsm *f)
fsm_log(f, LOG_INFO,
"failed to negotiate a auth protocol.");
fsm_close(f, "Authentication is required");
+ ppp_set_disconnect_cause(f->ppp,
+ PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
+ _this->auth_order[0] /* first one */,
+ 1 /* peer refused */, NULL);
ppp_stop(f->ppp, "Authentication is required");
return;
}
@@ -232,6 +236,20 @@ static void
lcp_down(fsm *f)
{
lcp *_this;
+
+ if (f->ppp->disconnect_code == PPP_DISCON_NO_INFORMATION) {
+ /*
+ * disconnect code is set when we are closing the lcp, so
+ * 'no info' means the lcp is going down by peer's termreq.
+ */
+ ppp_set_disconnect_cause(f->ppp, PPP_DISCON_NORMAL, 0,
+ 1 /* peer */, NULL);
+#ifdef USE_NPPPD_RADIUS
+ ppp_set_radius_terminate_cause(f->ppp,
+ RADIUS_TERMNATE_CAUSE_USER_REQUEST);
+#endif
+ }
+
_this = &f->ppp->lcp;
UNTIMEOUT(lcp_timeout, _this);
}
@@ -707,6 +725,10 @@ lcp_nakci(fsm *f, u_char *inp, int inlen)
"protocols are agreeable. peer's "
"auth proto=%s",
peer_auth);
+ ppp_set_disconnect_cause(f->ppp,
+ PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
+ authproto, 2 /* couldn't accept peer's */,
+ NULL);
ppp_stop(f->ppp, "Authentication is required");
return 1;
}
@@ -811,6 +833,9 @@ lcp_rejci(fsm *f, u_char *inp, int inlen)
if (NO_AUTH_AGREEABLE(_this)) {
fsm_log(f, LOG_INFO, "No authentication "
"protocols are agreeable.");
+ ppp_set_disconnect_cause(f->ppp,
+ PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
+ authproto, 1 /* rejected by peer */, NULL);
ppp_stop(f->ppp, "Authentication is required");
return 1;
}
@@ -911,8 +936,13 @@ lcp_timeout(void *ctx)
_this = ctx;
if (_this->echo_failures >= _this->echo_max_retries) {
fsm_log(&_this->fsm, LOG_NOTICE, "keepalive failure.");
- if (_this->fsm.ppp != NULL)
+ if (_this->fsm.ppp != NULL) {
+#ifdef USE_NPPPD_RADIUS
+ ppp_set_radius_terminate_cause(_this->fsm.ppp,
+ RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT);
+#endif
ppp_stop(_this->fsm.ppp, NULL);
+ }
return;
}
cp = buf;
@@ -976,11 +1006,11 @@ lcp_ext(fsm *f, int code, int id, u_char *inp, int inlen)
return 1;
case ECHOREP:
if (f->state == OPENED) {
- if (inlen >= 4) {
- GETLONG(magic, inp);
- if (_this->peer_magic_number == magic) {
- _this->echo_failures = 0;
- lcp_reset_timeout(_this);
+ if (inlen >= 4) {
+ GETLONG(magic, inp);
+ if (_this->peer_magic_number == magic) {
+ _this->echo_failures = 0;
+ lcp_reset_timeout(_this);
}
}
}
diff --git a/usr.sbin/npppd/npppd/npppd.c b/usr.sbin/npppd/npppd/npppd.c
index edb6266b0b2..002d92ab6b4 100644
--- a/usr.sbin/npppd/npppd/npppd.c
+++ b/usr.sbin/npppd/npppd/npppd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd.c,v 1.10 2011/05/15 15:47:52 markus Exp $ */
+/* $OpenBSD: npppd.c,v 1.11 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -29,7 +29,7 @@
* Next pppd(nppd). This file provides a npppd daemon process and operations
* for npppd instance.
* @author Yasuoka Masahiko
- * $Id: npppd.c,v 1.10 2011/05/15 15:47:52 markus Exp $
+ * $Id: npppd.c,v 1.11 2011/07/06 20:52:28 yasuoka Exp $
*/
#include <sys/cdefs.h>
#include "version.h"
@@ -287,6 +287,8 @@ npppd_init(npppd *_this, const char *config_file)
seed_random(&seed);
srandom(seed);
+ _this->boot_id = (uint32_t)random();
+
/* load configuration */
if ((status = npppd_reload_config(_this)) != 0)
return status;
@@ -1284,6 +1286,11 @@ pipex_periodic(npppd *_this)
continue;
}
ppp_log(ppp, LOG_INFO, "Stop requested by the kernel");
+ /* TODO: PIPEX doesn't return the disconect reason */
+#ifdef USE_NPPPD_RADIUS
+ ppp_set_radius_terminate_cause(ppp,
+ RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT);
+#endif
ppp_stop(ppp, NULL);
}
pipex_done:
@@ -2020,10 +2027,10 @@ npppd_ppp_bind_realm(npppd *_this, npppd_ppp *ppp, const char *username, int
strcmp(username + lusername - lsuffix,
npppd_auth_get_suffix(realm0)) == 0))) {
/* check prefix */
- lprefix = strlen(npppd_auth_get_suffix(realm0));
+ lprefix = strlen(npppd_auth_get_prefix(realm0));
if (lprefix > 0 &&
strncmp(username,
- npppd_auth_get_suffix(realm0),
+ npppd_auth_get_prefix(realm0),
lprefix) != 0)
continue;
@@ -2218,7 +2225,7 @@ npppd_rd_walktree_delete(struct radish_head *rh)
* @return return NULL if no usable RADIUS setting.
*/
void *
-npppd_get_radius_req_setting(npppd *_this, npppd_ppp *ppp)
+npppd_get_radius_auth_setting(npppd *_this, npppd_ppp *ppp)
{
NPPPD_ASSERT(_this != NULL);
NPPPD_ASSERT(ppp != NULL);
@@ -2228,21 +2235,7 @@ npppd_get_radius_req_setting(npppd *_this, npppd_ppp *ppp)
if (!npppd_ppp_is_realm_radius(_this, ppp))
return NULL;
- return npppd_auth_radius_get_radius_req_setting(
- (npppd_auth_radius *)ppp->realm);
-}
-
-/** Notice a failure on RAIDUS request/response */
-void
-npppd_radius_server_failure_notify(npppd *_this, npppd_ppp *ppp, void *rad_ctx,
- const char *reason)
-{
- NPPPD_ASSERT(rad_ctx != NULL);
- NPPPD_ASSERT(ppp != NULL);
-
- npppd_auth_radius_server_failure_notify(
- (npppd_auth_radius *)ppp->realm, radius_get_server_address(rad_ctx),
- reason);
+ return npppd_auth_radius_get_radius_auth_setting(ppp->realm);
}
#endif
@@ -2288,8 +2281,10 @@ npppd_auth_finalizer_periodic(npppd *_this)
slist_itr_remove(&users);
}
}
- if (refcnt == 0)
+ if (refcnt == 0) {
npppd_auth_destroy(auth_base);
+ slist_itr_remove(&_this->realms);
+ }
}
if (ndisposing > 0)
slist_fini(&users);
diff --git a/usr.sbin/npppd/npppd/npppd.h b/usr.sbin/npppd/npppd/npppd.h
index 104914fb973..f0004194f4c 100644
--- a/usr.sbin/npppd/npppd/npppd.h
+++ b/usr.sbin/npppd/npppd/npppd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd.h,v 1.5 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: npppd.h,v 1.6 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -35,10 +35,11 @@
#endif
-#define DEFAULT_RADIUS_AUTH_IPADDR "127.0.0.1"
#define DEFAULT_RADIUS_AUTH_PORT 1812
-#define DEFAULT_RADIUS_AUTH_TIMEOUT 9
-
+#define DEFAULT_RADIUS_ACCT_PORT 1813
+#define DEFAULT_RADIUS_TIMEOUT 9
+#define DEFAULT_RADIUS_MAX_TRIES 3
+#define DEFAULT_RADIUS_MAX_FAILOVERS 1
#define DEFAULT_AUTH_TIMEOUT 30
/** assign fixed IP address */
@@ -117,8 +118,8 @@ const char *npppd_ppp_get_realm_name(npppd *, npppd_ppp *);
int npppd_ppp_bind_iface(npppd *, npppd_ppp *);
void npppd_ppp_unbind_iface(npppd *, npppd_ppp *);
const char *npppd_ppp_get_iface_name(npppd *, npppd_ppp *);
-void * npppd_get_radius_req_setting(npppd *, npppd_ppp *);
-void npppd_radius_server_failure_notify(npppd *, npppd_ppp *, void *, const char *);
+void * npppd_get_radius_auth_setting(npppd *, npppd_ppp *);
+void npppd_radius_auth_server_failure_notify(npppd *, npppd_ppp *, void *, const char *);
int npppd_ppp_pipex_enable(npppd *, npppd_ppp *);
int npppd_ppp_pipex_disable(npppd *, npppd_ppp *);
const char *npppd_ppp_get_username_for_auth(npppd *, npppd_ppp *, const char *, char *);
diff --git a/usr.sbin/npppd/npppd/npppd_auth.c b/usr.sbin/npppd/npppd/npppd_auth.c
index 479ef06888d..9138a691067 100644
--- a/usr.sbin/npppd/npppd/npppd_auth.c
+++ b/usr.sbin/npppd/npppd/npppd_auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_auth.c,v 1.6 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: npppd_auth.c,v 1.7 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -26,7 +26,7 @@
* SUCH DAMAGE.
*/
/**@file authentication realm */
-/* $Id: npppd_auth.c,v 1.6 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $Id: npppd_auth.c,v 1.7 2011/07/06 20:52:28 yasuoka Exp $ */
/* I hope to write the source code in npppd-independent as possible. */
#include <sys/types.h>
#include <sys/stat.h>
@@ -93,14 +93,31 @@ npppd_auth_create(int auth_type, const char *label, void *_npppd)
#ifdef USE_NPPPD_RADIUS
case NPPPD_AUTH_TYPE_RADIUS:
if ((base = malloc(sizeof(npppd_auth_radius))) != NULL) {
+ npppd_auth_radius *_this = (npppd_auth_radius *)base;
memset(base, 0, sizeof(npppd_auth_radius));
base->type = NPPPD_AUTH_TYPE_RADIUS;
base->strip_nt_domain = 0;
strlcpy(base->label, label, sizeof(base->label));
base->npppd = _npppd;
+ if ((_this->rad_auth_setting =
+ radius_req_setting_create()) == NULL)
+ goto radius_reigai;
+ if ((_this->rad_acct_setting =
+ radius_req_setting_create()) == NULL)
+ goto radius_reigai;
return base;
+radius_reigai:
+ if (_this->rad_auth_setting != NULL)
+ radius_req_setting_destroy(
+ _this->rad_auth_setting);
+ if (_this->rad_acct_setting != NULL)
+ radius_req_setting_destroy(
+ _this->rad_acct_setting);
+ free(base);
+ return NULL;
}
+
break;
#endif
@@ -153,8 +170,17 @@ npppd_auth_destroy(npppd_auth_base *base)
break;
case NPPPD_AUTH_TYPE_RADIUS:
+ {
+ npppd_auth_radius *_this = (npppd_auth_radius *)base;
+ if (_this->rad_auth_setting != NULL)
+ radius_req_setting_destroy(_this->rad_auth_setting);
+ _this->rad_auth_setting = NULL;
+ if (_this->rad_acct_setting != NULL)
+ radius_req_setting_destroy(_this->rad_acct_setting);
+ _this->rad_acct_setting = NULL;
memset(base, 0, sizeof(npppd_auth_local));
break;
+ }
}
free(base);
@@ -432,6 +458,12 @@ npppd_auth_get_suffix(npppd_auth_base *base)
}
const char *
+npppd_auth_get_prefix(npppd_auth_base *base)
+{
+ return base->pppprefix;
+}
+
+const char *
npppd_auth_username_for_auth(npppd_auth_base *base, const char *username,
char *username_buffer)
{
@@ -690,10 +722,10 @@ npppd_auth_find_user(npppd_auth_base *base, const char *username)
static int
radius_server_address_load(radius_req_setting *radius, int idx,
- const char *address)
+ const char *address, enum RADIUS_SERVER_TYPE type)
{
struct addrinfo *ai;
- struct sockaddr_in *sin;
+ struct sockaddr_in *sin4;
memset(&radius->server[idx], 0, sizeof(radius->server[0]));
@@ -709,9 +741,11 @@ radius_server_address_load(radius_req_setting *radius, int idx,
break;
}
- sin = (struct sockaddr_in *)(ai->ai_addr);
- if (sin->sin_port == 0)
- sin->sin_port = htons(DEFAULT_RADIUS_AUTH_PORT);
+ sin4 = (struct sockaddr_in *)(ai->ai_addr);
+ if (sin4->sin_port == 0)
+ sin4->sin_port = htons((type == RADIUS_SERVER_TYPE_AUTH)
+ ? DEFAULT_RADIUS_AUTH_PORT : DEFAULT_RADIUS_ACCT_PORT);
+
memcpy(&radius->server[idx].peer, ai->ai_addr,
MIN(sizeof(radius->server[idx].peer), ai->ai_addrlen));
@@ -721,131 +755,161 @@ radius_server_address_load(radius_req_setting *radius, int idx,
return 0;
}
+#define VAL_SEP " \t\r\n"
/** reload the configuration of RADIUS authentication realm */
static int
npppd_auth_radius_reload(npppd_auth_base *base)
{
npppd_auth_radius *_this = (npppd_auth_radius *)base;
+ int i, nauth, nacct;
+
+ _this->rad_acct_setting->timeout = _this->rad_auth_setting->timeout =
+ npppd_auth_config_int(base, "timeout", DEFAULT_RADIUS_TIMEOUT);
+
+ _this->rad_acct_setting->max_tries =
+ _this->rad_auth_setting->max_tries =
+ npppd_auth_config_int(base, "max_tries",
+ DEFAULT_RADIUS_MAX_TRIES);
+
+ _this->rad_acct_setting->max_failovers =
+ _this->rad_auth_setting->max_failovers =
+ npppd_auth_config_int(base, "max_failovers",
+ DEFAULT_RADIUS_MAX_FAILOVERS);
+
+ _this->rad_acct_setting->curr_server =
+ _this->rad_auth_setting->curr_server = 0;
+ if ((nauth = radius_loadconfig(base, _this->rad_auth_setting,
+ RADIUS_SERVER_TYPE_AUTH)) < 0)
+ goto reigai;
+ if ((nacct = radius_loadconfig(base, _this->rad_acct_setting,
+ RADIUS_SERVER_TYPE_ACCT)) < 0)
+ goto reigai;
+
+ for (i = 0; i < countof(_this->rad_auth_setting->server); i++) {
+ if (_this->rad_auth_setting->server[i].enabled)
+ base->radius_ready = 1;
+ }
+
+ npppd_auth_base_log(&_this->nar_base, LOG_INFO,
+ "Loaded configuration. %d authentication server%s, %d accounting "
+ "server%s. timeout=%dsec",
+ nauth, (nauth > 1)? "s" : "", nacct, (nacct > 1)? "s" : "",
+ _this->rad_auth_setting->timeout);
+
+ return 0;
+reigai:
+ npppd_auth_destroy(base);
+
+ return 1;
+}
+
+static int
+radius_loadconfig(npppd_auth_base *base, radius_req_setting *radius,
+ enum RADIUS_SERVER_TYPE srvtype)
+{
+ npppd_auth_radius *_this = (npppd_auth_radius *)base;
int i, n;
const char *val;
- char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ], logbuf[BUFSIZ];
+ char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ];
char label[256];
+ struct rad_cfglabel {
+ const char *list;
+ const char *address;
+ const char *secret;
+ const char *addressL;
+ const char *secretL;
+ } const rad_auth_cfglabel = {
+ .list = "server_list",
+ .address = "server.address",
+ .secret = "server.secret",
+ .addressL = "server.%s.address",
+ .secretL = "server.%s.secret"
+ }, rad_acct_cfglabel = {
+ .list = "acct_server_list",
+ .address = "acct_server.address",
+ .secret = "acct_server.secret",
+ .addressL = "acct_server.%s.address",
+ .secretL = "acct_server.%s.secret"
+ }, *cfglabel;
+
+ if (srvtype == RADIUS_SERVER_TYPE_AUTH)
+ cfglabel = &rad_auth_cfglabel;
+ else
+ cfglabel = &rad_acct_cfglabel;
-#define VAL_SEP " \t\r\n"
- n = 0;
- _this->rad_setting.timeout =
- npppd_auth_config_int(base, "timeout", DEFAULT_RADIUS_AUTH_TIMEOUT);
- _this->rad_setting.curr_server = 0;
+ for (i = 0; i < countof(radius->server); i++)
+ radius->server[i].enabled = 0;
- if ((val = npppd_auth_config_str(base, "server_list")) != NULL) {
+ n = 0;
+ if ((val = npppd_auth_config_str(base, cfglabel->list)) != NULL) {
strlcpy(buf, val, sizeof(buf));
buf0 = buf;
while ((tok = strsep(&buf0, VAL_SEP)) != NULL) {
if (tok[0] == '\0')
continue;
- snprintf(label, sizeof(label), "server.%s.address",tok);
- if ((val = npppd_auth_config_str(base, label)) == NULL)
+ snprintf(label, sizeof(label), cfglabel->addressL,tok);
+ if ((val = npppd_auth_config_str(base, label)) == NULL){
+ npppd_auth_base_log(&_this->nar_base, LOG_INFO,
+ "property %s is not found", label);
goto fail;
- if (radius_server_address_load(&_this->rad_setting, n,
- val) != 0) {
+ }
+ if (radius_server_address_load(radius, n, val, srvtype)
+ != 0) {
npppd_auth_base_log(base, LOG_INFO,
"parse error at %s", label);
goto fail;
}
- snprintf(label, sizeof(label), "server.%s.secret",
- tok);
+ snprintf(label, sizeof(label), cfglabel->secretL, tok);
if ((val = npppd_auth_config_str(base, label)) != NULL)
- strlcpy(_this->rad_setting.server[n].secret,
- val, sizeof(_this->rad_setting
- .server[n].secret));
+ strlcpy(radius->server[n].secret, val,
+ sizeof(radius->server[n].secret));
else
- _this->rad_setting.server[n].secret[0] = '\0';
- if (n != 0)
- strlcat(logbuf, " ", sizeof(logbuf));
+ radius->server[n].secret[0] = '\0';
n++;
}
- } else if ((val = npppd_auth_config_str(base, "server.address"))
+ } else if ((val = npppd_auth_config_str(base, cfglabel->address))
!= NULL) {
- if (radius_server_address_load(&_this->rad_setting, n, val)
- != 0) {
+ if (radius_server_address_load(radius, n, val, srvtype) != 0) {
npppd_auth_base_log(base, LOG_INFO,
"parse error at %s", label);
goto fail;
}
- if ((val = npppd_auth_config_str(base, "server.secret"))!= NULL)
- strlcpy(_this->rad_setting.server[n].secret, val,
- sizeof(_this->rad_setting.server[n].secret));
+ if ((val = npppd_auth_config_str(base, cfglabel->secret))
+ != NULL)
+ strlcpy(radius->server[n].secret, val,
+ sizeof(radius->server[n].secret));
else
- _this->rad_setting.server[n].secret[0] = '\0';
+ radius->server[n].secret[0] = '\0';
n++;
}
- for (i = n; i < countof(_this->rad_setting.server); i++) {
- memset(&_this->rad_setting.server[i], 0,
- sizeof(_this->rad_setting.server[0]));
- }
- for (i = 0; i < countof(_this->rad_setting.server); i++) {
- if (_this->rad_setting.server[i].enabled)
- base->radius_ready = 1;
- }
-
- npppd_auth_base_log(base, LOG_INFO,
- "Loaded configuration timeout=%d nserver=%d",
- _this->rad_setting.timeout, n);
+ for (i = n; i < countof(radius->server); i++)
+ memset(&radius->server[i], 0, sizeof(radius->server[0]));
- return 0;
+ return n;
fail:
- npppd_auth_destroy(base);
-
- return 1;
+ return -1;
}
/**
- * Get {@link ::radius_req_setting} of specified {@link ::npppd_auth_base}
- * object.
+ * Get {@link ::radius_req_setting} for RADIUS authentication of specified
+ * {@link ::npppd_auth_base} object.
*/
void *
-npppd_auth_radius_get_radius_req_setting(npppd_auth_radius *_this)
+npppd_auth_radius_get_radius_auth_setting(npppd_auth_radius *_this)
{
- return &_this->rad_setting;
+ return _this->rad_auth_setting;
}
-/** This function notifies that RADIUS server failed the request. */
-void
-npppd_auth_radius_server_failure_notify(npppd_auth_radius *_this,
- struct sockaddr *server, const char *reason)
+/**
+ * Get {@link ::radius_req_setting} for RADIUS accounting of specified
+ * {@link ::npppd_auth_base} object.
+ */
+void *
+npppd_auth_radius_get_radius_acct_setting(npppd_auth_radius *_this)
{
- int i, n;
- radius_req_setting *rad_setting;
- char buf0[BUFSIZ];
-
- NPPPD_AUTH_ASSERT(_this != NULL);
- NPPPD_AUTH_ASSERT(server != NULL);
-
- if (reason == NULL)
- reason = "failure";
-
- rad_setting = &_this->rad_setting;
- if (memcmp(&rad_setting->server[rad_setting->curr_server].peer,
- server, server->sa_len) == 0) {
- /*
- * The RADIUS server which request was failed is currently selected,
- * so next RADIUS server will be selected.
- */
- for (i = 1; i < countof(rad_setting->server); i++) {
- n = (rad_setting->curr_server + i) %
- countof(rad_setting->server);
- if (rad_setting->server[n].enabled == 0)
- continue;
- rad_setting->curr_server = n;
- break;
- }
- }
-
- npppd_auth_base_log(&_this->nar_base, LOG_NOTICE,
- "server=%s request failure: %s",
- addrport_tostring(server, server->sa_len, buf0, sizeof(buf0)),
- reason);
+ return _this->rad_acct_setting;
}
+
#endif
/***********************************************************************
diff --git a/usr.sbin/npppd/npppd/npppd_auth.h b/usr.sbin/npppd/npppd/npppd_auth.h
index b3cf65bc049..d84504f8836 100644
--- a/usr.sbin/npppd/npppd/npppd_auth.h
+++ b/usr.sbin/npppd/npppd/npppd_auth.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_auth.h,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: npppd_auth.h,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -64,9 +64,10 @@ int npppd_auth_is_eap_capable (npppd_auth_base *);
const char *npppd_auth_get_label (npppd_auth_base *);
const char *npppd_auth_get_name (npppd_auth_base *);
const char *npppd_auth_get_suffix (npppd_auth_base *);
+const char *npppd_auth_get_prefix (npppd_auth_base *);
const char *npppd_auth_username_for_auth (npppd_auth_base *, const char *, char *);
-void *npppd_auth_radius_get_radius_req_setting (npppd_auth_radius *);
-void npppd_auth_radius_server_failure_notify (npppd_auth_radius *, struct sockaddr *, const char *);
+void *npppd_auth_radius_get_radius_auth_setting (npppd_auth_radius *);
+void *npppd_auth_radius_get_radius_acct_setting (npppd_auth_radius *);
#ifdef __cplusplus
}
diff --git a/usr.sbin/npppd/npppd/npppd_auth_local.h b/usr.sbin/npppd/npppd/npppd_auth_local.h
index 829e4d36f3d..04e8e605472 100644
--- a/usr.sbin/npppd/npppd/npppd_auth_local.h
+++ b/usr.sbin/npppd/npppd/npppd_auth_local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_auth_local.h,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: npppd_auth_local.h,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -73,12 +73,11 @@ struct _npppd_auth_radius {
/** parent of npppd_auth_base */
npppd_auth_base nar_base;
- /** server currently in use */
- int curr_server;
-
- /** RADIUS server */
- radius_req_setting rad_setting;
+ /** RADIUS authentication server setting */
+ radius_req_setting *rad_auth_setting;
+ /** RADIUS accounting server setting */
+ radius_req_setting *rad_acct_setting;
};
#endif
@@ -106,8 +105,6 @@ typedef struct _npppd_auth_user {
static int npppd_auth_reload_acctlist (npppd_auth_base *);
static npppd_auth_user *npppd_auth_find_user (npppd_auth_base *, const char *);
-static int radius_server_address_load (radius_req_setting *, int, const char *);
-static int npppd_auth_radius_reload (npppd_auth_base *);
static int npppd_auth_base_log (npppd_auth_base *, int, const char *, ...);
static uint32_t str_hash (const void *, int);
static const char * npppd_auth_default_label(npppd_auth_base *);
@@ -116,6 +113,17 @@ static const char *npppd_auth_config_str (npppd_auth_base *, const char
static int npppd_auth_config_int (npppd_auth_base *, const char *, int);
static int npppd_auth_config_str_equal (npppd_auth_base *, const char *, const char *, int);
+#ifdef USE_NPPPD_RADIUS
+enum RADIUS_SERVER_TYPE {
+ RADIUS_SERVER_TYPE_AUTH,
+ RADIUS_SERVER_TYPE_ACCT
+};
+
+static int npppd_auth_radius_reload (npppd_auth_base *);
+static int radius_server_address_load (radius_req_setting *, int, const char *, enum RADIUS_SERVER_TYPE);
+static int radius_loadconfig(npppd_auth_base *, radius_req_setting *, enum RADIUS_SERVER_TYPE);
+#endif
+
#ifdef NPPPD_AUTH_DEBUG
#define NPPPD_AUTH_DBG(x) npppd_auth_base_log x
#define NPPPD_AUTH_ASSERT(x) ASSERT(x)
diff --git a/usr.sbin/npppd/npppd/npppd_local.h b/usr.sbin/npppd/npppd/npppd_local.h
index a63e151a1a1..c87e1c6d013 100644
--- a/usr.sbin/npppd/npppd/npppd_local.h
+++ b/usr.sbin/npppd/npppd/npppd_local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_local.h,v 1.5 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: npppd_local.h,v 1.6 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -203,6 +203,9 @@ struct _npppd {
/** process id */
pid_t pid;
+ /** boot identifier */
+ uint32_t boot_id;
+
#ifdef USE_NPPPD_L2TP
/** structure of L2TP daemon */
l2tpd l2tpd;
diff --git a/usr.sbin/npppd/npppd/npppd_radius.c b/usr.sbin/npppd/npppd/npppd_radius.c
new file mode 100644
index 00000000000..ccdde2c3317
--- /dev/null
+++ b/usr.sbin/npppd/npppd/npppd_radius.c
@@ -0,0 +1,435 @@
+/* $Id: npppd_radius.c,v 1.1 2011/07/06 20:52:28 yasuoka Exp $ */
+/*-
+ * Copyright (c) 2009 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE"AUTHOR" AND CONTRIBUTORS AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * RFC 2865 Remote Authentication Dial In User Service (RADIUS)
+ * RFC 2866 RADIUS Accounting
+ * RFC 2868 RADIUS Attributes for Tunnel Protocol Support
+ * RFC 2869 RADIUS Extensions
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/syslog.h>
+#include <netinet/in.h>
+#include <net/if_dl.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <event.h> /* event(3) */
+#include <radius+.h> /* radius+(3) */
+#include <radiusconst.h> /* radius+(3) */
+
+#include "radius_req.h"
+#include "npppd_local.h"
+#include "npppd_radius.h"
+
+#ifdef NPPPD_RADIUS_DEBUG
+#define NPPPD_RADIUS_DBG(x) ppp_log x
+#define NPPPD_RADIUS_ASSERT(x) ASSERT(x)
+#else
+#define NPPPD_RADIUS_DBG(x)
+#define NPPPD_RADIUS_ASSERT(x)
+#endif
+
+static int l2tp_put_tunnel_attributes(RADIUS_PACKET *, void *);
+static int pptp_put_tunnel_attributes(RADIUS_PACKET *, void *);
+static int radius_acct_request(npppd *, npppd_ppp *, int );
+static void npppd_ppp_radius_acct_reqcb(void *, RADIUS_PACKET *, int, RADIUS_REQUEST_CTX);
+
+/***********************************************************************
+ * RADIUS common fucntions
+ ***********************************************************************/
+/**
+ * Retribute Framed-IP-Address and Framed-IP-Netmask attribute of from
+ * the given RADIUS packet and set them as the fields of ppp context.
+ */
+void
+ppp_proccess_radius_framed_ip(npppd_ppp *_this, RADIUS_PACKET *pkt)
+{
+ struct in_addr ip4;
+
+ if (radius_get_ipv4_attr(pkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, &ip4)
+ == 0)
+ _this->realm_framed_ip_address = ip4;
+
+ _this->realm_framed_ip_netmask.s_addr = 0xffffffffL;
+#ifndef NPPPD_COMPAT_4_2
+ if (radius_get_ipv4_attr(pkt, RADIUS_TYPE_FRAMED_IP_NETMASK, &ip4)
+ == 0)
+ _this->realm_framed_ip_netmask = ip4;
+#endif
+}
+
+/***********************************************************************
+ * RADIUS Accounting Events
+ ***********************************************************************/
+
+/** Called by PPP on start */
+void
+npppd_ppp_radius_acct_start(npppd *pppd, npppd_ppp *ppp)
+{
+ NPPPD_RADIUS_DBG((ppp, LOG_INFO, "%s()", __func__));
+
+ if (ppp->realm == NULL || !npppd_ppp_is_realm_radius(pppd, ppp))
+ return;
+ radius_acct_request(pppd, ppp, 0);
+}
+
+/** Called by PPP on stop*/
+void
+npppd_ppp_radius_acct_stop(npppd *pppd, npppd_ppp *ppp)
+{
+ NPPPD_RADIUS_DBG((ppp, LOG_INFO, "%s()", __func__));
+
+ if (ppp->realm == NULL || !npppd_ppp_is_realm_radius(pppd, ppp))
+ return;
+ radius_acct_request(pppd, ppp, 1);
+}
+
+/** Called by radius_req.c */
+static void
+npppd_ppp_radius_acct_reqcb(void *context, RADIUS_PACKET *pkt, int flags,
+ RADIUS_REQUEST_CTX ctx)
+{
+ int ppp_id;
+
+ ppp_id = (int)context;
+ if ((flags & RADIUS_REQUEST_TIMEOUT) != 0) {
+ log_printf(LOG_WARNING, "ppp id=%d radius accounting request "
+ "failed: no response from the server.", ppp_id);
+ }
+ else if ((flags & RADIUS_REQUEST_ERROR) != 0)
+ log_printf(LOG_WARNING, "ppp id=%d radius accounting request "
+ "failed: %m", ppp_id);
+ else if ((flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK) == 0 &&
+ (flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK) == 0)
+ log_printf(LOG_WARNING, "ppp id=%d radius accounting request "
+ "failed: the server responses with bad authenticator",
+ ppp_id);
+ else {
+#ifdef NPPPD_RADIUS_DEBUG
+ log_printf(LOG_DEBUG, "ppp id=%d radius accounting request "
+ "succeeded.", ppp_id);
+#endif
+ return;
+ /* NOTREACHED */
+ }
+ if (radius_request_can_failover(ctx)) {
+ if (radius_request_failover(ctx) == 0) {
+ struct sockaddr *sa;
+ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+
+ sa = radius_get_server_address(ctx);
+ if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
+ sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)
+ != 0) {
+ strlcpy(hbuf, "unknown", sizeof(hbuf));
+ strlcpy(sbuf, "", sizeof(hbuf));
+ }
+ log_printf(LOG_DEBUG, "ppp id=%d "
+ "fail over to %s:%s for radius accounting request",
+ ppp_id, hbuf, sbuf);
+ } else {
+ log_printf(LOG_WARNING, "ppp id=%d "
+ "failed to fail over for radius accounting request",
+ ppp_id);
+ }
+ }
+}
+
+/***********************************************************************
+ * RADIUS attributes
+ ***********************************************************************/
+#define ATTR_INT32(_a,_v) \
+ do { \
+ if (radius_put_uint32_attr(radpkt, (_a), (_v)) != 0) \
+ goto reigai; \
+ } while (0 /* CONSTCOND */)
+#define ATTR_STR(_a,_v) \
+ do { \
+ if (radius_put_string_attr(radpkt, (_a), (_v)) != 0) \
+ goto reigai; \
+ } while (0 /* CONSTCOND */)
+
+static int
+radius_acct_request(npppd *pppd, npppd_ppp *ppp, int stop)
+{
+ RADIUS_PACKET *radpkt;
+ RADIUS_REQUEST_CTX radctx;
+ radius_req_setting *rad_setting;
+ char buf[128];
+
+ if (ppp->username[0] == '\0')
+ return 0;
+
+ radpkt = NULL;
+ radctx = NULL;
+ rad_setting = npppd_auth_radius_get_radius_acct_setting(ppp->realm);
+ if (!radius_req_setting_has_server(rad_setting))
+ return 0;
+ if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCOUNTING_REQUEST))
+ == NULL)
+ goto reigai;
+
+ if (radius_prepare(rad_setting, (void *)ppp->id, &radctx,
+ npppd_ppp_radius_acct_reqcb, 0) != 0)
+ goto reigai;
+
+ /* NAS Information */
+ /*
+ * RFC 2865 "5.4. NAS-IP-Address" or RFC 3162 "2.1. NAS-IPv6-Address"
+ */
+ if (radius_prepare_nas_address(rad_setting, radpkt) != 0)
+ goto reigai;
+
+ /* RFC 2865 "5.41. NAS-Port-Type" */
+ ATTR_INT32(RADIUS_TYPE_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_VIRTUAL);
+
+ /* RFC 2865 "5.5. NAS-Port" */
+ ATTR_INT32(RADIUS_TYPE_NAS_PORT, ppp->id);
+ /* npppd has no physical / virtual ports in design. */
+
+ /* RFC 2865 5.31. Calling-Station-Id */
+ if (ppp->calling_number[0] != '\0')
+ ATTR_STR(RADIUS_TYPE_CALLING_STATION_ID, ppp->calling_number);
+
+ /* Tunnel Protocol Information */
+ switch (ppp->tunnel_type) {
+ case PPP_TUNNEL_L2TP:
+ /* RFC 2868 3.1. Tunnel-Type */
+ ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_L2TP);
+ if (l2tp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0)
+ goto reigai;
+ break;
+ case PPP_TUNNEL_PPTP:
+ /* RFC 2868 3.1. Tunnel-Type */
+ ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_PPTP);
+ if (pptp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0)
+ goto reigai;
+ break;
+ }
+
+ /* Framed Protocol (PPP) Information */
+ /* RFC 2865 5.1 User-Name */
+ ATTR_STR(RADIUS_TYPE_USER_NAME, ppp->username);
+
+ /* RFC 2865 "5.7. Service-Type" */
+ ATTR_INT32(RADIUS_TYPE_SERVICE_TYPE, RADIUS_SERVICE_TYPE_FRAMED);
+
+ /* RFC 2865 "5.8. Framed-Protocol" */
+ ATTR_INT32(RADIUS_TYPE_FRAMED_PROTOCOL, RADIUS_FRAMED_PROTOCOL_PPP);
+
+ /* RFC 2865 "5.8. Framed-IP-Address" */
+ if (ppp_ip_assigned(ppp) && !stop)
+ ppp->realm_framed_ip_address = ppp->ppp_framed_ip_address;
+ if (ppp->realm_framed_ip_address.s_addr != INADDR_ANY) {
+ ATTR_INT32(RADIUS_TYPE_FRAMED_IP_ADDRESS,
+ ntohl(ppp->realm_framed_ip_address.s_addr));
+ }
+
+ /* Accounting */
+ /* RFC 2866 5.1. Acct-Status-Type */
+ ATTR_INT32(RADIUS_TYPE_ACCT_STATUS_TYPE, (stop)
+ ? RADIUS_ACCT_STATUS_TYPE_STOP : RADIUS_ACCT_STATUS_TYPE_START);
+
+ /* RFC 2866 5.2. Acct-Delay-Time */
+ ATTR_INT32(RADIUS_TYPE_ACCT_DELAY_TIME, 0);
+
+ if (stop) {
+ /* RFC 2866 5.3 Acct-Input-Octets */
+ ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_OCTETS,
+ (uint32_t)(ppp->ibytes & 0xFFFFFFFFU)); /* LSB 32bit */
+
+ /* RFC 2866 5.4 Acct-Output-Octets */
+ ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_OCTETS,
+ (uint32_t)(ppp->obytes & 0xFFFFFFFFU)); /* LSB 32bit */
+ }
+
+ /* RFC 2866 5.5 Acct-Session-Id */
+ snprintf(buf, sizeof(buf), "%08X%08X", pppd->boot_id, ppp->id);
+ ATTR_STR(RADIUS_TYPE_ACCT_SESSION_ID, buf);
+
+ /* RFC 2866 5.6. Acct-Authentic */
+ ATTR_INT32(RADIUS_TYPE_ACCT_AUTHENTIC, RADIUS_ACCT_AUTHENTIC_RADIUS);
+
+ if (stop) {
+ /* RFC 2866 5.7. Acct-Session-Time */
+ ATTR_INT32(RADIUS_TYPE_ACCT_SESSION_TIME,
+ ppp->end_monotime - ppp->start_monotime);
+
+ /* RFC 2866 5.8 Acct-Input-Packets */
+ ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_PACKETS, ppp->ipackets);
+
+ /* RFC 2866 5.9 Acct-Output-Packets */
+ ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_PACKETS, ppp->opackets);
+
+ /* RFC 2866 5.10. Acct-Terminate-Cause */
+ if (ppp->terminate_cause != 0)
+ ATTR_INT32(RADIUS_TYPE_ACCT_TERMINATE_CAUSE,
+ ppp->terminate_cause);
+
+ /* RFC 2869 5.1 Acct-Input-Gigawords */
+ ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, ppp->ibytes >> 32);
+
+ /* RFC 2869 5.2 Acct-Output-Gigawords */
+ ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS,
+ ppp->obytes >> 32);
+ }
+
+ radius_set_request_authenticator(radpkt,
+ radius_get_server_secret(radctx));
+
+ /* Send the request */
+ radius_request(radctx, radpkt);
+
+ return 0;
+
+reigai:
+ ppp_log(ppp, LOG_WARNING, "radius accounting request failed: %m");
+
+ if (radctx != NULL)
+ radius_cancel_request(radctx);
+ if (radpkt != NULL)
+ radius_delete_packet(radpkt);
+
+ return -1;
+}
+
+#ifdef USE_NPPPD_PPTP
+#include "pptp.h"
+#endif
+
+static int
+pptp_put_tunnel_attributes(RADIUS_PACKET *radpkt, void *call0)
+{
+#ifdef USE_NPPPD_PPTP
+ pptp_call *call = call0;
+ pptp_ctrl *ctrl;
+ char hbuf[NI_MAXHOST], buf[128];
+
+ ctrl = call->ctrl;
+
+ /* RFC 2868 3.2. Tunnel-Medium-Type */
+ switch (ctrl->peer.ss_family) {
+ case AF_INET:
+ ATTR_INT32(RADIUS_TYPE_TUNNEL_MEDIUM_TYPE,
+ RADIUS_TUNNEL_MEDIUM_TYPE_IPV4);
+ break;
+
+ case AF_INET6:
+ ATTR_INT32(RADIUS_TYPE_TUNNEL_MEDIUM_TYPE,
+ RADIUS_TUNNEL_MEDIUM_TYPE_IPV6);
+ break;
+
+ default:
+ return -1;
+ }
+
+ /* RFC 2868 3.3. Tunnel-Client-Endpoint */
+ if (getnameinfo((struct sockaddr *)&ctrl->peer, ctrl->peer.ss_len, hbuf,
+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
+ return 1;
+ ATTR_STR(RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT, hbuf);
+
+ /* RFC 2868 3.4. Tunnel-Server-Endpoint */
+ if (getnameinfo((struct sockaddr *)&ctrl->our, ctrl->our.ss_len, hbuf,
+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
+ return 1;
+ ATTR_STR(RADIUS_TYPE_TUNNEL_SERVER_ENDPOINT, hbuf);
+
+ /* RFC 2868 3.7. Tunnel-Assignment-ID */
+ snprintf(buf, sizeof(buf), "PPTP-CALL-%d", call->id);
+ ATTR_STR(RADIUS_TYPE_TUNNEL_ASSIGNMENT_ID, buf);
+
+ /* RFC 2867 4.1. Acct-Tunnel-Connection */
+ snprintf(buf, sizeof(buf), "PPTP-CTRL-%d", ctrl->id);
+ ATTR_STR(RADIUS_TYPE_ACCT_TUNNEL_CONNECTION, buf);
+
+ return 0;
+reigai:
+#endif
+ return 1;
+}
+
+#ifdef USE_NPPPD_L2TP
+#include "l2tp.h"
+#endif
+
+static int
+l2tp_put_tunnel_attributes(RADIUS_PACKET *radpkt, void *call0)
+{
+#ifdef USE_NPPPD_L2TP
+ l2tp_call *call = call0;
+ l2tp_ctrl *ctrl;
+ char hbuf[NI_MAXHOST], buf[128];
+
+ ctrl = call->ctrl;
+
+ /* RFC 2868 3.2. Tunnel-Medium-Type */
+ switch (ctrl->peer.ss_family) {
+ case AF_INET:
+ ATTR_INT32(RADIUS_TYPE_TUNNEL_MEDIUM_TYPE,
+ RADIUS_TUNNEL_MEDIUM_TYPE_IPV4);
+ break;
+
+ case AF_INET6:
+ ATTR_INT32(RADIUS_TYPE_TUNNEL_MEDIUM_TYPE,
+ RADIUS_TUNNEL_MEDIUM_TYPE_IPV6);
+ break;
+
+ default:
+ return -1;
+ }
+
+ /* RFC 2868 3.3. Tunnel-Client-Endpoint */
+ if (getnameinfo((struct sockaddr *)&ctrl->peer, ctrl->peer.ss_len, hbuf,
+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
+ return 1;
+ ATTR_STR(RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT, hbuf);
+
+ /* RFC 2868 3.4. Tunnel-Server-Endpoint */
+ if (getnameinfo((struct sockaddr *)&ctrl->sock, ctrl->sock.ss_len, hbuf,
+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
+ return 1;
+ ATTR_STR(RADIUS_TYPE_TUNNEL_SERVER_ENDPOINT, hbuf);
+
+ /* RFC 2868 3.7. Tunnel-Assignment-ID */
+ snprintf(buf, sizeof(buf), "L2TP-CALL-%d", call->id);
+ ATTR_STR(RADIUS_TYPE_TUNNEL_ASSIGNMENT_ID, buf);
+
+ /* RFC 2867 4.1. Acct-Tunnel-Connection */
+ snprintf(buf, sizeof(buf), "L2TP-CTRL-%d", ctrl->id);
+ ATTR_STR(RADIUS_TYPE_ACCT_TUNNEL_CONNECTION, buf);
+
+ return 0;
+reigai:
+#endif
+ return 1;
+}
diff --git a/usr.sbin/npppd/npppd/npppd_radius.h b/usr.sbin/npppd/npppd/npppd_radius.h
new file mode 100644
index 00000000000..e9b7d743681
--- /dev/null
+++ b/usr.sbin/npppd/npppd/npppd_radius.h
@@ -0,0 +1,16 @@
+#ifndef NPPPD_RADIUS_H
+#define NPPPD_RADIUS_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ppp_proccess_radius_framed_ip (npppd_ppp *, RADIUS_PACKET *);
+int ppp_set_radius_attrs_for_authreq (npppd_ppp *, radius_req_setting *, RADIUS_PACKET *);
+void npppd_ppp_radius_acct_start (npppd *, npppd_ppp *);
+void npppd_ppp_radius_acct_stop (npppd *, npppd_ppp *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/usr.sbin/npppd/npppd/pap.c b/usr.sbin/npppd/npppd/pap.c
index db8f9c1d87a..d5bf98408ee 100644
--- a/usr.sbin/npppd/npppd/pap.c
+++ b/usr.sbin/npppd/npppd/pap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pap.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: pap.c,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* $Id: pap.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $Id: pap.c,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/**@file
* This file provides Password Authentication Protocol (PAP) handlers.
* @author Yasuoka Masahiko
@@ -44,14 +44,18 @@
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <errno.h>
#include "slist.h"
#include "npppd.h"
#include "ppp.h"
#ifdef USE_NPPPD_RADIUS
+#include <radius+.h>
#include "radius_chap_const.h"
+#include "npppd_radius.h"
#endif
+
#include "debugutil.h"
#define AUTHREQ 0x01
@@ -89,7 +93,7 @@ static void pap_authenticate(pap *, const char *);
static void pap_local_authenticate (pap *, const char *, const char *);
#ifdef USE_NPPPD_RADIUS
static void pap_radius_authenticate (pap *, const char *, const char *);
-static void pap_radius_response (void *, RADIUS_PACKET *, int);
+static void pap_radius_response (void *, RADIUS_PACKET *, int, RADIUS_REQUEST_CTX);
#endif
#ifdef __cplusplus
@@ -307,8 +311,9 @@ pap_response(pap *_this, int authok, const char *mes)
"logtype=Failure username=\"%s\" realm=%s", _this->name,
realm);
pap_stop(_this);
- ppp_stop_ex(_this->ppp, "Authentication Required",
+ ppp_set_disconnect_cause(_this->ppp,
PPP_DISCON_AUTH_FAILED, PPP_PROTO_PAP, 1 /* peer */, NULL);
+ ppp_stop(_this->ppp, "Authentication Required");
} else {
strlcpy(_this->ppp->username, _this->name,
sizeof(_this->ppp->username));
@@ -388,7 +393,7 @@ pap_radius_authenticate(pap *_this, const char *username, const char *password)
radius_req_setting *rad_setting = NULL;
char buf0[MAX_USERNAME_LENGTH];
- if ((rad_setting = npppd_get_radius_req_setting(_this->ppp->pppd,
+ if ((rad_setting = npppd_get_radius_auth_setting(_this->ppp->pppd,
_this->ppp)) == NULL)
goto fail;
@@ -463,7 +468,8 @@ fail:
}
static void
-pap_radius_response(void *context, RADIUS_PACKET *pkt, int flags)
+pap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
+ RADIUS_REQUEST_CTX reqctx)
{
int code = -1;
const char *reason = NULL;
@@ -475,15 +481,12 @@ pap_radius_response(void *context, RADIUS_PACKET *pkt, int flags)
_this->radctx = NULL; /* important */
if (pkt == NULL) {
- if (flags & RADIUS_REQUST_TIMEOUT) {
+ if (flags & RADIUS_REQUEST_TIMEOUT)
reason = "timeout";
- npppd_radius_server_failure_notify(_this->ppp->pppd,
- _this->ppp, radctx, "request timeout");
- } else {
+ else if (flags & RADIUS_REQUEST_ERROR)
+ reason = strerror(errno);
+ else
reason = "error";
- npppd_radius_server_failure_notify(_this->ppp->pppd,
- _this->ppp, radctx, "unknown error");
- }
goto auth_failed;
}
code = radius_get_code(pkt);
@@ -494,11 +497,9 @@ pap_radius_response(void *context, RADIUS_PACKET *pkt, int flags)
reason="error";
goto auth_failed;
}
- if ((flags & RADIUS_REQUST_CHECK_AUTHENTICTOR_OK) == 0 &&
- (flags & RADIUS_REQUST_CHECK_AUTHENTICTOR_NO_CHECK) == 0) {
+ if ((flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK) == 0 &&
+ (flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK) == 0) {
reason="bad_authenticator";
- npppd_radius_server_failure_notify(_this->ppp->pppd, _this->ppp,
- radctx, "bad authenticator");
goto auth_failed;
}
/* Autentication succeeded */
diff --git a/usr.sbin/npppd/npppd/ppp.c b/usr.sbin/npppd/npppd/ppp.c
index 68740307922..fc772df8f5c 100644
--- a/usr.sbin/npppd/npppd/ppp.c
+++ b/usr.sbin/npppd/npppd/ppp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ppp.c,v 1.7 2010/09/24 14:50:30 yasuoka Exp $ */
+/* $OpenBSD: ppp.c,v 1.8 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* $Id: ppp.c,v 1.7 2010/09/24 14:50:30 yasuoka Exp $ */
+/* $Id: ppp.c,v 1.8 2011/07/06 20:52:28 yasuoka Exp $ */
/**@file
* This file provides PPP(Point-to-Point Protocol, RFC 1661) and
* {@link :: _npppd_ppp PPP instance} related functions.
@@ -54,6 +54,10 @@
#include "time_utils.h"
#include "ppp.h"
#include "psm-opt.h"
+#ifdef USE_NPPPD_RADIUS
+#include <radius+.h>
+#include "npppd_radius.h"
+#endif
#include "debugutil.h"
@@ -281,37 +285,54 @@ ppp_down_others(npppd_ppp *_this)
evtimer_del(&_this->idle_event);
}
-void
-ppp_stop(npppd_ppp *_this, const char *reason)
-{
- ppp_stop_ex(_this, reason, PPP_DISCON_NO_INFORMATION, 0, 0, NULL);
-}
-
/**
* Stop the PPP and destroy the npppd_ppp instance
* @param reason Reason of stopping the PPP. Specify NULL if there is
* no special reason. This reason will be used as a
* reason field of LCP Terminate-Request message and
* notified to the peer.
+ */
+void
+ppp_stop(npppd_ppp *_this, const char *reason)
+{
+
+ PPP_ASSERT(_this != NULL);
+
+#ifdef USE_NPPPD_RADIUS
+ ppp_set_radius_terminate_cause(_this,
+ RADIUS_TERMNATE_CAUSE_ADMIN_RESET);
+#endif
+ ppp_set_disconnect_cause(_this, PPP_DISCON_NORMAL, 0, 2 /* by local */,
+ NULL);
+
+ ppp_down_others(_this);
+ fsm_close(&_this->lcp.fsm, reason);
+}
+
+/**
+ * Set disconnect cause
* @param code disconnect code in {@link ::npppd_ppp_disconnect_code}.
* @param proto control protocol number. see RFC3145.
* @param direction disconnect direction. see RFC 3145
*/
void
-ppp_stop_ex(npppd_ppp *_this, const char *reason,
- npppd_ppp_disconnect_code code, int proto, int direction,
- const char *message)
+ppp_set_disconnect_cause(npppd_ppp *_this, npppd_ppp_disconnect_code code,
+ int proto, int direction, const char *message)
{
- PPP_ASSERT(_this != NULL);
-
if (_this->disconnect_code == PPP_DISCON_NO_INFORMATION) {
_this->disconnect_code = code;
_this->disconnect_proto = proto;
_this->disconnect_direction = direction;
_this->disconnect_message = message;
}
- ppp_down_others(_this);
- fsm_close(&_this->lcp.fsm, reason);
+}
+
+/** Set RADIUS Acct-Terminate-Cause code */
+void
+ppp_set_radius_terminate_cause(npppd_ppp *_this, int cause)
+{
+ if (_this->terminate_cause == 0)
+ _this->terminate_cause = cause;
}
static void
@@ -320,6 +341,12 @@ ppp_stop0(npppd_ppp *_this)
char mppe_str[BUFSIZ];
char label[512];
+#ifdef USE_NPPPD_RADIUS
+ ppp_set_radius_terminate_cause(_this, RADIUS_TERMNATE_CAUSE_NAS_ERROR);
+#endif
+ ppp_set_disconnect_cause(_this, PPP_DISCON_NORMAL, 0, 1 /* by local */,
+ NULL);
+
_this->end_monotime = get_monosec();
if (_this->phy_close != NULL)
@@ -372,6 +399,9 @@ ppp_stop0(npppd_ppp *_this)
_this->ierrors, _this->oerrors, mppe_str,
npppd_ppp_get_iface_name(_this->pppd, _this));
+#ifdef USE_NPPPD_RADIUS
+ npppd_ppp_radius_acct_stop(_this->pppd, _this);
+#endif
npppd_ppp_unbind_iface(_this->pppd, _this);
#ifdef USE_NPPPD_MPPE
mppe_fini(&_this->mppe);
@@ -500,6 +530,10 @@ ppp_phy_downed(npppd_ppp *_this)
fsm_lowerdown(&_this->lcp.fsm);
fsm_close(&_this->lcp.fsm, NULL);
+#ifdef USE_NPPPD_RADIUS
+ ppp_set_radius_terminate_cause(_this,
+ RADIUS_TERMNATE_CAUSE_LOST_CARRIER);
+#endif
ppp_stop0(_this);
}
@@ -592,6 +626,10 @@ ppp_idle_timeout(int fd, short evtype, void *context)
_this = context;
ppp_log(_this, LOG_NOTICE, "Idle timeout(%d sec)", _this->timeout_sec);
+#ifdef USE_NPPPD_RADIUS
+ ppp_set_radius_terminate_cause(_this,
+ RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT);
+#endif
ppp_stop(_this, NULL);
}
@@ -643,6 +681,10 @@ ppp_ipcp_opened(npppd_ppp *_this)
ipstr, npppd_ppp_get_iface_name(_this->pppd, _this),
(_this->lcp.dialin_proxy != 0)? " dialin_proxy=yes" : ""
);
+#ifdef USE_NPPPD_RADIUS
+ npppd_ppp_radius_acct_start(_this->pppd, _this);
+#endif
+
_this->logged_acct_start = 1;
ppp_reset_idle_timeout(_this);
}
diff --git a/usr.sbin/npppd/npppd/ppp.h b/usr.sbin/npppd/npppd/ppp.h
index 3f8658ba7ff..1b3879ef761 100644
--- a/usr.sbin/npppd/npppd/ppp.h
+++ b/usr.sbin/npppd/npppd/ppp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ppp.h,v 1.5 2010/09/24 02:57:43 yasuoka Exp $ */
+/* $OpenBSD: ppp.h,v 1.6 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -520,6 +520,9 @@ struct _npppd_ppp {
/** Address pool used by IP asssignment */
void *assigned_pool;
+ /** Framed-IP-Address for Accounting */
+ struct in_addr acct_framed_ip_address;
+
struct in_addr realm_framed_ip_address;
struct in_addr realm_framed_ip_netmask;
@@ -581,6 +584,9 @@ struct _npppd_ppp {
/** Number of output packet bytes */
uint64_t obytes;
+ /** RADIUS Accouting (RFC2866) Terminate Cause */
+ int terminate_cause;
+
/*
* Disconnect cause information for RFC3145
*/
@@ -746,7 +752,8 @@ int ppp_init (npppd *, npppd_ppp *);
void ppp_start (npppd_ppp *);
int ppp_dialin_proxy_prepare (npppd_ppp *, dialin_proxy_info *);
void ppp_stop (npppd_ppp *, const char *);
-void ppp_stop_ex (npppd_ppp *, const char *, npppd_ppp_disconnect_code, int, int, const char *);
+void ppp_set_disconnect_cause (npppd_ppp *, npppd_ppp_disconnect_code, int, int, const char *);
+void ppp_set_radius_terminate_cause(npppd_ppp *, int);
void ppp_destroy (void *);
void ppp_lcp_up (npppd_ppp *);
diff --git a/usr.sbin/npppd/npppd/radius+.c b/usr.sbin/npppd/npppd/radius+.c
index b067349b51f..bf37cb7a19f 100644
--- a/usr.sbin/npppd/npppd/radius+.c
+++ b/usr.sbin/npppd/npppd/radius+.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: radius+.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: radius+.c,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -33,10 +33,10 @@
#include <mpatrol.h>
#endif
+#include <sys/param.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
#include <md5.h>
#include "radius+.h"
#include "radiusconst.h"
@@ -185,6 +185,11 @@ u_int8_t radius_get_id(const RADIUS_PACKET* packet)
return packet->pdata->id;
}
+void radius_update_id(RADIUS_PACKET* packet)
+{
+ packet->pdata->id = radius_id_counter++;
+}
+
void radius_get_authenticator(const RADIUS_PACKET* packet, char* authenticator)
{
memcpy(authenticator, packet->pdata->authenticator, 16);
@@ -240,6 +245,23 @@ void radius_set_response_authenticator(RADIUS_PACKET* packet,
MD5Final((unsigned char*)packet->pdata->authenticator ,&ctx);
}
+void radius_set_request_authenticator(RADIUS_PACKET* packet,
+ const char* secret)
+{
+ MD5_CTX ctx;
+ u_char zero[16];
+
+ memset(zero, 0, sizeof(zero));
+ MD5Init(&ctx);
+ MD5Update(&ctx, (unsigned char*)packet->pdata, 4);
+ MD5Update(&ctx, zero, 16);
+ MD5Update(&ctx,
+ (unsigned char*)packet->pdata->attributes,
+ radius_get_length(packet) - 20);
+ MD5Update(&ctx, (unsigned char*)secret, strlen(secret));
+ MD5Final((unsigned char*)packet->pdata->authenticator ,&ctx);
+}
+
u_int16_t radius_get_length(const RADIUS_PACKET* packet)
{
return ntohs(packet->pdata->length);
@@ -348,6 +370,31 @@ int radius_put_raw_attr_all(RADIUS_PACKET* packet, u_int8_t type,
return 0;
}
+static int radius_set_raw_attr(RADIUS_PACKET* packet, u_int8_t type,
+ const void* buf, u_int8_t length)
+{
+ RADIUS_ATTRIBUTE* attr;
+ const RADIUS_ATTRIBUTE* end;
+
+ if(length > 255-2)
+ return 1;
+
+ attr = ATTRS_BEGIN(packet->pdata);
+ end = ATTRS_END(packet->pdata);
+
+ for(; attr<end; ADVANCE(attr))
+ {
+ if(attr->type != type)
+ continue;
+ if(attr->length != length + 2)
+ return 1; /* XXX */
+ memcpy(attr->data, buf, length);
+ return 0;
+ }
+
+ return 1;
+}
+
int radius_get_vs_raw_attr(const RADIUS_PACKET* packet, u_int32_t vendor,
u_int8_t vtype, void* buf, u_int8_t* length)
{
@@ -524,6 +571,14 @@ int radius_put_uint32_attr(RADIUS_PACKET* packet, u_int8_t type, u_int32_t val)
return radius_put_raw_attr(packet, type, &nval, sizeof(u_int32_t));
}
+int radius_set_uint32_attr(RADIUS_PACKET* packet, u_int8_t type, u_int32_t val)
+{
+ u_int32_t nval;
+
+ nval = htonl(val);
+ return radius_set_raw_attr(packet, type, &nval, sizeof(u_int32_t));
+}
+
int radius_get_string_attr(const RADIUS_PACKET* packet, u_int8_t type,
char* str)
{
@@ -590,6 +645,11 @@ int radius_put_ipv4_attr(RADIUS_PACKET* packet, u_int8_t type, struct in_addr ad
return radius_put_raw_attr(packet, type, &addr, sizeof(struct in_addr));
}
+int radius_set_ipv4_attr(RADIUS_PACKET* packet, u_int8_t type, struct in_addr addr)
+{
+ return radius_set_raw_attr(packet, type, &addr, sizeof(struct in_addr));
+}
+
RADIUS_PACKET* radius_recvfrom(int s, int flags, struct sockaddr* addr, socklen_t* len)
{
char buf[0x10000];
@@ -613,6 +673,28 @@ int radius_sendto(int s, const RADIUS_PACKET* packet,
return 0;
}
+RADIUS_PACKET* radius_recv(int s, int flags)
+{
+ char buf[0x10000];
+ ssize_t n;
+
+ n = recv(s, buf, sizeof(buf), flags);
+ if(n <= 0)
+ return NULL;
+
+ return radius_convert_packet(buf, (size_t)n);
+}
+
+int radius_send(int s, const RADIUS_PACKET* packet, int flags)
+{
+ ssize_t n;
+
+ n = send(s, packet->pdata, radius_get_length(packet), flags);
+ if(n != radius_get_length(packet))
+ return 1;
+ return 0;
+}
+
/**
* Calculate keyed-hashing for message authenticaiton using md5.
*
diff --git a/usr.sbin/npppd/npppd/radius+.h b/usr.sbin/npppd/npppd/radius+.h
index a239f17f045..0bdef81e3bf 100644
--- a/usr.sbin/npppd/npppd/radius+.h
+++ b/usr.sbin/npppd/npppd/radius+.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: radius+.h,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: radius+.h,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -55,11 +55,14 @@ int radius_delete_packet(RADIUS_PACKET* packet);
/* accessors - header values */
u_int8_t radius_get_id(const RADIUS_PACKET* packet);
+void radius_update_id(RADIUS_PACKET* packet);
u_int8_t radius_get_code(const RADIUS_PACKET* packet);
void radius_get_authenticator(const RADIUS_PACKET* packet, char* authenticator);
void radius_set_request_packet(RADIUS_PACKET* packet, const RADIUS_PACKET* response);
int radius_check_response_authenticator(const RADIUS_PACKET* packet, const char *secret);
const char* radius_get_authenticator_retval(const RADIUS_PACKET* packet);
+void radius_set_request_authenticator(RADIUS_PACKET* packet,
+ const char* secret);
void radius_set_response_authenticator(RADIUS_PACKET* packet,
const char* secret);
u_int16_t radius_get_length(const RADIUS_PACKET* packet);
@@ -93,6 +96,8 @@ u_int32_t radius_get_uint32_attr_retval(const RADIUS_PACKET* packet,
u_int8_t type);
int radius_put_uint32_attr(RADIUS_PACKET* packet, u_int8_t type, u_int32_t val);
+int radius_set_uint32_attr(RADIUS_PACKET* packet, u_int8_t type, u_int32_t val);
+
int radius_get_string_attr(const RADIUS_PACKET* packet, u_int8_t type,
char* str);
int radius_put_string_attr(RADIUS_PACKET* packet, u_int8_t type,
@@ -107,6 +112,8 @@ int radius_get_ipv4_attr(const RADIUS_PACKET* packet, u_int8_t type,
struct in_addr radius_get_ipv4_attr_retval(const RADIUS_PACKET* packet, u_int8_t type);
int radius_put_ipv4_attr(RADIUS_PACKET* packet, u_int8_t type,
struct in_addr addr);
+int radius_set_ipv4_attr(RADIUS_PACKET* packet, u_int8_t type,
+ struct in_addr addr);
int radius_put_message_authenticator(RADIUS_PACKET *packet, const char *secret);
int radius_check_message_authenticator(RADIUS_PACKET *packet,
const char *secret);
@@ -116,6 +123,8 @@ RADIUS_PACKET* radius_recvfrom(int s, int flags,
struct sockaddr* saddr, socklen_t* slen);
int radius_sendto(int s, const RADIUS_PACKET* packet, int flags,
const struct sockaddr* saddr, socklen_t slen);
+RADIUS_PACKET* radius_recv(int s, int flags);
+int radius_send(int s, const RADIUS_PACKET* packet, int flags);
/******* client support (sending request / receiving response) *******/
diff --git a/usr.sbin/npppd/npppd/radius+_local.h b/usr.sbin/npppd/npppd/radius+_local.h
index 450016cefc2..4d3601362ba 100644
--- a/usr.sbin/npppd/npppd/radius+_local.h
+++ b/usr.sbin/npppd/npppd/radius+_local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: radius+_local.h,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: radius+_local.h,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -77,8 +77,4 @@ extern u_int8_t radius_id_counter;
#define ATTRS_END(pdata) \
((RADIUS_ATTRIBUTE*)(((char*)pdata) + ntohs(pdata->length)))
-#ifndef MIN
-#define MIN(m,n) (((m) < (n))? (m) : (n))
-#endif
-
#endif /* RADIUSPLUS_LOCAL_H */
diff --git a/usr.sbin/npppd/npppd/radius_common.c b/usr.sbin/npppd/npppd/radius_common.c
index 39484590481..e69de29bb2d 100644
--- a/usr.sbin/npppd/npppd/radius_common.c
+++ b/usr.sbin/npppd/npppd/radius_common.c
@@ -1,74 +0,0 @@
-/* $OpenBSD: radius_common.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
-
-/*-
- * Copyright (c) 2009 Internet Initiative Japan Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/**@file
- * This file provides functions commonly used for RADIUS request.
- * @author Yasuoka Masahiko
- * $Id: radius_common.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $
- */
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <time.h>
-#include <event.h>
-#include <stdio.h>
-
-#include <radius+.h>
-#include <radiusconst.h>
-
-#include "slist.h"
-#include "npppd.h"
-#include "npppd_local.h"
-
-#include "radius_common.h"
-
-void
-ppp_proccess_radius_framed_ip_address(npppd_ppp *_this, RADIUS_PACKET *pkt)
-{
- uint8_t len;
- u_char buf[256], *bufp;
-
- if ((_this->pppd->ip_assign_flags & NPPPD_IP_ASSIGN_RADIUS) == 0)
- return;
-
- if (radius_get_raw_attr(pkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, buf,
- &len) != 0)
- return;
-
- bufp = buf;
- if (len == 4)
- GETLONG(_this->radius_framed_ip_address.s_addr, bufp);
-
-}
-
-radius_req_setting *
-npppd_get_radius_req_setting(npppd *_this)
-{
- return &_this->rad_auth;
-}
diff --git a/usr.sbin/npppd/npppd/radius_common.h b/usr.sbin/npppd/npppd/radius_common.h
index 0754232314b..e69de29bb2d 100644
--- a/usr.sbin/npppd/npppd/radius_common.h
+++ b/usr.sbin/npppd/npppd/radius_common.h
@@ -1,42 +0,0 @@
-/* $OpenBSD: radius_common.h,v 1.2 2010/07/02 21:20:57 yasuoka Exp $ */
-
-/*-
- * Copyright (c) 2009 Internet Initiative Japan Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#ifndef RADIUS_COMMON_H
-#define RADIUS_COMMON_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void ppp_proccess_radius_framed_ip_address (npppd_ppp *, RADIUS_PACKET *);
-radius_req_setting *npppd_get_radius_req_setting (npppd *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/usr.sbin/npppd/npppd/radius_req.c b/usr.sbin/npppd/npppd/radius_req.c
index 1d97ac0d8dc..1b9d098eb99 100644
--- a/usr.sbin/npppd/npppd/radius_req.c
+++ b/usr.sbin/npppd/npppd/radius_req.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: radius_req.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: radius_req.c,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -28,7 +28,7 @@
/**@file
* This file provides functions for RADIUS request using radius+.c and event(3).
* @author Yasuoka Masahiko
- * $Id: radius_req.c,v 1.3 2010/07/02 21:20:57 yasuoka Exp $
+ * $Id: radius_req.c,v 1.4 2011/07/06 20:52:28 yasuoka Exp $
*/
#include <sys/types.h>
#include <sys/param.h>
@@ -45,26 +45,40 @@
#include <time.h>
#include <event.h>
#include <string.h>
+#include <errno.h>
#include "radius_req.h"
+#ifndef nitems
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
struct overlapped {
struct event ev_sock;
int socket;
int ntry;
- int timeout;
+ int max_tries;
+ int failovers;
struct sockaddr_storage ss;
+ struct timespec req_time;
void *context;
radius_response *response_fn;
char secret[MAX_RADIUS_SECRET];
RADIUS_PACKET *pkt;
+ radius_req_setting *setting;
+ int acct_delay_time;
};
-static int radius_request0 (struct overlapped *);
+static int radius_request0 (struct overlapped *, int);
+static int radius_prepare_socket(struct overlapped *);
static void radius_request_io_event (int, short, void *);
-static int select_srcaddr(struct sockaddr const *, struct sockaddr *, socklen_t *);
+static void radius_on_response(RADIUS_REQUEST_CTX, RADIUS_PACKET *, int, int);
+static int select_srcaddr(struct sockaddr const *, struct sockaddr *, socklen_t *);
+static void radius_req_setting_ref(radius_req_setting *);
+static void radius_req_setting_unref(radius_req_setting *);
#ifdef RADIUS_REQ_DEBUG
+#define RADIUS_REQ_DBG(x) log_printf x
#define RADIUS_REQ_ASSERT(cond) \
if (!(cond)) { \
fprintf(stderr, \
@@ -74,6 +88,7 @@ static int select_srcaddr(struct sockaddr const *, struct sockaddr *, socklen_t
}
#else
#define RADIUS_REQ_ASSERT(cond)
+#define RADIUS_REQ_DBG(x)
#endif
/**
@@ -83,17 +98,17 @@ static int select_srcaddr(struct sockaddr const *, struct sockaddr *, socklen_t
void
radius_request(RADIUS_REQUEST_CTX ctx, RADIUS_PACKET *pkt)
{
+ uint32_t ival;
struct overlapped *lap;
RADIUS_REQ_ASSERT(pkt != NULL);
RADIUS_REQ_ASSERT(ctx != NULL);
lap = ctx;
lap->pkt = pkt;
- if (radius_request0(lap) != 0) {
- if (lap->response_fn != NULL)
- lap->response_fn(lap->context, NULL,
- RADIUS_REQUST_ERROR);
- }
+ if (radius_get_uint32_attr(pkt, RADIUS_TYPE_ACCT_DELAY_TIME, &ival)
+ == 0)
+ lap->acct_delay_time = 1;
+ radius_request0(lap, 0);
}
/**
@@ -156,6 +171,83 @@ fail:
return 1;
}
+
+/** Checks whether the request can fail over to another server */
+int
+radius_request_can_failover(RADIUS_REQUEST_CTX ctx)
+{
+ struct overlapped *lap;
+ radius_req_setting *setting;
+
+ lap = ctx;
+ setting = lap->setting;
+
+ if (lap->failovers >= setting->max_failovers)
+ return 0;
+ if (memcmp(&lap->ss, &setting->server[setting->curr_server].peer,
+ setting->server[setting->curr_server].peer.sin6.sin6_len) == 0)
+ /* flagged server doesn't differ from the last server. */
+ return 0;
+
+ return 1;
+}
+
+/** Send RADIUS request failing over to another server. */
+int
+radius_request_failover(RADIUS_REQUEST_CTX ctx)
+{
+ struct overlapped *lap;
+
+ lap = ctx;
+ RADIUS_REQ_ASSERT(lap != NULL);
+ RADIUS_REQ_ASSERT(lap->socket >= 0)
+
+ if (!radius_request_can_failover(lap))
+ return -1;
+
+ if (radius_prepare_socket(lap) != 0)
+ return -1;
+
+ if (radius_request0(lap, 1) != 0)
+ return -1;
+
+ lap->failovers++;
+
+ return 0;
+}
+
+static int
+radius_prepare_socket(struct overlapped *lap)
+{
+ int sock;
+ radius_req_setting *setting;
+ struct sockaddr *sa;
+
+ setting = lap->setting;
+ if (lap->socket >= 0)
+ close(lap->socket);
+ lap->socket = -1;
+
+ sa = (struct sockaddr *)&setting->server[setting->curr_server].peer;
+
+ if ((sock = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ log_printf(LOG_ERR, "socket() failed in %s: %m", __func__);
+ return -1;
+ }
+ if (connect(sock, sa, sa->sa_len) != 0) {
+ log_printf(LOG_ERR, "connect() failed in %s: %m", __func__);
+ close(sock);
+ return -1;
+ }
+ memcpy(&lap->ss, sa, sa->sa_len);
+ lap->socket = sock;
+ memcpy(lap->secret, setting->server[setting->curr_server].secret,
+ sizeof(lap->secret));
+ lap->ntry = lap->max_tries;
+
+ return 0;
+}
+
/**
* Prepare sending RADIUS request. This implementation will call back to
* notice that it receives the response or it fails for timeouts to the
@@ -175,9 +267,7 @@ int
radius_prepare(radius_req_setting *setting, void *context,
RADIUS_REQUEST_CTX *pctx, radius_response response_fn, int timeout)
{
- int sock;
struct overlapped *lap;
- struct sockaddr_in6 *sin6;
RADIUS_REQ_ASSERT(setting != NULL);
lap = NULL;
@@ -188,25 +278,30 @@ radius_prepare(radius_req_setting *setting, void *context,
log_printf(LOG_ERR, "malloc() failed in %s: %m", __func__);
goto fail;
}
- sin6 = &setting->server[setting->curr_server].peer.sin6;
- if ((sock = socket(sin6->sin6_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- log_printf(LOG_ERR, "socket() failed in %s: %m", __func__);
- goto fail;
- }
memset(lap, 0, sizeof(struct overlapped));
- memcpy(&lap->ss, &setting->server[setting->curr_server].peer,
- setting->server[setting->curr_server].peer.sin6.sin6_len);
-
- lap->socket = sock;
- lap->timeout = MIN(setting->timeout, timeout);
- lap->ntry = timeout / lap->timeout;
lap->context = context;
lap->response_fn = response_fn;
- memcpy(lap->secret, setting->server[setting->curr_server].secret,
- sizeof(lap->secret));
+ lap->socket = -1;
+ lap->setting = setting;
+
+ if (timeout != 0 &&
+ (setting->max_tries == 0 ||
+ timeout < setting->max_tries * setting->timeout))
+ lap->max_tries = timeout / setting->timeout;
+ else
+ lap->max_tries = setting->max_tries;
+
+ if (lap->max_tries <= 0)
+ lap->max_tries = 3; /* default max tries */
+
+ if (radius_prepare_socket(lap) != 0)
+ goto fail;
+
if (pctx != NULL)
*pctx = lap;
+ radius_req_setting_ref(setting);
+
return 0;
fail:
if (lap != NULL)
@@ -234,6 +329,8 @@ radius_cancel_request(RADIUS_REQUEST_CTX ctx)
radius_delete_packet(lap->pkt);
lap->pkt = NULL;
}
+ radius_req_setting_unref(lap->setting);
+
memset(lap->secret, 0x41, sizeof(lap->secret));
free(lap);
@@ -264,20 +361,47 @@ radius_get_server_address(RADIUS_REQUEST_CTX ctx)
}
static int
-radius_request0(struct overlapped *lap)
+radius_request0(struct overlapped *lap, int new_message)
{
struct timeval tv0;
RADIUS_REQ_ASSERT(lap->ntry > 0);
+ if (lap->acct_delay_time != 0) {
+ struct timespec curr, delta;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &curr) != 0) {
+ log_printf(LOG_CRIT,
+ "clock_gettime(CLOCK_MONOTONIC,) failed: %m");
+ RADIUS_REQ_ASSERT(0);
+ }
+ if (!timespecisset(&lap->req_time))
+ lap->req_time = curr;
+ else {
+ timespecsub(&curr, &lap->req_time, &delta);
+ if (radius_set_uint32_attr(lap->pkt,
+ RADIUS_TYPE_ACCT_DELAY_TIME, delta.tv_sec) == 0) {
+ radius_update_id(lap->pkt);
+ new_message = 1;
+ }
+ }
+ }
+ if (new_message) {
+ radius_set_request_authenticator(lap->pkt,
+ radius_get_server_secret(lap));
+ }
+
lap->ntry--;
- if (radius_sendto(lap->socket, lap->pkt, 0, (struct sockaddr *)
- &lap->ss, lap->ss.ss_len) != 0)
+ if (radius_send(lap->socket, lap->pkt, 0) != 0) {
+ log_printf(LOG_ERR, "sendto() failed in %s: %m",
+ __func__);
+ radius_on_response(lap, NULL, RADIUS_REQUEST_ERROR, 1);
return 1;
+ }
tv0.tv_usec = 0;
- tv0.tv_sec = lap->timeout;
+ tv0.tv_sec = lap->setting->timeout;
- event_set(&lap->ev_sock, lap->socket, EV_READ,
+ event_set(&lap->ev_sock, lap->socket, EV_READ | EV_PERSIST,
radius_request_io_event, lap);
event_add(&lap->ev_sock, &tv0);
@@ -295,53 +419,87 @@ radius_request_io_event(int fd, short evmask, void *context)
RADIUS_REQ_ASSERT(context != NULL);
+ lap = context;
+ respkt = NULL;
+ flags = 0;
if ((evmask & EV_READ) != 0) {
- lap = context;
- flags = 0;
-
RADIUS_REQ_ASSERT(lap->socket >= 0);
if (lap->socket < 0)
return;
RADIUS_REQ_ASSERT(lap->pkt != NULL);
-
memset(&ss, 0, sizeof(ss));
len = sizeof(ss);
- if ((respkt = radius_recvfrom(lap->socket, 0,
- (struct sockaddr *)&ss, &len)) == NULL) {
- log_printf(LOG_ERR, "recvfrom() failed in %s: %m",
- __func__);
- flags |= RADIUS_REQUST_ERROR;
+ if ((respkt = radius_recv(lap->socket, 0)) == NULL) {
+ RADIUS_REQ_DBG((LOG_DEBUG,
+ "radius_recv() on %s(): %m", __func__));
+ /*
+ * Ignore error by icmp. Wait a response from the
+ * server anyway, it may eventually become ready.
+ */
+ switch (errno) {
+ case EHOSTDOWN: case EHOSTUNREACH: case ECONNREFUSED:
+ return; /* sleep the rest of timeout time */
+ }
+ flags |= RADIUS_REQUEST_ERROR;
} else if (lap->secret[0] == '\0') {
- flags |= RADIUS_REQUST_CHECK_AUTHENTICTOR_NO_CHECK;
+ flags |= RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK;
} else {
radius_set_request_packet(respkt, lap->pkt);
if (!radius_check_response_authenticator(respkt,
lap->secret))
- flags |= RADIUS_REQUST_CHECK_AUTHENTICTOR_OK;
+ flags |= RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK;
}
-
- if (lap->response_fn != NULL)
- lap->response_fn(lap->context, respkt, flags);
-
- if (respkt != NULL)
- radius_delete_packet(respkt);
- radius_cancel_request(lap);
+ radius_on_response(lap, respkt, flags, 0);
+ radius_delete_packet(respkt);
} else if ((evmask & EV_TIMEOUT) != 0) {
- lap = context;
if (lap->ntry > 0) {
- if (radius_request0(lap) != 0) {
- if (lap->response_fn != NULL)
- lap->response_fn(lap->context, NULL,
- RADIUS_REQUST_ERROR);
- radius_cancel_request(lap);
- }
+ RADIUS_REQ_DBG((LOG_DEBUG,
+ "%s() timed out retry", __func__));
+ radius_request0(lap, 0);
return;
}
- if (lap->response_fn != NULL)
- lap->response_fn(lap->context, NULL,
- RADIUS_REQUST_TIMEOUT);
- radius_cancel_request(lap);
+ RADIUS_REQ_DBG((LOG_DEBUG, "%s() timed out", __func__));
+ flags |= RADIUS_REQUEST_TIMEOUT;
+ radius_on_response(lap, NULL, flags, 1);
+ }
+}
+
+static void
+radius_on_response(RADIUS_REQUEST_CTX ctx, RADIUS_PACKET *pkt, int flags,
+ int server_failure)
+{
+ struct overlapped *lap;
+ int failovers;
+
+ lap = ctx;
+ if (server_failure) {
+ int i, n;
+ struct sockaddr *sa_curr;
+
+ sa_curr = (struct sockaddr *)&lap->setting->server[
+ lap->setting->curr_server].peer;
+ if (sa_curr->sa_len == lap->ss.ss_len &&
+ memcmp(sa_curr, &lap->ss, sa_curr->sa_len) == 0) {
+ /*
+ * The server on failure is flagged as the current.
+ * change the current
+ */
+ for (i = 1; i < nitems(lap->setting->server); i++) {
+ n = (lap->setting->curr_server + i) %
+ nitems(lap->setting->server);
+ if (lap->setting->server[n].enabled) {
+ lap->setting->curr_server = n;
+ break;
+ }
+ }
+ }
}
+
+ failovers = lap->failovers;
+ if (lap->response_fn != NULL)
+ lap->response_fn(lap->context, pkt, flags, ctx);
+ if (failovers == lap->failovers)
+ radius_cancel_request(lap);
}
static int
@@ -367,3 +525,44 @@ fail:
return 1;
}
+
+radius_req_setting *
+radius_req_setting_create(void)
+{
+ radius_req_setting *setting;
+
+ if ((setting = malloc(sizeof(radius_req_setting))) == NULL)
+ return NULL;
+ memset(setting, 0, sizeof(radius_req_setting));
+
+ return setting;
+}
+
+int
+radius_req_setting_has_server(radius_req_setting *setting)
+{
+ return setting->server[setting->curr_server].enabled;
+}
+
+void
+radius_req_setting_destroy(radius_req_setting *setting)
+{
+ setting->destroyed = 1;
+
+ if (setting->refcnt == 0)
+ free(setting);
+}
+
+static void
+radius_req_setting_ref(radius_req_setting *setting)
+{
+ setting->refcnt++;
+}
+
+static void
+radius_req_setting_unref(radius_req_setting *setting)
+{
+ setting->refcnt--;
+ if (setting->destroyed)
+ radius_req_setting_destroy(setting);
+}
diff --git a/usr.sbin/npppd/npppd/radius_req.h b/usr.sbin/npppd/npppd/radius_req.h
index 65caf36bf00..b2a70146ca4 100644
--- a/usr.sbin/npppd/npppd/radius_req.h
+++ b/usr.sbin/npppd/npppd/radius_req.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: radius_req.h,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: radius_req.h,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -35,23 +35,23 @@
#define MAX_RADIUS_SERVERS 16
/** RADIUS request failed */
-#define RADIUS_REQUST_ERROR 0x0001
+#define RADIUS_REQUEST_ERROR 0x0001
/** RADIUS request timed out */
-#define RADIUS_REQUST_TIMEOUT 0x0002
+#define RADIUS_REQUEST_TIMEOUT 0x0002
/** response has valid authenticator */
-#define RADIUS_REQUST_CHECK_AUTHENTICTOR_OK 0x0010
+#define RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK 0x0010
/** authenticator is not checked */
-#define RADIUS_REQUST_CHECK_AUTHENTICTOR_NO_CHECK 0x0020
-
-/** type for callback function to receive the RADIUS response */
-typedef void (radius_response)(void *context, RADIUS_PACKET *pkt, int flags);
+#define RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK 0x0020
/** type for context to handle RADIUS request / response */
typedef void * RADIUS_REQUEST_CTX;
+/** type for callback function to receive the RADIUS response */
+typedef void (radius_response)(void *context, RADIUS_PACKET *pkt, int flags, RADIUS_REQUEST_CTX reqctx);
+
/** type for setting of RADIUS request */
typedef struct _radius_req_setting
{
@@ -74,18 +74,33 @@ typedef struct _radius_req_setting
int curr_server;
/** request timeout(in second) */
int timeout;
+ /** The maximum number of RADIUS request transmission */
+ int max_tries;
+ /** The maximum number of RADIUS request failover */
+ int max_failovers;
+
+ /** references by radius request */
+ int refcnt;
+ /** destroy is requested */
+ int destroyed;
+
} radius_req_setting;
#ifdef __cplusplus
extern "C" {
#endif
-int radius_prepare (radius_req_setting *, void *, RADIUS_REQUEST_CTX *, radius_response *, int);
-void radius_request (RADIUS_REQUEST_CTX, RADIUS_PACKET *);
-void radius_cancel_request (RADIUS_REQUEST_CTX);
-const char *radius_get_server_secret(RADIUS_REQUEST_CTX);
-struct sockaddr *radius_get_server_address(RADIUS_REQUEST_CTX);
-int radius_prepare_nas_address(radius_req_setting *, RADIUS_PACKET *);
+void radius_request (RADIUS_REQUEST_CTX, RADIUS_PACKET *);
+int radius_prepare_nas_address (radius_req_setting *, RADIUS_PACKET *);
+int radius_request_can_failover (RADIUS_REQUEST_CTX);
+int radius_request_failover (RADIUS_REQUEST_CTX);
+int radius_prepare (radius_req_setting *, void *, RADIUS_REQUEST_CTX *, radius_response, int);
+void radius_cancel_request (RADIUS_REQUEST_CTX);
+const char *radius_get_server_secret (RADIUS_REQUEST_CTX);
+struct sockaddr *radius_get_server_address (RADIUS_REQUEST_CTX);
+radius_req_setting *radius_req_setting_create (void);
+int radius_req_setting_has_server(radius_req_setting *);
+void radius_req_setting_destroy (radius_req_setting *);
#ifdef __cplusplus
}
diff --git a/usr.sbin/npppd/npppd/radiusconst.h b/usr.sbin/npppd/npppd/radiusconst.h
index 91056b4bcd0..0fbbe0a9e5f 100644
--- a/usr.sbin/npppd/npppd/radiusconst.h
+++ b/usr.sbin/npppd/npppd/radiusconst.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: radiusconst.h,v 1.3 2010/07/02 21:20:57 yasuoka Exp $ */
+/* $OpenBSD: radiusconst.h,v 1.4 2011/07/06 20:52:28 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -138,18 +138,18 @@
#define RADIUS_TYPE_TUNNEL_CLIENT_AUTH_ID 90
#define RADIUS_TYPE_TUNNEL_SERVER_AUTH_ID 91
-/* RFC 3162 "RADIUS and IPv6" */
-#define RADIUS_TYPE_NAS_IPV6_ADDRESS 95
-#define RADIUS_TYPE_FRAMED_INTERFACE_ID 96
-#define RADIUS_TYPE_FRAMED_IPV6_PREFIX 97
-#define RADIUS_TYPE_LOGIN_IPV6_HOST 98
-#define RADIUS_TYPE_FRAMED_IPV6_ROUTE 99
-#define RADIUS_TYPE_FRAMED_IPV6_POOL 100
/* RFC 2865 "5.6. Service-Type" */
-#define RADIUS_FRAMED_PROTOCOL_PPP 1
+#define RADIUS_FRAMED_PROTOCOL_PPP 1 /* PPP */
+#define RADIUS_FRAMED_PROTOCOL_SLIP 2 /* SLIP */
+#define RADIUS_FRAMED_PROTOCOL_ARAP 3 /* AppleTalk Remote Access Protocol
+ (ARAP) */
+#define RADIUS_FRAMED_PROTOCOL_GANDALF 4 /* Gandalf proprietary
+ SingleLink/MultiLink protocol */
+#define RADIUS_FRAMED_PROTOCOL_XYLOGICS 5 /* Xylogics proprietary IPX/SLIP */
+#define RADIUS_FRAMED_PROTOCOL_X75 6 /* X.75 Synchronous */
-/* RFC 2865 "5.7. Framed-Protocol" */
+/* RFC 2865 "5.7. Service-Type" */
#define RADIUS_SERVICE_TYPE_LOGIN 1
#define RADIUS_SERVICE_TYPE_FRAMED 2
#define RADIUS_SERVICE_TYPE_CB_LOGIN 3
@@ -197,6 +197,113 @@
/* unassigned? 32 */
#define RADIUS_VTYPE_MS_ARAP_CHALLENGE 33
+/* NAS-Port-Type: see RFC2865 */
+#define RADIUS_NAS_PORT_TYPE_ASYNC 0 /* Async */
+#define RADIUS_NAS_PORT_TYPE_SYNC 1 /* Sync */
+#define RADIUS_NAS_PORT_TYPE_ISDN_SYNC 2 /* ISDN Sync */
+#define RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V120 3 /* ISDN Async V.120 */
+#define RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V110 4 /* ISDN Async V.110 */
+#define RADIUS_NAS_PORT_TYPE_VIRTUAL 5 /* Virtual */
+#define RADIUS_NAS_PORT_TYPE_PIAFS 6 /* PIAFS */
+#define RADIUS_NAS_PORT_TYPE_HDLC_CLEAR_CHANNEL 7 /* HDLC Clear Channel */
+#define RADIUS_NAS_PORT_TYPE_X_25 8 /* X.25 */
+#define RADIUS_NAS_PORT_TYPE_X_75 9 /* X.75 */
+#define RADIUS_NAS_PORT_TYPE_G3_FAX 10 /* G.3 Fax */
+#define RADIUS_NAS_PORT_TYPE_SDSL 11 /* SDSL - Symmetric DSL */
+#define RADIUS_NAS_PORT_TYPE_ADSL_CAP 12 /* ADSL-CAP - Asymmetric DSL,
+ Carrierless Amplitude
+ Phase Modulation */
+#define RADIUS_NAS_PORT_TYPE_ADSL_DMT 13 /* ADSL-DMT - Asymmetric DSL,
+ Discrete Multi-Tone */
+#define RADIUS_NAS_PORT_TYPE_IDSL 14 /* IDSL - ISDN Digital
+ Subscriber Line */
+#define RADIUS_NAS_PORT_TYPE_ETHERNET 15 /* Ethernet */
+#define RADIUS_NAS_PORT_TYPE_XDSL 16 /* xDSL - Digital Subscriber
+ Line of unknown type */
+#define RADIUS_NAS_PORT_TYPE_CABLE 17 /* Cable */
+#define RADIUS_NAS_PORT_TYPE_WIRELESS 18 /* Wireless - Other */
+#define RADIUS_NAS_PORT_TYPE_WIRELESS_802_11 19 /* Wireless - IEEE 802.11 */
+
+
+/* RFC 2866 5.1. Acct-Status-Type */
+#define RADIUS_ACCT_STATUS_TYPE_START 1 /* Start */
+#define RADIUS_ACCT_STATUS_TYPE_STOP 2 /* Stop */
+#define RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE 3 /* Interim-Update */
+#define RADIUS_ACCT_STATUS_TYPE_ACCT_ON 7 /* Accounting-On */
+#define RADIUS_ACCT_STATUS_TYPE_ACCT_OFF 8 /* Accounting-Off */
+
+
+/* RFC 2866 5.6. Acct-Authentic */
+#define RADIUS_ACCT_AUTHENTIC_RADIUS 1 /* RADIUS */
+#define RADIUS_ACCT_AUTHENTIC_LOCAL 2 /* Local */
+#define RADIUS_ACCT_AUTHENTIC_REMOTE 3 /* Remote */
+
+
+/* RFC 2866 5.10. Acct-Terminate-Cause */
+#define RADIUS_TERMNATE_CAUSE_USER_REQUEST 1 /* User Request */
+#define RADIUS_TERMNATE_CAUSE_LOST_CARRIER 2 /* Lost Carrier */
+#define RADIUS_TERMNATE_CAUSE_LOST_SERVICE 3 /* Lost Service */
+#define RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT 4 /* Idle Timeout */
+#define RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT 5 /* Session Timeout */
+#define RADIUS_TERMNATE_CAUSE_ADMIN_RESET 6 /* Admin Reset */
+#define RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT 7 /* Admin Reboot */
+#define RADIUS_TERMNATE_CAUSE_PORT_ERROR 8 /* Port Error */
+#define RADIUS_TERMNATE_CAUSE_NAS_ERROR 9 /* NAS Error */
+#define RADIUS_TERMNATE_CAUSE_NAS_RESET 10 /* NAS Request */
+#define RADIUS_TERMNATE_CAUSE_NAS_REBOOT 11 /* NAS Reboot */
+#define RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED 12 /* Port Unneeded */
+#define RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED 13 /* Port Preempted */
+#define RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED 14 /* Port Suspended */
+#define RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL 15 /* Service Unavailable */
+#define RADIUS_TERMNATE_CAUSE_CALLBACK 16 /* Callback */
+#define RADIUS_TERMNATE_CAUSE_USER_ERROR 17 /* User Error */
+#define RADIUS_TERMNATE_CAUSE_HOST_REQUEST 18 /* Host Request */
+
+
+/* RFC 2868 3.1. Tunnel-Type */
+#define RADIUS_TUNNEL_TYPE_PPTP 1 /* Point-to-Point Tunneling Protocol
+ (PPTP) */
+#define RADIUS_TUNNEL_TYPE_L2F 2 /* Layer Two Forwarding (L2F) */
+#define RADIUS_TUNNEL_TYPE_L2TP 3 /* Layer Two Tunneling Protocol
+ (L2TP) */
+#define RADIUS_TUNNEL_TYPE_ATMP 4 /* Ascend Tunnel Management Protocol
+ (ATMP) */
+#define RADIUS_TUNNEL_TYPE_VTP 5 /* Virtual Tunneling Protocol (VTP)*/
+#define RADIUS_TUNNEL_TYPE_AH 6 /* IP Authentication Header in the
+ Tunnel-mode (AH) */
+#define RADIUS_TUNNEL_TYPE_IP 7 /* IP-in-IP Encapsulation (IP-IP) */
+#define RADIUS_TUNNEL_TYPE_MOBILE 8 /* Minimal IP-in-IP Encapsulation
+ (MIN-IP-IP) */
+#define RADIUS_TUNNEL_TYPE_ESP 9 /* IP Encapsulating Security Payload
+ in the Tunnel-mode (ESP) */
+#define RADIUS_TUNNEL_TYPE_GRE 10 /* Generic Route Encapsulation
+ (GRE) */
+#define RADIUS_TUNNEL_TYPE_VDS 11 /* Bay Dial Virtual Services (DVS) */
+#define RADIUS_TUNNEL_TYPE_IPIP 12 /* IP-in-IP Tunneling */
+
+/* RFC 2868 3.2. Tunnel-Medium-Type */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV4 1 /* IPv4 (IP version 4) */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2 /* IPv6 (IP version 6) */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_NSAP 3 /* NSAP */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_HDLC 4 /* HDLC (8-bit multidrop) */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_BBN1822 5 /* BBN 1822 */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_802 6 /* 802 (includes all 802
+ media plus Ethernet
+ "canonical format") */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_E163 7 /* E.163 (POTS) */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_E164 8 /* E.164 (SMDS, Frame Relay,
+ ATM) */
+
+
+/* RFC 3162 "RADIUS and IPv6" */
+#define RADIUS_TYPE_NAS_IPV6_ADDRESS 95
+#define RADIUS_TYPE_FRAMED_INTERFACE_ID 96
+#define RADIUS_TYPE_FRAMED_IPV6_PREFIX 97
+#define RADIUS_TYPE_LOGIN_IPV6_HOST 98
+#define RADIUS_TYPE_FRAMED_IPV6_ROUTE 99
+#define RADIUS_TYPE_FRAMED_IPV6_POOL 100
+
+
/* IIJ vendor specific attributes */
#define RADIUS_VENDOR_IIJ 770