sync with OpenBSD -current

This commit is contained in:
purplerain 2024-07-02 03:24:35 +00:00
parent f5750f4f6e
commit e42955765e
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
32 changed files with 1329 additions and 320 deletions

View file

@ -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. # Placed in the Public Domain.
# XXX - TODO: # XXX - TODO:
@ -22,7 +22,7 @@ rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
mkdir ${COPY}.dd mkdir ${COPY}.dd
verbose "$tid: lls" 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" grep copy.dd >/dev/null || fail "lls failed"
verbose "$tid: lls w/path" verbose "$tid: lls w/path"

View file

@ -32,7 +32,9 @@ our %args = (
loggrep => { loggrep => {
qr{Keyfile /etc/ssl/private/localhost.key} => 1, qr{Keyfile /etc/ssl/private/localhost.key} => 1,
qr{Certfile /etc/ssl/localhost.crt} => 1, qr{Certfile /etc/ssl/localhost.crt} => 1,
qr/Accepting tcp connection/ => 1,
qr/syslogd\[\d+\]: tls logger .* accepted/ => 1, qr/syslogd\[\d+\]: tls logger .* accepted/ => 1,
qr/Completed tls handshake/ => 1,
qr/syslogd\[\d+\]: tls logger .* connection close/ => 1, qr/syslogd\[\d+\]: tls logger .* connection close/ => 1,
}, },
}, },

View file

@ -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 <reyk@openbsd.org> * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@ -644,16 +644,16 @@ prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
const char * const char *
print_addr(void *addr) 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; static int idx;
struct sockaddr *sa = addr; struct sockaddr *sa = addr;
char *buf; char *buf, *hbuf;
size_t len; size_t len, hlen;
char pbuf[7]; char pbuf[7];
in_port_t port; in_port_t port;
buf = sbuf[idx]; hbuf = buf = sbuf[idx];
len = sizeof(sbuf[idx]); hlen = len = sizeof(sbuf[idx]);
if (++idx >= IKED_CYCLE_BUFFERS) if (++idx >= IKED_CYCLE_BUFFERS)
idx = 0; idx = 0;
@ -662,13 +662,21 @@ print_addr(void *addr)
return (buf); return (buf);
} }
if ((port = socket_getport(sa)) != 0 && sa->sa_family == AF_INET6) {
/* surround [] */
*(hbuf++) = '[';
hlen--;
}
if (getnameinfo(sa, sa->sa_len, if (getnameinfo(sa, sa->sa_len,
buf, len, NULL, 0, NI_NUMERICHOST) != 0) { hbuf, hlen, NULL, 0, NI_NUMERICHOST) != 0) {
strlcpy(buf, "unknown", len); strlcpy(buf, "unknown", len);
return (buf); 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); snprintf(pbuf, sizeof(pbuf), ":%d", port);
(void)strlcat(buf, pbuf, len); (void)strlcat(buf, pbuf, len);
} }

View file

@ -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 * Copyright (c) 2019 Mark Kettenis
* *
@ -306,12 +306,12 @@ thermal_zone_poll(void *arg)
int32_t temp, delta; int32_t temp, delta;
int i; int i;
tp = tz->tz_trips;
temp = thermal_get_temperature_cells(tz->tz_sensors); temp = thermal_get_temperature_cells(tz->tz_sensors);
if (temp == THERMAL_SENSOR_MAX) if (temp == THERMAL_SENSOR_MAX)
goto out; goto out;
newtp = NULL; newtp = NULL;
tp = tz->tz_trips;
for (i = 0; i < tz->tz_ntrips; i++) { for (i = 0; i < tz->tz_ntrips; i++) {
if (temp < tp->tp_temperature && tp != tz->tz_tp) if (temp < tp->tp_temperature && tp != tz->tz_tp)
break; break;
@ -372,7 +372,7 @@ out:
if (polling_delay > 0) if (polling_delay > 0)
timeout_add_msec(&tz->tz_poll_to, polling_delay); timeout_add_msec(&tz->tz_poll_to, polling_delay);
else else if (tp)
thermal_set_limit_cells(tz->tz_sensors, tp->tp_temperature); thermal_set_limit_cells(tz->tz_sensors, tp->tp_temperature);
} }

View file

@ -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 <reyk@openbsd.org> * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
@ -79,10 +79,13 @@ lg_help(struct cmd *cmds, char **argv)
void void
lg_sig_alarm(int sig) lg_sig_alarm(int sig)
{ {
int save_errno = errno;
if (child != -1) { if (child != -1) {
/* Forcibly kill the child, no excuse... */ /* Forcibly kill the child, no excuse... */
kill(child, SIGKILL); kill(child, SIGKILL);
} }
errno = save_errno;
} }
int int

View file

@ -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) /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved. * All rights reserved.
* *
@ -150,7 +150,7 @@
#include "./testrsa.h" #include "./testrsa.h"
#define BUFSIZE (1024*8+64) #define BUFSIZE (1024*8+64)
int run = 0; volatile sig_atomic_t run = 0;
static int mr = 0; static int mr = 0;
static int usertime = 1; static int usertime = 1;
@ -193,7 +193,10 @@ static void sig_done(int sig);
static void static void
sig_done(int sig) sig_done(int sig)
{ {
int save_errno = errno;
signal(SIGALRM, sig_done); signal(SIGALRM, sig_done);
errno = save_errno;
run = 0; run = 0;
} }

View file

@ -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 <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -598,8 +598,9 @@ obfuscate_keystroke_timing(struct ssh *ssh, struct timespec *timeout,
if (timespeccmp(&now, &chaff_until, >=)) { if (timespeccmp(&now, &chaff_until, >=)) {
/* Stop if there have been no keystrokes for a while */ /* Stop if there have been no keystrokes for a while */
stop_reason = "chaff time expired"; stop_reason = "chaff time expired";
} else if (timespeccmp(&now, &next_interval, >=)) { } else if (timespeccmp(&now, &next_interval, >=) &&
/* Otherwise if we were due to send, then send chaff */ !ssh_packet_have_data_to_write(ssh)) {
/* If due to send but have no data, then send chaff */
if (send_chaff(ssh)) if (send_chaff(ssh))
nchaff++; nchaff++;
} }

View file

@ -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"

View file

@ -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. * Copyright (c) 2009 Internet Initiative Japan Inc.
@ -36,7 +36,7 @@
* </ul></p> * </ul></p>
*/ */
/* RFC 1994, 2433 */ /* 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 <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/time.h> #include <sys/time.h>
@ -914,7 +914,7 @@ chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
break; break;
} }
} }
ppp_process_radius_framed_ip(_this->ppp, pkt); ppp_process_radius_attrs(_this->ppp, pkt);
return; return;
auth_failed: auth_failed:

View file

@ -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 <yasuoka@openbsd.org> .\" Copyright (c) 2012 YASUOKA Masahiko <yasuoka@openbsd.org>
.\" .\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" 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 .Dt NPPPD.CONF 5
.Os .Os
.Sh NAME .Sh NAME
@ -506,8 +506,20 @@ The default is
This option can be used multiple times. This option can be used multiple times.
.It Ic dns-servers Ar primary-server-address Op Ar secondary-server-address .It Ic dns-servers Ar primary-server-address Op Ar secondary-server-address
Specify the DNS servers' IP addresses. 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 .It Ic nbns-servers Ar primary-server-address Op Ar secondary-server-address
Specify the NetBIOS name servers' IP addresses. 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 .It Ic allow-user-selected-address Ar yes | no
Specify whether Specify whether
.Xr npppd 8 .Xr npppd 8

View file

@ -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. * Copyright (c) 2009 Internet Initiative Japan Inc.
@ -174,7 +174,9 @@ struct ipcpconf {
TAILQ_ENTRY(ipcpconf) entry; TAILQ_ENTRY(ipcpconf) entry;
char name[NPPPD_GENERIC_NAME_LEN]; char name[NPPPD_GENERIC_NAME_LEN];
bool dns_use_resolver; bool dns_use_resolver;
bool dns_configured;
struct in_addr dns_servers[2]; struct in_addr dns_servers[2];
bool nbns_configured;
struct in_addr nbns_servers[2]; struct in_addr nbns_servers[2];
bool allow_user_select; bool allow_user_select;
struct in_addr_range *dynamic_pool; struct in_addr_range *dynamic_pool;

View file

@ -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. * Copyright (c) 2009 Internet Initiative Japan Inc.
* All rights reserved. * All rights reserved.
@ -38,6 +38,7 @@
#include <sys/syslog.h> #include <sys/syslog.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <net/if_dl.h> #include <net/if_dl.h>
#include <arpa/inet.h>
#include <stdio.h> #include <stdio.h>
#include <netdb.h> #include <netdb.h>
#include <stdint.h> #include <stdint.h>
@ -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. * the given RADIUS packet and set them as the fields of ppp context.
*/ */
void 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) if (radius_get_ipv4_attr(pkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, &ip4)
== 0) == 0)
_this->realm_framed_ip_address = ip4; _this->realm_framed_ip_address = ip4;
@ -87,6 +89,53 @@ ppp_proccess_radius_framed_ip(npppd_ppp *_this, RADIUS_PACKET *pkt)
== 0) == 0)
_this->realm_framed_ip_netmask = ip4; _this->realm_framed_ip_netmask = ip4;
#endif #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 #endif
return 1; 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;
}

View file

@ -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. * 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 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 /**@file
* This file provides Password Authentication Protocol (PAP) handlers. * This file provides Password Authentication Protocol (PAP) handlers.
* @author Yasuoka Masahiko * @author Yasuoka Masahiko
@ -508,7 +508,7 @@ pap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
} }
/* Authentication succeeded */ /* Authentication succeeded */
pap_response(_this, 1, DEFAULT_SUCCESS_MESSAGE); pap_response(_this, 1, DEFAULT_SUCCESS_MESSAGE);
ppp_process_radius_framed_ip(_this->ppp, pkt); ppp_process_radius_attrs(_this->ppp, pkt);
return; return;
auth_failed: auth_failed:

View file

@ -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 <henning@openbsd.org> * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -818,19 +818,23 @@ ipcpopt : POOL_ADDRESS STRING ipcppooltype {
} }
| DNS_SERVERS in4_addr in4_addr { | DNS_SERVERS in4_addr in4_addr {
curr_ipcpconf->dns_use_resolver = false; curr_ipcpconf->dns_use_resolver = false;
curr_ipcpconf->dns_configured = true;
curr_ipcpconf->dns_servers[0] = $2; curr_ipcpconf->dns_servers[0] = $2;
curr_ipcpconf->dns_servers[1] = $3; curr_ipcpconf->dns_servers[1] = $3;
} }
| DNS_SERVERS in4_addr { | DNS_SERVERS in4_addr {
curr_ipcpconf->dns_use_resolver = false; curr_ipcpconf->dns_use_resolver = false;
curr_ipcpconf->dns_configured = true;
curr_ipcpconf->dns_servers[0] = $2; curr_ipcpconf->dns_servers[0] = $2;
curr_ipcpconf->dns_servers[1].s_addr = 0; curr_ipcpconf->dns_servers[1].s_addr = 0;
} }
| NBNS_SERVERS in4_addr in4_addr { | NBNS_SERVERS in4_addr in4_addr {
curr_ipcpconf->nbns_configured = true;
curr_ipcpconf->nbns_servers[0] = $2; curr_ipcpconf->nbns_servers[0] = $2;
curr_ipcpconf->nbns_servers[1] = $3; curr_ipcpconf->nbns_servers[1] = $3;
} }
| NBNS_SERVERS in4_addr { | NBNS_SERVERS in4_addr {
curr_ipcpconf->nbns_configured = true;
curr_ipcpconf->nbns_servers[0] = $2; curr_ipcpconf->nbns_servers[0] = $2;
curr_ipcpconf->nbns_servers[1].s_addr = 0; curr_ipcpconf->nbns_servers[1].s_addr = 0;
} }

View file

@ -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. * 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 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 /**@file
* This file provides PPP(Point-to-Point Protocol, RFC 1661) and * This file provides PPP(Point-to-Point Protocol, RFC 1661) and
* {@link :: _npppd_ppp PPP instance} related functions. * {@link :: _npppd_ppp PPP instance} related functions.
@ -1061,65 +1061,6 @@ ppp_log(npppd_ppp *_this, int prio, const char *fmt, ...)
return status; 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 #ifdef USE_NPPPD_PIPEX
/** The callback function on network is available for pipex */ /** The callback function on network is available for pipex */
static void static void

View file

@ -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. * 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); int ppp_log (npppd_ppp *, int, const char *, ...) __printflike(3,4);
void ppp_reset_idle_timeout(npppd_ppp *); void ppp_reset_idle_timeout(npppd_ppp *);
#ifdef USE_NPPPD_RADIUS #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 *); int ppp_set_radius_attrs_for_authreq (npppd_ppp *, radius_req_setting *, RADIUS_PACKET *);
#endif #endif
struct tunnconf *ppp_get_tunnconf(npppd_ppp *); struct tunnconf *ppp_get_tunnconf(npppd_ppp *);

View file

@ -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 <henning@openbsd.org> * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -37,14 +37,17 @@
#include "log.h" #include "log.h"
static struct radiusd *conf; static struct radiusd *conf;
static struct radiusd_authentication authen; static struct radiusd_authentication authen;
static struct radiusd_client client; static struct radiusd_module *conf_module = NULL;
static struct radiusd_client client;
static struct radiusd_module *find_module (const char *); static struct radiusd_module *find_module(const char *);
static void free_str_l (void *); static void free_str_l(void *);
static struct radiusd_module_ref *create_module_ref (const char *); static struct radiusd_module_ref *create_module_ref(const char *);
static void radiusd_authentication_init (struct radiusd_authentication *); static void radiusd_authentication_init(struct radiusd_authentication *);
static void radiusd_client_init (struct radiusd_client *); 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); TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
static struct file { static struct file {
@ -89,17 +92,18 @@ typedef struct {
%} %}
%token INCLUDE LISTEN ON PORT CLIENT SECRET LOAD MODULE MSGAUTH_REQUIRED %token INCLUDE LISTEN ON PORT CLIENT SECRET LOAD MODULE MSGAUTH_REQUIRED
%token AUTHENTICATE AUTHENTICATE_BY DECORATE_BY SET %token ACCOUNT ACCOUNTING AUTHENTICATE AUTHENTICATE_BY BY DECORATE_BY QUICK
%token ERROR YES NO %token SET TO ERROR YES NO
%token <v.string> STRING %token <v.string> STRING
%token <v.number> NUMBER %token <v.number> NUMBER
%type <v.number> optport %type <v.number> optport optacct
%type <v.listen> listen_addr %type <v.listen> listen_addr
%type <v.str_l> str_l %type <v.str_l> str_l optdeco
%type <v.prefix> prefix %type <v.prefix> prefix
%type <v.yesno> yesno %type <v.yesno> yesno optquick
%type <v.string> strnum %type <v.string> strnum
%type <v.string> key %type <v.string> key
%type <v.string> optstring
%% %%
grammar : /* empty */ grammar : /* empty */
@ -109,6 +113,7 @@ grammar : /* empty */
| grammar client '\n' | grammar client '\n'
| grammar module '\n' | grammar module '\n'
| grammar authenticate '\n' | grammar authenticate '\n'
| grammar account '\n'
| grammar error '\n' | grammar error '\n'
; ;
@ -139,7 +144,7 @@ outofmemory:
*n = $3; *n = $3;
TAILQ_INSERT_TAIL(&conf->listen, n, next); TAILQ_INSERT_TAIL(&conf->listen, n, next);
} }
listen_addr : STRING optport { listen_addr : STRING optacct optport {
int gai_errno; int gai_errno;
struct addrinfo hints, *res; struct addrinfo hints, *res;
@ -160,11 +165,22 @@ listen_addr : STRING optport {
free($1); free($1);
$$.stype = res->ai_socktype; $$.stype = res->ai_socktype;
$$.sproto = res->ai_protocol; $$.sproto = res->ai_protocol;
$$.accounting = $2;
memcpy(&$$.addr, res->ai_addr, res->ai_addrlen); memcpy(&$$.addr, res->ai_addr, res->ai_addrlen);
$$.addr.ipv4.sin_port = ($2 == 0)? if ($3 != 0)
htons(RADIUS_DEFAULT_PORT) : htons($2); $$.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); freeaddrinfo(res);
} }
optacct : ACCOUNTING { $$ = 1; }
| { $$ = 0; }
;
optport : { $$ = 0; } optport : { $$ = 0; }
| PORT NUMBER { $$ = $2; } | PORT NUMBER { $$ = $2; }
; ;
@ -265,7 +281,45 @@ prefix : STRING '/' NUMBER {
freeaddrinfo(res); 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; struct radiusd_module *module;
if ((module = radiusd_module_load(conf, $4, $3)) if ((module = radiusd_module_load(conf, $4, $3))
== NULL) { == 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 key : STRING
| SECRET { $$ = strdup("secret"); } | 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); radiusd_authentication_init(&authen);
} str_l optnl '{' authopts '}' { authen.username = $2.v;
struct radiusd_authentication *a; } authopts '}' {
int i;
struct radiusd_authentication *a;
if (authen.auth == NULL) { if (authen.auth == NULL) {
free_str_l(&$3);
yyerror("no authentication module specified"); yyerror("no authentication module specified");
for (i = 0; authen.username[i] != NULL; i++)
free(authen.username[i]);
free(authen.username);
YYERROR; YYERROR;
} }
if ((a = calloc(1, if ((a = calloc(1,
sizeof(struct radiusd_authentication))) == NULL) { 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; goto outofmemory;
} }
a->auth = authen.auth; a->auth = authen.auth;
authen.auth = NULL; authen.auth = NULL;
a->deco = authen.deco; a->deco = authen.deco;
a->username = $3.v; a->username = authen.username;
TAILQ_INSERT_TAIL(&conf->authen, a, next); TAILQ_INSERT_TAIL(&conf->authen, a, next);
} }
; ;
optdeco : { $$.c = 0; $$.v = NULL; }
| DECORATE_BY str_l { $$ = $2; }
;
authopts : authopts '\n' authopt authopts : authopts '\n' authopt
| authopt | authopt
; ;
@ -363,8 +487,53 @@ authopt : AUTHENTICATE_BY STRING {
} }
free_str_l(&$2); 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 { str_l : str_l strnum {
int i; int i;
char **v; char **v;
@ -397,6 +566,9 @@ strnum : STRING { $$ = $1; }
optnl : optnl :
| '\n' | '\n'
; ;
optstring : { $$ = NULL; }
| STRING { $$ = $1; }
;
yesno : YES { $$ = true; } yesno : YES { $$ = true; }
| NO { $$ = false; } | NO { $$ = false; }
; ;
@ -434,8 +606,11 @@ lookup(char *s)
{ {
/* this has to be sorted always */ /* this has to be sorted always */
static const struct keywords keywords[] = { static const struct keywords keywords[] = {
{ "account", ACCOUNT},
{ "accounting", ACCOUNTING},
{ "authenticate", AUTHENTICATE}, { "authenticate", AUTHENTICATE},
{ "authenticate-by", AUTHENTICATE_BY}, { "authenticate-by", AUTHENTICATE_BY},
{ "by", BY},
{ "client", CLIENT}, { "client", CLIENT},
{ "decorate-by", DECORATE_BY}, { "decorate-by", DECORATE_BY},
{ "include", INCLUDE}, { "include", INCLUDE},
@ -446,8 +621,10 @@ lookup(char *s)
{ "no", NO}, { "no", NO},
{ "on", ON}, { "on", ON},
{ "port", PORT}, { "port", PORT},
{ "quick", QUICK},
{ "secret", SECRET}, { "secret", SECRET},
{ "set", SET}, { "set", SET},
{ "to", TO},
{ "yes", YES}, { "yes", YES},
}; };
const struct keywords *p; const struct keywords *p;
@ -724,7 +901,6 @@ parse_config(const char *filename, struct radiusd *radiusd)
{ {
int errors = 0; int errors = 0;
struct radiusd_listen *l; struct radiusd_listen *l;
struct radiusd_module_ref *m, *mt;
conf = radiusd; conf = radiusd;
radiusd_conf_init(conf); radiusd_conf_init(conf);
@ -758,10 +934,8 @@ parse_config(const char *filename, struct radiusd *radiusd)
l->sock = -1; l->sock = -1;
} }
radiusd_authentication_init(&authen); radiusd_authentication_init(&authen);
TAILQ_FOREACH_SAFE(m, &authen.deco, next, mt) { if (conf_module != NULL)
TAILQ_REMOVE(&authen.deco, m, next); radiusd_module_unload(conf_module);
free(m);
}
out: out:
conf = NULL; conf = NULL;
return (errors ? -1 : 0); return (errors ? -1 : 0);
@ -827,3 +1001,24 @@ radiusd_client_init(struct radiusd_client *clnt)
memset(clnt, 0, sizeof(struct radiusd_client)); memset(clnt, 0, sizeof(struct radiusd_client));
clnt->msgauth_required = true; 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);
}

View file

@ -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. * Copyright (c) 2013, 2023 Internet Initiative Japan Inc.
@ -33,6 +33,7 @@
#include <imsg.h> #include <imsg.h>
#include <md5.h> #include <md5.h>
#include <netdb.h> #include <netdb.h>
#include <paths.h>
#include <pwd.h> #include <pwd.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
@ -62,15 +63,18 @@ static void radiusd_on_sighup(int, short, void *);
static void radiusd_on_sigchld(int, short, void *); static void radiusd_on_sigchld(int, short, void *);
static void raidus_query_access_request(struct radius_query *); static void raidus_query_access_request(struct radius_query *);
static void radius_query_access_response(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_code_string(int);
static const char *radius_acct_status_type_string(uint32_t);
static int radiusd_access_response_fixup (struct radius_query *); static int radiusd_access_response_fixup (struct radius_query *);
static void radiusd_module_reset_ev_handler( static void radiusd_module_reset_ev_handler(
struct radiusd_module *); struct radiusd_module *);
static int radiusd_module_imsg_read(struct radiusd_module *, static int radiusd_module_imsg_read(struct radiusd_module *);
bool);
static void radiusd_module_imsg(struct radiusd_module *, static void radiusd_module_imsg(struct radiusd_module *,
struct imsg *); struct imsg *);
@ -89,8 +93,11 @@ static void radiusd_module_request_decoration(
struct radiusd_module *, struct radius_query *); struct radiusd_module *, struct radius_query *);
static void radiusd_module_response_decoration( static void radiusd_module_response_decoration(
struct radiusd_module *, struct radius_query *); 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 *, static int imsg_compose_radius_packet(struct imsgbuf *,
uint32_t, u_int, RADIUS_PACKET *); uint32_t, u_int, RADIUS_PACKET *);
static void close_stdio(void);
static u_int radius_query_id_seq = 0; static u_int radius_query_id_seq = 0;
int debug = 0; int debug = 0;
@ -144,16 +151,20 @@ main(int argc, char *argv[])
TAILQ_INIT(&radiusd->listen); TAILQ_INIT(&radiusd->listen);
TAILQ_INIT(&radiusd->query); TAILQ_INIT(&radiusd->query);
log_init(debug); if (!noaction && debug == 0)
daemon(0, 1); /* pend closing stdio files */
if (parse_config(conffile, radiusd) != 0) if (parse_config(conffile, radiusd) != 0)
errx(EXIT_FAILURE, "config error"); errx(EXIT_FAILURE, "config error");
log_init(debug);
if (noaction) { if (noaction) {
fprintf(stderr, "configuration OK\n"); fprintf(stderr, "configuration OK\n");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
if (debug == 0) if (debug == 0)
daemon(0, 0); close_stdio(); /* close stdio files now */
event_init(); event_init();
if ((pw = getpwnam(RADIUSD_USER)) == NULL) if ((pw = getpwnam(RADIUSD_USER)) == NULL)
@ -187,10 +198,16 @@ main(int argc, char *argv[])
if (event_loop(0) < 0) if (event_loop(0) < 0)
radiusd_stop(radiusd); radiusd_stop(radiusd);
if (radiusd->error != 0)
log_warnx("exiting on error");
radiusd_free(radiusd); radiusd_free(radiusd);
event_base_free(NULL); event_base_free(NULL);
exit(EXIT_SUCCESS); if (radiusd->error != 0)
exit(EXIT_FAILURE);
else
exit(EXIT_SUCCESS);
} }
static int static int
@ -198,7 +215,7 @@ radiusd_start(struct radiusd *radiusd)
{ {
struct radiusd_listen *l; struct radiusd_listen *l;
struct radiusd_module *module; struct radiusd_module *module;
int s; int s, on;
char hbuf[NI_MAXHOST]; char hbuf[NI_MAXHOST];
TAILQ_FOREACH(l, &radiusd->listen, next) { TAILQ_FOREACH(l, &radiusd->listen, next) {
@ -214,6 +231,12 @@ radiusd_start(struct radiusd *radiusd)
hbuf, (int)htons(l->addr.ipv4.sin_port)); hbuf, (int)htons(l->addr.ipv4.sin_port));
goto on_error; 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) if (bind(s, (struct sockaddr *)&l->addr, l->addr.ipv4.sin_len)
!= 0) { != 0) {
log_warn("Listen %s port %d is failed: bind()", log_warn("Listen %s port %d is failed: bind()",
@ -251,6 +274,7 @@ radiusd_start(struct radiusd *radiusd)
return (0); return (0);
on_error: on_error:
radiusd->error++;
radiusd_stop(radiusd); radiusd_stop(radiusd);
return (-1); return (-1);
@ -387,8 +411,10 @@ radiusd_listen_handle_packet(struct radiusd_listen *listn,
static char username[256]; static char username[256];
char peerstr[NI_MAXHOST + NI_MAXSERV + 30]; char peerstr[NI_MAXHOST + NI_MAXSERV + 30];
struct radiusd_authentication *authen; struct radiusd_authentication *authen;
struct radiusd_accounting *accounting;
struct radiusd_client *client; struct radiusd_client *client;
struct radius_query *q = NULL; struct radius_query *q = NULL;
uint32_t acct_status;
#define in(_x) (((struct sockaddr_in *)_x)->sin_addr) #define in(_x) (((struct sockaddr_in *)_x)->sin_addr)
#define in6(_x) (((struct sockaddr_in6 *)_x)->sin6_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; 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 */ /* Check the client's Message-Authenticator */
if (client->msgauth_required && !radius_has_attr(packet, if (client->msgauth_required && !listn->accounting &&
RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) { !radius_has_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR)) {
log_warnx("Received %s(code=%d) from %s id=%d: no message " log_warnx("Received %s(code=%d) from %s id=%d: no message "
"authenticator", radius_code_string(req_code), req_code, "authenticator", radius_code_string(req_code), req_code,
peerstr, req_id); peerstr, req_id);
@ -485,6 +521,13 @@ radiusd_listen_handle_packet(struct radiusd_listen *listn,
switch (req_code) { switch (req_code) {
case RADIUS_CODE_ACCESS_REQUEST: 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 * Find a matching `authenticate' entry
*/ */
@ -521,6 +564,47 @@ radiusd_listen_handle_packet(struct radiusd_listen *listn,
raidus_query_access_request(q); raidus_query_access_request(q);
return; 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: default:
log_info("Received %s(code=%d) from %s id=%d: %s is not " log_info("Received %s(code=%d) from %s id=%d: %s is not "
"supported in this implementation", radius_code_string( "supported in this implementation", radius_code_string(
@ -609,6 +693,53 @@ on_error:
radiusd_access_request_aborted(q); 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 * Callback functions from the modules
***********************************************************************/ ***********************************************************************/
@ -691,7 +822,7 @@ radiusd_on_sigchld(int fd, short evmask, void *ctx)
struct radiusd *radiusd = ctx; struct radiusd *radiusd = ctx;
struct radiusd_module *module; struct radiusd_module *module;
pid_t pid; pid_t pid;
int status; int status, ndeath = 0;
log_debug("Received SIGCHLD"); log_debug("Received SIGCHLD");
while ((pid = wait3(&status, WNOHANG, NULL)) != 0) { 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 " log_warnx("module `%s'(pid=%d) exited "
"by signal %d", module->name, "by signal %d", module->name,
(int)pid, WTERMSIG(status)); (int)pid, WTERMSIG(status));
ndeath++;
break; break;
} }
} }
@ -721,6 +853,10 @@ radiusd_on_sigchld(int fd, short evmask, void *ctx)
WTERMSIG(status)); WTERMSIG(status));
} }
} }
if (ndeath > 0) {
radiusd->error++;
event_loopbreak();
}
} }
static const char * static const char *
@ -749,6 +885,29 @@ radius_code_string(int code)
return ("Unknown"); 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 void
radiusd_conf_init(struct radiusd *conf) radiusd_conf_init(struct radiusd *conf)
{ {
@ -756,6 +915,7 @@ radiusd_conf_init(struct radiusd *conf)
TAILQ_INIT(&conf->listen); TAILQ_INIT(&conf->listen);
TAILQ_INIT(&conf->module); TAILQ_INIT(&conf->module);
TAILQ_INIT(&conf->authen); TAILQ_INIT(&conf->authen);
TAILQ_INIT(&conf->account);
TAILQ_INIT(&conf->client); TAILQ_INIT(&conf->client);
return; return;
@ -1085,9 +1245,8 @@ radiusd_module_on_imsg_io(int fd, short evmask, void *ctx)
if (evmask & EV_WRITE) if (evmask & EV_WRITE)
module->writeready = true; module->writeready = true;
if (evmask & EV_READ || module->ibuf.r.wpos > IMSG_HEADER_SIZE) { if (evmask & EV_READ) {
if (radiusd_module_imsg_read(module, if (radiusd_module_imsg_read(module) == -1)
(evmask & EV_READ)? true : false) == -1)
goto on_error; goto on_error;
} }
@ -1124,8 +1283,7 @@ radiusd_module_reset_ev_handler(struct radiusd_module *module)
evmask |= EV_WRITE; evmask |= EV_WRITE;
else else
tvp = &tv; /* fire immediately */ 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 */ /* module stopped and no event handler is set */
if (evmask & EV_WRITE && tvp == NULL && module->stopped) { if (evmask & EV_WRITE && tvp == NULL && module->stopped) {
@ -1144,22 +1302,20 @@ radiusd_module_reset_ev_handler(struct radiusd_module *module)
} }
static int static int
radiusd_module_imsg_read(struct radiusd_module *module, bool doread) radiusd_module_imsg_read(struct radiusd_module *module)
{ {
int n; int n;
struct imsg imsg; struct imsg imsg;
if (doread) { if ((n = imsg_read(&module->ibuf)) == -1 || n == 0) {
if ((n = imsg_read(&module->ibuf)) == -1 || n == 0) { if (n == -1 && errno == EAGAIN)
if (n == -1 && errno == EAGAIN) return (0);
return (0); if (n == -1)
if (n == -1) log_warn("Receiving a message from module `%s' "
log_warn("Receiving a message from module `%s' " "failed: imsg_read", module->name);
"failed: imsg_read", module->name); /* else closed */
/* else closed */ radiusd_module_close(module);
radiusd_module_close(module); return (-1);
return (-1);
}
} }
for (;;) { for (;;) {
if ((n = imsg_get(&module->ibuf, &imsg)) == -1) { 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; module->radpktoff = 0;
switch (imsg->hdr.type) { switch (imsg->hdr.type) {
case IMSG_RADIUSD_MODULE_REQDECO_DONE: 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) { if (radpkt != NULL) {
radius_delete_packet(q->req); radius_delete_packet(q->req);
q->req = radpkt; q->req = radpkt;
@ -1283,7 +1447,7 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
break; break;
case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER: case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER:
if (radpkt == NULL) { if (radpkt == NULL) {
log_warn("q=%u wrong pkt from module", log_warnx("q=%u wrong pkt from module",
q->id); q->id);
radiusd_access_request_aborted(q); radiusd_access_request_aborted(q);
break; break;
@ -1292,6 +1456,14 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg)
radiusd_access_request_answer(q); radiusd_access_request_answer(q);
break; break;
case IMSG_RADIUSD_MODULE_RESDECO_DONE: 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) { if (radpkt != NULL) {
radius_delete_packet(q->res); radius_delete_packet(q->res);
radius_set_request_packet(radpkt, 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: 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_id = *((u_int *)imsg->data);
q = radiusd_find_query(module->radiusd, q_id); q = radiusd_find_query(module->radiusd, q_id);
if (q == NULL) { if (q == NULL) {
@ -1531,6 +1708,8 @@ radiusd_module_request_decoration(struct radiusd_module *module,
radiusd_access_request_aborted(q); radiusd_access_request_aborted(q);
return; return;
} }
RADIUSD_ASSERT(q->deco != NULL);
q->deco->type = IMSG_RADIUSD_MODULE_REQDECO;
radiusd_module_reset_ev_handler(module); radiusd_module_reset_ev_handler(module);
} }
@ -1558,9 +1737,34 @@ radiusd_module_response_decoration(struct radiusd_module *module,
radiusd_access_request_aborted(q); radiusd_access_request_aborted(q);
return; return;
} }
RADIUSD_ASSERT(q->deco != NULL);
q->deco->type = IMSG_RADIUSD_MODULE_RESDECO;
radiusd_module_reset_ev_handler(module); 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 static int
imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id, imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id,
RADIUS_PACKET *radpkt) RADIUS_PACKET *radpkt)
@ -1593,3 +1797,17 @@ imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id,
} }
return (0); 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);
}
}

View file

@ -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 Esdenera Networks GmbH
.\" Copyright (c) 2014, 2023 Internet Initiative Japan Inc. .\" Copyright (c) 2014, 2023 Internet Initiative Japan Inc.
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" 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 .Dt RADIUSD.CONF 5
.Os .Os
.Sh NAME .Sh NAME
@ -35,14 +35,18 @@ Keywords may be specified multiple times within the configuration file.
The configuration options are as follows: The configuration options are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo .It Xo
.Ic listen on Ar address .Ic listen on Ar address Oo Ic accounting Oc Ic port Ar port
.Ic port Ar port
.Xc .Xc
Specify an Specify an
.Ar address .Ar address
and a and a
.Ar port .Ar port
to listen on. 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 ... .It Ic client Ar address/mask Brq ...
Allow access to a client with the specified Allow access to a client with the specified
.Ar address .Ar address
@ -57,40 +61,46 @@ This option cannot be omitted.
Specify if message authentication is required. Specify if message authentication is required.
The default is to require message authentication. The default is to require message authentication.
.El .El
.It Ic module load Ar name path .It Ic module Ar name Oo Ar path Oc Op Brq ...
Load a module Load a module.
from Specify one of the predefined names for
.Ar path .Ar name ,
and name it with the given or specify
.Ar name . .Ar name
The following modules are available: and
.Bl -column "/usr/libexec/radiusd/radiusd_bsdauthXXX" .Ar path .
.It Sy "Path" Ta Sy "Description" When multiple modules of the same path are loaded with different names,
.It Pa /usr/libexec/radiusd/radiusd_bsdauth Ta Do bsdauth Dc module each module can have configurations respectively and work independently.
.It Pa /usr/libexec/radiusd/radiusd_radius Ta Do radius Dc module .Pp
.It Pa /usr/libexec/radiusd/radiusd_standard Ta Do standard Dc module The following module are predefined:
.El
.Bl -tag -width Ds .Bl -tag -width Ds
.It Do bsdauth Dc module .It Do bsdauth Dc module
The The
.Dq bsdauth .Dq bsdauth
module provides authentication from the local system's module
provides authentication from the local system's
.Xr authenticate 3 .Xr authenticate 3
interface, interface.
known as See
.Dq bsd auth . .Xr radiusd_bsdauth 8 .
It only supports PAP, password based authentication.
.It Do radius Dc module .It Do radius Dc module
The The
.Dq radius .Dq radius
module provides authentication from upstream RADIUS servers. module provides authentication from upstream RADIUS servers.
See
.Xr radiusd_radius 8 .
.It Do standard Dc module .It Do standard Dc module
The The
.Dq standard .Dq standard
module provides standard decorations for Access-Request messages or its module provides standard decorations for RADIUS messages.
response messages. See
.Xr radiusd_standard 8 .
.El .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 Configure the module specific configurations by
.Ar key .Ar key
and and
@ -98,92 +108,18 @@ and
for the module specified by for the module specified by
.Ar module . .Ar module .
Notice that Notice that
.Ar module ,
.Ar key , .Ar key ,
and and
.Ar value .Ar value
must be quoted to be distinguished from the reserved word (e.g.\& must be quoted to be distinguished from the reserved word if needed.
.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.
.El .El
.Pp .It Ic authenticate Ar username-pattern ... Ic by Ar auth Oo Ic decorated-by \
The Ar deco ... Oc
.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 ...
Specify an authentication configuration for the users specified by 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; Use shell globbing rules for the pattern;
multiple patterns can be specified by separating with space characters. multiple patterns can be specified by separating with space characters.
When multiple When multiple
@ -193,60 +129,78 @@ lines are specified, the first
setting whose setting whose
.Ar username-pattern .Ar username-pattern
matches an authenticating user is used. matches an authenticating user is used.
It is followed by a block of options enclosed in curly brackets: .Pp
.Bl -tag -width Ds Optionally decoration modules can be specified by
.It Ic authenticate-by Ar module .Ar deco .
Specify the module name. The specified modules decorate the RADIUS messages in the configured order.
.It Ic decorate-by Ar module .It Ic account Oo Ic quick Oc Ar username-pattern ... Ic to Ar module \
Specify the module name. Oo Ic decoratd by Ar deco ... Oc
.El 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 .El
.Sh FILES .Sh FILES
.Bl -tag -width "/usr/libexec/radiusd/radiusd_bsdauth" -compact .Bl -tag -width "/etc/examples/radiusd.conf" -compact
.It Pa /etc/radiusd.conf .It Pa /etc/radiusd.conf
Default Default
.Xr radiusd 8 .Xr radiusd 8
configuration file. configuration file.
.It Pa /etc/examples/radiusd.conf .It Pa /etc/examples/radiusd.conf
Example configuration file. 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 .El
.Sh EXAMPLES .Sh EXAMPLES
.Bd -literal -offset indent .Bd -literal -offset indent
listen on 0.0.0.0 listen on 0.0.0.0
listen on 0.0.0.0 accounting
listen on :: listen on ::
listen on :: accounting
client 127.0.0.1/32 { client 127.0.0.1/32 {
secret "secret" secret "secret"
msgauth-required no msgauth-required no
} }
client 192.168.0.0/24 { client 192.168.0.0/24 {
secret "secret" secret "secret"
} }
module load bsdauth "/usr/libexec/radiusd/radiusd_bsdauth" module bsdauth {
module set bsdauth restrict-group operator set 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
} }
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 .Ed
.Sh SEE ALSO .Sh SEE ALSO
.Xr authenticate 3 , .Xr radiusd 8 ,
.Xr radiusd 8 .Xr radiusd_bsdauth 8 ,
.Xr radiusd_radius 8 ,
.Xr radiusd_standard 8

View file

@ -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 #ifndef RADIUSD_H
#define RADIUSD_H 1 #define RADIUSD_H 1
@ -45,16 +45,18 @@ enum imsg_type {
IMSG_RADIUSD_MODULE_RESDECO0_REQ, /* request pkt for RESDECO */ IMSG_RADIUSD_MODULE_RESDECO0_REQ, /* request pkt for RESDECO */
IMSG_RADIUSD_MODULE_RESDECO, IMSG_RADIUSD_MODULE_RESDECO,
IMSG_RADIUSD_MODULE_RESDECO_DONE, IMSG_RADIUSD_MODULE_RESDECO_DONE,
IMSG_RADIUSD_MODULE_STOP IMSG_RADIUSD_MODULE_ACCTREQ,
IMSG_RADIUSD_MODULE_STOP,
}; };
/* Module sends LOAD when it becomes ready */ /* Module sends LOAD when it becomes ready */
struct radiusd_module_load_arg { struct radiusd_module_load_arg {
uint32_t cap; /* module capabity bits */ uint32_t cap; /* module capabity bits */
#define RADIUSD_MODULE_CAP_USERPASS 0x1 #define RADIUSD_MODULE_CAP_USERPASS 0x01
#define RADIUSD_MODULE_CAP_ACCSREQ 0x2 #define RADIUSD_MODULE_CAP_ACCSREQ 0x02
#define RADIUSD_MODULE_CAP_REQDECO 0x4 #define RADIUSD_MODULE_CAP_REQDECO 0x04
#define RADIUSD_MODULE_CAP_RESDECO 0x8 #define RADIUSD_MODULE_CAP_RESDECO 0x08
#define RADIUSD_MODULE_CAP_ACCTREQ 0x10
}; };
struct radiusd_module_object { struct radiusd_module_object {

View file

@ -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 .

View file

@ -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 PROG= radiusd_bsdauth
BINDIR= /usr/libexec/radiusd BINDIR= /usr/libexec/radiusd
SRCS= radiusd_bsdauth.c radiusd_module.c imsg_subr.c SRCS= radiusd_bsdauth.c radiusd_module.c imsg_subr.c
LDADD+= -lradius -lcrypto -lutil LDADD+= -lradius -lcrypto -lutil
DPADD+= ${LIBRADIUS} ${LIBCRYPTO} ${LIBUTIL} DPADD+= ${LIBRADIUS} ${LIBCRYPTO} ${LIBUTIL}
NOMAN= # MAN= radiusd_bsdauth.8
.include <bsd.prog.mk> .include <bsd.prog.mk>

View file

@ -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. * Copyright (c) 2013 Internet Initiative Japan Inc.
@ -44,6 +44,7 @@ struct radiusd_listen {
struct radiusd *radiusd; struct radiusd *radiusd;
struct event ev; struct event ev;
int sock; int sock;
int accounting;
union { union {
struct sockaddr_in ipv4; struct sockaddr_in ipv4;
struct sockaddr_in6 ipv6; struct sockaddr_in6 ipv6;
@ -85,17 +86,26 @@ struct radiusd_module {
struct radiusd_module_ref { struct radiusd_module_ref {
struct radiusd_module *module; struct radiusd_module *module;
unsigned int type;
TAILQ_ENTRY(radiusd_module_ref) next; TAILQ_ENTRY(radiusd_module_ref) next;
}; };
struct radiusd_authentication { struct radiusd_authentication {
char **username; char **username;
char *secret;
struct radiusd_module_ref *auth; struct radiusd_module_ref *auth;
TAILQ_HEAD(,radiusd_module_ref) deco; TAILQ_HEAD(,radiusd_module_ref) deco;
TAILQ_ENTRY(radiusd_authentication) next; 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 {
struct radiusd_listen_head listen; struct radiusd_listen_head listen;
struct event ev_sigterm; struct event ev_sigterm;
@ -104,8 +114,10 @@ struct radiusd {
struct event ev_sigchld; struct event ev_sigchld;
TAILQ_HEAD(,radiusd_module) module; TAILQ_HEAD(,radiusd_module) module;
TAILQ_HEAD(,radiusd_authentication) authen; TAILQ_HEAD(,radiusd_authentication) authen;
TAILQ_HEAD(,radiusd_accounting) account;
TAILQ_HEAD(,radiusd_client) client; TAILQ_HEAD(,radiusd_client) client;
TAILQ_HEAD(,radius_query) query; TAILQ_HEAD(,radius_query) query;
int error;
}; };
struct radius_query { struct radius_query {
@ -150,6 +162,9 @@ struct radius_query {
#define MODULE_DO_ACCSREQ(_m) \ #define MODULE_DO_ACCSREQ(_m) \
((_m)->fd >= 0 && \ ((_m)->fd >= 0 && \
((_m)->capabilities & RADIUSD_MODULE_CAP_ACCSREQ) != 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) \ #define MODULE_DO_REQDECO(_m) \
((_m)->fd >= 0 && \ ((_m)->fd >= 0 && \
((_m)->capabilities & RADIUSD_MODULE_CAP_REQDECO) != 0) ((_m)->capabilities & RADIUSD_MODULE_CAP_REQDECO) != 0)

View file

@ -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 <yasuoka@yasuoka.net> * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
@ -50,6 +50,8 @@ static void (*module_request_decoration) (void *, u_int, const u_char *,
size_t) = NULL; size_t) = NULL;
static void (*module_response_decoration) (void *, u_int, const u_char *, static void (*module_response_decoration) (void *, u_int, const u_char *,
size_t, const u_char *, size_t) = NULL; 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 { struct module_base {
void *ctx; void *ctx;
@ -98,6 +100,7 @@ module_create(int sock, void *ctx, struct module_handlers *handler)
module_config_set = handler->config_set; module_config_set = handler->config_set;
module_request_decoration = handler->request_decoration; module_request_decoration = handler->request_decoration;
module_response_decoration = handler->response_decoration; module_response_decoration = handler->response_decoration;
module_accounting_request = handler->accounting_request;
module_start_module = handler->start; module_start_module = handler->start;
module_stop_module = handler->stop; module_stop_module = handler->stop;
@ -156,6 +159,8 @@ module_load(struct module_base *base)
load.cap |= RADIUSD_MODULE_CAP_REQDECO; load.cap |= RADIUSD_MODULE_CAP_REQDECO;
if (module_response_decoration != NULL) if (module_response_decoration != NULL)
load.cap |= RADIUSD_MODULE_CAP_RESDECO; 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, imsg_compose(&base->ibuf, IMSG_RADIUSD_MODULE_LOAD, 0, 0, -1, &load,
sizeof(load)); sizeof(load));
imsg_flush(&base->ibuf); 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_REQDECO:
case IMSG_RADIUSD_MODULE_RESDECO0_REQ: case IMSG_RADIUSD_MODULE_RESDECO0_REQ:
case IMSG_RADIUSD_MODULE_RESDECO: case IMSG_RADIUSD_MODULE_RESDECO:
case IMSG_RADIUSD_MODULE_ACCTREQ:
{ {
struct radiusd_module_radpkt_arg *accessreq; struct radiusd_module_radpkt_arg *accessreq;
int chunklen; int chunklen;
@ -459,6 +465,13 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg)
break; break;
} }
typestr = "ACCSREQ"; 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) { } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_REQDECO) {
if (module_request_decoration == NULL) { if (module_request_decoration == NULL) {
syslog(LOG_ERR, "Received REQDECO message, but " 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); memcpy(base->radpkt2, base->radpkt, base->radpktoff);
base->radpkt2len = base->radpktoff; base->radpkt2len = base->radpktoff;
} else { } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_RESDECO) {
module_response_decoration(base->ctx, accessreq->q_id, module_response_decoration(base->ctx, accessreq->q_id,
base->radpkt2, base->radpkt2len, base->radpkt, base->radpkt2, base->radpkt2len, base->radpkt,
base->radpktoff); base->radpktoff);
base->radpkt2len = 0; base->radpkt2len = 0;
} } else
module_accounting_request(base->ctx, accessreq->q_id,
base->radpkt, base->radpktoff);
base->radpktoff = 0; base->radpktoff = 0;
accsreq_out: accsreq_out:
break; break;
} }
} }

View file

@ -20,6 +20,7 @@
#include "radiusd.h" #include "radiusd.h"
struct module_ctx; struct module_ctx;
struct imsg;
struct module_handlers { struct module_handlers {
/* Should send IMSG_OK or IMSG_NG */ /* Should send IMSG_OK or IMSG_NG */
@ -42,6 +43,11 @@ struct module_handlers {
void (*response_decoration)(void *ctx, u_int query_id, void (*response_decoration)(void *ctx, u_int query_id,
const u_char *req, size_t reqlen, const u_char *res, size_t reslen); 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) \ #define SYNTAX_ASSERT(_cond, _msg) \
@ -77,6 +83,10 @@ int module_reqdeco_done(struct module_base *, u_int,
const u_char *, size_t); const u_char *, size_t);
int module_resdeco_done(struct module_base *, u_int, int module_resdeco_done(struct module_base *, u_int,
const u_char *, size_t); 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 __END_DECLS

View file

@ -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 .

View file

@ -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. * 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)) if (radius_has_attr(req->q_pkt, RADIUS_TYPE_MESSAGE_AUTHENTICATOR))
radius_del_attr_all(req->q_pkt, radius_del_attr_all(req->q_pkt,
RADIUS_TYPE_MESSAGE_AUTHENTICATOR); RADIUS_TYPE_MESSAGE_AUTHENTICATOR);
radius_put_message_authenticator(req->q_pkt, radius_put_message_authenticator(req->q_pkt, req->module->secret);
req->module->secret);
} }
static void static void

View file

@ -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 PROG= radiusd_radius
BINDIR= /usr/libexec/radiusd BINDIR= /usr/libexec/radiusd
SRCS= radiusd_radius.c radiusd_module.c util.c imsg_subr.c log.c SRCS= radiusd_radius.c radiusd_module.c util.c imsg_subr.c log.c
CFLAGS+= -DUSE_LIBEVENT CFLAGS+= -DUSE_LIBEVENT
LDADD+= -lradius -lcrypto -lutil -levent LDADD+= -lradius -lcrypto -lutil -levent
DPADD+= ${LIBRADIUS} ${LIBCRYPTO} ${LIBUTIL} ${LIBEVENT} DPADD+= ${LIBRADIUS} ${LIBCRYPTO} ${LIBUTIL} ${LIBEVENT}
NOMAN= # MAN= radiusd_radius.8
.include <bsd.prog.mk> .include <bsd.prog.mk>

View file

@ -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 .

View file

@ -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. * Copyright (c) 2013, 2023 Internet Initiative Japan Inc.
@ -17,6 +17,8 @@
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
@ -49,11 +51,34 @@ struct module_standard {
struct attrs remove_resattrs; 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, static void module_standard_config_set(void *, const char *, int,
char * const *); char * const *);
static void module_standard_reqdeco(void *, u_int, const u_char *, size_t); 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, static void module_standard_resdeco(void *, u_int, const u_char *, size_t,
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 int
main(int argc, char *argv[]) main(int argc, char *argv[])
@ -62,7 +87,8 @@ main(int argc, char *argv[])
struct module_handlers handlers = { struct module_handlers handlers = {
.config_set = module_standard_config_set, .config_set = module_standard_config_set,
.request_decoration = module_standard_reqdeco, .request_decoration = module_standard_reqdeco,
.response_decoration = module_standard_resdeco .response_decoration = module_standard_resdeco,
.accounting_request = module_accounting_request
}; };
struct attr *attr; 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) if (radres != NULL)
radius_delete_packet(radres); 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 }
};

View file

@ -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 PROG= radiusd_standard
BINDIR= /usr/libexec/radiusd BINDIR= /usr/libexec/radiusd
SRCS= radiusd_standard.c radiusd_module.c SRCS= radiusd_standard.c radiusd_module.c
LDADD= -lutil -lradius -lcrypto LDADD= -lutil -lradius -lcrypto
NOMAN= # MAN= radiusd_standard.8
.include <bsd.prog.mk> .include <bsd.prog.mk>

View file

@ -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 <bluhm@genua.de> * Copyright (c) 2014-2021 Alexander Bluhm <bluhm@genua.de>
@ -314,6 +314,7 @@ int reserve_accept4(int, int, struct event *,
void tcp_acceptcb(int, short, void *); void tcp_acceptcb(int, short, void *);
void tls_acceptcb(int, short, void *); void tls_acceptcb(int, short, void *);
void acceptcb(int, short, void *, int); void acceptcb(int, short, void *, int);
void tls_handshakecb(struct bufferevent *, void *);
int octet_counting(struct evbuffer *, char **, int); int octet_counting(struct evbuffer *, char **, int);
int non_transparent_framing(struct evbuffer *, char **); int non_transparent_framing(struct evbuffer *, char **);
void tcp_readcb(struct bufferevent *, void *); void tcp_readcb(struct bufferevent *, void *);
@ -1188,6 +1189,7 @@ acceptcb(int lfd, short event, void *arg, int usetls)
close(fd); close(fd);
return; return;
} }
p->p_bufev->readcb = tls_handshakecb;
buffertls_set(&p->p_buftls, p->p_bufev, p->p_ctx, fd); buffertls_set(&p->p_buftls, p->p_bufev, p->p_ctx, fd);
buffertls_accept(&p->p_buftls, fd); buffertls_accept(&p->p_buftls, fd);
log_debug("tcp accept callback: tls context success"); 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); 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 * Syslog over TCP RFC 6587 3.4.1. Octet Counting
*/ */