diff --git a/regress/usr.bin/ssh/sftp-cmds.sh b/regress/usr.bin/ssh/sftp-cmds.sh
index 52189287d..7a4f2fbdd 100644
--- a/regress/usr.bin/ssh/sftp-cmds.sh
+++ b/regress/usr.bin/ssh/sftp-cmds.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: sftp-cmds.sh,v 1.19 2024/03/29 10:40:07 dtucker Exp $
+# $OpenBSD: sftp-cmds.sh,v 1.20 2024/07/01 03:10:19 djm Exp $
# Placed in the Public Domain.
# XXX - TODO:
@@ -22,7 +22,7 @@ rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
mkdir ${COPY}.dd
verbose "$tid: lls"
-printf "cd ${OBJ}\nlls\n" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
+printf "lcd ${OBJ}\nlls\n" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
grep copy.dd >/dev/null || fail "lls failed"
verbose "$tid: lls w/path"
diff --git a/regress/usr.sbin/syslogd/args-client-tls.pl b/regress/usr.sbin/syslogd/args-client-tls.pl
index 2fa726d9a..8a385f23b 100644
--- a/regress/usr.sbin/syslogd/args-client-tls.pl
+++ b/regress/usr.sbin/syslogd/args-client-tls.pl
@@ -32,7 +32,9 @@ our %args = (
loggrep => {
qr{Keyfile /etc/ssl/private/localhost.key} => 1,
qr{Certfile /etc/ssl/localhost.crt} => 1,
+ qr/Accepting tcp connection/ => 1,
qr/syslogd\[\d+\]: tls logger .* accepted/ => 1,
+ qr/Completed tls handshake/ => 1,
qr/syslogd\[\d+\]: tls logger .* connection close/ => 1,
},
},
diff --git a/sbin/iked/util.c b/sbin/iked/util.c
index 2cd34d12b..5d987eb66 100644
--- a/sbin/iked/util.c
+++ b/sbin/iked/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.44 2024/02/03 00:38:08 jsg Exp $ */
+/* $OpenBSD: util.c,v 1.45 2024/07/01 14:15:15 yasuoka Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter
@@ -644,16 +644,16 @@ prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
const char *
print_addr(void *addr)
{
- static char sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 7];
+ static char sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 9];
static int idx;
struct sockaddr *sa = addr;
- char *buf;
- size_t len;
+ char *buf, *hbuf;
+ size_t len, hlen;
char pbuf[7];
in_port_t port;
- buf = sbuf[idx];
- len = sizeof(sbuf[idx]);
+ hbuf = buf = sbuf[idx];
+ hlen = len = sizeof(sbuf[idx]);
if (++idx >= IKED_CYCLE_BUFFERS)
idx = 0;
@@ -662,13 +662,21 @@ print_addr(void *addr)
return (buf);
}
+ if ((port = socket_getport(sa)) != 0 && sa->sa_family == AF_INET6) {
+ /* surround [] */
+ *(hbuf++) = '[';
+ hlen--;
+ }
+
if (getnameinfo(sa, sa->sa_len,
- buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
+ hbuf, hlen, NULL, 0, NI_NUMERICHOST) != 0) {
strlcpy(buf, "unknown", len);
return (buf);
}
- if ((port = socket_getport(sa)) != 0) {
+ if (port != 0) {
+ if (sa->sa_family == AF_INET6)
+ (void)strlcat(buf, "]", len);
snprintf(pbuf, sizeof(pbuf), ":%d", port);
(void)strlcat(buf, pbuf, len);
}
diff --git a/sys/dev/ofw/ofw_thermal.c b/sys/dev/ofw/ofw_thermal.c
index 3e7ab6813..b895281f9 100644
--- a/sys/dev/ofw/ofw_thermal.c
+++ b/sys/dev/ofw/ofw_thermal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofw_thermal.c,v 1.9 2024/06/27 09:37:07 kettenis Exp $ */
+/* $OpenBSD: ofw_thermal.c,v 1.10 2024/07/01 14:13:43 kettenis Exp $ */
/*
* Copyright (c) 2019 Mark Kettenis
*
@@ -306,12 +306,12 @@ thermal_zone_poll(void *arg)
int32_t temp, delta;
int i;
+ tp = tz->tz_trips;
temp = thermal_get_temperature_cells(tz->tz_sensors);
if (temp == THERMAL_SENSOR_MAX)
goto out;
newtp = NULL;
- tp = tz->tz_trips;
for (i = 0; i < tz->tz_ntrips; i++) {
if (temp < tp->tp_temperature && tp != tz->tz_tp)
break;
@@ -372,7 +372,7 @@ out:
if (polling_delay > 0)
timeout_add_msec(&tz->tz_poll_to, polling_delay);
- else
+ else if (tp)
thermal_set_limit_cells(tz->tz_sensors, tp->tp_temperature);
}
diff --git a/usr.bin/bgplg/misc.c b/usr.bin/bgplg/misc.c
index fc5665f97..bf7f71486 100644
--- a/usr.bin/bgplg/misc.c
+++ b/usr.bin/bgplg/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.8 2017/12/18 09:12:49 job Exp $ */
+/* $OpenBSD: misc.c,v 1.9 2024/07/01 18:43:50 deraadt Exp $ */
/*
* Copyright (c) 2005, 2006 Reyk Floeter
@@ -79,10 +79,13 @@ lg_help(struct cmd *cmds, char **argv)
void
lg_sig_alarm(int sig)
{
+ int save_errno = errno;
+
if (child != -1) {
/* Forcibly kill the child, no excuse... */
kill(child, SIGKILL);
}
+ errno = save_errno;
}
int
diff --git a/usr.bin/openssl/speed.c b/usr.bin/openssl/speed.c
index f50d22406..84ecb9b3b 100644
--- a/usr.bin/openssl/speed.c
+++ b/usr.bin/openssl/speed.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: speed.c,v 1.34 2023/07/27 07:01:50 tb Exp $ */
+/* $OpenBSD: speed.c,v 1.35 2024/07/01 18:52:22 deraadt Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -150,7 +150,7 @@
#include "./testrsa.h"
#define BUFSIZE (1024*8+64)
-int run = 0;
+volatile sig_atomic_t run = 0;
static int mr = 0;
static int usertime = 1;
@@ -193,7 +193,10 @@ static void sig_done(int sig);
static void
sig_done(int sig)
{
+ int save_errno = errno;
+
signal(SIGALRM, sig_done);
+ errno = save_errno;
run = 0;
}
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c
index 2129c151f..c5296e32f 100644
--- a/usr.bin/ssh/clientloop.c
+++ b/usr.bin/ssh/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.407 2024/05/17 06:42:04 jsg Exp $ */
+/* $OpenBSD: clientloop.c,v 1.408 2024/07/01 04:31:17 djm Exp $ */
/*
* Author: Tatu Ylonen
* Copyright (c) 1995 Tatu Ylonen , Espoo, Finland
@@ -598,8 +598,9 @@ obfuscate_keystroke_timing(struct ssh *ssh, struct timespec *timeout,
if (timespeccmp(&now, &chaff_until, >=)) {
/* Stop if there have been no keystrokes for a while */
stop_reason = "chaff time expired";
- } else if (timespeccmp(&now, &next_interval, >=)) {
- /* Otherwise if we were due to send, then send chaff */
+ } else if (timespeccmp(&now, &next_interval, >=) &&
+ !ssh_packet_have_data_to_write(ssh)) {
+ /* If due to send but have no data, then send chaff */
if (send_chaff(ssh))
nchaff++;
}
diff --git a/usr.bin/ssh/version.h b/usr.bin/ssh/version.h
index f519deb89..8491b8656 100644
--- a/usr.bin/ssh/version.h
+++ b/usr.bin/ssh/version.h
@@ -1,3 +1,3 @@
-/* $OpenBSD: version.h,v 1.101 2024/03/11 04:59:47 djm Exp $ */
+/* $OpenBSD: version.h,v 1.102 2024/07/01 04:31:59 djm Exp $ */
-#define SSH_VERSION "OpenSSH_9.7"
+#define SSH_VERSION "OpenSSH_9.8"
diff --git a/usr.sbin/npppd/npppd/chap.c b/usr.sbin/npppd/npppd/chap.c
index 88c65a010..ac76db5fb 100644
--- a/usr.sbin/npppd/npppd/chap.c
+++ b/usr.sbin/npppd/npppd/chap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: chap.c,v 1.18 2024/02/26 08:47:28 yasuoka Exp $ */
+/* $OpenBSD: chap.c,v 1.19 2024/07/01 07:09:07 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -36,7 +36,7 @@
*
*/
/* RFC 1994, 2433 */
-/* $Id: chap.c,v 1.18 2024/02/26 08:47:28 yasuoka Exp $ */
+/* $Id: chap.c,v 1.19 2024/07/01 07:09:07 yasuoka Exp $ */
#include
#include
#include
@@ -914,7 +914,7 @@ chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
break;
}
}
- ppp_process_radius_framed_ip(_this->ppp, pkt);
+ ppp_process_radius_attrs(_this->ppp, pkt);
return;
auth_failed:
diff --git a/usr.sbin/npppd/npppd/npppd.conf.5 b/usr.sbin/npppd/npppd/npppd.conf.5
index 2c38b2221..ab2ed0b5d 100644
--- a/usr.sbin/npppd/npppd/npppd.conf.5
+++ b/usr.sbin/npppd/npppd/npppd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: npppd.conf.5,v 1.32 2023/03/02 17:09:53 jmc Exp $
+.\" $OpenBSD: npppd.conf.5,v 1.34 2024/07/01 14:56:19 jmc Exp $
.\"
.\" Copyright (c) 2012 YASUOKA Masahiko
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 2 2023 $
+.Dd $Mdocdate: July 1 2024 $
.Dt NPPPD.CONF 5
.Os
.Sh NAME
@@ -506,8 +506,20 @@ The default is
This option can be used multiple times.
.It Ic dns-servers Ar primary-server-address Op Ar secondary-server-address
Specify the DNS servers' IP addresses.
+When this option is not specified and the authenticated realm
+.Pq the RADIUS server
+specifies the DNS servers' addresses,
+they are used as the default.
+To stop using them, set this option to
+.Qq 0.0.0.0 .
.It Ic nbns-servers Ar primary-server-address Op Ar secondary-server-address
Specify the NetBIOS name servers' IP addresses.
+When this option is not specified and the authenticated realm
+.Pq the RADIUS server
+specifies the NetBIOS servers' addresses,
+they are used as the default.
+To stop using them, set this option to
+.Qq 0.0.0.0 .
.It Ic allow-user-selected-address Ar yes | no
Specify whether
.Xr npppd 8
diff --git a/usr.sbin/npppd/npppd/npppd.h b/usr.sbin/npppd/npppd/npppd.h
index 3fc4e9677..3cf9b2bcb 100644
--- a/usr.sbin/npppd/npppd/npppd.h
+++ b/usr.sbin/npppd/npppd/npppd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd.h,v 1.19 2017/08/12 11:20:34 goda Exp $ */
+/* $OpenBSD: npppd.h,v 1.20 2024/07/01 07:09:07 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -174,7 +174,9 @@ struct ipcpconf {
TAILQ_ENTRY(ipcpconf) entry;
char name[NPPPD_GENERIC_NAME_LEN];
bool dns_use_resolver;
+ bool dns_configured;
struct in_addr dns_servers[2];
+ bool nbns_configured;
struct in_addr nbns_servers[2];
bool allow_user_select;
struct in_addr_range *dynamic_pool;
diff --git a/usr.sbin/npppd/npppd/npppd_radius.c b/usr.sbin/npppd/npppd/npppd_radius.c
index 640e9a440..2d3ef6f9d 100644
--- a/usr.sbin/npppd/npppd/npppd_radius.c
+++ b/usr.sbin/npppd/npppd/npppd_radius.c
@@ -1,4 +1,4 @@
-/* $Id: npppd_radius.c,v 1.10 2024/02/26 10:42:05 yasuoka Exp $ */
+/* $Id: npppd_radius.c,v 1.11 2024/07/01 07:09:07 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
* All rights reserved.
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -73,10 +74,11 @@ static void npppd_ppp_radius_acct_reqcb(void *, RADIUS_PACKET *, int, RADIUS_REQ
* 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)
+ppp_process_radius_attrs(npppd_ppp *_this, RADIUS_PACKET *pkt)
{
- struct in_addr ip4;
-
+ struct in_addr ip4;
+ int got_pri, got_sec;
+ char buf0[40], buf1[40];
if (radius_get_ipv4_attr(pkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, &ip4)
== 0)
_this->realm_framed_ip_address = ip4;
@@ -87,6 +89,53 @@ ppp_proccess_radius_framed_ip(npppd_ppp *_this, RADIUS_PACKET *pkt)
== 0)
_this->realm_framed_ip_netmask = ip4;
#endif
+
+ if (!ppp_ipcp(_this)->dns_configured) {
+ got_pri = got_sec = 0;
+ if (radius_get_vs_ipv4_attr(pkt, RADIUS_VENDOR_MICROSOFT,
+ RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, &ip4) == 0) {
+ got_pri = 1;
+ _this->ipcp.dns_pri = ip4;
+ }
+ if (radius_get_vs_ipv4_attr(pkt, RADIUS_VENDOR_MICROSOFT,
+ RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER, &ip4) == 0) {
+ got_sec = 1;
+ _this->ipcp.dns_sec = ip4;
+ }
+ if (got_pri || got_sec)
+ ppp_log(_this, LOG_INFO, "DNS server address%s "
+ "(%s%s%s) %s configured by RADIUS server",
+ ((got_pri + got_sec) > 1)? "es" : "",
+ (got_pri)? inet_ntop(AF_INET, &_this->ipcp.dns_pri,
+ buf0, sizeof(buf0)) : "",
+ (got_pri != 0 && got_sec != 0)? "," : "",
+ (got_sec)? inet_ntop(AF_INET, &_this->ipcp.dns_sec,
+ buf1, sizeof(buf1)) : "",
+ ((got_pri + got_sec) > 1)? "are" : "is");
+ }
+ if (!ppp_ipcp(_this)->nbns_configured) {
+ got_pri = got_sec = 0;
+ if (radius_get_vs_ipv4_attr(pkt, RADIUS_VENDOR_MICROSOFT,
+ RADIUS_VTYPE_MS_PRIMARY_NBNS_SERVER, &ip4) == 0) {
+ got_pri = 1;
+ _this->ipcp.nbns_pri = ip4;
+ }
+ if (radius_get_vs_ipv4_attr(pkt, RADIUS_VENDOR_MICROSOFT,
+ RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER, &ip4) == 0) {
+ got_sec = 1;
+ _this->ipcp.nbns_sec = ip4;
+ }
+ if (got_pri || got_sec)
+ ppp_log(_this, LOG_INFO, "NBNS server address%s "
+ "(%s%s%s) %s configured by RADIUS server",
+ ((got_pri + got_sec) > 1)? "es" : "",
+ (got_pri)? inet_ntop(AF_INET, &_this->ipcp.nbns_pri,
+ buf0, sizeof(buf0)) : "",
+ (got_pri != 0 && got_sec != 0)? "," : "",
+ (got_sec)? inet_ntop(AF_INET, &_this->ipcp.nbns_sec,
+ buf1, sizeof(buf1)) : "",
+ ((got_pri + got_sec) > 1)? "are" : "is");
+ }
}
/***********************************************************************
@@ -480,3 +529,35 @@ fail:
#endif
return 1;
}
+
+/**
+ * Set RADIUS attributes for RADIUS authentication request.
+ * Return 0 on success.
+ */
+int
+ppp_set_radius_attrs_for_authreq(npppd_ppp *_this,
+ radius_req_setting *rad_setting, RADIUS_PACKET *radpkt)
+{
+ /* RFC 2865 "5.4 NAS-IP-Address" or RFC3162 "2.1. NAS-IPv6-Address" */
+ if (radius_prepare_nas_address(rad_setting, radpkt) != 0)
+ goto fail;
+
+ /* RFC 2865 "5.6. Service-Type" */
+ if (radius_put_uint32_attr(radpkt, RADIUS_TYPE_SERVICE_TYPE,
+ RADIUS_SERVICE_TYPE_FRAMED) != 0)
+ goto fail;
+
+ /* RFC 2865 "5.7. Framed-Protocol" */
+ if (radius_put_uint32_attr(radpkt, RADIUS_TYPE_FRAMED_PROTOCOL,
+ RADIUS_FRAMED_PROTOCOL_PPP) != 0)
+ goto fail;
+
+ if (_this->calling_number[0] != '\0') {
+ if (radius_put_string_attr(radpkt,
+ RADIUS_TYPE_CALLING_STATION_ID, _this->calling_number) != 0)
+ return 1;
+ }
+ return 0;
+fail:
+ return 1;
+}
diff --git a/usr.sbin/npppd/npppd/pap.c b/usr.sbin/npppd/npppd/pap.c
index b9b2f334f..f981809ee 100644
--- a/usr.sbin/npppd/npppd/pap.c
+++ b/usr.sbin/npppd/npppd/pap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pap.c,v 1.13 2024/02/26 08:47:28 yasuoka Exp $ */
+/* $OpenBSD: pap.c,v 1.14 2024/07/01 07:09:07 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.13 2024/02/26 08:47:28 yasuoka Exp $ */
+/* $Id: pap.c,v 1.14 2024/07/01 07:09:07 yasuoka Exp $ */
/**@file
* This file provides Password Authentication Protocol (PAP) handlers.
* @author Yasuoka Masahiko
@@ -508,7 +508,7 @@ pap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
}
/* Authentication succeeded */
pap_response(_this, 1, DEFAULT_SUCCESS_MESSAGE);
- ppp_process_radius_framed_ip(_this->ppp, pkt);
+ ppp_process_radius_attrs(_this->ppp, pkt);
return;
auth_failed:
diff --git a/usr.sbin/npppd/npppd/parse.y b/usr.sbin/npppd/npppd/parse.y
index 669e3050e..a589c5a70 100644
--- a/usr.sbin/npppd/npppd/parse.y
+++ b/usr.sbin/npppd/npppd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.27 2023/04/19 13:33:37 jsg Exp $ */
+/* $OpenBSD: parse.y,v 1.28 2024/07/01 07:09:07 yasuoka Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer
@@ -818,19 +818,23 @@ ipcpopt : POOL_ADDRESS STRING ipcppooltype {
}
| DNS_SERVERS in4_addr in4_addr {
curr_ipcpconf->dns_use_resolver = false;
+ curr_ipcpconf->dns_configured = true;
curr_ipcpconf->dns_servers[0] = $2;
curr_ipcpconf->dns_servers[1] = $3;
}
| DNS_SERVERS in4_addr {
curr_ipcpconf->dns_use_resolver = false;
+ curr_ipcpconf->dns_configured = true;
curr_ipcpconf->dns_servers[0] = $2;
curr_ipcpconf->dns_servers[1].s_addr = 0;
}
| NBNS_SERVERS in4_addr in4_addr {
+ curr_ipcpconf->nbns_configured = true;
curr_ipcpconf->nbns_servers[0] = $2;
curr_ipcpconf->nbns_servers[1] = $3;
}
| NBNS_SERVERS in4_addr {
+ curr_ipcpconf->nbns_configured = true;
curr_ipcpconf->nbns_servers[0] = $2;
curr_ipcpconf->nbns_servers[1].s_addr = 0;
}
diff --git a/usr.sbin/npppd/npppd/ppp.c b/usr.sbin/npppd/npppd/ppp.c
index 64716acc9..5aff7506f 100644
--- a/usr.sbin/npppd/npppd/ppp.c
+++ b/usr.sbin/npppd/npppd/ppp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ppp.c,v 1.31 2024/02/26 10:42:05 yasuoka Exp $ */
+/* $OpenBSD: ppp.c,v 1.32 2024/07/01 07:09:07 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.31 2024/02/26 10:42:05 yasuoka Exp $ */
+/* $Id: ppp.c,v 1.32 2024/07/01 07:09:07 yasuoka Exp $ */
/**@file
* This file provides PPP(Point-to-Point Protocol, RFC 1661) and
* {@link :: _npppd_ppp PPP instance} related functions.
@@ -1061,65 +1061,6 @@ ppp_log(npppd_ppp *_this, int prio, const char *fmt, ...)
return status;
}
-#ifdef USE_NPPPD_RADIUS
-#define UCHAR_BUFSIZ 255
-/**
- * Process the Framed-IP-Address attribute and the Framed-IP-Netmask
- * attribute of given RADIUS packet.
- */
-void
-ppp_process_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;
- if (radius_get_ipv4_attr(pkt, RADIUS_TYPE_FRAMED_IP_NETMASK, &ip4)
- == 0)
- _this->realm_framed_ip_netmask = ip4;
-}
-
-/**
- * Set RADIUS attributes for RADIUS authentication request.
- * Return 0 on success.
- */
-int
-ppp_set_radius_attrs_for_authreq(npppd_ppp *_this,
- radius_req_setting *rad_setting, RADIUS_PACKET *radpkt)
-{
- /* RFC 2865 "5.4 NAS-IP-Address" or RFC3162 "2.1. NAS-IPv6-Address" */
- if (radius_prepare_nas_address(rad_setting, radpkt) != 0)
- goto fail;
-
- /* RFC 2865 5.32. NAS-Identifier */
- if (radius_put_string_attr(radpkt, RADIUS_TYPE_NAS_IDENTIFIER, "npppd")
- != 0)
- goto fail;
-
- /* RFC 2865 "5.6. Service-Type" */
- if (radius_put_uint32_attr(radpkt, RADIUS_TYPE_SERVICE_TYPE,
- RADIUS_SERVICE_TYPE_FRAMED) != 0)
- goto fail;
-
- /* RFC 2865 "5.7. Framed-Protocol" */
- if (radius_put_uint32_attr(radpkt, RADIUS_TYPE_FRAMED_PROTOCOL,
- RADIUS_FRAMED_PROTOCOL_PPP) != 0)
- goto fail;
-
- if (_this->calling_number[0] != '\0') {
- if (radius_put_string_attr(radpkt,
- RADIUS_TYPE_CALLING_STATION_ID, _this->calling_number) != 0)
- return 1;
- }
- return 0;
-fail:
- return 1;
-}
-#endif
-
#ifdef USE_NPPPD_PIPEX
/** The callback function on network is available for pipex */
static void
diff --git a/usr.sbin/npppd/npppd/ppp.h b/usr.sbin/npppd/npppd/ppp.h
index ebabe30fa..c42059af0 100644
--- a/usr.sbin/npppd/npppd/ppp.h
+++ b/usr.sbin/npppd/npppd/ppp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ppp.h,v 1.24 2022/12/28 21:30:17 jmc Exp $ */
+/* $OpenBSD: ppp.h,v 1.25 2024/07/01 07:09:07 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -779,7 +779,7 @@ u_char *ppp_packetbuf (npppd_ppp *, int);
int ppp_log (npppd_ppp *, int, const char *, ...) __printflike(3,4);
void ppp_reset_idle_timeout(npppd_ppp *);
#ifdef USE_NPPPD_RADIUS
-void ppp_process_radius_framed_ip (npppd_ppp *, RADIUS_PACKET *);
+void ppp_process_radius_attrs (npppd_ppp *, RADIUS_PACKET *);
int ppp_set_radius_attrs_for_authreq (npppd_ppp *, radius_req_setting *, RADIUS_PACKET *);
#endif
struct tunnconf *ppp_get_tunnconf(npppd_ppp *);
diff --git a/usr.sbin/radiusd/parse.y b/usr.sbin/radiusd/parse.y
index a382dd499..6513ca5c4 100644
--- a/usr.sbin/radiusd/parse.y
+++ b/usr.sbin/radiusd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.17 2023/09/08 05:56:22 yasuoka Exp $ */
+/* $OpenBSD: parse.y,v 1.20 2024/07/02 00:33:51 yasuoka Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer
@@ -37,14 +37,17 @@
#include "log.h"
static struct radiusd *conf;
-static struct radiusd_authentication authen;
-static struct radiusd_client client;
+static struct radiusd_authentication authen;
+static struct radiusd_module *conf_module = NULL;
+static struct radiusd_client client;
-static struct radiusd_module *find_module (const char *);
-static void free_str_l (void *);
-static struct radiusd_module_ref *create_module_ref (const char *);
-static void radiusd_authentication_init (struct radiusd_authentication *);
-static void radiusd_client_init (struct radiusd_client *);
+static struct radiusd_module *find_module(const char *);
+static void free_str_l(void *);
+static struct radiusd_module_ref *create_module_ref(const char *);
+static void radiusd_authentication_init(struct radiusd_authentication *);
+static void radiusd_client_init(struct radiusd_client *);
+static const char
+ *default_module_path(const char *);
TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
static struct file {
@@ -89,17 +92,18 @@ typedef struct {
%}
%token INCLUDE LISTEN ON PORT CLIENT SECRET LOAD MODULE MSGAUTH_REQUIRED
-%token AUTHENTICATE AUTHENTICATE_BY DECORATE_BY SET
-%token ERROR YES NO
+%token ACCOUNT ACCOUNTING AUTHENTICATE AUTHENTICATE_BY BY DECORATE_BY QUICK
+%token SET TO ERROR YES NO
%token STRING
%token NUMBER
-%type optport
+%type optport optacct
%type listen_addr
-%type str_l
+%type str_l optdeco
%type prefix
-%type yesno
+%type yesno optquick
%type strnum
%type key
+%type optstring
%%
grammar : /* empty */
@@ -109,6 +113,7 @@ grammar : /* empty */
| grammar client '\n'
| grammar module '\n'
| grammar authenticate '\n'
+ | grammar account '\n'
| grammar error '\n'
;
@@ -139,7 +144,7 @@ outofmemory:
*n = $3;
TAILQ_INSERT_TAIL(&conf->listen, n, next);
}
-listen_addr : STRING optport {
+listen_addr : STRING optacct optport {
int gai_errno;
struct addrinfo hints, *res;
@@ -160,11 +165,22 @@ listen_addr : STRING optport {
free($1);
$$.stype = res->ai_socktype;
$$.sproto = res->ai_protocol;
+ $$.accounting = $2;
memcpy(&$$.addr, res->ai_addr, res->ai_addrlen);
- $$.addr.ipv4.sin_port = ($2 == 0)?
- htons(RADIUS_DEFAULT_PORT) : htons($2);
+ if ($3 != 0)
+ $$.addr.ipv4.sin_port = htons($3);
+ else if ($2)
+ $$.addr.ipv4.sin_port =
+ htons(RADIUS_ACCT_DEFAULT_PORT);
+ else
+ $$.addr.ipv4.sin_port =
+ htons(RADIUS_DEFAULT_PORT);
+
freeaddrinfo(res);
}
+optacct : ACCOUNTING { $$ = 1; }
+ | { $$ = 0; }
+ ;
optport : { $$ = 0; }
| PORT NUMBER { $$ = $2; }
;
@@ -265,7 +281,45 @@ prefix : STRING '/' NUMBER {
freeaddrinfo(res);
}
;
-module : MODULE LOAD STRING STRING {
+module : MODULE STRING optstring {
+ const char *path = $3;
+ if (path == NULL && (path = default_module_path($2))
+ == NULL) {
+ yyerror("default path for `%s' is unknown.",
+ $2);
+ free($2);
+ free($3);
+ YYERROR;
+ }
+ conf_module = radiusd_module_load(conf, path, $2);
+ free($2);
+ free($3);
+ if (conf_module == NULL)
+ YYERROR;
+ TAILQ_INSERT_TAIL(&conf->module, conf_module, next);
+ conf_module = NULL;
+ }
+ | MODULE STRING optstring {
+ const char *path = $3;
+ if (path == NULL && (path = default_module_path($2))
+ == NULL) {
+ yyerror("default path for `%s' is unknown.",
+ $2);
+ free($2);
+ free($3);
+ YYERROR;
+ }
+ conf_module = radiusd_module_load(conf, path, $2);
+ free($2);
+ free($3);
+ if (conf_module == NULL)
+ YYERROR;
+ } '{' moduleopts '}' {
+ TAILQ_INSERT_TAIL(&conf->module, conf_module, next);
+ conf_module = NULL;
+ }
+ /* following syntaxes are for backward compatilities */
+ | MODULE LOAD STRING STRING {
struct radiusd_module *module;
if ((module = radiusd_module_load(conf, $4, $3))
== NULL) {
@@ -303,34 +357,104 @@ setstrerr:
}
;
+moduleopts : moduleopts '\n' moduleopt
+ | moduleopt
+ ;
+moduleopt : /* empty */
+ | SET key str_l {
+ if ($2[0] == '_') {
+ yyerror("setting `%s' is not allowed", $2);
+ free($2);
+ free_str_l(&$3);
+ YYERROR;
+ }
+ if (radiusd_module_set(conf_module, $2, $3.c, $3.v)) {
+ yyerror("syntax error by module `%s'",
+ conf_module->name);
+ free($2);
+ free_str_l(&$3);
+ YYERROR;
+ }
+ free($2);
+ free_str_l(&$3);
+ }
+ ;
+
key : STRING
| SECRET { $$ = strdup("secret"); }
;
-authenticate : AUTHENTICATE {
+authenticate : AUTHENTICATE str_l BY STRING optdeco {
+ int i;
+ struct radiusd_authentication *auth;
+ struct radiusd_module_ref *modref, *modreft;
+
+ if ((auth = calloc(1,
+ sizeof(struct radiusd_authentication))) == NULL) {
+ yyerror("Out of memory: %s", strerror(errno));
+ goto authenticate_error;
+ }
+ modref = create_module_ref($4);
+ if ((auth->auth = create_module_ref($4)) == NULL)
+ goto authenticate_error;
+ auth->username = $2.v;
+ TAILQ_INIT(&auth->deco);
+ for (i = 0; i < $5.c; i++) {
+ if ((modref = create_module_ref($5.v[i]))
+ == NULL)
+ goto authenticate_error;
+ TAILQ_INSERT_TAIL(&auth->deco, modref, next);
+ }
+ TAILQ_INSERT_TAIL(&conf->authen, auth, next);
+ auth = NULL;
+ authenticate_error:
+ if (auth != NULL) {
+ free(auth->auth);
+ TAILQ_FOREACH_SAFE(modref, &auth->deco, next,
+ modreft) {
+ TAILQ_REMOVE(&auth->deco, modref, next);
+ free(modref);
+ }
+ free_str_l(&$2);
+ }
+ free(auth);
+ free($4);
+ free_str_l(&$5);
+ }
+ /* the followings are for backward compatibilities */
+ | AUTHENTICATE str_l optnl '{' {
radiusd_authentication_init(&authen);
- } str_l optnl '{' authopts '}' {
- struct radiusd_authentication *a;
+ authen.username = $2.v;
+ } authopts '}' {
+ int i;
+ struct radiusd_authentication *a;
if (authen.auth == NULL) {
- free_str_l(&$3);
yyerror("no authentication module specified");
+ for (i = 0; authen.username[i] != NULL; i++)
+ free(authen.username[i]);
+ free(authen.username);
YYERROR;
}
if ((a = calloc(1,
sizeof(struct radiusd_authentication))) == NULL) {
- free_str_l(&$3);
+ for (i = 0; authen.username[i] != NULL; i++)
+ free(authen.username[i]);
+ free(authen.username);
goto outofmemory;
}
a->auth = authen.auth;
authen.auth = NULL;
a->deco = authen.deco;
- a->username = $3.v;
-
+ a->username = authen.username;
TAILQ_INSERT_TAIL(&conf->authen, a, next);
}
;
+optdeco : { $$.c = 0; $$.v = NULL; }
+ | DECORATE_BY str_l { $$ = $2; }
+ ;
+
authopts : authopts '\n' authopt
| authopt
;
@@ -363,8 +487,53 @@ authopt : AUTHENTICATE_BY STRING {
}
free_str_l(&$2);
}
- |
;
+
+account : ACCOUNT optquick str_l TO STRING optdeco {
+ int i, error = 1;
+ struct radiusd_accounting *acct;
+ struct radiusd_module_ref *modref, *modreft;
+
+ if ((acct = calloc(1,
+ sizeof(struct radiusd_authentication))) == NULL) {
+ yyerror("Out of memory: %s", strerror(errno));
+ goto account_error;
+ }
+ if ((acct->acct = create_module_ref($5)) == NULL)
+ goto account_error;
+ acct->username = $3.v;
+ acct->quick = $2;
+ TAILQ_INIT(&acct->deco);
+ for (i = 0; i < $6.c; i++) {
+ if ((modref = create_module_ref($6.v[i]))
+ == NULL)
+ goto account_error;
+ TAILQ_INSERT_TAIL(&acct->deco, modref, next);
+ }
+ TAILQ_INSERT_TAIL(&conf->account, acct, next);
+ acct = NULL;
+ error = 0;
+ account_error:
+ if (acct != NULL) {
+ free(acct->acct);
+ TAILQ_FOREACH_SAFE(modref, &acct->deco, next,
+ modreft) {
+ TAILQ_REMOVE(&acct->deco, modref, next);
+ free(modref);
+ }
+ free_str_l(&$3);
+ }
+ free(acct);
+ free($5);
+ free_str_l(&$6);
+ if (error > 0)
+ YYERROR;
+ }
+ ;
+
+optquick : { $$ = 0; }
+ | QUICK { $$ = 1; }
+
str_l : str_l strnum {
int i;
char **v;
@@ -397,6 +566,9 @@ strnum : STRING { $$ = $1; }
optnl :
| '\n'
;
+optstring : { $$ = NULL; }
+ | STRING { $$ = $1; }
+ ;
yesno : YES { $$ = true; }
| NO { $$ = false; }
;
@@ -434,8 +606,11 @@ lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
+ { "account", ACCOUNT},
+ { "accounting", ACCOUNTING},
{ "authenticate", AUTHENTICATE},
{ "authenticate-by", AUTHENTICATE_BY},
+ { "by", BY},
{ "client", CLIENT},
{ "decorate-by", DECORATE_BY},
{ "include", INCLUDE},
@@ -446,8 +621,10 @@ lookup(char *s)
{ "no", NO},
{ "on", ON},
{ "port", PORT},
+ { "quick", QUICK},
{ "secret", SECRET},
{ "set", SET},
+ { "to", TO},
{ "yes", YES},
};
const struct keywords *p;
@@ -724,7 +901,6 @@ parse_config(const char *filename, struct radiusd *radiusd)
{
int errors = 0;
struct radiusd_listen *l;
- struct radiusd_module_ref *m, *mt;
conf = radiusd;
radiusd_conf_init(conf);
@@ -758,10 +934,8 @@ parse_config(const char *filename, struct radiusd *radiusd)
l->sock = -1;
}
radiusd_authentication_init(&authen);
- TAILQ_FOREACH_SAFE(m, &authen.deco, next, mt) {
- TAILQ_REMOVE(&authen.deco, m, next);
- free(m);
- }
+ if (conf_module != NULL)
+ radiusd_module_unload(conf_module);
out:
conf = NULL;
return (errors ? -1 : 0);
@@ -827,3 +1001,24 @@ radiusd_client_init(struct radiusd_client *clnt)
memset(clnt, 0, sizeof(struct radiusd_client));
clnt->msgauth_required = true;
}
+
+static const char *
+default_module_path(const char *name)
+{
+ unsigned i;
+ struct {
+ const char *name;
+ const char *path;
+ } module_paths[] = {
+ { "bsdauth", "/usr/libexec/radiusd/radiusd_bsdauth" },
+ { "radius", "/usr/libexec/radiusd/radiusd_radius" },
+ { "standard", "/usr/libexec/radiusd/radiusd_standard" }
+ };
+
+ for (i = 0; i < nitems(module_paths); i++) {
+ if (strcmp(name, module_paths[i].name) == 0)
+ return (module_paths[i].path);
+ }
+
+ return (NULL);
+}
diff --git a/usr.sbin/radiusd/radiusd.c b/usr.sbin/radiusd/radiusd.c
index 4419e3095..e9202ba28 100644
--- a/usr.sbin/radiusd/radiusd.c
+++ b/usr.sbin/radiusd/radiusd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: radiusd.c,v 1.36 2024/02/14 02:44:58 jsg Exp $ */
+/* $OpenBSD: radiusd.c,v 1.44 2024/07/02 00:33:51 yasuoka Exp $ */
/*
* Copyright (c) 2013, 2023 Internet Initiative Japan Inc.
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -62,15 +63,18 @@ static void radiusd_on_sighup(int, short, void *);
static void radiusd_on_sigchld(int, short, void *);
static void raidus_query_access_request(struct radius_query *);
static void radius_query_access_response(struct radius_query *);
+static void raidus_query_accounting_request(
+ struct radiusd_accounting *, struct radius_query *);
+static void radius_query_accounting_response(struct radius_query *);
static const char *radius_code_string(int);
+static const char *radius_acct_status_type_string(uint32_t);
static int radiusd_access_response_fixup (struct radius_query *);
static void radiusd_module_reset_ev_handler(
struct radiusd_module *);
-static int radiusd_module_imsg_read(struct radiusd_module *,
- bool);
+static int radiusd_module_imsg_read(struct radiusd_module *);
static void radiusd_module_imsg(struct radiusd_module *,
struct imsg *);
@@ -89,8 +93,11 @@ static void radiusd_module_request_decoration(
struct radiusd_module *, struct radius_query *);
static void radiusd_module_response_decoration(
struct radiusd_module *, struct radius_query *);
+static void radiusd_module_account_request(struct radiusd_module *,
+ struct radius_query *);
static int imsg_compose_radius_packet(struct imsgbuf *,
uint32_t, u_int, RADIUS_PACKET *);
+static void close_stdio(void);
static u_int radius_query_id_seq = 0;
int debug = 0;
@@ -144,16 +151,20 @@ main(int argc, char *argv[])
TAILQ_INIT(&radiusd->listen);
TAILQ_INIT(&radiusd->query);
- log_init(debug);
+ if (!noaction && debug == 0)
+ daemon(0, 1); /* pend closing stdio files */
+
if (parse_config(conffile, radiusd) != 0)
errx(EXIT_FAILURE, "config error");
+ log_init(debug);
if (noaction) {
fprintf(stderr, "configuration OK\n");
exit(EXIT_SUCCESS);
}
if (debug == 0)
- daemon(0, 0);
+ close_stdio(); /* close stdio files now */
+
event_init();
if ((pw = getpwnam(RADIUSD_USER)) == NULL)
@@ -187,10 +198,16 @@ main(int argc, char *argv[])
if (event_loop(0) < 0)
radiusd_stop(radiusd);
+ if (radiusd->error != 0)
+ log_warnx("exiting on error");
+
radiusd_free(radiusd);
event_base_free(NULL);
- exit(EXIT_SUCCESS);
+ if (radiusd->error != 0)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
}
static int
@@ -198,7 +215,7 @@ radiusd_start(struct radiusd *radiusd)
{
struct radiusd_listen *l;
struct radiusd_module *module;
- int s;
+ int s, on;
char hbuf[NI_MAXHOST];
TAILQ_FOREACH(l, &radiusd->listen, next) {
@@ -214,6 +231,12 @@ radiusd_start(struct radiusd *radiusd)
hbuf, (int)htons(l->addr.ipv4.sin_port));
goto on_error;
}
+
+ on = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
+ == -1)
+ log_warn("%s: setsockopt(,,SO_REUSEADDR) failed: %m",
+ __func__);
if (bind(s, (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len)
!= 0) {
log_warn("Listen %s port %d is failed: bind()",
@@ -251,6 +274,7 @@ radiusd_start(struct radiusd *radiusd)
return (0);
on_error:
+ radiusd->error++;
radiusd_stop(radiusd);
return (-1);
@@ -387,8 +411,10 @@ radiusd_listen_handle_packet(struct radiusd_listen *listn,
static char username[256];
char peerstr[NI_MAXHOST + NI_MAXSERV + 30];
struct radiusd_authentication *authen;
+ struct radiusd_accounting *accounting;
struct radiusd_client *client;
struct radius_query *q = NULL;
+ uint32_t acct_status;
#define in(_x) (((struct sockaddr_in *)_x)->sin_addr)
#define in6(_x) (((struct sockaddr_in6 *)_x)->sin6_addr)
@@ -421,9 +447,19 @@ radiusd_listen_handle_packet(struct radiusd_listen *listn,
goto on_error;
}
+ /* Check the request authenticator if accounting */
+ if ((req_code == RADIUS_CODE_ACCOUNTING_REQUEST ||
+ listn->accounting) && radius_check_accounting_request_authenticator(
+ packet, client->secret) != 0) {
+ log_warnx("Received %s(code=%d) from %s id=%d: bad request "
+ "authenticator", radius_code_string(req_code), req_code,
+ peerstr, req_id);
+ goto on_error;
+ }
+
/* Check the client's Message-Authenticator */
- if (client->msgauth_required && !radius_has_attr(packet,
- RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) {
+ if (client->msgauth_required && !listn->accounting &&
+ !radius_has_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) {
log_warnx("Received %s(code=%d) from %s id=%d: no message "
"authenticator", radius_code_string(req_code), req_code,
peerstr, req_id);
@@ -485,6 +521,13 @@ radiusd_listen_handle_packet(struct radiusd_listen *listn,
switch (req_code) {
case RADIUS_CODE_ACCESS_REQUEST:
+ if (listn->accounting) {
+ log_info("Received %s(code=%d) from %s id=%d: "
+ "ignored because the port is for authentication",
+ radius_code_string(req_code), req_code, peerstr,
+ req_id);
+ break;
+ }
/*
* Find a matching `authenticate' entry
*/
@@ -521,6 +564,47 @@ radiusd_listen_handle_packet(struct radiusd_listen *listn,
raidus_query_access_request(q);
return;
+ case RADIUS_CODE_ACCOUNTING_REQUEST:
+ if (!listn->accounting) {
+ log_info("Received %s(code=%d) from %s id=%d: "
+ "ignored because the port is for accounting",
+ radius_code_string(req_code), req_code, peerstr,
+ req_id);
+ break;
+ }
+ if (radius_get_uint32_attr(q->req, RADIUS_TYPE_ACCT_STATUS_TYPE,
+ &acct_status) != 0)
+ acct_status = 0;
+ /*
+ * Find a matching `accounting' entry
+ */
+ TAILQ_FOREACH(accounting, &listn->radiusd->account, next) {
+ if (acct_status == RADIUS_ACCT_STATUS_TYPE_ACCT_ON ||
+ acct_status == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) {
+ raidus_query_accounting_request(accounting, q);
+ continue;
+ }
+ for (i = 0; accounting->username[i] != NULL; i++) {
+ if (fnmatch(accounting->username[i], username,
+ 0) == 0)
+ break;
+ }
+ if (accounting->username[i] == NULL)
+ continue;
+ raidus_query_accounting_request(accounting, q);
+ if (accounting->quick)
+ break;
+ }
+ /* pass NULL to hadnle this self without module */
+ raidus_query_accounting_request(NULL, q);
+
+ if ((q->res = radius_new_response_packet(
+ RADIUS_CODE_ACCOUNTING_RESPONSE, q->req)) == NULL)
+ log_warn("%s: radius_new_response_packet() failed",
+ __func__);
+ else
+ radius_query_accounting_response(q);
+ break;
default:
log_info("Received %s(code=%d) from %s id=%d: %s is not "
"supported in this implementation", radius_code_string(
@@ -609,6 +693,53 @@ on_error:
radiusd_access_request_aborted(q);
}
+static void
+raidus_query_accounting_request(struct radiusd_accounting *accounting,
+ struct radius_query *q)
+{
+ int req_code;
+ uint32_t acct_status;
+ char buf0[NI_MAXHOST + NI_MAXSERV + 30];
+
+ if (accounting != NULL) {
+ /* handle by the module */
+ if (MODULE_DO_ACCTREQ(accounting->acct->module))
+ radiusd_module_account_request(accounting->acct->module,
+ q);
+ return;
+ }
+ req_code = radius_get_code(q->req);
+ if (radius_get_uint32_attr(q->req, RADIUS_TYPE_ACCT_STATUS_TYPE,
+ &acct_status) != 0)
+ acct_status = 0;
+ log_info("Received %s(code=%d) type=%s(%lu) from %s id=%d username=%s "
+ "q=%u", radius_code_string(req_code), req_code,
+ radius_acct_status_type_string(acct_status), (unsigned long)
+ acct_status, addrport_tostring((struct sockaddr *)&q->clientaddr,
+ q->clientaddrlen, buf0, sizeof(buf0)), q->req_id, q->username,
+ q->id);
+}
+
+static void
+radius_query_accounting_response(struct radius_query *q)
+{
+ int sz, res_id, res_code;
+ char buf[NI_MAXHOST + NI_MAXSERV + 30];
+
+ radius_set_response_authenticator(q->res, q->client->secret);
+ res_id = radius_get_id(q->res);
+ res_code = radius_get_code(q->res);
+
+ log_info("Sending %s(code=%d) to %s id=%u q=%u",
+ radius_code_string(res_code), res_code,
+ addrport_tostring((struct sockaddr *)&q->clientaddr,
+ q->clientaddrlen, buf, sizeof(buf)), res_id, q->id);
+
+ if ((sz = sendto(q->listen->sock, radius_get_data(q->res),
+ radius_get_length(q->res), 0,
+ (struct sockaddr *)&q->clientaddr, q->clientaddrlen)) <= 0)
+ log_warn("Sending a RADIUS response failed");
+}
/***********************************************************************
* Callback functions from the modules
***********************************************************************/
@@ -691,7 +822,7 @@ radiusd_on_sigchld(int fd, short evmask, void *ctx)
struct radiusd *radiusd = ctx;
struct radiusd_module *module;
pid_t pid;
- int status;
+ int status, ndeath = 0;
log_debug("Received SIGCHLD");
while ((pid = wait3(&status, WNOHANG, NULL)) != 0) {
@@ -707,6 +838,7 @@ radiusd_on_sigchld(int fd, short evmask, void *ctx)
log_warnx("module `%s'(pid=%d) exited "
"by signal %d", module->name,
(int)pid, WTERMSIG(status));
+ ndeath++;
break;
}
}
@@ -721,6 +853,10 @@ radiusd_on_sigchld(int fd, short evmask, void *ctx)
WTERMSIG(status));
}
}
+ if (ndeath > 0) {
+ radiusd->error++;
+ event_loopbreak();
+ }
}
static const char *
@@ -749,6 +885,29 @@ radius_code_string(int code)
return ("Unknown");
}
+static const char *
+radius_acct_status_type_string(uint32_t type)
+{
+ int i;
+ struct _typestrings {
+ uint32_t type;
+ const char *string;
+ } typestrings[] = {
+ { RADIUS_ACCT_STATUS_TYPE_START, "Start" },
+ { RADIUS_ACCT_STATUS_TYPE_STOP, "Stop" },
+ { RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE, "Interim-Update" },
+ { RADIUS_ACCT_STATUS_TYPE_ACCT_ON, "Accounting-On" },
+ { RADIUS_ACCT_STATUS_TYPE_ACCT_OFF, "Accounting-Off" },
+ { -1, NULL }
+ };
+
+ for (i = 0; typestrings[i].string != NULL; i++)
+ if (typestrings[i].type == type)
+ return (typestrings[i].string);
+
+ return ("Unknown");
+}
+
void
radiusd_conf_init(struct radiusd *conf)
{
@@ -756,6 +915,7 @@ radiusd_conf_init(struct radiusd *conf)
TAILQ_INIT(&conf->listen);
TAILQ_INIT(&conf->module);
TAILQ_INIT(&conf->authen);
+ TAILQ_INIT(&conf->account);
TAILQ_INIT(&conf->client);
return;
@@ -1085,9 +1245,8 @@ radiusd_module_on_imsg_io(int fd, short evmask, void *ctx)
if (evmask & EV_WRITE)
module->writeready = true;
- if (evmask & EV_READ || module->ibuf.r.wpos > IMSG_HEADER_SIZE) {
- if (radiusd_module_imsg_read(module,
- (evmask & EV_READ)? true : false) == -1)
+ if (evmask & EV_READ) {
+ if (radiusd_module_imsg_read(module) == -1)
goto on_error;
}
@@ -1124,8 +1283,7 @@ radiusd_module_reset_ev_handler(struct radiusd_module *module)
evmask |= EV_WRITE;
else
tvp = &tv; /* fire immediately */
- } else if (module->ibuf.r.wpos > IMSG_HEADER_SIZE)
- tvp = &tv; /* fire immediately */
+ }
/* module stopped and no event handler is set */
if (evmask & EV_WRITE && tvp == NULL && module->stopped) {
@@ -1144,22 +1302,20 @@ radiusd_module_reset_ev_handler(struct radiusd_module *module)
}
static int
-radiusd_module_imsg_read(struct radiusd_module *module, bool doread)
+radiusd_module_imsg_read(struct radiusd_module *module)
{
int n;
struct imsg imsg;
- if (doread) {
- if ((n = imsg_read(&module->ibuf)) == -1 || n == 0) {
- if (n == -1 && errno == EAGAIN)
- return (0);
- if (n == -1)
- log_warn("Receiving a message from module `%s' "
- "failed: imsg_read", module->name);
- /* else closed */
- radiusd_module_close(module);
- return (-1);
- }
+ if ((n = imsg_read(&module->ibuf)) == -1 || n == 0) {
+ if (n == -1 && errno == EAGAIN)
+ return (0);
+ if (n == -1)
+ log_warn("Receiving a message from module `%s' "
+ "failed: imsg_read", module->name);
+ /* else closed */
+ radiusd_module_close(module);
+ return (-1);
}
for (;;) {
if ((n = imsg_get(&module->ibuf, &imsg)) == -1) {
@@ -1275,6 +1431,14 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
module->radpktoff = 0;
switch (imsg->hdr.type) {
case IMSG_RADIUSD_MODULE_REQDECO_DONE:
+ if (q->deco == NULL || q->deco->type !=
+ IMSG_RADIUSD_MODULE_REQDECO) {
+ log_warnx("q=%u received %s "
+ "but not requested", q->id, typestr);
+ if (radpkt != NULL)
+ radius_delete_packet(radpkt);
+ break;
+ }
if (radpkt != NULL) {
radius_delete_packet(q->req);
q->req = radpkt;
@@ -1283,7 +1447,7 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
break;
case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
if (radpkt == NULL) {
- log_warn("q=%u wrong pkt from module",
+ log_warnx("q=%u wrong pkt from module",
q->id);
radiusd_access_request_aborted(q);
break;
@@ -1292,6 +1456,14 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
radiusd_access_request_answer(q);
break;
case IMSG_RADIUSD_MODULE_RESDECO_DONE:
+ if (q->deco == NULL || q->deco->type !=
+ IMSG_RADIUSD_MODULE_RESDECO) {
+ log_warnx("q=%u received %s but not "
+ "requested", q->id, typestr);
+ if (radpkt != NULL)
+ radius_delete_packet(radpkt);
+ break;
+ }
if (radpkt != NULL) {
radius_delete_packet(q->res);
radius_set_request_packet(radpkt,
@@ -1306,6 +1478,11 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
}
case IMSG_RADIUSD_MODULE_ACCSREQ_ABORTED:
{
+ if (datalen < (ssize_t)sizeof(u_int)) {
+ log_warnx("Received ACCSREQ_ABORTED message, but "
+ "length is wrong");
+ break;
+ }
q_id = *((u_int *)imsg->data);
q = radiusd_find_query(module->radiusd, q_id);
if (q == NULL) {
@@ -1531,6 +1708,8 @@ radiusd_module_request_decoration(struct radiusd_module *module,
radiusd_access_request_aborted(q);
return;
}
+ RADIUSD_ASSERT(q->deco != NULL);
+ q->deco->type = IMSG_RADIUSD_MODULE_REQDECO;
radiusd_module_reset_ev_handler(module);
}
@@ -1558,9 +1737,34 @@ radiusd_module_response_decoration(struct radiusd_module *module,
radiusd_access_request_aborted(q);
return;
}
+ RADIUSD_ASSERT(q->deco != NULL);
+ q->deco->type = IMSG_RADIUSD_MODULE_RESDECO;
radiusd_module_reset_ev_handler(module);
}
+static void
+radiusd_module_account_request(struct radiusd_module *module,
+ struct radius_query *q)
+{
+ RADIUS_PACKET *radpkt;
+
+ if ((radpkt = radius_convert_packet(radius_get_data(q->req),
+ radius_get_length(q->req))) == NULL) {
+ log_warn("q=%u Could not send ACCSREQ to `%s'", q->id,
+ module->name);
+ radiusd_access_request_aborted(q);
+ return;
+ }
+ if (imsg_compose_radius_packet(&module->ibuf,
+ IMSG_RADIUSD_MODULE_ACCTREQ, q->id, radpkt) == -1) {
+ log_warn("q=%u Could not send ACCTREQ to `%s'", q->id,
+ module->name);
+ radiusd_access_request_aborted(q);
+ }
+ radiusd_module_reset_ev_handler(module);
+ radius_delete_packet(radpkt);
+}
+
static int
imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id,
RADIUS_PACKET *radpkt)
@@ -1593,3 +1797,17 @@ imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id,
}
return (0);
}
+
+static void
+close_stdio(void)
+{
+ int fd;
+
+ if ((fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > STDERR_FILENO)
+ close(fd);
+ }
+}
diff --git a/usr.sbin/radiusd/radiusd.conf.5 b/usr.sbin/radiusd/radiusd.conf.5
index f461217c6..54dc62983 100644
--- a/usr.sbin/radiusd/radiusd.conf.5
+++ b/usr.sbin/radiusd/radiusd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: radiusd.conf.5,v 1.18 2023/09/14 09:55:28 yasuoka Exp $
+.\" $OpenBSD: radiusd.conf.5,v 1.22 2024/07/02 00:35:56 yasuoka Exp $
.\"
.\" Copyright (c) 2014 Esdenera Networks GmbH
.\" Copyright (c) 2014, 2023 Internet Initiative Japan Inc.
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 14 2023 $
+.Dd $Mdocdate: July 2 2024 $
.Dt RADIUSD.CONF 5
.Os
.Sh NAME
@@ -35,14 +35,18 @@ Keywords may be specified multiple times within the configuration file.
The configuration options are as follows:
.Bl -tag -width Ds
.It Xo
-.Ic listen on Ar address
-.Ic port Ar port
+.Ic listen on Ar address Oo Ic accounting Oc Ic port Ar port
.Xc
Specify an
.Ar address
and a
.Ar port
to listen on.
+When
+.Ar accouting
+is specified,
+it is used for waiting for RADIUS accounting messages.
+The default port number is 1812 for authentication and 1813 for accounting.
.It Ic client Ar address/mask Brq ...
Allow access to a client with the specified
.Ar address
@@ -57,40 +61,46 @@ This option cannot be omitted.
Specify if message authentication is required.
The default is to require message authentication.
.El
-.It Ic module load Ar name path
-Load a module
-from
-.Ar path
-and name it with the given
-.Ar name .
-The following modules are available:
-.Bl -column "/usr/libexec/radiusd/radiusd_bsdauthXXX"
-.It Sy "Path" Ta Sy "Description"
-.It Pa /usr/libexec/radiusd/radiusd_bsdauth Ta Do bsdauth Dc module
-.It Pa /usr/libexec/radiusd/radiusd_radius Ta Do radius Dc module
-.It Pa /usr/libexec/radiusd/radiusd_standard Ta Do standard Dc module
-.El
+.It Ic module Ar name Oo Ar path Oc Op Brq ...
+Load a module.
+Specify one of the predefined names for
+.Ar name ,
+or specify
+.Ar name
+and
+.Ar path .
+When multiple modules of the same path are loaded with different names,
+each module can have configurations respectively and work independently.
+.Pp
+The following module are predefined:
.Bl -tag -width Ds
.It Do bsdauth Dc module
The
.Dq bsdauth
-module provides authentication from the local system's
+module
+provides authentication from the local system's
.Xr authenticate 3
-interface,
-known as
-.Dq bsd auth .
-It only supports PAP, password based authentication.
+interface.
+See
+.Xr radiusd_bsdauth 8 .
.It Do radius Dc module
The
.Dq radius
module provides authentication from upstream RADIUS servers.
+See
+.Xr radiusd_radius 8 .
.It Do standard Dc module
The
.Dq standard
-module provides standard decorations for Access-Request messages or its
-response messages.
+module provides standard decorations for RADIUS messages.
+See
+.Xr radiusd_standard 8 .
.El
-.It Ic module set Ar module key value ...
+.Pp
+It is optionally followed by a block of options enclosed in curly brackets.
+The following option can be used in the block:
+.Bl -tag -width Ds
+.It Ic set Ar key value ...
Configure the module specific configurations by
.Ar key
and
@@ -98,92 +108,18 @@ and
for the module specified by
.Ar module .
Notice that
-.Ar module ,
.Ar key ,
and
.Ar value
-must be quoted to be distinguished from the reserved word (e.g.\&
-.Dq secret )
-if needed.
-.Pp
-The
-.Dq bsdauth
-module supports the following configuration key and value:
-.Bl -tag -width Ds -offset indent
-.It Ic restrict-group Ar group ...
-Restrict login only if the user is a member of the specified groups.
+must be quoted to be distinguished from the reserved word if needed.
.El
-.Pp
-The
-.Dq radius
-module supports the following configuration key and value:
-.Bl -tag -width Ds -offset indent
-.It Ic server Ar address Ns Op : Ns Ar port
-Specify the upstream server's address and port.
-If
-.Ar port
-is omitted, 1812 is used.
-This configuration can be specified multiple times.
-.It Ic secret Ar secret
-Specify the shared secret with the servers.
-This configuration cannot be omitted.
-.It Ic max-tries Ar number
-Specify the maximum number of retransmissions for a server.
-.Xr radiusd 8
-will retransmit 2, 6, 14, 22, and 30 seconds after the first transmission
-and subsequent retransmissions will occur every 8 seconds.
-If the number of retransmissions per server reaches this value,
-the current server is marked as
-.Dq fail ,
-and the next server is used for subsequent requests.
-The default value is 3.
-.It Ic max-failovers Ar number
-If a positive number is specified,
-.Xr radiusd 8
-will failover to the next server
-when the current server is marked
-.Dq fail .
-This key and value specifies the maximum number of failovers.
-The default value is 0.
-.It Ic request-timeout Ar sec
-Specify the request timeout in seconds.
-If this value is specified,
-.Ar max-tries
-and
-.Ar max-failover
-will not be used.
-.El
-.Pp
-The
-.Dq standard
-module supports the following configuration key and value:
-.Pp
-.Bl -tag -width Ds -offset indent -compact
-.It Ic strip-atmark-realm Ar true | false
-Remove the realm part which starts with @
-.Pq atmark
-from the User-Name attribute of the Access-Request.
-.Pp
-.It Ic strip-nt-domain Ar true | false
-Remove NT domain which ends with \\
-.Pq backslash
-from the User-Name attribute of the Access-Request.
-.Pp
-.It Cm remove-request-attribute Oo Ar vendor Oc Ar type
-.It Cm remove-response-attribute Oo Ar vendor Oc Ar type
-Remove all the specified attributes from request or response
-messages of Access-Request.
-Specify
-.Ar type
-of the attribute in a decimal number.
-To specify a vendor attribute,
-specify the Vendor-Id
-in a decimal number for
-.Ar vendor .
-.El
-.It Ic authenticate Ar username-pattern ... Brq ...
+.It Ic authenticate Ar username-pattern ... Ic by Ar auth Oo Ic decorated-by \
+Ar deco ... Oc
Specify an authentication configuration for the users specified by
-.Ar username-pattern .
+.Ar username-pattern.
+The users matched by the pattern is authenticated by the module
+specified by
+.Ar auth .
Use shell globbing rules for the pattern;
multiple patterns can be specified by separating with space characters.
When multiple
@@ -193,60 +129,78 @@ lines are specified, the first
setting whose
.Ar username-pattern
matches an authenticating user is used.
-It is followed by a block of options enclosed in curly brackets:
-.Bl -tag -width Ds
-.It Ic authenticate-by Ar module
-Specify the module name.
-.It Ic decorate-by Ar module
-Specify the module name.
-.El
+.Pp
+Optionally decoration modules can be specified by
+.Ar deco .
+The specified modules decorate the RADIUS messages in the configured order.
+.It Ic account Oo Ic quick Oc Ar username-pattern ... Ic to Ar module \
+Oo Ic decoratd by Ar deco ... Oc
+Specify an accounting configuration for the users specified by
+.Ar username-pattern .
+The accounting messages for the users matched by the pattern are handled
+by the module specified by the
+.Ar module .
+Use shell globbing rules for the patterns;
+multiple patterns can be determined by separating them with space characters.
+When multiple
+.Ic account
+lines are selected,
+all account settings whose
+.Ar username-pattern
+matches an accounting users are used.
+until the user matches the setting with the
+.Ar quick
+option.
+.Pp
+Optionally decoration modules can be specified by
+.Ar deco .
+The specified modules decorate the RADIUS messages in the configured order.
.El
.Sh FILES
-.Bl -tag -width "/usr/libexec/radiusd/radiusd_bsdauth" -compact
+.Bl -tag -width "/etc/examples/radiusd.conf" -compact
.It Pa /etc/radiusd.conf
Default
.Xr radiusd 8
configuration file.
.It Pa /etc/examples/radiusd.conf
Example configuration file.
-.It Pa /usr/libexec/radiusd/radiusd_bsdauth
-.Dq bsdauth
-module executable.
-.It Pa /usr/libexec/radiusd/radiusd_radius
-.Dq radius
-module executable.
.El
.Sh EXAMPLES
.Bd -literal -offset indent
listen on 0.0.0.0
+listen on 0.0.0.0 accounting
listen on ::
+listen on :: accounting
client 127.0.0.1/32 {
- secret "secret"
- msgauth-required no
+ secret "secret"
+ msgauth-required no
}
client 192.168.0.0/24 {
- secret "secret"
+ secret "secret"
}
-module load bsdauth "/usr/libexec/radiusd/radiusd_bsdauth"
-module set bsdauth restrict-group operator
-
-module load radius "/usr/libexec/radiusd/radiusd_radius"
-module set radius secret "testing123"
-module set radius server "127.0.0.1"
-
-module load strip-realm "/usr/libexec/radiusd/radiusd_standard"
-module set strip-realm strip-atmark-realm true
-
-authenticate *@local {
- authenticate-by bsdauth
- decorate-by strip-realm
+module bsdauth {
+ set restrict-group operator
}
-authenticate * {
- authenticate-by radius
+
+module radius {
+ set secret "testing123"
+ set server "127.0.0.1"
}
+
+module strip-realm "/usr/libexec/radiusd/radiusd_standard" {
+ set strip-atmark-realm true
+}
+
+authenticate *@local by bsdauth decorate-by strip-realm
+
+authenticate * by radius
+
+account * to standard
.Ed
.Sh SEE ALSO
-.Xr authenticate 3 ,
-.Xr radiusd 8
+.Xr radiusd 8 ,
+.Xr radiusd_bsdauth 8 ,
+.Xr radiusd_radius 8 ,
+.Xr radiusd_standard 8
diff --git a/usr.sbin/radiusd/radiusd.h b/usr.sbin/radiusd/radiusd.h
index 6cc56b64a..3d7241760 100644
--- a/usr.sbin/radiusd/radiusd.h
+++ b/usr.sbin/radiusd/radiusd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: radiusd.h,v 1.6 2024/01/08 04:16:48 yasuoka Exp $ */
+/* $OpenBSD: radiusd.h,v 1.7 2024/07/02 00:33:51 yasuoka Exp $ */
#ifndef RADIUSD_H
#define RADIUSD_H 1
@@ -45,16 +45,18 @@ enum imsg_type {
IMSG_RADIUSD_MODULE_RESDECO0_REQ, /* request pkt for RESDECO */
IMSG_RADIUSD_MODULE_RESDECO,
IMSG_RADIUSD_MODULE_RESDECO_DONE,
- IMSG_RADIUSD_MODULE_STOP
+ IMSG_RADIUSD_MODULE_ACCTREQ,
+ IMSG_RADIUSD_MODULE_STOP,
};
/* Module sends LOAD when it becomes ready */
struct radiusd_module_load_arg {
uint32_t cap; /* module capabity bits */
-#define RADIUSD_MODULE_CAP_USERPASS 0x1
-#define RADIUSD_MODULE_CAP_ACCSREQ 0x2
-#define RADIUSD_MODULE_CAP_REQDECO 0x4
-#define RADIUSD_MODULE_CAP_RESDECO 0x8
+#define RADIUSD_MODULE_CAP_USERPASS 0x01
+#define RADIUSD_MODULE_CAP_ACCSREQ 0x02
+#define RADIUSD_MODULE_CAP_REQDECO 0x04
+#define RADIUSD_MODULE_CAP_RESDECO 0x08
+#define RADIUSD_MODULE_CAP_ACCTREQ 0x10
};
struct radiusd_module_object {
diff --git a/usr.sbin/radiusd/radiusd_bsdauth.8 b/usr.sbin/radiusd/radiusd_bsdauth.8
new file mode 100644
index 000000000..219eee0ea
--- /dev/null
+++ b/usr.sbin/radiusd/radiusd_bsdauth.8
@@ -0,0 +1,61 @@
+.\" $OpenBSD: radiusd_bsdauth.8,v 1.1 2024/07/02 00:00:12 yasuoka Exp $
+.\"
+.\" Copyright (c) 2014 Esdenera Networks GmbH
+.\" Copyright (c) 2014, 2024 Internet Initiative Japan Inc.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" The following requests are required for all man pages.
+.\"
+.Dd $Mdocdate: July 2 2024 $
+.Dt RADIUSD_BSDAUTH 8
+.Os
+.Sh NAME
+.Nm radiusd_bsdauth
+.Nd provide authentication by BSD authentication system
+.Sh SYNOPSIS
+.Nm radiusd_bsdauth
+.Sh DESCRIPTION
+The
+.Nm
+utility is executed by
+.Xr radiusd 8
+as a module to provide authentication from the local system's
+.Xr authenticate 3
+interface,
+known as
+.Dq bsd auth .
+It only supports PAP, password based authentication.
+.Sh CONFIGURATIONS
+The
+.Nm
+supports the following configuration key and value:
+.Bl -tag -width Ds
+.It Ic restrict-group Ar group ...
+Restrict login only if the user is a member of the specified groups.
+.El
+.Sh FILES
+.Bl -tag -width "/usr/libexec/radiusd/radiusd_bsdauth" -compact
+.It Pa /usr/libexec/radiusd/radiusd_bsdauth
+.Dq bsdauth
+module executable.
+.El
+.Sh SEE ALSO
+.Xr authenticate 3 ,
+.Xr radiusd 8 ,
+.Xr radiusd.conf 5
+.Sh HISTORY
+The
+.Nm
+daemon first appeared in
+.Ox 5.8 .
diff --git a/usr.sbin/radiusd/radiusd_bsdauth/Makefile b/usr.sbin/radiusd/radiusd_bsdauth/Makefile
index f5e904d18..008f6f4a1 100644
--- a/usr.sbin/radiusd/radiusd_bsdauth/Makefile
+++ b/usr.sbin/radiusd/radiusd_bsdauth/Makefile
@@ -1,9 +1,9 @@
-# $OpenBSD: Makefile,v 1.2 2024/01/28 18:38:16 deraadt Exp $
+# $OpenBSD: Makefile,v 1.3 2024/07/02 00:00:12 yasuoka Exp $
PROG= radiusd_bsdauth
BINDIR= /usr/libexec/radiusd
SRCS= radiusd_bsdauth.c radiusd_module.c imsg_subr.c
LDADD+= -lradius -lcrypto -lutil
DPADD+= ${LIBRADIUS} ${LIBCRYPTO} ${LIBUTIL}
-NOMAN= #
+MAN= radiusd_bsdauth.8
.include
diff --git a/usr.sbin/radiusd/radiusd_local.h b/usr.sbin/radiusd/radiusd_local.h
index 5cc4b2230..a36373c82 100644
--- a/usr.sbin/radiusd/radiusd_local.h
+++ b/usr.sbin/radiusd/radiusd_local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: radiusd_local.h,v 1.7 2024/05/21 05:00:48 jsg Exp $ */
+/* $OpenBSD: radiusd_local.h,v 1.11 2024/07/02 00:33:51 yasuoka Exp $ */
/*
* Copyright (c) 2013 Internet Initiative Japan Inc.
@@ -44,6 +44,7 @@ struct radiusd_listen {
struct radiusd *radiusd;
struct event ev;
int sock;
+ int accounting;
union {
struct sockaddr_in ipv4;
struct sockaddr_in6 ipv6;
@@ -85,17 +86,26 @@ struct radiusd_module {
struct radiusd_module_ref {
struct radiusd_module *module;
+ unsigned int type;
TAILQ_ENTRY(radiusd_module_ref) next;
};
struct radiusd_authentication {
char **username;
- char *secret;
struct radiusd_module_ref *auth;
TAILQ_HEAD(,radiusd_module_ref) deco;
TAILQ_ENTRY(radiusd_authentication) next;
};
+struct radiusd_accounting {
+ char **username;
+ char *secret;
+ struct radiusd_module_ref *acct;
+ int quick;
+ TAILQ_HEAD(,radiusd_module_ref) deco;
+ TAILQ_ENTRY(radiusd_accounting) next;
+};
+
struct radiusd {
struct radiusd_listen_head listen;
struct event ev_sigterm;
@@ -104,8 +114,10 @@ struct radiusd {
struct event ev_sigchld;
TAILQ_HEAD(,radiusd_module) module;
TAILQ_HEAD(,radiusd_authentication) authen;
+ TAILQ_HEAD(,radiusd_accounting) account;
TAILQ_HEAD(,radiusd_client) client;
TAILQ_HEAD(,radius_query) query;
+ int error;
};
struct radius_query {
@@ -150,6 +162,9 @@ struct radius_query {
#define MODULE_DO_ACCSREQ(_m) \
((_m)->fd >= 0 && \
((_m)->capabilities & RADIUSD_MODULE_CAP_ACCSREQ) != 0)
+#define MODULE_DO_ACCTREQ(_m) \
+ ((_m)->fd >= 0 && \
+ ((_m)->capabilities & RADIUSD_MODULE_CAP_ACCTREQ) != 0)
#define MODULE_DO_REQDECO(_m) \
((_m)->fd >= 0 && \
((_m)->capabilities & RADIUSD_MODULE_CAP_REQDECO) != 0)
diff --git a/usr.sbin/radiusd/radiusd_module.c b/usr.sbin/radiusd/radiusd_module.c
index 85236db2c..9a2b63606 100644
--- a/usr.sbin/radiusd/radiusd_module.c
+++ b/usr.sbin/radiusd/radiusd_module.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: radiusd_module.c,v 1.16 2024/02/09 07:41:32 yasuoka Exp $ */
+/* $OpenBSD: radiusd_module.c,v 1.17 2024/07/02 00:33:51 yasuoka Exp $ */
/*
* Copyright (c) 2015 YASUOKA Masahiko
@@ -50,6 +50,8 @@ static void (*module_request_decoration) (void *, u_int, const u_char *,
size_t) = NULL;
static void (*module_response_decoration) (void *, u_int, const u_char *,
size_t, const u_char *, size_t) = NULL;
+static void (*module_accounting_request) (void *, u_int, const u_char *,
+ size_t) = NULL;
struct module_base {
void *ctx;
@@ -98,6 +100,7 @@ module_create(int sock, void *ctx, struct module_handlers *handler)
module_config_set = handler->config_set;
module_request_decoration = handler->request_decoration;
module_response_decoration = handler->response_decoration;
+ module_accounting_request = handler->accounting_request;
module_start_module = handler->start;
module_stop_module = handler->stop;
@@ -156,6 +159,8 @@ module_load(struct module_base *base)
load.cap |= RADIUSD_MODULE_CAP_REQDECO;
if (module_response_decoration != NULL)
load.cap |= RADIUSD_MODULE_CAP_RESDECO;
+ if (module_accounting_request != NULL)
+ load.cap |= RADIUSD_MODULE_CAP_ACCTREQ;
imsg_compose(&base->ibuf, IMSG_RADIUSD_MODULE_LOAD, 0, 0, -1, &load,
sizeof(load));
imsg_flush(&base->ibuf);
@@ -447,6 +452,7 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg)
case IMSG_RADIUSD_MODULE_REQDECO:
case IMSG_RADIUSD_MODULE_RESDECO0_REQ:
case IMSG_RADIUSD_MODULE_RESDECO:
+ case IMSG_RADIUSD_MODULE_ACCTREQ:
{
struct radiusd_module_radpkt_arg *accessreq;
int chunklen;
@@ -459,6 +465,13 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg)
break;
}
typestr = "ACCSREQ";
+ } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_ACCTREQ) {
+ if (module_accounting_request == NULL) {
+ syslog(LOG_ERR, "Received ACCTREQ message, but "
+ "module doesn't support");
+ break;
+ }
+ typestr = "ACCTREQ";
} else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_REQDECO) {
if (module_request_decoration == NULL) {
syslog(LOG_ERR, "Received REQDECO message, but "
@@ -539,14 +552,16 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg)
}
memcpy(base->radpkt2, base->radpkt, base->radpktoff);
base->radpkt2len = base->radpktoff;
- } else {
+ } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_RESDECO) {
module_response_decoration(base->ctx, accessreq->q_id,
base->radpkt2, base->radpkt2len, base->radpkt,
base->radpktoff);
base->radpkt2len = 0;
- }
+ } else
+ module_accounting_request(base->ctx, accessreq->q_id,
+ base->radpkt, base->radpktoff);
base->radpktoff = 0;
-accsreq_out:
+ accsreq_out:
break;
}
}
diff --git a/usr.sbin/radiusd/radiusd_module.h b/usr.sbin/radiusd/radiusd_module.h
index 5fb44513f..9b3b84760 100644
--- a/usr.sbin/radiusd/radiusd_module.h
+++ b/usr.sbin/radiusd/radiusd_module.h
@@ -20,6 +20,7 @@
#include "radiusd.h"
struct module_ctx;
+struct imsg;
struct module_handlers {
/* Should send IMSG_OK or IMSG_NG */
@@ -42,6 +43,11 @@ struct module_handlers {
void (*response_decoration)(void *ctx, u_int query_id,
const u_char *req, size_t reqlen, const u_char *res, size_t reslen);
+
+ void (*accounting_request)(void *ctx, u_int query_id, const u_char *pkt,
+ size_t pktlen);
+
+ void (*dispatch_control)(void *ctx, struct imsg *);
};
#define SYNTAX_ASSERT(_cond, _msg) \
@@ -77,6 +83,10 @@ int module_reqdeco_done(struct module_base *, u_int,
const u_char *, size_t);
int module_resdeco_done(struct module_base *, u_int,
const u_char *, size_t);
+int module_imsg_compose(struct module_base *, uint32_t,
+ uint32_t, pid_t, int, const void *, size_t);
+int module_imsg_composev(struct module_base *, uint32_t,
+ uint32_t, pid_t, int, const struct iovec *, int);
__END_DECLS
diff --git a/usr.sbin/radiusd/radiusd_radius.8 b/usr.sbin/radiusd/radiusd_radius.8
new file mode 100644
index 000000000..2ab83faf1
--- /dev/null
+++ b/usr.sbin/radiusd/radiusd_radius.8
@@ -0,0 +1,84 @@
+.\" $OpenBSD: radiusd_radius.8,v 1.1 2024/07/02 00:00:12 yasuoka Exp $
+.\"
+.\" Copyright (c) 2014 Esdenera Networks GmbH
+.\" Copyright (c) 2014, 2024 Internet Initiative Japan Inc.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" The following requests are required for all man pages.
+.\"
+.Dd $Mdocdate: July 2 2024 $
+.Dt RADIUSD_RADIUS 8
+.Os
+.Sh NAME
+.Nm radiusd_radius
+.Nd provide authentication from upstream RADIUS servers
+.Sh SYNOPSIS
+.Nm radiusd_radius
+.Sh DESCRIPTION
+The
+.Nm
+utility is executed by
+.Xr radiusd 8
+as a module to provide authentication from upstream RADIUS servers.
+.Sh CONFIGURATIONS
+The
+.Nm
+supports the following configuration key and value:
+.Bl -tag -width Ds
+.It Ic server Ar address Ns Op : Ns Ar port
+Specify the upstream server's address and port.
+If
+.Ar port
+is omitted, 1812 is used.
+This configuration can be specified multiple times.
+.It Ic secret Ar secret
+Specify the shared secret with the servers.
+This configuration cannot be omitted.
+.It Ic max-tries Ar number
+Specify the maximum number of retransmissions for a server.
+.Xr radiusd 8
+will retransmit 2, 6, 14, 22, and 30 seconds after the first transmission
+and subsequent retransmissions will occur every 8 seconds.
+If the number of retransmissions per server reaches this value,
+the current server is marked as
+.Dq fail ,
+and the next server is used for subsequent requests.
+The default value is 3.
+.It Ic max-failovers Ar number
+If a positive number is specified,
+.Xr radiusd 8
+will failover to the next server
+when the current server is marked
+.Dq fail .
+This key and value specifies the maximum number of failovers.
+The default value is 0.
+.It Ic request-timeout Ar sec
+Specify the request timeout in seconds.
+If this value is specified,
+.Ar max-tries
+and
+.Ar max-failover
+will not be used.
+.El
+.Sh FILES
+.Bl -tag -width "/usr/libexec/radiusd/radiusd_radius" -compact
+.It Pa /usr/libexec/radiusd/radiusd_radius
+.Dq radius
+module executable.
+.El
+.Sh HISTORY
+The
+.Nm
+daemon first appeared in
+.Ox 5.8 .
diff --git a/usr.sbin/radiusd/radiusd_radius.c b/usr.sbin/radiusd/radiusd_radius.c
index c0aa8f825..99a6798fd 100644
--- a/usr.sbin/radiusd/radiusd_radius.c
+++ b/usr.sbin/radiusd/radiusd_radius.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: radiusd_radius.c,v 1.20 2024/02/09 07:41:32 yasuoka Exp $ */
+/* $OpenBSD: radiusd_radius.c,v 1.21 2024/07/01 03:17:00 yasuoka Exp $ */
/*
* Copyright (c) 2013 Internet Initiative Japan Inc.
@@ -613,8 +613,7 @@ module_radius_req_reset_msgauth(struct module_radius_req *req)
if (radius_has_attr(req->q_pkt, RADIUS_TYPE_MESSAGE_AUTHENTICATOR))
radius_del_attr_all(req->q_pkt,
RADIUS_TYPE_MESSAGE_AUTHENTICATOR);
- radius_put_message_authenticator(req->q_pkt,
- req->module->secret);
+ radius_put_message_authenticator(req->q_pkt, req->module->secret);
}
static void
diff --git a/usr.sbin/radiusd/radiusd_radius/Makefile b/usr.sbin/radiusd/radiusd_radius/Makefile
index 41aaac34f..cd6d9731e 100644
--- a/usr.sbin/radiusd/radiusd_radius/Makefile
+++ b/usr.sbin/radiusd/radiusd_radius/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.2 2024/01/28 18:38:16 deraadt Exp $
+# $OpenBSD: Makefile,v 1.3 2024/07/02 00:00:12 yasuoka Exp $
PROG= radiusd_radius
BINDIR= /usr/libexec/radiusd
SRCS= radiusd_radius.c radiusd_module.c util.c imsg_subr.c log.c
CFLAGS+= -DUSE_LIBEVENT
LDADD+= -lradius -lcrypto -lutil -levent
DPADD+= ${LIBRADIUS} ${LIBCRYPTO} ${LIBUTIL} ${LIBEVENT}
-NOMAN= #
+MAN= radiusd_radius.8
.include
diff --git a/usr.sbin/radiusd/radiusd_standard.8 b/usr.sbin/radiusd/radiusd_standard.8
new file mode 100644
index 000000000..d434c7c22
--- /dev/null
+++ b/usr.sbin/radiusd/radiusd_standard.8
@@ -0,0 +1,77 @@
+.\" $OpenBSD: radiusd_standard.8,v 1.2 2024/07/02 00:33:51 yasuoka Exp $
+.\"
+.\" Copyright (c) 2014 Esdenera Networks GmbH
+.\" Copyright (c) 2014, 2024 Internet Initiative Japan Inc.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" The following requests are required for all man pages.
+.\"
+.Dd $Mdocdate: July 2 2024 $
+.Dt RADIUSD_STANDARD 8
+.Os
+.Sh NAME
+.Nm radiusd_standard
+.Nd provide standard decorations for RADIUS messages
+.Sh SYNOPSIS
+.Nm radiusd_standard
+.Sh DESCRIPTION
+The
+.Nm
+utility is executed by
+.Xr radiusd 8
+as a module to provide various standard functionalities.
+It can be configured as a module for decoration which modifies request and
+response RADIUS messages.
+Also it can be configured as an accounting module that logs accounting
+information through
+.Xr syslog 3 .
+.Sh CONFIGURATIONS
+The
+.Nm
+module supports the following configuration key and value:
+.Pp
+.Bl -tag -width Ds
+.It Ic strip-atmark-realm Ar true | false
+Remove the realm part which starts with @
+.Pq atmark
+from the User-Name attribute of the Access-Request.
+.Pp
+.It Ic strip-nt-domain Ar true | false
+Remove NT domain which ends with \\
+.Pq backslash
+from the User-Name attribute of the Access-Request.
+.Pp
+.It Cm remove-request-attribute Oo Ar vendor Oc Ar type
+.It Cm remove-response-attribute Oo Ar vendor Oc Ar type
+Remove all the specified attributes from request or response
+messages of Access-Request.
+Specify
+.Ar type
+of the attribute in a decimal number.
+To specify a vendor attribute,
+specify the Vendor-Id
+in a decimal number for
+.Ar vendor .
+.El
+.Sh FILES
+.Bl -tag -width "/usr/libexec/radiusd/radiusd_standard" -compact
+.It Pa /usr/libexec/radiusd/radiusd_standard
+.Dq standard
+module executable.
+.El
+.Sh HISTORY
+The
+.Nm
+daemon first appeared in
+.Ox 5.8 .
diff --git a/usr.sbin/radiusd/radiusd_standard.c b/usr.sbin/radiusd/radiusd_standard.c
index 68d5f8e0f..b925ec4c1 100644
--- a/usr.sbin/radiusd/radiusd_standard.c
+++ b/usr.sbin/radiusd/radiusd_standard.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: radiusd_standard.c,v 1.5 2024/04/23 13:34:51 jsg Exp $ */
+/* $OpenBSD: radiusd_standard.c,v 1.6 2024/07/02 00:33:51 yasuoka Exp $ */
/*
* Copyright (c) 2013, 2023 Internet Initiative Japan Inc.
@@ -17,6 +17,8 @@
*/
#include
#include
+#include
+#include
#include
#include
@@ -49,11 +51,34 @@ struct module_standard {
struct attrs remove_resattrs;
};
+struct radius_const_str {
+ const unsigned constval;
+ const char *label;
+};
+
+static void radius_const_print(FILE *, RADIUS_PACKET *, uint8_t,
+ const char *, struct radius_const_str *);
static void module_standard_config_set(void *, const char *, int,
char * const *);
static void module_standard_reqdeco(void *, u_int, const u_char *, size_t);
static void module_standard_resdeco(void *, u_int, const u_char *, size_t,
const u_char *, size_t);
+static void module_accounting_request(void *, u_int, const u_char *,
+ size_t);
+static void radius_u32_print(FILE *, RADIUS_PACKET *, uint8_t,
+ const char *);
+static void radius_str_print(FILE *, RADIUS_PACKET *, uint8_t,
+ const char *);
+static void radius_ipv4_print(FILE *, RADIUS_PACKET *, uint8_t,
+ const char *);
+static void radius_ipv6_print(FILE *, RADIUS_PACKET *, uint8_t,
+ const char *);
+
+static struct radius_const_str
+ nas_port_type_consts[], tunnel_type_consts[],
+ service_type_consts[], framed_protocol_consts[],
+ acct_status_type_consts[], acct_authentic_consts[],
+ terminate_cause_consts[], tunnel_medium_type_consts[];
int
main(int argc, char *argv[])
@@ -62,7 +87,8 @@ main(int argc, char *argv[])
struct module_handlers handlers = {
.config_set = module_standard_config_set,
.request_decoration = module_standard_reqdeco,
- .response_decoration = module_standard_resdeco
+ .response_decoration = module_standard_resdeco,
+ .accounting_request = module_accounting_request
};
struct attr *attr;
@@ -298,3 +324,286 @@ module_standard_resdeco(void *ctx, u_int q_id, const u_char *req, size_t reqlen,
if (radres != NULL)
radius_delete_packet(radres);
}
+
+static void
+module_accounting_request(void *ctx, u_int query_id, const u_char *pkt,
+ size_t pktlen)
+{
+ RADIUS_PACKET *radpkt = NULL;
+ struct module_standard *module = ctx;
+ FILE *fp;
+ char *buf = NULL;
+ size_t size = 0;
+
+ if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) {
+ syslog(LOG_ERR,
+ "%s: radius_convert_packet() failed: %m", __func__);
+ module_stop(module->base);
+ return;
+ }
+
+ if ((fp = open_memstream(&buf, &size)) == NULL) {
+ syslog(LOG_ERR, "%s: open_memstream() failed: %m", __func__);
+ module_stop(module->base);
+ goto out;
+ }
+ radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_STATUS_TYPE,
+ "Acct-Status-Type", acct_status_type_consts);
+
+ radius_ipv4_print(fp, radpkt, RADIUS_TYPE_NAS_IP_ADDRESS,
+ "NAS-IP-Address");
+ radius_ipv6_print(fp, radpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS,
+ "NAS-IPv6-Address");
+ radius_const_print(fp, radpkt, RADIUS_TYPE_NAS_PORT_TYPE,
+ "NAS-Port-Type", nas_port_type_consts);
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_NAS_PORT, "NAS-Port");
+ radius_str_print(fp, radpkt, RADIUS_TYPE_NAS_IDENTIFIER,
+ "NAS-Identifier");
+ radius_str_print(fp, radpkt, RADIUS_TYPE_CALLING_STATION_ID,
+ "Calling-Station-ID");
+ radius_str_print(fp, radpkt, RADIUS_TYPE_CALLED_STATION_ID,
+ "Called-Station-ID");
+
+ radius_const_print(fp, radpkt, RADIUS_TYPE_TUNNEL_MEDIUM_TYPE,
+ "Tunnel-Medium-Type", tunnel_medium_type_consts);
+ radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT,
+ "Tunnel-Client-Endpoint");
+ radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_SERVER_ENDPOINT,
+ "Tunnel-Server-Endpoint");
+ radius_str_print(fp, radpkt, RADIUS_TYPE_TUNNEL_ASSIGNMENT_ID,
+ "Tunnel-Assignment-ID");
+ radius_str_print(fp, radpkt, RADIUS_TYPE_ACCT_TUNNEL_CONNECTION,
+ "Acct-Tunnel-Connection");
+
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_TIME,
+ "Acct-Session-Time");
+ radius_const_print(fp, radpkt,
+ RADIUS_TYPE_TUNNEL_TYPE, "Tunnel-Type", tunnel_type_consts);
+ radius_str_print(fp, radpkt, RADIUS_TYPE_USER_NAME, "User-Name");
+ radius_const_print(fp, radpkt,
+ RADIUS_TYPE_SERVICE_TYPE, "Service-Type", service_type_consts);
+ radius_const_print(fp, radpkt, RADIUS_TYPE_FRAMED_PROTOCOL,
+ "Framed-Protocol", framed_protocol_consts);
+ radius_ipv4_print(fp, radpkt, RADIUS_TYPE_FRAMED_IP_ADDRESS,
+ "Framed-IP-Address");
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_DELAY_TIME,
+ "Acct-Delay-Time");
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_OCTETS,
+ "Acct-Input-Octets");
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_OCTETS,
+ "Acct-Output-Octets");
+ radius_str_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_ID,
+ "Acct-Session-ID");
+ radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_AUTHENTIC,
+ "Acct-Authentic", acct_authentic_consts);
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_SESSION_TIME,
+ "Acct-Sesion-Time");
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_PACKETS,
+ "Acct-Input-Packets");
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS,
+ "Acct-Output-Packets");
+ radius_const_print(fp, radpkt, RADIUS_TYPE_ACCT_TERMINATE_CAUSE,
+ "Acct-Terminate-Cause", terminate_cause_consts);
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_INPUT_GIGAWORDS,
+ "Acct-Input-Gigawords");
+ radius_u32_print(fp, radpkt, RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS,
+ "Acct-Output-Gigawords");
+
+ fputc('\0', fp);
+ fclose(fp);
+ syslog(LOG_INFO, "Accounting q=%u %s", query_id, buf + 1);
+ out:
+ radius_delete_packet(radpkt);
+ freezero(buf, size);
+}
+
+/***********************************************************************
+ * print RADIUS attribute
+ ***********************************************************************/
+static void
+radius_const_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
+ const char *attr_name, struct radius_const_str *consts)
+{
+ struct radius_const_str *const_;
+ uint32_t u32val;
+
+ if (radius_get_uint32_attr(radpkt, attr_type, &u32val) != 0)
+ return;
+
+ for (const_ = consts; const_->label != NULL; const_++) {
+ if (const_->constval == u32val)
+ break;
+ }
+
+ fprintf(fout, " %s=%s(%u)", attr_name, (const_ != NULL)? const_->label
+ : "unknown", (unsigned)u32val);
+}
+
+static void
+radius_u32_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
+ const char *attr_name)
+{
+ uint32_t u32val;
+
+ if (radius_get_uint32_attr(radpkt, attr_type, &u32val) != 0)
+ return;
+ fprintf(fout, " %s=%u", attr_name, u32val);
+}
+
+static void
+radius_str_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
+ const char *attr_name)
+{
+ char strval[256];
+
+ if (radius_get_string_attr(radpkt, attr_type, strval, sizeof(strval))
+ != 0)
+ return;
+ fprintf(fout, " %s=%s", attr_name, strval);
+}
+
+static void
+radius_ipv4_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
+ const char *attr_name)
+{
+ struct in_addr ipv4;
+ char buf[128];
+
+ if (radius_get_ipv4_attr(radpkt, attr_type, &ipv4) != 0)
+ return;
+ fprintf(fout, " %s=%s", attr_name,
+ inet_ntop(AF_INET, &ipv4, buf, sizeof(buf)));
+}
+
+static void
+radius_ipv6_print(FILE *fout, RADIUS_PACKET *radpkt, uint8_t attr_type,
+ const char *attr_name)
+{
+ struct in6_addr ipv6;
+ char buf[128];
+
+ if (radius_get_ipv6_attr(radpkt, attr_type, &ipv6) != 0)
+ return;
+
+ fprintf(fout, " %s=%s", attr_name,
+ inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf)));
+}
+
+static struct radius_const_str nas_port_type_consts[] = {
+ { RADIUS_NAS_PORT_TYPE_ASYNC, "\"Async\"" },
+ { RADIUS_NAS_PORT_TYPE_SYNC, "\"Sync\"" },
+ { RADIUS_NAS_PORT_TYPE_ISDN_SYNC, "\"ISDN Sync\"" },
+ { RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V120, "\"ISDN Async V.120\"" },
+ { RADIUS_NAS_PORT_TYPE_ISDN_ASYNC_V110, "\"ISDN Async V.110\"" },
+ { RADIUS_NAS_PORT_TYPE_VIRTUAL, "\"Virtual\"" },
+ { RADIUS_NAS_PORT_TYPE_PIAFS, "\"PIAFS\"" },
+ { RADIUS_NAS_PORT_TYPE_HDLC_CLEAR_CHANNEL, "\"HDLC Clear Channel\"" },
+ { RADIUS_NAS_PORT_TYPE_X_25, "\"X.25\"" },
+ { RADIUS_NAS_PORT_TYPE_X_75, "\"X.75\"" },
+ { RADIUS_NAS_PORT_TYPE_G3_FAX, "\"G.3 Fax\"" },
+ { RADIUS_NAS_PORT_TYPE_SDSL, "\"SDSL\"" },
+ { RADIUS_NAS_PORT_TYPE_ADSL_CAP, "\"ADSL-CAP\"" },
+ { RADIUS_NAS_PORT_TYPE_ADSL_DMT, "\"ADSL-DMT\"" },
+ { RADIUS_NAS_PORT_TYPE_IDSL, "\"IDSL\"" },
+ { RADIUS_NAS_PORT_TYPE_ETHERNET, "\"Ethernet\"" },
+ { RADIUS_NAS_PORT_TYPE_XDSL, "\"xDSL\"" },
+ { RADIUS_NAS_PORT_TYPE_CABLE, "\"Cable\"" },
+ { RADIUS_NAS_PORT_TYPE_WIRELESS, "\"Wireless\"" },
+ { RADIUS_NAS_PORT_TYPE_WIRELESS_802_11, "\"Wireless - IEEE 802.11\"" },
+ { 0, NULL }
+};
+
+static struct radius_const_str tunnel_type_consts[] = {
+ { RADIUS_TUNNEL_TYPE_PPTP, "PPTP" },
+ { RADIUS_TUNNEL_TYPE_L2F, "L2F" },
+ { RADIUS_TUNNEL_TYPE_L2TP, "L2TP" },
+ { RADIUS_TUNNEL_TYPE_ATMP, "ATMP" },
+ { RADIUS_TUNNEL_TYPE_VTP, "VTP" },
+ { RADIUS_TUNNEL_TYPE_AH, "AH" },
+ { RADIUS_TUNNEL_TYPE_IP, "IP" },
+ { RADIUS_TUNNEL_TYPE_MOBILE, "MIN-IP-IP" },
+ { RADIUS_TUNNEL_TYPE_ESP, "ESP" },
+ { RADIUS_TUNNEL_TYPE_GRE, "GRE" },
+ { RADIUS_TUNNEL_TYPE_VDS, "DVS" },
+ { 0, NULL }
+};
+
+static struct radius_const_str service_type_consts[] = {
+ { RADIUS_SERVICE_TYPE_LOGIN, "\"Login\"" },
+ { RADIUS_SERVICE_TYPE_FRAMED, "\"Framed\"" },
+ { RADIUS_SERVICE_TYPE_CB_LOGIN, "\"Callback Login\"" },
+ { RADIUS_SERVICE_TYPE_CB_FRAMED, "\"Callback Framed\"" },
+ { RADIUS_SERVICE_TYPE_OUTBOUND, "\"Outbound\"" },
+ { RADIUS_SERVICE_TYPE_ADMINISTRATIVE, "\"Administrative\"" },
+ { RADIUS_SERVICE_TYPE_NAS_PROMPT, "\"NAS Propmt\"" },
+/* there had been a typo in radius.h */
+#if !defined(RADIUS_SERVICE_TYPE_CB_NAS_PROMPT) && \
+ defined(RADIUS_SERVICE_TYPE_CB_NAS_PROMPTi)
+#define RADIUS_SERVICE_TYPE_CB_NAS_PROMPT RADIUS_SERVICE_TYPE_CB_NAS_PROMPTi
+#endif
+ { RADIUS_SERVICE_TYPE_AUTHENTICAT_ONLY, "\"Authenticat Only\"" },
+ { RADIUS_SERVICE_TYPE_CB_NAS_PROMPT, "\"Callback NAS Prompt\"" },
+ { RADIUS_SERVICE_TYPE_CALL_CHECK, "\"Call Check\"" },
+ { RADIUS_SERVICE_TYPE_CB_ADMINISTRATIVE, "\"Callback Administrative\"" },
+ { 0, NULL }
+};
+
+static struct radius_const_str framed_protocol_consts[] = {
+ { RADIUS_FRAMED_PROTOCOL_PPP, "PPP" },
+ { RADIUS_FRAMED_PROTOCOL_SLIP, "SLIP" },
+ { RADIUS_FRAMED_PROTOCOL_ARAP, "ARAP" },
+ { RADIUS_FRAMED_PROTOCOL_GANDALF, "Gandalf" },
+ { RADIUS_FRAMED_PROTOCOL_XYLOGICS, "Xylogics" },
+ { RADIUS_FRAMED_PROTOCOL_X75, "X.75" },
+ { 0, NULL }
+};
+
+static struct radius_const_str acct_status_type_consts[] = {
+ { RADIUS_ACCT_STATUS_TYPE_START, "Start" },
+ { RADIUS_ACCT_STATUS_TYPE_STOP, "Stop" },
+ { RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE, "Interim-Update" },
+ { RADIUS_ACCT_STATUS_TYPE_ACCT_ON, "Accounting-On" },
+ { RADIUS_ACCT_STATUS_TYPE_ACCT_OFF, "Accounting-Off" },
+ { 0, NULL }
+};
+
+static struct radius_const_str acct_authentic_consts[] = {
+ { RADIUS_ACCT_AUTHENTIC_RADIUS, "RADIUS" },
+ { RADIUS_ACCT_AUTHENTIC_LOCAL, "Local" },
+ { RADIUS_ACCT_AUTHENTIC_REMOTE, "Remote" },
+ { 0, NULL }
+};
+
+static struct radius_const_str terminate_cause_consts[] = {
+ { RADIUS_TERMNATE_CAUSE_USER_REQUEST, "\"User Request\"" },
+ { RADIUS_TERMNATE_CAUSE_LOST_CARRIER, "\"Lost Carrier\"" },
+ { RADIUS_TERMNATE_CAUSE_LOST_SERVICE, "\"Lost Service\"" },
+ { RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT, "\"Idle Timeout\"" },
+ { RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT, "\"Session Timeout\"" },
+ { RADIUS_TERMNATE_CAUSE_ADMIN_RESET, "\"Admin Reset\"" },
+ { RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT, "\"Admin Reboot\"" },
+ { RADIUS_TERMNATE_CAUSE_PORT_ERROR, "\"Port Error\"" },
+ { RADIUS_TERMNATE_CAUSE_NAS_ERROR, "\"NAS Error\"" },
+ { RADIUS_TERMNATE_CAUSE_NAS_RESET, "\"NAS Request\"" },
+ { RADIUS_TERMNATE_CAUSE_NAS_REBOOT, "\"NAS Reboot\"" },
+ { RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED, "\"Port Unneeded\"" },
+ { RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED, "\"Port Preempted\"" },
+ { RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED, "\"Port Suspended\"" },
+ { RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL, "\"Service Unavailable\"" },
+ { RADIUS_TERMNATE_CAUSE_CALLBACK, "\"Callback\"" },
+ { RADIUS_TERMNATE_CAUSE_USER_ERROR, "\"User Error\"" },
+ { RADIUS_TERMNATE_CAUSE_HOST_REQUEST, "\"Host Request\"" },
+ { 0, NULL }
+};
+
+static struct radius_const_str tunnel_medium_type_consts[] = {
+ { RADIUS_TUNNEL_MEDIUM_TYPE_IPV4, "IPv4" },
+ { RADIUS_TUNNEL_MEDIUM_TYPE_IPV6, "IPv6" },
+ { RADIUS_TUNNEL_MEDIUM_TYPE_NSAP, "NSAP" },
+ { RADIUS_TUNNEL_MEDIUM_TYPE_HDLC, "HDLC" },
+ { RADIUS_TUNNEL_MEDIUM_TYPE_BBN1822, "BBN1822" },
+ { RADIUS_TUNNEL_MEDIUM_TYPE_802, "802" },
+ { RADIUS_TUNNEL_MEDIUM_TYPE_E163, "E.163" },
+ { RADIUS_TUNNEL_MEDIUM_TYPE_E164, "E.164" },
+ { 0, NULL }
+};
diff --git a/usr.sbin/radiusd/radiusd_standard/Makefile b/usr.sbin/radiusd/radiusd_standard/Makefile
index 5dbea5e19..d873dc2a8 100644
--- a/usr.sbin/radiusd/radiusd_standard/Makefile
+++ b/usr.sbin/radiusd/radiusd_standard/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.1 2023/09/08 05:56:22 yasuoka Exp $
+# $OpenBSD: Makefile,v 1.2 2024/07/02 00:00:12 yasuoka Exp $
PROG= radiusd_standard
BINDIR= /usr/libexec/radiusd
SRCS= radiusd_standard.c radiusd_module.c
LDADD= -lutil -lradius -lcrypto
-NOMAN= #
+MAN= radiusd_standard.8
.include
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index 112969bb8..eba53c958 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: syslogd.c,v 1.281 2024/06/29 11:29:55 jsg Exp $ */
+/* $OpenBSD: syslogd.c,v 1.282 2024/07/01 12:06:45 bluhm Exp $ */
/*
* Copyright (c) 2014-2021 Alexander Bluhm
@@ -314,6 +314,7 @@ int reserve_accept4(int, int, struct event *,
void tcp_acceptcb(int, short, void *);
void tls_acceptcb(int, short, void *);
void acceptcb(int, short, void *, int);
+void tls_handshakecb(struct bufferevent *, void *);
int octet_counting(struct evbuffer *, char **, int);
int non_transparent_framing(struct evbuffer *, char **);
void tcp_readcb(struct bufferevent *, void *);
@@ -1188,6 +1189,7 @@ acceptcb(int lfd, short event, void *arg, int usetls)
close(fd);
return;
}
+ p->p_bufev->readcb = tls_handshakecb;
buffertls_set(&p->p_buftls, p->p_bufev, p->p_ctx, fd);
buffertls_accept(&p->p_buftls, fd);
log_debug("tcp accept callback: tls context success");
@@ -1209,6 +1211,17 @@ acceptcb(int lfd, short event, void *arg, int usetls)
p->p_ctx ? "tls" : "tcp", peername);
}
+void
+tls_handshakecb(struct bufferevent *bufev, void *arg)
+{
+ struct peer *p = arg;
+
+ log_debug("Completed tls handshake");
+
+ bufev->readcb = tcp_readcb;
+ tcp_readcb(bufev, p);
+}
+
/*
* Syslog over TCP RFC 6587 3.4.1. Octet Counting
*/