diff --git a/regress/usr.bin/ssh/sftp-cmds.sh b/regress/usr.bin/ssh/sftp-cmds.sh index 52189287d..7a4f2fbdd 100644 --- a/regress/usr.bin/ssh/sftp-cmds.sh +++ b/regress/usr.bin/ssh/sftp-cmds.sh @@ -1,4 +1,4 @@ -# $OpenBSD: sftp-cmds.sh,v 1.19 2024/03/29 10:40:07 dtucker Exp $ +# $OpenBSD: sftp-cmds.sh,v 1.20 2024/07/01 03:10:19 djm Exp $ # Placed in the Public Domain. # XXX - TODO: @@ -22,7 +22,7 @@ rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2 mkdir ${COPY}.dd verbose "$tid: lls" -printf "cd ${OBJ}\nlls\n" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \ +printf "lcd ${OBJ}\nlls\n" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \ grep copy.dd >/dev/null || fail "lls failed" verbose "$tid: lls w/path" diff --git a/regress/usr.sbin/syslogd/args-client-tls.pl b/regress/usr.sbin/syslogd/args-client-tls.pl index 2fa726d9a..8a385f23b 100644 --- a/regress/usr.sbin/syslogd/args-client-tls.pl +++ b/regress/usr.sbin/syslogd/args-client-tls.pl @@ -32,7 +32,9 @@ our %args = ( loggrep => { qr{Keyfile /etc/ssl/private/localhost.key} => 1, qr{Certfile /etc/ssl/localhost.crt} => 1, + qr/Accepting tcp connection/ => 1, qr/syslogd\[\d+\]: tls logger .* accepted/ => 1, + qr/Completed tls handshake/ => 1, qr/syslogd\[\d+\]: tls logger .* connection close/ => 1, }, }, diff --git a/sbin/iked/util.c b/sbin/iked/util.c index 2cd34d12b..5d987eb66 100644 --- a/sbin/iked/util.c +++ b/sbin/iked/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.44 2024/02/03 00:38:08 jsg Exp $ */ +/* $OpenBSD: util.c,v 1.45 2024/07/01 14:15:15 yasuoka Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter @@ -644,16 +644,16 @@ prefixlen2mask6(uint8_t prefixlen, uint32_t *mask) const char * print_addr(void *addr) { - static char sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 7]; + static char sbuf[IKED_CYCLE_BUFFERS][NI_MAXHOST + 9]; static int idx; struct sockaddr *sa = addr; - char *buf; - size_t len; + char *buf, *hbuf; + size_t len, hlen; char pbuf[7]; in_port_t port; - buf = sbuf[idx]; - len = sizeof(sbuf[idx]); + hbuf = buf = sbuf[idx]; + hlen = len = sizeof(sbuf[idx]); if (++idx >= IKED_CYCLE_BUFFERS) idx = 0; @@ -662,13 +662,21 @@ print_addr(void *addr) return (buf); } + if ((port = socket_getport(sa)) != 0 && sa->sa_family == AF_INET6) { + /* surround [] */ + *(hbuf++) = '['; + hlen--; + } + if (getnameinfo(sa, sa->sa_len, - buf, len, NULL, 0, NI_NUMERICHOST) != 0) { + hbuf, hlen, NULL, 0, NI_NUMERICHOST) != 0) { strlcpy(buf, "unknown", len); return (buf); } - if ((port = socket_getport(sa)) != 0) { + if (port != 0) { + if (sa->sa_family == AF_INET6) + (void)strlcat(buf, "]", len); snprintf(pbuf, sizeof(pbuf), ":%d", port); (void)strlcat(buf, pbuf, len); } diff --git a/sys/dev/ofw/ofw_thermal.c b/sys/dev/ofw/ofw_thermal.c index 3e7ab6813..b895281f9 100644 --- a/sys/dev/ofw/ofw_thermal.c +++ b/sys/dev/ofw/ofw_thermal.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ofw_thermal.c,v 1.9 2024/06/27 09:37:07 kettenis Exp $ */ +/* $OpenBSD: ofw_thermal.c,v 1.10 2024/07/01 14:13:43 kettenis Exp $ */ /* * Copyright (c) 2019 Mark Kettenis * @@ -306,12 +306,12 @@ thermal_zone_poll(void *arg) int32_t temp, delta; int i; + tp = tz->tz_trips; temp = thermal_get_temperature_cells(tz->tz_sensors); if (temp == THERMAL_SENSOR_MAX) goto out; newtp = NULL; - tp = tz->tz_trips; for (i = 0; i < tz->tz_ntrips; i++) { if (temp < tp->tp_temperature && tp != tz->tz_tp) break; @@ -372,7 +372,7 @@ out: if (polling_delay > 0) timeout_add_msec(&tz->tz_poll_to, polling_delay); - else + else if (tp) thermal_set_limit_cells(tz->tz_sensors, tp->tp_temperature); } diff --git a/usr.bin/bgplg/misc.c b/usr.bin/bgplg/misc.c index fc5665f97..bf7f71486 100644 --- a/usr.bin/bgplg/misc.c +++ b/usr.bin/bgplg/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.8 2017/12/18 09:12:49 job Exp $ */ +/* $OpenBSD: misc.c,v 1.9 2024/07/01 18:43:50 deraadt Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter @@ -79,10 +79,13 @@ lg_help(struct cmd *cmds, char **argv) void lg_sig_alarm(int sig) { + int save_errno = errno; + if (child != -1) { /* Forcibly kill the child, no excuse... */ kill(child, SIGKILL); } + errno = save_errno; } int diff --git a/usr.bin/openssl/speed.c b/usr.bin/openssl/speed.c index f50d22406..84ecb9b3b 100644 --- a/usr.bin/openssl/speed.c +++ b/usr.bin/openssl/speed.c @@ -1,4 +1,4 @@ -/* $OpenBSD: speed.c,v 1.34 2023/07/27 07:01:50 tb Exp $ */ +/* $OpenBSD: speed.c,v 1.35 2024/07/01 18:52:22 deraadt Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -150,7 +150,7 @@ #include "./testrsa.h" #define BUFSIZE (1024*8+64) -int run = 0; +volatile sig_atomic_t run = 0; static int mr = 0; static int usertime = 1; @@ -193,7 +193,10 @@ static void sig_done(int sig); static void sig_done(int sig) { + int save_errno = errno; + signal(SIGALRM, sig_done); + errno = save_errno; run = 0; } diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index 2129c151f..c5296e32f 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.407 2024/05/17 06:42:04 jsg Exp $ */ +/* $OpenBSD: clientloop.c,v 1.408 2024/07/01 04:31:17 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -598,8 +598,9 @@ obfuscate_keystroke_timing(struct ssh *ssh, struct timespec *timeout, if (timespeccmp(&now, &chaff_until, >=)) { /* Stop if there have been no keystrokes for a while */ stop_reason = "chaff time expired"; - } else if (timespeccmp(&now, &next_interval, >=)) { - /* Otherwise if we were due to send, then send chaff */ + } else if (timespeccmp(&now, &next_interval, >=) && + !ssh_packet_have_data_to_write(ssh)) { + /* If due to send but have no data, then send chaff */ if (send_chaff(ssh)) nchaff++; } diff --git a/usr.bin/ssh/version.h b/usr.bin/ssh/version.h index f519deb89..8491b8656 100644 --- a/usr.bin/ssh/version.h +++ b/usr.bin/ssh/version.h @@ -1,3 +1,3 @@ -/* $OpenBSD: version.h,v 1.101 2024/03/11 04:59:47 djm Exp $ */ +/* $OpenBSD: version.h,v 1.102 2024/07/01 04:31:59 djm Exp $ */ -#define SSH_VERSION "OpenSSH_9.7" +#define SSH_VERSION "OpenSSH_9.8" diff --git a/usr.sbin/npppd/npppd/chap.c b/usr.sbin/npppd/npppd/chap.c index 88c65a010..ac76db5fb 100644 --- a/usr.sbin/npppd/npppd/chap.c +++ b/usr.sbin/npppd/npppd/chap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: chap.c,v 1.18 2024/02/26 08:47:28 yasuoka Exp $ */ +/* $OpenBSD: chap.c,v 1.19 2024/07/01 07:09:07 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -36,7 +36,7 @@ *

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