diff --git a/distrib/sets/lists/comp/mi b/distrib/sets/lists/comp/mi index 445331dbc..5b52798b9 100644 --- a/distrib/sets/lists/comp/mi +++ b/distrib/sets/lists/comp/mi @@ -1928,7 +1928,9 @@ ./usr/share/man/man3/EVP_DigestVerifyInit.3 ./usr/share/man/man3/EVP_EncodeInit.3 ./usr/share/man/man3/EVP_EncryptInit.3 +./usr/share/man/man3/EVP_MD_CTX_ctrl.3 ./usr/share/man/man3/EVP_MD_meth_new.3 +./usr/share/man/man3/EVP_MD_nid.3 ./usr/share/man/man3/EVP_OpenInit.3 ./usr/share/man/man3/EVP_PKCS82PKEY.3 ./usr/share/man/man3/EVP_PKEY_CTX_ctrl.3 diff --git a/lib/libcrypto/man/EVP_DigestInit.3 b/lib/libcrypto/man/EVP_DigestInit.3 index 562592b3c..a5ce6f84f 100644 --- a/lib/libcrypto/man/EVP_DigestInit.3 +++ b/lib/libcrypto/man/EVP_DigestInit.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: EVP_DigestInit.3,v 1.30 2023/09/07 14:22:11 schwarze Exp $ +.\" $OpenBSD: EVP_DigestInit.3,v 1.31 2023/09/07 19:59:58 schwarze Exp $ .\" full merge up to: OpenSSL 7f572e95 Dec 2 13:57:04 2015 +0000 .\" selective merge up to: OpenSSL 24a535ea Sep 22 13:14:20 2020 +0100 .\" @@ -89,7 +89,6 @@ .Nm EVP_DigestInit , .Nm EVP_DigestFinal , .Nm EVP_MD_CTX_copy , -.Nm EVP_MAX_MD_SIZE , .Nm EVP_MD_CTX_md , .Nm EVP_md_null , .Nm EVP_sha224 , @@ -177,7 +176,6 @@ .Fa "EVP_MD_CTX *out" .Fa "EVP_MD_CTX *in" .Fc -.Fd #define EVP_MAX_MD_SIZE 64 /* SHA512 */ .Ft const EVP_MD * .Fo EVP_MD_CTX_md .Fa "const EVP_MD_CTX *ctx" @@ -460,14 +458,19 @@ or if .Fa ctx is -.Dv NULL . +.Dv NULL +or does not have any message digest algorithm assigned yet. .Pp -.Fn EVP_md_null +.Fn EVP_md_null , +.Fn EVP_sha224 , +.Fn EVP_sha256 , +.Fn EVP_sha384 , +.Fn EVP_sha512 , +.Fn EVP_sha512_224 , +.Fn EVP_sha512_256 , and .Fn EVP_ripemd160 -return pointers to the corresponding -.Vt EVP_MD -structures. +return pointers to constant static objects owned by the library. .Pp .Fn EVP_get_digestbyname , .Fn EVP_get_digestbynid , @@ -551,9 +554,8 @@ main(int argc, char *argv[]) .Sh HISTORY .Fn EVP_DigestInit , .Fn EVP_DigestUpdate , -.Fn EVP_DigestFinal , and -.Dv EVP_MAX_MD_SIZE +.Fn EVP_DigestFinal first appeared in SSLeay 0.5.1. .Fn EVP_md_null and diff --git a/lib/libcrypto/man/EVP_MD_CTX_ctrl.3 b/lib/libcrypto/man/EVP_MD_CTX_ctrl.3 index 8b6f8724f..0aaeddd6d 100644 --- a/lib/libcrypto/man/EVP_MD_CTX_ctrl.3 +++ b/lib/libcrypto/man/EVP_MD_CTX_ctrl.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: EVP_MD_CTX_ctrl.3,v 1.1 2023/09/07 14:22:11 schwarze Exp $ +.\" $OpenBSD: EVP_MD_CTX_ctrl.3,v 1.2 2023/09/07 19:28:37 schwarze Exp $ .\" full merge up to: OpenSSL man3/EVP_DigestInit.pod .\" 24a535ea Sep 22 13:14:20 2020 +0100 .\" @@ -247,6 +247,12 @@ returns the bitwise OR of the .Fa flags argument and the flags set in .Fa ctx . +.Pp +.Fn EVP_MD_CTX_pkey_ctx +and +.Fn EVP_MD_CTX_md_data +return pointers to storage owned by +.Fa ctx . .Sh SEE ALSO .Xr evp 3 , .Xr EVP_DigestInit 3 , diff --git a/lib/libcrypto/man/EVP_PKEY_cmp.3 b/lib/libcrypto/man/EVP_PKEY_cmp.3 index e00147dc8..42bfb6fec 100644 --- a/lib/libcrypto/man/EVP_PKEY_cmp.3 +++ b/lib/libcrypto/man/EVP_PKEY_cmp.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: EVP_PKEY_cmp.3,v 1.12 2021/10/19 17:42:49 schwarze Exp $ +.\" $OpenBSD: EVP_PKEY_cmp.3,v 1.13 2023/09/08 11:37:58 schwarze Exp $ .\" full merge up to: OpenSSL 05ea606a May 20 20:52:46 2016 -0400 .\" selective merge up to: OpenSSL 99d63d46 Oct 26 13:56:48 2016 -0400 .\" @@ -67,7 +67,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED .\" OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: October 19 2021 $ +.Dd $Mdocdate: September 8 2023 $ .Dt EVP_PKEY_CMP 3 .Os .Sh NAME @@ -75,6 +75,10 @@ .Nm EVP_PKEY_copy_parameters , .Nm EVP_PKEY_cmp_parameters , .Nm EVP_PKEY_cmp +.\" .Nm EVP_PKEY_save_parameters is intentionally undocumented +.\" because nothing uses it according to codesearch.debian.net +.\" and it only affects X509_PUBKEY_set(3) for DSA and GOST2001 keys, +.\" resulting in incomplete output without the public key parameters. .Nd public key parameter and comparison functions .Sh SYNOPSIS .In openssl/evp.h diff --git a/regress/usr.bin/ssh/scp.sh b/regress/usr.bin/ssh/scp.sh index 341e760c5..db16de050 100644 --- a/regress/usr.bin/ssh/scp.sh +++ b/regress/usr.bin/ssh/scp.sh @@ -1,4 +1,4 @@ -# $OpenBSD: scp.sh,v 1.18 2023/01/13 04:47:34 dtucker Exp $ +# $OpenBSD: scp.sh,v 1.19 2023/09/08 05:50:57 djm Exp $ # Placed in the Public Domain. tid="scp" @@ -25,13 +25,25 @@ scpclean() { chmod 755 ${DIR} ${DIR2} ${DIR3} } +# Create directory structure for recursive copy tests. +forest() { + scpclean + rm -rf ${DIR2} + cp ${DATA} ${DIR}/copy + ln -s ${DIR}/copy ${DIR}/copy-sym + mkdir ${DIR}/subdir + cp ${DATA} ${DIR}/subdir/copy + ln -s ${DIR}/subdir ${DIR}/subdir-sym +} + for mode in scp sftp ; do tag="$tid: $mode mode" if test $mode = scp ; then scpopts="-O -q -S ${OBJ}/scp-ssh-wrapper.scp" else - scpopts="-s -D ${SFTPSERVER}" + scpopts="-qs -D ${SFTPSERVER}" fi + verbose "$tag: simple copy local file to local file" scpclean $SCP $scpopts ${DATA} ${COPY} || fail "copy failed" @@ -91,21 +103,19 @@ for mode in scp sftp ; do cmp ${COPY} ${DIR}/copy || fail "corrupted copy" verbose "$tag: recursive local dir to remote dir" - scpclean - rm -rf ${DIR2} - cp ${DATA} ${DIR}/copy + forest $SCP $scpopts -r ${DIR} somehost:${DIR2} || fail "copy failed" diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy" verbose "$tag: recursive local dir to local dir" - scpclean + forest rm -rf ${DIR2} cp ${DATA} ${DIR}/copy $SCP $scpopts -r ${DIR} ${DIR2} || fail "copy failed" diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy" verbose "$tag: recursive remote dir to local dir" - scpclean + forest rm -rf ${DIR2} cp ${DATA} ${DIR}/copy $SCP $scpopts -r somehost:${DIR} ${DIR2} || fail "copy failed" diff --git a/regress/usr.bin/ssh/scp3.sh b/regress/usr.bin/ssh/scp3.sh index 383121f45..eeb7a9dde 100644 --- a/regress/usr.bin/ssh/scp3.sh +++ b/regress/usr.bin/ssh/scp3.sh @@ -1,10 +1,8 @@ -# $OpenBSD: scp3.sh,v 1.4 2023/01/13 04:47:34 dtucker Exp $ +# $OpenBSD: scp3.sh,v 1.5 2023/09/08 06:10:57 djm Exp $ # Placed in the Public Domain. tid="scp3" -set -x - COPY2=${OBJ}/copy2 DIR=${COPY}.dd DIR2=${COPY}.dd2 @@ -22,6 +20,17 @@ scpclean() { chmod 755 ${DIR} ${DIR2} } +# Create directory structure for recursive copy tests. +forest() { + scpclean + rm -rf ${DIR2} + cp ${DATA} ${DIR}/copy + ln -s ${DIR}/copy ${DIR}/copy-sym + mkdir ${DIR}/subdir + cp ${DATA} ${DIR}/subdir/copy + ln -s ${DIR}/subdir ${DIR}/subdir-sym +} + for mode in scp sftp ; do scpopts="-F${OBJ}/ssh_proxy -S ${SSH} -q" tag="$tid: $mode mode" @@ -43,9 +52,7 @@ for mode in scp sftp ; do cmp ${COPY} ${DIR}/copy || fail "corrupted copy" verbose "$tag: recursive remote dir to remote dir" - scpclean - rm -rf ${DIR2} - cp ${DATA} ${DIR}/copy + forest $SCP $scpopts -3r hostA:${DIR} hostB:${DIR2} || fail "copy failed" diff -r ${DIR} ${DIR2} || fail "corrupted copy" diff -r ${DIR2} ${DIR} || fail "corrupted copy" diff --git a/share/man/man5/bsd.port.mk.5 b/share/man/man5/bsd.port.mk.5 index 660d0063e..b1a0adac2 100644 --- a/share/man/man5/bsd.port.mk.5 +++ b/share/man/man5/bsd.port.mk.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bsd.port.mk.5,v 1.620 2023/09/07 17:26:14 espie Exp $ +.\" $OpenBSD: bsd.port.mk.5,v 1.621 2023/09/07 23:32:56 espie Exp $ .\" .\" Copyright (c) 2000-2008 Marc Espie .\" @@ -4347,8 +4347,6 @@ and .Bl -tag -width Ds .It Pa ../Makefile.inc Common Makefile fragment for a set of ports, included automatically. -.It Pa /cdrom/distfiles -Default path to a CD-ROM (or other media) full of distribution files. .It Pa ${PORTSDIR}/distfiles Default setup of ${DISTDIR}. .It Pa ${DISTDIR} diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 7dbb63dac..460833afc 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.213 2023/09/04 13:18:41 claudio Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.214 2023/09/08 09:06:31 claudio Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -157,12 +157,10 @@ exit1(struct proc *p, int xexit, int xsig, int flags) } /* unlink ourselves from the active threads */ - SCHED_LOCK(s); - TAILQ_REMOVE(&pr->ps_threads, p, p_thr_link); - SCHED_UNLOCK(s); - mtx_enter(&pr->ps_mtx); + TAILQ_REMOVE(&pr->ps_threads, p, p_thr_link); pr->ps_threadcnt--; + wake = (pr->ps_single && pr->ps_singlecnt == pr->ps_threadcnt); mtx_leave(&pr->ps_mtx); if (wake) @@ -170,9 +168,11 @@ exit1(struct proc *p, int xexit, int xsig, int flags) if ((p->p_flag & P_THREAD) == 0) { /* main thread gotta wait because it has the pid, et al */ - /* XXX locking depends on kernel lock here. */ + mtx_enter(&pr->ps_mtx); while (pr->ps_threadcnt > 0) - tsleep_nsec(&pr->ps_threads, PWAIT, "thrdeath", INFSLP); + msleep_nsec(&pr->ps_threads, &pr->ps_mtx, PWAIT, + "thrdeath", INFSLP); + mtx_leave(&pr->ps_mtx); if (pr->ps_flags & PS_PROFIL) stopprofclock(pr); } @@ -345,8 +345,10 @@ exit1(struct proc *p, int xexit, int xsig, int flags) /* just a thread? detach it from its process */ if (p->p_flag & P_THREAD) { /* scheduler_wait_hook(pr->ps_mainproc, p); XXX */ + mtx_enter(&pr->ps_mtx); if (pr->ps_threadcnt == 0) wakeup(&pr->ps_threads); + mtx_leave(&pr->ps_mtx); } /* Release the thread's read reference of resource limit structure. */ diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index c37dd2fea..da1665f31 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.250 2023/09/04 13:18:41 claudio Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.251 2023/09/08 09:06:31 claudio Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -519,7 +519,7 @@ thread_fork(struct proc *curp, void *stack, void *tcb, pid_t *tidptr, struct proc *p; pid_t tid; vaddr_t uaddr; - int s, error; + int error; if (stack == NULL) return EINVAL; @@ -561,11 +561,8 @@ thread_fork(struct proc *curp, void *stack, void *tcb, pid_t *tidptr, LIST_INSERT_HEAD(&allproc, p, p_list); LIST_INSERT_HEAD(TIDHASH(p->p_tid), p, p_hash); - SCHED_LOCK(s); - TAILQ_INSERT_TAIL(&pr->ps_threads, p, p_thr_link); - SCHED_UNLOCK(s); - mtx_enter(&pr->ps_mtx); + TAILQ_INSERT_TAIL(&pr->ps_threads, p, p_thr_link); pr->ps_threadcnt++; /* diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 1f4a043da..3293905c0 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_resource.c,v 1.78 2023/08/29 16:19:34 claudio Exp $ */ +/* $OpenBSD: kern_resource.c,v 1.79 2023/09/08 09:06:31 claudio Exp $ */ /* $NetBSD: kern_resource.c,v 1.38 1996/10/23 07:19:38 matthias Exp $ */ /*- @@ -212,11 +212,13 @@ donice(struct proc *curp, struct process *chgpr, int n) if (n < chgpr->ps_nice && suser(curp)) return (EACCES); chgpr->ps_nice = n; - SCHED_LOCK(s); + mtx_enter(&chgpr->ps_mtx); TAILQ_FOREACH(p, &chgpr->ps_threads, p_thr_link) { + SCHED_LOCK(s); setpriority(p, p->p_estcpu, n); + SCHED_UNLOCK(s); } - SCHED_UNLOCK(s); + mtx_leave(&chgpr->ps_mtx); return (0); } @@ -476,8 +478,9 @@ dogetrusage(struct proc *p, int who, struct rusage *rup) struct process *pr = p->p_p; struct proc *q; - switch (who) { + KERNEL_ASSERT_LOCKED(); + switch (who) { case RUSAGE_SELF: /* start with the sum of dead threads, if any */ if (pr->ps_ru != NULL) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index a003797c0..b48ca292c 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.314 2023/09/04 13:18:41 claudio Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.315 2023/09/08 09:06:31 claudio Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -2105,12 +2105,11 @@ single_thread_set(struct proc *p, enum single_thread_mode mode, int wait) } pr->ps_singlecnt = 1; /* count ourselfs in already */ pr->ps_single = p; - mtx_leave(&pr->ps_mtx); - SCHED_LOCK(s); TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { if (q == p) continue; + SCHED_LOCK(s); if (q->p_flag & P_WEXIT) { if (mode == SINGLE_EXIT && q->p_stat == SSTOP) setrunnable(q); @@ -2146,10 +2145,9 @@ single_thread_set(struct proc *p, enum single_thread_mode mode, int wait) signotify(q); break; } + SCHED_UNLOCK(s); } - SCHED_UNLOCK(s); - mtx_enter(&pr->ps_mtx); pr->ps_singlecnt += count; mtx_leave(&pr->ps_mtx); @@ -2194,11 +2192,10 @@ single_thread_clear(struct proc *p, int flag) KASSERT(pr->ps_single == p); KASSERT(curproc == p); - /* can do this without holding pr->ps_mtx since no concurrency */ + mtx_enter(&pr->ps_mtx); pr->ps_single = NULL; atomic_clearbits_int(&pr->ps_flags, PS_SINGLEUNWIND | PS_SINGLEEXIT); - SCHED_LOCK(s); TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { if (q == p || (q->p_flag & P_SUSPSINGLE) == 0) continue; @@ -2209,6 +2206,7 @@ single_thread_clear(struct proc *p, int flag) * then clearing that either makes it runnable or puts * it back into some sleep queue */ + SCHED_LOCK(s); if (q->p_stat == SSTOP && (q->p_flag & flag) == 0) { if (q->p_wchan == NULL) setrunnable(q); @@ -2217,8 +2215,9 @@ single_thread_clear(struct proc *p, int flag) q->p_stat = SSLEEP; } } + SCHED_UNLOCK(s); } - SCHED_UNLOCK(s); + mtx_leave(&pr->ps_mtx); } void diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 624bf52b2..06db10f04 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_synch.c,v 1.198 2023/08/16 07:55:52 claudio Exp $ */ +/* $OpenBSD: kern_synch.c,v 1.199 2023/09/08 09:06:31 claudio Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /* @@ -566,15 +566,18 @@ sys_sched_yield(struct proc *p, void *v, register_t *retval) uint8_t newprio; int s; - SCHED_LOCK(s); /* * If one of the threads of a multi-threaded process called * sched_yield(2), drop its priority to ensure its siblings * can make some progress. */ + mtx_enter(&p->p_p->ps_mtx); newprio = p->p_usrpri; TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) newprio = max(newprio, q->p_runpri); + mtx_leave(&p->p_p->ps_mtx); + + SCHED_LOCK(s); setrunqueue(p->p_cpu, p, newprio); p->p_ru.ru_nvcsw++; mi_switch(); diff --git a/sys/net/pf.c b/sys/net/pf.c index 8e4e64a02..55fab0b2a 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.1185 2023/09/07 09:59:43 sashan Exp $ */ +/* $OpenBSD: pf.c,v 1.1186 2023/09/08 13:40:52 naddy Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -4148,10 +4148,6 @@ enter_ruleset: (r->rule_flag & PFRULE_STATESLOPPY) == 0 && ctx->icmp_dir != PF_IN), TAILQ_NEXT(r, entries)); - /* icmp packet must match existing state */ - PF_TEST_ATTRIB(r->keep_state && ctx->state_icmp && - (r->rule_flag & PFRULE_STATESLOPPY) == 0, - TAILQ_NEXT(r, entries)); break; case IPPROTO_ICMPV6: @@ -4169,10 +4165,6 @@ enter_ruleset: ctx->icmp_dir != PF_IN && ctx->icmptype != ND_NEIGHBOR_ADVERT), TAILQ_NEXT(r, entries)); - /* icmp packet must match existing state */ - PF_TEST_ATTRIB(r->keep_state && ctx->state_icmp && - (r->rule_flag & PFRULE_STATESLOPPY) == 0, - TAILQ_NEXT(r, entries)); break; default: diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 6cdef43ff..eb987674a 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.349 2023/09/04 13:18:41 claudio Exp $ */ +/* $OpenBSD: proc.h,v 1.350 2023/09/08 09:06:31 claudio Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -138,7 +138,7 @@ struct process { struct ucred *ps_ucred; /* Process owner's identity. */ LIST_ENTRY(process) ps_list; /* List of all processes. */ - TAILQ_HEAD(,proc) ps_threads; /* [K|S] Threads in this process. */ + TAILQ_HEAD(,proc) ps_threads; /* [K|m] Threads in this process. */ LIST_ENTRY(process) ps_pglist; /* List of processes in pgrp. */ struct process *ps_pptr; /* Pointer to parent process. */ @@ -310,13 +310,14 @@ struct p_inentry { * U uidinfolk * l read only reference, see lim_read_enter() * o owned (read/modified only) by this thread + * m this proc's' `p->p_p->ps_mtx' */ struct proc { TAILQ_ENTRY(proc) p_runq; /* [S] current run/sleep queue */ LIST_ENTRY(proc) p_list; /* List of all threads. */ struct process *p_p; /* [I] The process of this thread. */ - TAILQ_ENTRY(proc) p_thr_link; /* Threads in a process linkage. */ + TAILQ_ENTRY(proc) p_thr_link; /* [K|m] Threads in a process linkage. */ TAILQ_ENTRY(proc) p_fut_link; /* Threads in a futex linkage. */ struct futex *p_futex; /* Current sleeping futex. */ diff --git a/usr.bin/ssh/scp.c b/usr.bin/ssh/scp.c index 3a279a105..6ad841c83 100644 --- a/usr.bin/ssh/scp.c +++ b/usr.bin/ssh/scp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scp.c,v 1.257 2023/07/14 05:31:44 djm Exp $ */ +/* $OpenBSD: scp.c,v 1.258 2023/09/08 05:56:13 djm Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -967,7 +967,7 @@ do_sftp_connect(char *host, char *user, int port, char *sftp_direct, reminp, remoutp, pidp) < 0) return NULL; } - return do_init(*reminp, *remoutp, + return sftp_init(*reminp, *remoutp, sftp_copy_buflen, sftp_nrequests, limit_kbps); } @@ -1263,8 +1263,8 @@ prepare_remote_path(struct sftp_conn *conn, const char *path) return xstrdup("."); return xstrdup(path + 2 + nslash); } - if (can_expand_path(conn)) - return do_expand_path(conn, path); + if (sftp_can_expand_path(conn)) + return sftp_expand_path(conn, path); /* No protocol extension */ error("server expand-path extension is required " "for ~user paths in SFTP mode"); @@ -1292,17 +1292,17 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) */ if ((target = prepare_remote_path(conn, targ)) == NULL) cleanup_exit(255); - target_is_dir = remote_is_dir(conn, target); + target_is_dir = sftp_remote_is_dir(conn, target); if (targetshouldbedirectory && !target_is_dir) { debug("target directory \"%s\" does not exist", target); a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = st.st_mode | 0700; /* ensure writable */ - if (do_mkdir(conn, target, &a, 1) != 0) + if (sftp_mkdir(conn, target, &a, 1) != 0) cleanup_exit(255); /* error already logged */ target_is_dir = 1; } if (target_is_dir) - abs_dst = path_append(target, filename); + abs_dst = sftp_path_append(target, filename); else { abs_dst = target; target = NULL; @@ -1310,12 +1310,12 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) debug3_f("copying local %s to remote %s", src, abs_dst); if (src_is_dir && iamrecursive) { - if (upload_dir(conn, src, abs_dst, pflag, + if (sftp_upload_dir(conn, src, abs_dst, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { error("failed to upload directory %s to %s", src, targ); errs = 1; } - } else if (do_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { + } else if (sftp_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { error("failed to upload file %s to %s", src, targ); errs = 1; } @@ -1524,7 +1524,7 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) * a GLOB_NOCHECK result. Check whether the unglobbed path * exists so we can give a nice error message early. */ - if (do_stat(conn, g.gl_pathv[0], 1) == NULL) { + if (sftp_stat(conn, g.gl_pathv[0], 1, NULL) != 0) { error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; @@ -1560,17 +1560,17 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) } if (dst_is_dir) - abs_dst = path_append(dst, filename); + abs_dst = sftp_path_append(dst, filename); else abs_dst = xstrdup(dst); debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); - if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { - if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, - pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) + if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { + if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst, + NULL, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) err = -1; } else { - if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, + if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL, pflag, 0, 0, 1) == -1) err = -1; } @@ -1924,7 +1924,7 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, cleanup_exit(255); memset(&g, 0, sizeof(g)); - targetisdir = remote_is_dir(to, target); + targetisdir = sftp_remote_is_dir(to, target); if (!targetisdir && targetshouldbedirectory) { error("%s: destination is not a directory", targ); err = -1; @@ -1949,7 +1949,7 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, * a GLOB_NOCHECK result. Check whether the unglobbed path * exists so we can give a nice error message early. */ - if (do_stat(from, g.gl_pathv[0], 1) == NULL) { + if (sftp_stat(from, g.gl_pathv[0], 1, NULL) != 0) { error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; @@ -1965,18 +1965,18 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, } if (targetisdir) - abs_dst = path_append(target, filename); + abs_dst = sftp_path_append(target, filename); else abs_dst = xstrdup(target); debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); - if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { - if (crossload_dir(from, to, g.gl_pathv[i], abs_dst, + if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { + if (sftp_crossload_dir(from, to, g.gl_pathv[i], abs_dst, NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1) err = -1; } else { - if (do_crossload(from, to, g.gl_pathv[i], abs_dst, NULL, - pflag) == -1) + if (sftp_crossload(from, to, g.gl_pathv[i], abs_dst, + NULL, pflag) == -1) err = -1; } free(abs_dst); diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c index fea3bdfbe..a3c3270ab 100644 --- a/usr.bin/ssh/servconf.c +++ b/usr.bin/ssh/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.401 2023/09/06 23:35:35 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.402 2023/09/08 06:34:24 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -1900,15 +1900,15 @@ process_server_config_line_depth(ServerOptions *options, char *line, options->subsystem_name = xrecallocarray( options->subsystem_name, options->num_subsystems, options->num_subsystems + 1, - sizeof(options->subsystem_name)); + sizeof(*options->subsystem_name)); options->subsystem_command = xrecallocarray( options->subsystem_command, options->num_subsystems, options->num_subsystems + 1, - sizeof(options->subsystem_command)); + sizeof(*options->subsystem_command)); options->subsystem_args = xrecallocarray( options->subsystem_args, options->num_subsystems, options->num_subsystems + 1, - sizeof(options->subsystem_args)); + sizeof(*options->subsystem_args)); options->subsystem_name[options->num_subsystems] = xstrdup(arg); arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { @@ -2660,13 +2660,13 @@ servconf_merge_subsystems(ServerOptions *dst, ServerOptions *src) debug_f("add \"%s\"", src->subsystem_name[i]); dst->subsystem_name = xrecallocarray( dst->subsystem_name, dst->num_subsystems, - dst->num_subsystems + 1, sizeof(dst->subsystem_name)); + dst->num_subsystems + 1, sizeof(*dst->subsystem_name)); dst->subsystem_command = xrecallocarray( dst->subsystem_command, dst->num_subsystems, - dst->num_subsystems + 1, sizeof(dst->subsystem_command)); + dst->num_subsystems + 1, sizeof(*dst->subsystem_command)); dst->subsystem_args = xrecallocarray( dst->subsystem_args, dst->num_subsystems, - dst->num_subsystems + 1, sizeof(dst->subsystem_args)); + dst->num_subsystems + 1, sizeof(*dst->subsystem_args)); j = dst->num_subsystems++; dst->subsystem_name[j] = xstrdup(src->subsystem_name[i]); dst->subsystem_command[j] = xstrdup(src->subsystem_command[i]); diff --git a/usr.bin/ssh/sftp-client.c b/usr.bin/ssh/sftp-client.c index 230e8791e..c30d782d4 100644 --- a/usr.bin/ssh/sftp-client.c +++ b/usr.bin/ssh/sftp-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.c,v 1.171 2023/04/30 22:54:22 djm Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.174 2023/09/08 06:10:02 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -322,16 +322,17 @@ get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, return handle; } -/* XXX returning &static is error-prone. Refactor to fill *Attrib argument */ -static Attrib * -get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) +static int +get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, Attrib *a) { struct sshbuf *msg; u_int id; u_char type; int r; - static Attrib a; + Attrib attr; + if (a != NULL) + memset(a, '\0', sizeof(*a)); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); @@ -352,21 +353,24 @@ get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) else error("stat remote: %s", fx2txt(status)); sshbuf_free(msg); - return(NULL); + return -1; } else if (type != SSH2_FXP_ATTRS) { fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", SSH2_FXP_ATTRS, type); } - if ((r = decode_attrib(msg, &a)) != 0) { + if ((r = decode_attrib(msg, &attr)) != 0) { error_fr(r, "decode_attrib"); sshbuf_free(msg); - return NULL; + return -1; } + /* success */ + if (a != NULL) + *a = attr; debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o", - type, id, a.flags, a.perm); + type, id, attr.flags, attr.perm); sshbuf_free(msg); - return &a; + return 0; } static int @@ -429,7 +433,7 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, } struct sftp_conn * -do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, +sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, u_int64_t limit_kbps) { u_char type; @@ -540,7 +544,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, /* Query the server for its limits */ if (ret->exts & SFTP_EXT_LIMITS) { struct sftp_limits limits; - if (do_limits(ret, &limits) != 0) + if (sftp_get_limits(ret, &limits) != 0) fatal_f("limits failed"); /* If the caller did not specify, find a good value */ @@ -594,7 +598,7 @@ sftp_proto_version(struct sftp_conn *conn) } int -do_limits(struct sftp_conn *conn, struct sftp_limits *limits) +sftp_get_limits(struct sftp_conn *conn, struct sftp_limits *limits) { u_int id, msg_id; u_char type; @@ -648,7 +652,7 @@ do_limits(struct sftp_conn *conn, struct sftp_limits *limits) } int -do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) +sftp_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) { u_int id, status; struct sshbuf *msg; @@ -676,7 +680,7 @@ do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) static int -do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, +sftp_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, SFTP_DIRENT ***dir) { struct sshbuf *msg; @@ -801,16 +805,16 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, out: sshbuf_free(msg); - do_close(conn, handle, handle_len); + sftp_close(conn, handle, handle_len); free(handle); if (status != 0 && dir != NULL) { /* Don't return results on error */ - free_sftp_dirents(*dir); + sftp_free_dirents(*dir); *dir = NULL; } else if (interrupted && dir != NULL && *dir != NULL) { /* Don't return partial matches on interrupt */ - free_sftp_dirents(*dir); + sftp_free_dirents(*dir); *dir = xcalloc(1, sizeof(**dir)); **dir = NULL; } @@ -819,12 +823,12 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, } int -do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) +sftp_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) { - return(do_lsreaddir(conn, path, 0, dir)); + return sftp_lsreaddir(conn, path, 0, dir); } -void free_sftp_dirents(SFTP_DIRENT **s) +void sftp_free_dirents(SFTP_DIRENT **s) { int i; @@ -839,7 +843,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) } int -do_rm(struct sftp_conn *conn, const char *path) +sftp_rm(struct sftp_conn *conn, const char *path) { u_int status, id; @@ -854,7 +858,7 @@ do_rm(struct sftp_conn *conn, const char *path) } int -do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) +sftp_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) { u_int status, id; @@ -872,7 +876,7 @@ do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) } int -do_rmdir(struct sftp_conn *conn, const char *path) +sftp_rmdir(struct sftp_conn *conn, const char *path) { u_int status, id; @@ -889,8 +893,8 @@ do_rmdir(struct sftp_conn *conn, const char *path) return status == SSH2_FX_OK ? 0 : -1; } -Attrib * -do_stat(struct sftp_conn *conn, const char *path, int quiet) +int +sftp_stat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a) { u_int id; @@ -902,33 +906,31 @@ do_stat(struct sftp_conn *conn, const char *path, int quiet) conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, path, strlen(path)); - return(get_decode_stat(conn, id, quiet)); + return get_decode_stat(conn, id, quiet, a); } -Attrib * -do_lstat(struct sftp_conn *conn, const char *path, int quiet) +int +sftp_lstat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a) { u_int id; if (conn->version == 0) { - if (quiet) - debug("Server version does not support lstat operation"); - else - logit("Server version does not support lstat operation"); - return(do_stat(conn, path, quiet)); + do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, + "Server version does not support lstat operation"); + return sftp_stat(conn, path, quiet, a); } id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_LSTAT, path, strlen(path)); - return(get_decode_stat(conn, id, quiet)); + return get_decode_stat(conn, id, quiet, a); } #ifdef notyet -Attrib * -do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, - int quiet) +int +sftp_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, + int quiet, Attrib *a) { u_int id; @@ -938,12 +940,12 @@ do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, send_string_request(conn, id, SSH2_FXP_FSTAT, handle, handle_len); - return(get_decode_stat(conn, id, quiet)); + return get_decode_stat(conn, id, quiet, a); } #endif int -do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) +sftp_setstat(struct sftp_conn *conn, const char *path, Attrib *a) { u_int status, id; @@ -961,7 +963,7 @@ do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) } int -do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, +sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a) { u_int status, id; @@ -981,7 +983,7 @@ do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, /* Implements both the realpath and expand-path operations */ static char * -do_realpath_expand(struct sftp_conn *conn, const char *path, int expand) +sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) { struct sshbuf *msg; u_int expected_id, count, id; @@ -1056,31 +1058,31 @@ do_realpath_expand(struct sftp_conn *conn, const char *path, int expand) } char * -do_realpath(struct sftp_conn *conn, const char *path) +sftp_realpath(struct sftp_conn *conn, const char *path) { - return do_realpath_expand(conn, path, 0); + return sftp_realpath_expand(conn, path, 0); } int -can_expand_path(struct sftp_conn *conn) +sftp_can_expand_path(struct sftp_conn *conn) { return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0; } char * -do_expand_path(struct sftp_conn *conn, const char *path) +sftp_expand_path(struct sftp_conn *conn, const char *path) { - if (!can_expand_path(conn)) { + if (!sftp_can_expand_path(conn)) { debug3_f("no server support, fallback to realpath"); - return do_realpath_expand(conn, path, 0); + return sftp_realpath_expand(conn, path, 0); } - return do_realpath_expand(conn, path, 1); + return sftp_realpath_expand(conn, path, 1); } int -do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) +sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) { - Attrib junk, *a; + Attrib junk, attr; struct sshbuf *msg; u_char *old_handle, *new_handle; u_int mode, status, id; @@ -1094,14 +1096,14 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) } /* Make sure the file exists, and we can copy its perms */ - if ((a = do_stat(conn, oldpath, 0)) == NULL) + if (sftp_stat(conn, oldpath, 0, &attr) != 0) return -1; /* Do not preserve set[ug]id here, as we do not preserve ownership */ - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { - mode = a->perm & 0777; + if (attr.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { + mode = attr.perm & 0777; - if (!S_ISREG(a->perm)) { + if (!S_ISREG(attr.perm)) { error("Cannot copy non-regular file: %s", oldpath); return -1; } @@ -1111,9 +1113,9 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) } /* Set up the new perms for the new file */ - attrib_clear(a); - a->perm = mode; - a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; + attrib_clear(&attr); + attr.perm = mode; + attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); @@ -1147,7 +1149,7 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) (r = sshbuf_put_cstring(msg, newpath)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| SSH2_FXF_TRUNC)) != 0 || - (r = encode_attrib(msg, a)) != 0) + (r = encode_attrib(msg, &attr)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath); @@ -1184,8 +1186,8 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) /* Clean up everything */ sshbuf_free(msg); - do_close(conn, old_handle, old_handle_len); - do_close(conn, new_handle, new_handle_len); + sftp_close(conn, old_handle, old_handle_len); + sftp_close(conn, new_handle, new_handle_len); free(old_handle); free(new_handle); @@ -1193,7 +1195,7 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) } int -do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, +sftp_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy) { struct sshbuf *msg; @@ -1238,7 +1240,7 @@ do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, } int -do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) +sftp_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { struct sshbuf *msg; u_int status, id; @@ -1276,7 +1278,7 @@ do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) } int -do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) +sftp_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { struct sshbuf *msg; u_int status, id; @@ -1312,7 +1314,7 @@ do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) } int -do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) +sftp_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) { struct sshbuf *msg; u_int status, id; @@ -1345,7 +1347,7 @@ do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) #ifdef notyet char * -do_readlink(struct sftp_conn *conn, const char *path) +sftp_readlink(struct sftp_conn *conn, const char *path) { struct sshbuf *msg; u_int expected_id, count, id; @@ -1403,7 +1405,7 @@ do_readlink(struct sftp_conn *conn, const char *path) #endif int -do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, +sftp_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, int quiet) { struct sshbuf *msg; @@ -1434,7 +1436,7 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, #ifdef notyet int -do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, +sftp_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, struct sftp_statvfs *st, int quiet) { struct sshbuf *msg; @@ -1464,7 +1466,7 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, #endif int -do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) +sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) { struct sshbuf *msg; u_int status, id; @@ -1572,7 +1574,7 @@ progress_meter_path(const char *path) } int -do_download(struct sftp_conn *conn, const char *remote_path, +sftp_download(struct sftp_conn *conn, const char *remote_path, const char *local_path, Attrib *a, int preserve_flag, int resume_flag, int fsync_flag, int inplace_flag) { @@ -1588,14 +1590,18 @@ do_download(struct sftp_conn *conn, const char *remote_path, struct requests requests; struct request *req; u_char type; + Attrib attr; debug2_f("download remote \"%s\" to local \"%s\"", remote_path, local_path); TAILQ_INIT(&requests); - if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) - return -1; + if (a == NULL) { + if (sftp_stat(conn, remote_path, 0, &attr) != 0) + return -1; + a = &attr; + } /* Do not preserve set[ug]id here, as we do not preserve ownership */ if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) @@ -1641,7 +1647,7 @@ do_download(struct sftp_conn *conn, const char *remote_path, error("Unable to resume download of \"%s\": " "local file is larger than remote", local_path); fail: - do_close(conn, handle, handle_len); + sftp_close(conn, handle, handle_len); free(handle); if (local_fd != -1) close(local_fd); @@ -1816,14 +1822,14 @@ do_download(struct sftp_conn *conn, const char *remote_path, if (read_error) { error("read remote \"%s\" : %s", remote_path, fx2txt(status)); status = -1; - do_close(conn, handle, handle_len); + sftp_close(conn, handle, handle_len); } else if (write_error) { error("write local \"%s\": %s", local_path, strerror(write_errno)); status = SSH2_FX_FAILURE; - do_close(conn, handle, handle_len); + sftp_close(conn, handle, handle_len); } else { - if (do_close(conn, handle, handle_len) != 0 || interrupted) + if (sftp_close(conn, handle, handle_len) != 0 || interrupted) status = SSH2_FX_FAILURE; else status = SSH2_FX_OK; @@ -1866,6 +1872,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, SFTP_DIRENT **dir_entries; char *filename, *new_src = NULL, *new_dst = NULL; mode_t mode = 0777, tmpmode = mode; + Attrib *a, ldirattrib, lsym; if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); @@ -1874,10 +1881,12 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst); - if (dirattrib == NULL && - (dirattrib = do_stat(conn, src, 1)) == NULL) { - error("stat remote \"%s\" directory failed", src); - return -1; + if (dirattrib == NULL) { + if (sftp_stat(conn, src, 1, &ldirattrib) != 0) { + error("stat remote \"%s\" directory failed", src); + return -1; + } + dirattrib = &ldirattrib; } if (!S_ISDIR(dirattrib->perm)) { error("\"%s\" is not a directory", src); @@ -1899,7 +1908,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, return -1; } - if (do_readdir(conn, src, &dir_entries) == -1) { + if (sftp_readdir(conn, src, &dir_entries) == -1) { error("remote readdir \"%s\" failed", src); return -1; } @@ -1909,28 +1918,36 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, free(new_src); filename = dir_entries[i]->filename; - new_dst = path_append(dst, filename); - new_src = path_append(src, filename); + new_dst = sftp_path_append(dst, filename); + new_src = sftp_path_append(src, filename); - if (S_ISDIR(dir_entries[i]->a.perm)) { + a = &dir_entries[i]->a; + if (S_ISLNK(a->perm)) { + if (!follow_link_flag) { + logit("download \"%s\": not a regular file", + new_src); + continue; + } + /* Replace the stat contents with the symlink target */ + if (sftp_stat(conn, new_src, 1, &lsym) != 0) { + logit("remote stat \"%s\" failed", new_src); + ret = -1; + continue; + } + a = &lsym; + } + + if (S_ISDIR(a->perm)) { if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (download_dir_internal(conn, new_src, new_dst, - depth + 1, &(dir_entries[i]->a), preserve_flag, + depth + 1, a, preserve_flag, print_flag, resume_flag, fsync_flag, follow_link_flag, inplace_flag) == -1) ret = -1; - } else if (S_ISREG(dir_entries[i]->a.perm) || - (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { - /* - * If this is a symlink then don't send the link's - * Attrib. do_download() will do a FXP_STAT operation - * and get the link target's attributes. - */ - if (do_download(conn, new_src, new_dst, - S_ISLNK(dir_entries[i]->a.perm) ? NULL : - &(dir_entries[i]->a), + } else if (S_ISREG(a->perm)) { + if (sftp_download(conn, new_src, new_dst, a, preserve_flag, resume_flag, fsync_flag, inplace_flag) == -1) { error("Download of file %s to %s failed", @@ -1962,20 +1979,20 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, error("local chmod directory \"%s\": %s", dst, strerror(errno)); - free_sftp_dirents(dir_entries); + sftp_free_dirents(dir_entries); return ret; } int -download_dir(struct sftp_conn *conn, const char *src, const char *dst, +sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst, Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) { char *src_canon; int ret; - if ((src_canon = do_realpath(conn, src)) == NULL) { + if ((src_canon = sftp_realpath(conn, src)) == NULL) { error("download \"%s\": path canonicalization failed", src); return -1; } @@ -1988,7 +2005,7 @@ download_dir(struct sftp_conn *conn, const char *src, const char *dst, } int -do_upload(struct sftp_conn *conn, const char *local_path, +sftp_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path, int preserve_flag, int resume, int fsync_flag, int inplace_flag) { @@ -1998,7 +2015,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, u_char type, *handle, *data; struct sshbuf *msg; struct stat sb; - Attrib a, t, *c = NULL; + Attrib a, t, c; u_int32_t startid, ackid; u_int64_t highwater = 0, maxack = 0; struct request *ack = NULL; @@ -2034,19 +2051,19 @@ do_upload(struct sftp_conn *conn, const char *local_path, if (resume) { /* Get remote file size if it exists */ - if ((c = do_stat(conn, remote_path, 0)) == NULL) { + if (sftp_stat(conn, remote_path, 0, &c) != 0) { close(local_fd); return -1; } - if ((off_t)c->size >= sb.st_size) { + if ((off_t)c.size >= sb.st_size) { error("resume \"%s\": destination file " "same size or larger", local_path); close(local_fd); return -1; } - if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { + if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) { close(local_fd); return -1; } @@ -2070,7 +2087,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, data = xmalloc(conn->upload_buflen); /* Read from local and write to remote */ - offset = progress_counter = (resume ? c->size : 0); + offset = progress_counter = (resume ? c.size : 0); if (showprogress) { start_progress_meter(progress_meter_path(local_path), sb.st_size, &progress_counter); @@ -2181,7 +2198,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, attrib_clear(&t); t.flags = SSH2_FILEXFER_ATTR_SIZE; t.size = highwater; - do_fsetstat(conn, handle, handle_len, &t); + sftp_fsetstat(conn, handle, handle_len, &t); } if (close(local_fd) == -1) { @@ -2191,12 +2208,12 @@ do_upload(struct sftp_conn *conn, const char *local_path, /* Override umask and utimes if asked */ if (preserve_flag) - do_fsetstat(conn, handle, handle_len, &a); + sftp_fsetstat(conn, handle, handle_len, &a); if (fsync_flag) - (void)do_fsync(conn, handle, handle_len); + (void)sftp_fsync(conn, handle, handle_len); - if (do_close(conn, handle, handle_len) != 0) + if (sftp_close(conn, handle, handle_len) != 0) status = SSH2_FX_FAILURE; free(handle); @@ -2214,7 +2231,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, struct dirent *dp; char *filename, *new_src = NULL, *new_dst = NULL; struct stat sb; - Attrib a, *dirattrib; + Attrib a, dirattrib; u_int32_t saved_perm; debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst); @@ -2250,10 +2267,10 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, */ saved_perm = a.perm; a.perm |= (S_IWUSR|S_IXUSR); - if (do_mkdir(conn, dst, &a, 0) != 0) { - if ((dirattrib = do_stat(conn, dst, 0)) == NULL) + if (sftp_mkdir(conn, dst, &a, 0) != 0) { + if (sftp_stat(conn, dst, 0, &dirattrib) != 0) return -1; - if (!S_ISDIR(dirattrib->perm)) { + if (!S_ISDIR(dirattrib.perm)) { error("\"%s\" exists but is not a directory", dst); return -1; } @@ -2271,25 +2288,37 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, free(new_dst); free(new_src); filename = dp->d_name; - new_dst = path_append(dst, filename); - new_src = path_append(src, filename); + new_dst = sftp_path_append(dst, filename); + new_src = sftp_path_append(src, filename); + if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) + continue; if (lstat(new_src, &sb) == -1) { logit("local lstat \"%s\": %s", filename, strerror(errno)); ret = -1; - } else if (S_ISDIR(sb.st_mode)) { - if (strcmp(filename, ".") == 0 || - strcmp(filename, "..") == 0) + continue; + } + if (S_ISLNK(sb.st_mode)) { + if (!follow_link_flag) { + logit("%s: not a regular file", filename); continue; - + } + /* Replace the stat contents with the symlink target */ + if (stat(new_src, &sb) == -1) { + logit("local stat \"%s\": %s", filename, + strerror(errno)); + ret = -1; + continue; + } + } + if (S_ISDIR(sb.st_mode)) { if (upload_dir_internal(conn, new_src, new_dst, depth + 1, preserve_flag, print_flag, resume, fsync_flag, follow_link_flag, inplace_flag) == -1) ret = -1; - } else if (S_ISREG(sb.st_mode) || - (follow_link_flag && S_ISLNK(sb.st_mode))) { - if (do_upload(conn, new_src, new_dst, + } else if (S_ISREG(sb.st_mode)) { + if (sftp_upload(conn, new_src, new_dst, preserve_flag, resume, fsync_flag, inplace_flag) == -1) { error("upload \"%s\" to \"%s\" failed", @@ -2302,21 +2331,21 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, free(new_dst); free(new_src); - do_setstat(conn, dst, &a); + sftp_setstat(conn, dst, &a); (void) closedir(dirp); return ret; } int -upload_dir(struct sftp_conn *conn, const char *src, const char *dst, +sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int preserve_flag, int print_flag, int resume, int fsync_flag, int follow_link_flag, int inplace_flag) { char *dst_canon; int ret; - if ((dst_canon = do_realpath(conn, dst)) == NULL) { + if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { error("upload \"%s\": path canonicalization failed", dst); return -1; } @@ -2375,13 +2404,13 @@ handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, *write_errorp = status; } /* - * XXX this doesn't do full reply matching like do_upload and + * XXX this doesn't do full reply matching like sftp_upload and * so cannot gracefully truncate terminated uploads at a * high-water mark. ATM the only caller of this function (scp) * doesn't support transfer resumption, so this doesn't matter * a whole lot. * - * To be safe, do_crossload truncates the destination file to + * To be safe, sftp_crossload truncates the destination file to * zero length on upload failure, since we can't trust the * server not to have reordered replies that could have * inserted holes where none existed in the source file. @@ -2396,7 +2425,7 @@ handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, } int -do_crossload(struct sftp_conn *from, struct sftp_conn *to, +sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *a, int preserve_flag) { @@ -2411,13 +2440,17 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to, struct requests requests; struct request *req; u_char type; + Attrib attr; debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path); TAILQ_INIT(&requests); - if (a == NULL && (a = do_stat(from, from_path, 0)) == NULL) - return -1; + if (a == NULL) { + if (sftp_stat(from, from_path, 0, &attr) != 0) + return -1; + a = &attr; + } if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && (!S_ISREG(a->perm))) { @@ -2447,7 +2480,7 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to, if (send_open(to, to_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, &to_handle, &to_handle_len) != 0) { - do_close(from, from_handle, from_handle_len); + sftp_close(from, from_handle, from_handle_len); return -1; } @@ -2597,7 +2630,7 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to, /* Truncate at 0 length on interrupt or error to avoid holes at dest */ if (read_error || write_error || interrupted) { debug("truncating \"%s\" at 0", to_path); - do_close(to, to_handle, to_handle_len); + sftp_close(to, to_handle, to_handle_len); free(to_handle); if (send_open(to, to_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, @@ -2609,17 +2642,17 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to, if (read_error) { error("read origin \"%s\": %s", from_path, fx2txt(status)); status = -1; - do_close(from, from_handle, from_handle_len); + sftp_close(from, from_handle, from_handle_len); if (to_handle != NULL) - do_close(to, to_handle, to_handle_len); + sftp_close(to, to_handle, to_handle_len); } else if (write_error) { error("write dest \"%s\": %s", to_path, fx2txt(write_error)); status = SSH2_FX_FAILURE; - do_close(from, from_handle, from_handle_len); + sftp_close(from, from_handle, from_handle_len); if (to_handle != NULL) - do_close(to, to_handle, to_handle_len); + sftp_close(to, to_handle, to_handle_len); } else { - if (do_close(from, from_handle, from_handle_len) != 0 || + if (sftp_close(from, from_handle, from_handle_len) != 0 || interrupted) status = -1; else @@ -2627,8 +2660,8 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to, if (to_handle != NULL) { /* Need to resend utimes after write */ if (preserve_flag) - do_fsetstat(to, to_handle, to_handle_len, a); - do_close(to, to_handle, to_handle_len); + sftp_fsetstat(to, to_handle, to_handle_len, a); + sftp_close(to, to_handle, to_handle_len); } } sshbuf_free(msg); @@ -2648,7 +2681,7 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, SFTP_DIRENT **dir_entries; char *filename, *new_from_path = NULL, *new_to_path = NULL; mode_t mode = 0777; - Attrib curdir; + Attrib *a, curdir, ldirattrib, newdir, lsym; debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path); @@ -2657,10 +2690,12 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, return -1; } - if (dirattrib == NULL && - (dirattrib = do_stat(from, from_path, 1)) == NULL) { - error("stat remote \"%s\" failed", from_path); - return -1; + if (dirattrib == NULL) { + if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) { + error("stat remote \"%s\" failed", from_path); + return -1; + } + dirattrib = &ldirattrib; } if (!S_ISDIR(dirattrib->perm)) { error("\"%s\" is not a directory", from_path); @@ -2688,17 +2723,17 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, * the path already existed and is a directory. Ensure we can * write to the directory we create for the duration of the transfer. */ - if (do_mkdir(to, to_path, &curdir, 0) != 0) { - if ((dirattrib = do_stat(to, to_path, 0)) == NULL) + if (sftp_mkdir(to, to_path, &curdir, 0) != 0) { + if (sftp_stat(to, to_path, 0, &newdir) != 0) return -1; - if (!S_ISDIR(dirattrib->perm)) { + if (!S_ISDIR(newdir.perm)) { error("\"%s\" exists but is not a directory", to_path); return -1; } } curdir.perm = mode; - if (do_readdir(from, from_path, &dir_entries) == -1) { + if (sftp_readdir(from, from_path, &dir_entries) == -1) { error("origin readdir \"%s\" failed", from_path); return -1; } @@ -2708,28 +2743,36 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, free(new_to_path); filename = dir_entries[i]->filename; - new_from_path = path_append(from_path, filename); - new_to_path = path_append(to_path, filename); + new_from_path = sftp_path_append(from_path, filename); + new_to_path = sftp_path_append(to_path, filename); - if (S_ISDIR(dir_entries[i]->a.perm)) { + a = &dir_entries[i]->a; + if (S_ISLNK(a->perm)) { + if (!follow_link_flag) { + logit("%s: not a regular file", filename); + continue; + } + /* Replace the stat contents with the symlink target */ + if (sftp_stat(from, new_from_path, 1, &lsym) != 0) { + logit("remote stat \"%s\" failed", + new_from_path); + ret = -1; + continue; + } + a = &lsym; + } + if (S_ISDIR(a->perm)) { if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (crossload_dir_internal(from, to, new_from_path, new_to_path, - depth + 1, &(dir_entries[i]->a), preserve_flag, + depth + 1, a, preserve_flag, print_flag, follow_link_flag) == -1) ret = -1; - } else if (S_ISREG(dir_entries[i]->a.perm) || - (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { - /* - * If this is a symlink then don't send the link's - * Attrib. do_download() will do a FXP_STAT operation - * and get the link target's attributes. - */ - if (do_crossload(from, to, new_from_path, new_to_path, - S_ISLNK(dir_entries[i]->a.perm) ? NULL : - &(dir_entries[i]->a), preserve_flag) == -1) { + } else if (S_ISREG(a->perm)) { + if (sftp_crossload(from, to, new_from_path, + new_to_path, a, preserve_flag) == -1) { error("crossload \"%s\" to \"%s\" failed", new_from_path, new_to_path); ret = -1; @@ -2742,22 +2785,22 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, free(new_to_path); free(new_from_path); - do_setstat(to, to_path, &curdir); + sftp_setstat(to, to_path, &curdir); - free_sftp_dirents(dir_entries); + sftp_free_dirents(dir_entries); return ret; } int -crossload_dir(struct sftp_conn *from, struct sftp_conn *to, +sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) { char *from_path_canon; int ret; - if ((from_path_canon = do_realpath(from, from_path)) == NULL) { + if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { error("crossload \"%s\": path canonicalization failed", from_path); return -1; @@ -2770,13 +2813,13 @@ crossload_dir(struct sftp_conn *from, struct sftp_conn *to, } int -can_get_users_groups_by_id(struct sftp_conn *conn) +sftp_can_get_users_groups_by_id(struct sftp_conn *conn) { return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0; } int -do_get_users_groups_by_id(struct sftp_conn *conn, +sftp_get_users_groups_by_id(struct sftp_conn *conn, const u_int *uids, u_int nuids, const u_int *gids, u_int ngids, char ***usernamesp, char ***groupnamesp) @@ -2788,7 +2831,7 @@ do_get_users_groups_by_id(struct sftp_conn *conn, int r; *usernamesp = *groupnamesp = NULL; - if (!can_get_users_groups_by_id(conn)) + if (!sftp_can_get_users_groups_by_id(conn)) return SSH_ERR_FEATURE_UNSUPPORTED; if ((msg = sshbuf_new()) == NULL || @@ -2884,7 +2927,7 @@ do_get_users_groups_by_id(struct sftp_conn *conn, } char * -path_append(const char *p1, const char *p2) +sftp_path_append(const char *p1, const char *p2) { char *ret; size_t len = strlen(p1) + strlen(p2) + 2; @@ -2903,13 +2946,13 @@ path_append(const char *p1, const char *p2) * freed and a replacement allocated. Caller must free returned string. */ char * -make_absolute(char *p, const char *pwd) +sftp_make_absolute(char *p, const char *pwd) { char *abs_str; /* Derelativise */ if (p && !path_absolute(p)) { - abs_str = path_append(pwd, p); + abs_str = sftp_path_append(pwd, p); free(p); return(abs_str); } else @@ -2917,34 +2960,22 @@ make_absolute(char *p, const char *pwd) } int -remote_is_dir(struct sftp_conn *conn, const char *path) +sftp_remote_is_dir(struct sftp_conn *conn, const char *path) { - Attrib *a; + Attrib a; /* XXX: report errors? */ - if ((a = do_stat(conn, path, 1)) == NULL) + if (sftp_stat(conn, path, 1, &a) != 0) return(0); - if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) + if (!(a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) return(0); - return(S_ISDIR(a->perm)); + return S_ISDIR(a.perm); } -int -local_is_dir(const char *path) -{ - struct stat sb; - - /* XXX: report errors? */ - if (stat(path, &sb) == -1) - return(0); - - return(S_ISDIR(sb.st_mode)); -} - /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ int -globpath_is_dir(const char *pathname) +sftp_globpath_is_dir(const char *pathname) { size_t l = strlen(pathname); diff --git a/usr.bin/ssh/sftp-client.h b/usr.bin/ssh/sftp-client.h index 2403b1142..6da3f6bd9 100644 --- a/usr.bin/ssh/sftp-client.h +++ b/usr.bin/ssh/sftp-client.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.h,v 1.38 2022/09/19 10:43:12 djm Exp $ */ +/* $OpenBSD: sftp-client.h,v 1.39 2023/09/08 05:56:13 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller @@ -64,107 +64,106 @@ struct sftp_limits { * Initialise a SSH filexfer connection. Returns NULL on error or * a pointer to a initialized sftp_conn struct on success. */ -struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t); +struct sftp_conn *sftp_init(int, int, u_int, u_int, u_int64_t); u_int sftp_proto_version(struct sftp_conn *); /* Query server limits */ -int do_limits(struct sftp_conn *, struct sftp_limits *); +int sftp_get_limits(struct sftp_conn *, struct sftp_limits *); /* Close file referred to by 'handle' */ -int do_close(struct sftp_conn *, const u_char *, u_int); +int sftp_close(struct sftp_conn *, const u_char *, u_int); /* Read contents of 'path' to NULL-terminated array 'dir' */ -int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); +int sftp_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); -/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ -void free_sftp_dirents(SFTP_DIRENT **); +/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from sftp_readdir) */ +void sftp_free_dirents(SFTP_DIRENT **); /* Delete file 'path' */ -int do_rm(struct sftp_conn *, const char *); +int sftp_rm(struct sftp_conn *, const char *); /* Create directory 'path' */ -int do_mkdir(struct sftp_conn *, const char *, Attrib *, int); +int sftp_mkdir(struct sftp_conn *, const char *, Attrib *, int); /* Remove directory 'path' */ -int do_rmdir(struct sftp_conn *, const char *); +int sftp_rmdir(struct sftp_conn *, const char *); /* Get file attributes of 'path' (follows symlinks) */ -Attrib *do_stat(struct sftp_conn *, const char *, int); +int sftp_stat(struct sftp_conn *, const char *, int, Attrib *); /* Get file attributes of 'path' (does not follow symlinks) */ -Attrib *do_lstat(struct sftp_conn *, const char *, int); +int sftp_lstat(struct sftp_conn *, const char *, int, Attrib *); /* Set file attributes of 'path' */ -int do_setstat(struct sftp_conn *, const char *, Attrib *); +int sftp_setstat(struct sftp_conn *, const char *, Attrib *); /* Set file attributes of open file 'handle' */ -int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); +int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); /* Set file attributes of 'path', not following symlinks */ -int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); +int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); /* Canonicalise 'path' - caller must free result */ -char *do_realpath(struct sftp_conn *, const char *); +char *sftp_realpath(struct sftp_conn *, const char *); /* Canonicalisation with tilde expansion (requires server extension) */ -char *do_expand_path(struct sftp_conn *, const char *); +char *sftp_expand_path(struct sftp_conn *, const char *); /* Returns non-zero if server can tilde-expand paths */ -int can_expand_path(struct sftp_conn *); +int sftp_can_expand_path(struct sftp_conn *); /* Get statistics for filesystem hosting file at "path" */ -int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); +int sftp_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); /* Rename 'oldpath' to 'newpath' */ -int do_rename(struct sftp_conn *, const char *, const char *, int); +int sftp_rename(struct sftp_conn *, const char *, const char *, int); /* Copy 'oldpath' to 'newpath' */ -int do_copy(struct sftp_conn *, const char *, const char *); +int sftp_copy(struct sftp_conn *, const char *, const char *); /* Link 'oldpath' to 'newpath' */ -int do_hardlink(struct sftp_conn *, const char *, const char *); +int sftp_hardlink(struct sftp_conn *, const char *, const char *); /* Rename 'oldpath' to 'newpath' */ -int do_symlink(struct sftp_conn *, const char *, const char *); +int sftp_symlink(struct sftp_conn *, const char *, const char *); /* Call fsync() on open file 'handle' */ -int do_fsync(struct sftp_conn *conn, u_char *, u_int); +int sftp_fsync(struct sftp_conn *conn, u_char *, u_int); /* * Download 'remote_path' to 'local_path'. Preserve permissions and times * if 'pflag' is set */ -int do_download(struct sftp_conn *, const char *, const char *, Attrib *, +int sftp_download(struct sftp_conn *, const char *, const char *, Attrib *, int, int, int, int); /* * Recursively download 'remote_directory' to 'local_directory'. Preserve * times if 'pflag' is set */ -int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, +int sftp_download_dir(struct sftp_conn *, const char *, const char *, Attrib *, int, int, int, int, int, int); /* * Upload 'local_path' to 'remote_path'. Preserve permissions and times * if 'pflag' is set */ -int do_upload(struct sftp_conn *, const char *, const char *, +int sftp_upload(struct sftp_conn *, const char *, const char *, int, int, int, int); /* * Recursively upload 'local_directory' to 'remote_directory'. Preserve * times if 'pflag' is set */ -int upload_dir(struct sftp_conn *, const char *, const char *, +int sftp_upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, int, int, int); /* * Download a 'from_path' from the 'from' connection and upload it to * to 'to' connection at 'to_path'. */ -int -do_crossload(struct sftp_conn *from, struct sftp_conn *to, +int sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *a, int preserve_flag); @@ -172,7 +171,7 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to, * Recursively download a directory from 'from_path' from the 'from' * connection and upload it to 'to' connection at 'to_path'. */ -int crossload_dir(struct sftp_conn *from, struct sftp_conn *to, +int sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag); @@ -180,26 +179,23 @@ int crossload_dir(struct sftp_conn *from, struct sftp_conn *to, /* * User/group ID to name translation. */ -int can_get_users_groups_by_id(struct sftp_conn *conn); -int do_get_users_groups_by_id(struct sftp_conn *conn, +int sftp_can_get_users_groups_by_id(struct sftp_conn *conn); +int sftp_get_users_groups_by_id(struct sftp_conn *conn, const u_int *uids, u_int nuids, const u_int *gids, u_int ngids, char ***usernamesp, char ***groupnamesp); /* Concatenate paths, taking care of slashes. Caller must free result. */ -char *path_append(const char *, const char *); +char *sftp_path_append(const char *, const char *); /* Make absolute path if relative path and CWD is given. Does not modify * original if the path is already absolute. */ -char *make_absolute(char *, const char *); +char *sftp_make_absolute(char *, const char *); /* Check if remote path is directory */ -int remote_is_dir(struct sftp_conn *conn, const char *path); - -/* Check if local path is directory */ -int local_is_dir(const char *path); +int sftp_remote_is_dir(struct sftp_conn *conn, const char *path); /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ -int globpath_is_dir(const char *pathname); +int sftp_globpath_is_dir(const char *pathname); #endif diff --git a/usr.bin/ssh/sftp-glob.c b/usr.bin/ssh/sftp-glob.c index 32730913b..435acb904 100644 --- a/usr.bin/ssh/sftp-glob.c +++ b/usr.bin/ssh/sftp-glob.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-glob.c,v 1.31 2022/10/24 21:51:55 djm Exp $ */ +/* $OpenBSD: sftp-glob.c,v 1.32 2023/09/08 05:56:13 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -48,7 +48,7 @@ fudge_opendir(const char *path) r = xcalloc(1, sizeof(*r)); - if (do_readdir(cur.conn, path, &r->dir)) { + if (sftp_readdir(cur.conn, path, &r->dir)) { free(r); return(NULL); } @@ -76,32 +76,32 @@ fudge_readdir(struct SFTP_OPENDIR *od) static void fudge_closedir(struct SFTP_OPENDIR *od) { - free_sftp_dirents(od->dir); + sftp_free_dirents(od->dir); free(od); } static int fudge_lstat(const char *path, struct stat *st) { - Attrib *a; + Attrib a; - if (!(a = do_lstat(cur.conn, path, 1))) - return(-1); + if (sftp_lstat(cur.conn, path, 1, &a) != 0) + return -1; - attrib_to_stat(a, st); + attrib_to_stat(&a, st); - return(0); + return 0; } static int fudge_stat(const char *path, struct stat *st) { - Attrib *a; + Attrib a; - if (!(a = do_stat(cur.conn, path, 1))) - return(-1); + if (sftp_stat(cur.conn, path, 1, &a) != 0) + return -1; - attrib_to_stat(a, st); + attrib_to_stat(&a, st); return(0); } diff --git a/usr.bin/ssh/sftp-usergroup.c b/usr.bin/ssh/sftp-usergroup.c index 02f916428..47cf04a9a 100644 --- a/usr.bin/ssh/sftp-usergroup.c +++ b/usr.bin/ssh/sftp-usergroup.c @@ -105,9 +105,9 @@ lookup_and_record(struct sftp_conn *conn, u_int i; char **usernames = NULL, **groupnames = NULL; - if ((r = do_get_users_groups_by_id(conn, uids, nuids, gids, ngids, + if ((r = sftp_get_users_groups_by_id(conn, uids, nuids, gids, ngids, &usernames, &groupnames)) != 0) { - debug_fr(r, "do_get_users_groups_by_id"); + debug_fr(r, "sftp_get_users_groups_by_id"); return; } for (i = 0; i < nuids; i++) { @@ -175,7 +175,7 @@ get_remote_user_groups_from_glob(struct sftp_conn *conn, glob_t *g) { u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0; - if (!can_get_users_groups_by_id(conn)) + if (!sftp_can_get_users_groups_by_id(conn)) return; collect_ids_from_glob(g, 1, &uids, &nuids); @@ -214,7 +214,7 @@ get_remote_user_groups_from_dirents(struct sftp_conn *conn, SFTP_DIRENT **d) { u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0; - if (!can_get_users_groups_by_id(conn)) + if (!sftp_can_get_users_groups_by_id(conn)) return; collect_ids_from_dirents(d, 1, &uids, &nuids); diff --git a/usr.bin/ssh/sftp.c b/usr.bin/ssh/sftp.c index e5e679f87..baa309db6 100644 --- a/usr.bin/ssh/sftp.c +++ b/usr.bin/ssh/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.234 2023/04/12 08:53:54 jsg Exp $ */ +/* $OpenBSD: sftp.c,v 1.235 2023/09/08 05:56:13 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -607,11 +607,21 @@ make_absolute_pwd_glob(char *p, const char *pwd) escpwd = escape_glob(pwd); if (p == NULL) return escpwd; - ret = make_absolute(p, escpwd); + ret = sftp_make_absolute(p, escpwd); free(escpwd); return ret; } +static int +local_is_dir(const char *path) +{ + struct stat sb; + + if (stat(path, &sb) == -1) + return 0; + return S_ISDIR(sb.st_mode); +} + static int process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, int pflag, int rflag, int resume, int fflag) @@ -656,12 +666,12 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, if (g.gl_matchc == 1 && dst) { if (local_is_dir(dst)) { - abs_dst = path_append(dst, filename); + abs_dst = sftp_path_append(dst, filename); } else { abs_dst = xstrdup(dst); } } else if (dst) { - abs_dst = path_append(dst, filename); + abs_dst = sftp_path_append(dst, filename); } else { abs_dst = xstrdup(filename); } @@ -675,13 +685,14 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, mprintf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); /* XXX follow link flag */ - if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { - if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, - pflag || global_pflag, 1, resume, + if (sftp_globpath_is_dir(g.gl_pathv[i]) && + (rflag || global_rflag)) { + if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst, + NULL, pflag || global_pflag, 1, resume, fflag || global_fflag, 0, 0) == -1) err = -1; } else { - if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, + if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL, pflag || global_pflag, resume, fflag || global_fflag, 0) == -1) err = -1; @@ -710,7 +721,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, if (dst) { tmp_dst = xstrdup(dst); - tmp_dst = make_absolute(tmp_dst, pwd); + tmp_dst = sftp_make_absolute(tmp_dst, pwd); } memset(&g, 0, sizeof(g)); @@ -723,7 +734,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, /* If we aren't fetching to pwd then stash this status for later */ if (tmp_dst != NULL) - dst_is_dir = remote_is_dir(conn, tmp_dst); + dst_is_dir = sftp_remote_is_dir(conn, tmp_dst); /* If multiple matches, dst may be directory or unspecified */ if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) { @@ -753,13 +764,13 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, if (g.gl_matchc == 1 && tmp_dst) { /* If directory specified, append filename */ if (dst_is_dir) - abs_dst = path_append(tmp_dst, filename); + abs_dst = sftp_path_append(tmp_dst, filename); else abs_dst = xstrdup(tmp_dst); } else if (tmp_dst) { - abs_dst = path_append(tmp_dst, filename); + abs_dst = sftp_path_append(tmp_dst, filename); } else { - abs_dst = make_absolute(xstrdup(filename), pwd); + abs_dst = sftp_make_absolute(xstrdup(filename), pwd); } free(tmp); @@ -771,13 +782,14 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, mprintf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); /* XXX follow_link_flag */ - if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { - if (upload_dir(conn, g.gl_pathv[i], abs_dst, + if (sftp_globpath_is_dir(g.gl_pathv[i]) && + (rflag || global_rflag)) { + if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, 1, resume, fflag || global_fflag, 0, 0) == -1) err = -1; } else { - if (do_upload(conn, g.gl_pathv[i], abs_dst, + if (sftp_upload(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, resume, fflag || global_fflag, 0) == -1) err = -1; @@ -818,7 +830,7 @@ do_ls_dir(struct sftp_conn *conn, const char *path, u_int c = 1, colspace = 0, columns = 1; SFTP_DIRENT **d; - if ((n = do_readdir(conn, path, &d)) != 0) + if ((n = sftp_readdir(conn, path, &d)) != 0) return (n); if (!(lflag & LS_SHORT_VIEW)) { @@ -860,13 +872,13 @@ do_ls_dir(struct sftp_conn *conn, const char *path, if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL)) continue; - tmp = path_append(path, d[n]->filename); + tmp = sftp_path_append(path, d[n]->filename); fname = path_strip(tmp, strip_path); free(tmp); if (lflag & LS_LONG_VIEW) { if ((lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) != 0 || - can_get_users_groups_by_id(conn)) { + sftp_can_get_users_groups_by_id(conn)) { char *lname; struct stat sb; @@ -895,7 +907,7 @@ do_ls_dir(struct sftp_conn *conn, const char *path, if (!(lflag & LS_LONG_VIEW) && (c != 1)) printf("\n"); - free_sftp_dirents(d); + sftp_free_dirents(d); return (0); } @@ -1043,7 +1055,7 @@ do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE]; char s_icapacity[16], s_dcapacity[16]; - if (do_statvfs(conn, path, &st, 1) == -1) + if (sftp_statvfs(conn, path, &st, 1) == -1) return -1; if (st.f_files == 0) strlcpy(s_icapacity, "ERR", sizeof(s_icapacity)); @@ -1517,7 +1529,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, int lflag = 0, pflag = 0, rflag = 0, sflag = 0; int cmdnum, i; unsigned long n_arg = 0; - Attrib a, *aa; + Attrib a, aa; char path_buf[PATH_MAX]; int err = 0; glob_t g; @@ -1558,23 +1570,24 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, rflag, aflag, fflag); break; case I_COPY: - path1 = make_absolute(path1, *pwd); - path2 = make_absolute(path2, *pwd); - err = do_copy(conn, path1, path2); + path1 = sftp_make_absolute(path1, *pwd); + path2 = sftp_make_absolute(path2, *pwd); + err = sftp_copy(conn, path1, path2); break; case I_RENAME: - path1 = make_absolute(path1, *pwd); - path2 = make_absolute(path2, *pwd); - err = do_rename(conn, path1, path2, lflag); + path1 = sftp_make_absolute(path1, *pwd); + path2 = sftp_make_absolute(path2, *pwd); + err = sftp_rename(conn, path1, path2, lflag); break; case I_SYMLINK: sflag = 1; /* FALLTHROUGH */ case I_LINK: if (!sflag) - path1 = make_absolute(path1, *pwd); - path2 = make_absolute(path2, *pwd); - err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2); + path1 = sftp_make_absolute(path1, *pwd); + path2 = sftp_make_absolute(path2, *pwd); + err = (sflag ? sftp_symlink : sftp_hardlink)(conn, + path1, path2); break; case I_RM: path1 = make_absolute_pwd_glob(path1, *pwd); @@ -1582,42 +1595,42 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!quiet) mprintf("Removing %s\n", g.gl_pathv[i]); - err = do_rm(conn, g.gl_pathv[i]); + err = sftp_rm(conn, g.gl_pathv[i]); if (err != 0 && err_abort) break; } break; case I_MKDIR: - path1 = make_absolute(path1, *pwd); + path1 = sftp_make_absolute(path1, *pwd); attrib_clear(&a); a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = 0777; - err = do_mkdir(conn, path1, &a, 1); + err = sftp_mkdir(conn, path1, &a, 1); break; case I_RMDIR: - path1 = make_absolute(path1, *pwd); - err = do_rmdir(conn, path1); + path1 = sftp_make_absolute(path1, *pwd); + err = sftp_rmdir(conn, path1); break; case I_CHDIR: if (path1 == NULL || *path1 == '\0') path1 = xstrdup(startdir); - path1 = make_absolute(path1, *pwd); - if ((tmp = do_realpath(conn, path1)) == NULL) { + path1 = sftp_make_absolute(path1, *pwd); + if ((tmp = sftp_realpath(conn, path1)) == NULL) { err = 1; break; } - if ((aa = do_stat(conn, tmp, 0)) == NULL) { + if (sftp_stat(conn, tmp, 0, &aa) != 0) { free(tmp); err = 1; break; } - if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { + if (!(aa.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { error("Can't change directory: Can't check target"); free(tmp); err = 1; break; } - if (!S_ISDIR(aa->perm)) { + if (!S_ISDIR(aa.perm)) { error("Can't change directory: \"%s\" is not " "a directory", tmp); free(tmp); @@ -1645,7 +1658,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, /* Default to current directory if no path specified */ if (path1 == NULL) path1 = xstrdup(*pwd); - path1 = make_absolute(path1, *pwd); + path1 = sftp_make_absolute(path1, *pwd); err = do_df(conn, path1, hflag, iflag); break; case I_LCHDIR: @@ -1687,7 +1700,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, if (!quiet) mprintf("Changing mode on %s\n", g.gl_pathv[i]); - err = (hflag ? do_lsetstat : do_setstat)(conn, + err = (hflag ? sftp_lsetstat : sftp_setstat)(conn, g.gl_pathv[i], &a); if (err != 0 && err_abort) break; @@ -1698,15 +1711,15 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, path1 = make_absolute_pwd_glob(path1, *pwd); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { - if (!(aa = (hflag ? do_lstat : do_stat)(conn, - g.gl_pathv[i], 0))) { + if ((hflag ? sftp_lstat : sftp_stat)(conn, + g.gl_pathv[i], 0, &aa) != 0) { if (err_abort) { err = -1; break; } else continue; } - if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { + if (!(aa.flags & SSH2_FILEXFER_ATTR_UIDGID)) { error("Can't get current ownership of " "remote file \"%s\"", g.gl_pathv[i]); if (err_abort) { @@ -1715,20 +1728,20 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, } else continue; } - aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; + aa.flags &= SSH2_FILEXFER_ATTR_UIDGID; if (cmdnum == I_CHOWN) { if (!quiet) mprintf("Changing owner on %s\n", g.gl_pathv[i]); - aa->uid = n_arg; + aa.uid = n_arg; } else { if (!quiet) mprintf("Changing group on %s\n", g.gl_pathv[i]); - aa->gid = n_arg; + aa.gid = n_arg; } - err = (hflag ? do_lsetstat : do_setstat)(conn, - g.gl_pathv[i], aa); + err = (hflag ? sftp_lsetstat : sftp_setstat)(conn, + g.gl_pathv[i], &aa); if (err != 0 && err_abort) break; } @@ -2203,16 +2216,15 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL); } - remote_path = do_realpath(conn, "."); - if (remote_path == NULL) + if ((remote_path = sftp_realpath(conn, ".")) == NULL) fatal("Need cwd"); startdir = xstrdup(remote_path); if (file1 != NULL) { dir = xstrdup(file1); - dir = make_absolute(dir, remote_path); + dir = sftp_make_absolute(dir, remote_path); - if (remote_is_dir(conn, dir) && file2 == NULL) { + if (sftp_remote_is_dir(conn, dir) && file2 == NULL) { if (!quiet) mprintf("Changing to: %s\n", dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); @@ -2603,7 +2615,7 @@ main(int argc, char **argv) } freeargs(&args); - conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps); + conn = sftp_init(in, out, copy_buffer_len, num_requests, limit_kbps); if (conn == NULL) fatal("Couldn't initialise connection to server"); diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c index 430bb3565..2377697bc 100644 --- a/usr.bin/tmux/format.c +++ b/usr.bin/tmux/format.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.317 2023/08/17 14:10:28 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.318 2023/09/08 06:52:31 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -1126,7 +1126,6 @@ format_cb_mouse_word(struct format_tree *ft) struct window_pane *wp; struct grid *gd; u_int x, y; - char *s; if (!ft->m.valid) return (NULL); @@ -1139,7 +1138,7 @@ format_cb_mouse_word(struct format_tree *ft) if (!TAILQ_EMPTY(&wp->modes)) { if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode || TAILQ_FIRST(&wp->modes)->mode == &window_view_mode) - return (s = window_copy_get_word(wp, x, y)); + return (window_copy_get_word(wp, x, y)); return (NULL); } gd = wp->base.grid; @@ -4185,7 +4184,7 @@ static char * format_loop_clients(struct format_expand_state *es, const char *fmt) { struct format_tree *ft = es->ft; - struct client *c = ft->client; + struct client *c; struct cmdq_item *item = ft->item; struct format_tree *nft; struct format_expand_state next; diff --git a/usr.bin/tmux/tty-keys.c b/usr.bin/tmux/tty-keys.c index 63d9eca59..da6358c71 100644 --- a/usr.bin/tmux/tty-keys.c +++ b/usr.bin/tmux/tty-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-keys.c,v 1.170 2023/09/07 10:21:46 nicm Exp $ */ +/* $OpenBSD: tty-keys.c,v 1.172 2023/09/08 07:05:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1315,15 +1315,21 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, } /* - * Add terminal features. Technically, VT420 and VT525 do not support - * SIXEL, but some modern terminals report it anyway so we accept it - * here too. + * Add terminal features. Hardware level 5 does not offer SIXEL but + * some terminal emulators report it anyway and it does not harm + * to check it here. + * + * DECSLRM and DECFRA should be supported by level 5 as well as level + * 4, but VTE has rather ruined it by advertising level 5 despite not + * supporting them. */ switch (p[0]) { - case 62: /* VT220 */ - case 63: /* VT320 */ - case 64: /* VT420 */ - case 65: /* VT525 */ + case 64: /* level 4 */ + tty_add_features(features, "margins,rectfill", ","); + /* FALLTHROUGH */ + case 62: /* level 2 */ + case 63: /* level 3 */ + case 65: /* level 5 */ for (i = 1; i < n; i++) { log_debug("%s: DA feature: %d", c->name, p[i]); if (p[i] == 4) @@ -1393,12 +1399,15 @@ tty_keys_device_attributes2(struct tty *tty, const char *buf, size_t len, break; } - /* Add terminal features. */ + /* + * Add terminal features. We add DECSLRM and DECFRA for some + * identification codes here, notably 64 will catch VT520, even though + * we can't use level 5 from DA because of VTE. + */ switch (p[0]) { case 41: /* VT420 */ case 61: /* VT510 */ case 64: /* VT520 */ - case 65: /* VT525 */ tty_add_features(features, "margins,rectfill", ","); break; case 'M': /* mintty */ diff --git a/usr.sbin/radiusd/Makefile b/usr.sbin/radiusd/Makefile index 315e14901..cdfb12a2e 100644 --- a/usr.sbin/radiusd/Makefile +++ b/usr.sbin/radiusd/Makefile @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile,v 1.1 2015/07/21 04:06:04 yasuoka Exp $ +# $OpenBSD: Makefile,v 1.2 2023/09/08 05:56:22 yasuoka Exp $ SUBDIR= radiusd SUBDIR+= radiusd_bsdauth SUBDIR+= radiusd_radius +SUBDIR+= radiusd_standard .include diff --git a/usr.sbin/radiusd/parse.y b/usr.sbin/radiusd/parse.y index ef17ae1e7..a382dd499 100644 --- a/usr.sbin/radiusd/parse.y +++ b/usr.sbin/radiusd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.16 2023/09/05 00:32:01 yasuoka Exp $ */ +/* $OpenBSD: parse.y,v 1.17 2023/09/08 05:56:22 yasuoka Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -349,7 +349,6 @@ authopt : AUTHENTICATE_BY STRING { YYERROR; authen.auth = modref; } - /* XXX decoration doesn't work for this moment. */ | DECORATE_BY str_l { int i; struct radiusd_module_ref *modref; diff --git a/usr.sbin/radiusd/radiusd.c b/usr.sbin/radiusd/radiusd.c index 8e63f9783..22fd6b505 100644 --- a/usr.sbin/radiusd/radiusd.c +++ b/usr.sbin/radiusd/radiusd.c @@ -1,7 +1,7 @@ -/* $OpenBSD: radiusd.c,v 1.31 2023/09/05 00:32:01 yasuoka Exp $ */ +/* $OpenBSD: radiusd.c,v 1.32 2023/09/08 05:56:22 yasuoka Exp $ */ /* - * Copyright (c) 2013 Internet Initiative Japan Inc. + * Copyright (c) 2013, 2023 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 @@ -17,13 +17,14 @@ */ #include -#include +#include +#include #include +#include +#include #include #include -#include -#include #include #include #include @@ -40,7 +41,6 @@ #include #include #include -#include #include @@ -58,9 +58,8 @@ static void radiusd_on_sigterm(int, short, void *); static void radiusd_on_sigint(int, short, void *); static void radiusd_on_sighup(int, short, void *); static void radiusd_on_sigchld(int, short, void *); -static int radius_query_request_decoration(struct radius_query *); -static int radius_query_response_decoration( - struct radius_query *); +static void radius_query_request(struct radius_query *); +static void radius_query_response(struct radius_query *); static const char *radius_code_string(int); static int radiusd_access_response_fixup (struct radius_query *); @@ -84,6 +83,12 @@ static void radiusd_module_userpass(struct radiusd_module *, struct radius_query *); static void radiusd_module_access_request(struct radiusd_module *, struct radius_query *); +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 int imsg_compose_radius_packet(struct imsgbuf *, + uint32_t, u_int, RADIUS_PACKET *); static u_int radius_query_id_seq = 0; int debug = 0; @@ -482,6 +487,7 @@ radiusd_listen_on_event(int fd, short evmask, void *ctx) goto found; } } +found: if (authen == NULL) { log_warnx("Received %s(code=%d) from %s id=%d " "username=%s: no `authenticate' matches.", @@ -489,7 +495,6 @@ radiusd_listen_on_event(int fd, short evmask, void *ctx) req_id, username); goto on_error; } -found: RADIUSD_ASSERT(authen->auth != NULL); if (!MODULE_DO_USERPASS(authen->auth->module) && @@ -515,25 +520,13 @@ found: q->req_id = req_id; radius_get_authenticator(packet, q->req_auth); - if (radius_query_request_decoration(q) != 0) { - log_warnx( - "Received %s(code=%d) from %s id=%d username=%s " - "q=%u: failed to decorate the request", - radius_code_string(req_code), req_code, peerstr, - q->req_id, q->username, q->id); - radiusd_access_request_aborted(q); - return; - } log_info("Received %s(code=%d) from %s id=%d username=%s " "q=%u: `%s' authentication is starting", radius_code_string(req_code), req_code, peerstr, q->req_id, q->username, q->id, q->authen->auth->module->name); TAILQ_INSERT_TAIL(&listn->radiusd->query, q, next); - if (MODULE_DO_ACCSREQ(authen->auth->module)) { - radiusd_module_access_request(authen->auth->module, q); - } else if (MODULE_DO_USERPASS(authen->auth->module)) - radiusd_module_userpass(authen->auth->module, q); + radius_query_request(q); return; } @@ -546,77 +539,52 @@ on_error: return; } -static int -radius_query_request_decoration(struct radius_query *q) +static void +radius_query_request(struct radius_query *q) { - struct radiusd_module_ref *deco; + struct radiusd_authentication *authen = q->authen; - TAILQ_FOREACH(deco, &q->authen->deco, next) { - /* XXX decoration doesn't work for this moment. */ - if (deco->module->request_decoration != NULL && - deco->module->request_decoration(NULL, q) != 0) { - log_warnx("q=%u request decoration `%s' failed", q->id, - deco->module->name); - return (-1); - } + /* first or next request decoration */ + for (;;) { + if (q->deco == NULL) + q->deco = TAILQ_FIRST(&q->authen->deco); + else + q->deco = TAILQ_NEXT(q->deco, next); + if (q->deco == NULL || MODULE_DO_REQDECO(q->deco->module)) + break; } - return (0); -} - -static int -radius_query_response_decoration(struct radius_query *q) -{ - struct radiusd_module_ref *deco; - - TAILQ_FOREACH(deco, &q->authen->deco, next) { - /* XXX decoration doesn't work for this moment. */ - if (deco->module->response_decoration != NULL && - deco->module->response_decoration(NULL, q) != 0) { - log_warnx("q=%u response decoration `%s' failed", q->id, - deco->module->name); - return (-1); - } + if (q->deco != NULL) + radiusd_module_request_decoration(q->deco->module, q); + else { + RADIUSD_ASSERT(authen->auth != NULL); + if (MODULE_DO_ACCSREQ(authen->auth->module)) + radiusd_module_access_request(authen->auth->module, q); + else if (MODULE_DO_USERPASS(authen->auth->module)) + radiusd_module_userpass(authen->auth->module, q); } - - return (0); } -/*********************************************************************** - * Callback functions from the modules - ***********************************************************************/ -void -radiusd_access_request_answer(struct radius_query *q) +static void +radius_query_response(struct radius_query *q) { int sz, res_id, res_code; char buf[NI_MAXHOST + NI_MAXSERV + 30]; - const char *authen_secret = q->authen->auth->module->secret; - radius_set_request_packet(q->res, q->req); - - if (authen_secret == NULL) { - /* - * The module couldn't check the authenticators - */ - if (radius_check_response_authenticator(q->res, - q->client->secret) != 0) { - log_info("Response from module has bad response " - "authenticator: id=%d", q->id); - goto on_error; - } - if (radius_has_attr(q->res, - RADIUS_TYPE_MESSAGE_AUTHENTICATOR) && - radius_check_message_authenticator(q->res, - q->client->secret) != 0) { - log_info("Response from module has bad message " - "authenticator: id=%d", q->id); - goto on_error; - } + /* first or next response decoration */ + for (;;) { + if (q->deco == NULL) + q->deco = TAILQ_FIRST(&q->authen->deco); + else + q->deco = TAILQ_NEXT(q->deco, next); + if (q->deco == NULL || MODULE_DO_RESDECO(q->deco->module)) + break; } - /* Decorate the response */ - if (radius_query_response_decoration(q) != 0) - goto on_error; + if (q->deco != NULL) { + radiusd_module_response_decoration(q->deco->module, q); + return; + } if (radiusd_access_response_fixup(q) != 0) goto on_error; @@ -641,6 +609,45 @@ radiusd_access_request_answer(struct radius_query *q) log_warn("Sending a RADIUS response failed"); on_error: radiusd_access_request_aborted(q); + +} + +/*********************************************************************** + * Callback functions from the modules + ***********************************************************************/ +void +radiusd_access_request_answer(struct radius_query *q) +{ + const char *authen_secret = q->authen->auth->module->secret; + + radius_set_request_packet(q->res, q->req); + + if (authen_secret == NULL) { + /* + * The module diddn't check the authenticators + */ + if (radius_check_response_authenticator(q->res, + q->client->secret) != 0) { + log_info("Response from module has bad response " + "authenticator: id=%d", q->id); + goto on_error; + } + if (radius_has_attr(q->res, + RADIUS_TYPE_MESSAGE_AUTHENTICATOR) && + radius_check_message_authenticator(q->res, + q->client->secret) != 0) { + log_info("Response from module has bad message " + "authenticator: id=%d", q->id); + goto on_error; + } + } + + RADIUSD_ASSERT(q->deco == NULL); + radius_query_response(q); + + return; +on_error: + radiusd_access_request_aborted(q); } void @@ -754,23 +761,6 @@ radiusd_conf_init(struct radiusd *conf) TAILQ_INIT(&conf->authen); TAILQ_INIT(&conf->client); - /* - * TODO: load the standard modules - */ -#if 0 -static struct radiusd_module *radiusd_standard_modules[] = { - NULL -}; - - u_int i; - struct radiusd_module *module; - for (i = 0; radiusd_standard_modules[i] != NULL; i++) { - module = radiusd_create_module_class( - radiusd_standard_modules[i]); - TAILQ_INSERT_TAIL(&conf->module, module, next); - } -#endif - return; } @@ -793,6 +783,9 @@ radiusd_access_response_fixup(struct radius_query *q) const char *olds = q->client->secret; const char *news = authen_secret; + if (news == NULL) + news = olds; + /* RFC 2865 Tunnel-Password */ attrlen = sizeof(attrlen); if (radius_get_raw_attr(q->res, RADIUS_TYPE_TUNNEL_PASSWORD, @@ -1238,28 +1231,77 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg) break; } case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER: + case IMSG_RADIUSD_MODULE_REQDECO_DONE: + case IMSG_RADIUSD_MODULE_RESDECO_DONE: { static struct radiusd_module_radpkt_arg *ans; + const char *typestr = "unknown"; + + switch (imsg->hdr.type) { + case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER: + typestr = "ACCSREQ_ANSWER"; + break; + case IMSG_RADIUSD_MODULE_REQDECO_DONE: + typestr = "REQDECO_DONE"; + break; + case IMSG_RADIUSD_MODULE_RESDECO_DONE: + typestr = "RESDECO_DONE"; + break; + } + if (datalen < (ssize_t)sizeof(struct radiusd_module_radpkt_arg)) { - log_warnx("Received ACCSREQ_ANSWER message, but " - "length is wrong"); + log_warnx("Received %s message, but length is wrong", + typestr); break; } q_id = ((struct radiusd_module_radpkt_arg *)imsg->data)->q_id; q = radiusd_find_query(module->radiusd, q_id); if (q == NULL) { - log_warnx("Received ACCSREQ_ANSWER from %s, but query " - "id=%u unknown", module->name, q_id); + log_warnx("Received %s from %s, but query id=%u " + "unknown", typestr, module->name, q_id); break; } if ((ans = radiusd_module_recv_radpkt(module, imsg, - IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER, - "ACCSREQ_ANSWER")) != NULL) { - q->res = radius_convert_packet( - module->radpkt, module->radpktoff); - radiusd_access_request_answer(q); + imsg->hdr.type, typestr)) != NULL) { + RADIUS_PACKET *radpkt = NULL; + + if (module->radpktoff > 0 && + (radpkt = radius_convert_packet( + module->radpkt, module->radpktoff)) == NULL) { + log_warn("q=%u radius_convert_packet() failed", + q->id); + radiusd_access_request_aborted(q); + break; + } module->radpktoff = 0; + switch (imsg->hdr.type) { + case IMSG_RADIUSD_MODULE_REQDECO_DONE: + if (radpkt != NULL) { + radius_delete_packet(q->req); + q->req = radpkt; + } + radius_query_request(q); + break; + case IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER: + if (radpkt == NULL) { + log_warn("q=%u wrong pkt from module", + q->id); + radiusd_access_request_aborted(q); + } + q->res = radpkt; + radiusd_access_request_answer(q); + break; + case IMSG_RADIUSD_MODULE_RESDECO_DONE: + if (radpkt != NULL) { + radius_delete_packet(q->res); + radius_set_request_packet(radpkt, + q->req); + q->res = radpkt; + } + radius_query_response(q); + break; + } } break; } @@ -1276,8 +1318,8 @@ radiusd_module_imsg(struct radiusd_module *module, struct imsg *imsg) break; } default: - RADIUSD_DBG(("Unhandled imsg type=%d", - imsg->hdr.type)); + RADIUSD_DBG(("Unhandled imsg type=%d from %s", imsg->hdr.type, + module->name)); } } @@ -1306,9 +1348,11 @@ radiusd_module_recv_radpkt(struct radiusd_module *module, struct imsg *imsg, "received length is too big", type_str, module->name); goto on_fail; } - memcpy(module->radpkt + module->radpktoff, - (caddr_t)(ans + 1), chunklen); - module->radpktoff += chunklen; + if (chunklen > 0) { + memcpy(module->radpkt + module->radpktoff, + (caddr_t)(ans + 1), chunklen); + module->radpktoff += chunklen; + } if (!ans->final) return (NULL); /* again */ if (module->radpktoff != ans->pktlen) { @@ -1427,11 +1471,9 @@ radiusd_module_userpass(struct radiusd_module *module, struct radius_query *q) userpass.has_pass = true; else userpass.has_pass = false; - - if (strlcpy(userpass.user, q->username, sizeof(userpass.user)) - >= sizeof(userpass.user)) { - log_warnx("Could request USERPASS to module `%s': " - "User-Name too long", module->name); + if (radius_get_string_attr(q->req, RADIUS_TYPE_USER_NAME, + userpass.user, sizeof(userpass.user)) != 0) { + log_warnx("q=%u no User-Name attribute", q->id); goto on_error; } imsg_compose(&module->ibuf, IMSG_RADIUSD_MODULE_USERPASS, 0, 0, -1, @@ -1446,16 +1488,14 @@ static void radiusd_module_access_request(struct radiusd_module *module, struct radius_query *q) { - struct radiusd_module_radpkt_arg accsreq; - struct iovec iov[2]; - int off = 0, len, siz; - const u_char *pkt; RADIUS_PACKET *radpkt; char pass[256]; if ((radpkt = radius_convert_packet(radius_get_data(q->req), radius_get_length(q->req))) == NULL) { - log_warn("Could not send ACCSREQ for `%s'", module->name); + log_warn("q=%u Could not send ACCSREQ to `%s'", q->id, + module->name); + radiusd_access_request_aborted(q); return; } if (q->client->secret[0] != '\0' && module->secret != NULL && @@ -1465,30 +1505,85 @@ radiusd_module_access_request(struct radiusd_module *module, (void)radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD, pass, strlen(pass)); } - - pkt = radius_get_data(radpkt); - len = radius_get_length(radpkt); - memset(&accsreq, 0, sizeof(accsreq)); - accsreq.q_id = q->id; - accsreq.pktlen = len; - while (off < len) { - siz = MAX_IMSGSIZE - sizeof(accsreq); - if (len - off > siz) - accsreq.final = false; - else { - accsreq.final = true; - siz = len - off; - } - iov[0].iov_base = &accsreq; - iov[0].iov_len = sizeof(accsreq); - iov[1].iov_base = (caddr_t)pkt + off; - iov[1].iov_len = siz; - imsg_composev(&module->ibuf, IMSG_RADIUSD_MODULE_ACCSREQ, 0, 0, - -1, iov, 2); - off += siz; + if (imsg_compose_radius_packet(&module->ibuf, + IMSG_RADIUSD_MODULE_ACCSREQ, q->id, radpkt) == -1) { + log_warn("q=%u Could not send ACCSREQ to `%s'", q->id, + module->name); + radiusd_access_request_aborted(q); } radiusd_module_reset_ev_handler(module); radius_delete_packet(radpkt); - - return; +} + +static void +radiusd_module_request_decoration(struct radiusd_module *module, + struct radius_query *q) +{ + if (module->fd < 0) { + log_warnx("q=%u Could not send REQDECO to `%s': module is " + "not running?", q->id, module->name); + radiusd_access_request_aborted(q); + return; + } + if (imsg_compose_radius_packet(&module->ibuf, + IMSG_RADIUSD_MODULE_REQDECO, q->id, q->req) == -1) { + log_warn("q=%u Could not send REQDECO to `%s'", q->id, + module->name); + radiusd_access_request_aborted(q); + return; + } + radiusd_module_reset_ev_handler(module); +} + +static void +radiusd_module_response_decoration(struct radiusd_module *module, + struct radius_query *q) +{ + if (module->fd < 0) { + log_warnx("q=%u Could not send RESDECO to `%s': module is " + "not running?", q->id, module->name); + radiusd_access_request_aborted(q); + return; + } + if (imsg_compose_radius_packet(&module->ibuf, + IMSG_RADIUSD_MODULE_RESDECO, q->id, q->res) == -1) { + log_warn("q=%u Could not send RESDECO to `%s'", q->id, + module->name); + radiusd_access_request_aborted(q); + return; + } + radiusd_module_reset_ev_handler(module); +} + +static int +imsg_compose_radius_packet(struct imsgbuf *ibuf, uint32_t type, u_int q_id, + RADIUS_PACKET *radpkt) +{ + struct radiusd_module_radpkt_arg arg; + int off = 0, len, siz; + struct iovec iov[2]; + const u_char *pkt; + + pkt = radius_get_data(radpkt); + len = radius_get_length(radpkt); + memset(&arg, 0, sizeof(arg)); + arg.q_id = q_id; + arg.pktlen = len; + while (off < len) { + siz = MAX_IMSGSIZE - sizeof(arg); + if (len - off > siz) + arg.final = false; + else { + arg.final = true; + siz = len - off; + } + iov[0].iov_base = &arg; + iov[0].iov_len = sizeof(arg); + iov[1].iov_base = (caddr_t)pkt + off; + iov[1].iov_len = siz; + if (imsg_composev(ibuf, type, 0, 0, -1, iov, 2) == -1) + return (-1); + off += siz; + } + return (0); } diff --git a/usr.sbin/radiusd/radiusd.conf.5 b/usr.sbin/radiusd/radiusd.conf.5 index b2bd3f9d0..f1271f1ca 100644 --- a/usr.sbin/radiusd/radiusd.conf.5 +++ b/usr.sbin/radiusd/radiusd.conf.5 @@ -1,7 +1,7 @@ -.\" $OpenBSD: radiusd.conf.5,v 1.16 2023/09/04 12:28:18 yasuoka Exp $ +.\" $OpenBSD: radiusd.conf.5,v 1.17 2023/09/08 05:56:22 yasuoka Exp $ .\" .\" Copyright (c) 2014 Esdenera Networks GmbH -.\" Copyright (c) 2014 Internet Initiative Japan Inc. +.\" Copyright (c) 2014, 2023 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 @@ -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 4 2023 $ +.Dd $Mdocdate: September 8 2023 $ .Dt RADIUSD.CONF 5 .Os .Sh NAME @@ -68,6 +68,7 @@ The following modules are available: .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 .Bl -tag -width Ds .It Do bsdauth Dc module @@ -83,6 +84,11 @@ It only supports PAP, password based authentication. The .Dq radius module provides authentication from upstream RADIUS servers. +.It Do standard Dc module +The +.Dq standard +module provides standard decorations for Access-Request messages or its +response messages. .El .It Ic module set Ar module key value ... Configure the module specific configurations by @@ -146,6 +152,34 @@ 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 .Ar username-pattern . @@ -162,6 +196,8 @@ 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 .El .Sh FILES @@ -182,28 +218,32 @@ module executable. .Sh EXAMPLES .Bd -literal -offset indent listen on 0.0.0.0 -#listen on :: +listen on :: client 127.0.0.1/32 { secret "secret" + msgauth-required no } client 192.168.0.0/24 { secret "secret" - msgauth-required yes } module load bsdauth "/usr/libexec/radiusd/radiusd_bsdauth" -module set bsdauth restrict-group "operator" +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" -authenticate *@example.com { - authenticate-by radius +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 bsdauth + authenticate-by radius } .Ed .Sh SEE ALSO diff --git a/usr.sbin/radiusd/radiusd.h b/usr.sbin/radiusd/radiusd.h index 3d2676e8a..87ea9dd79 100644 --- a/usr.sbin/radiusd/radiusd.h +++ b/usr.sbin/radiusd/radiusd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: radiusd.h,v 1.4 2019/04/03 11:54:56 yasuoka Exp $ */ +/* $OpenBSD: radiusd.h,v 1.5 2023/09/08 05:56:22 yasuoka Exp $ */ #ifndef RADIUSD_H #define RADIUSD_H 1 @@ -17,6 +17,8 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include #define RADIUSD_MODULE_NAME_LEN 32 @@ -38,6 +40,10 @@ enum imsg_type { /* Check the response's authenticator if the module doesn't */ IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER, IMSG_RADIUSD_MODULE_ACCSREQ_ABORTED, + IMSG_RADIUSD_MODULE_REQDECO, + IMSG_RADIUSD_MODULE_REQDECO_DONE, + IMSG_RADIUSD_MODULE_RESDECO, + IMSG_RADIUSD_MODULE_RESDECO_DONE, IMSG_RADIUSD_MODULE_STOP }; @@ -46,6 +52,8 @@ 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 }; struct radiusd_module_object { diff --git a/usr.sbin/radiusd/radiusd_local.h b/usr.sbin/radiusd/radiusd_local.h index 4c9f1d2fd..2704ecc27 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.5 2019/04/01 11:05:41 yasuoka Exp $ */ +/* $OpenBSD: radiusd_local.h,v 1.6 2023/09/08 05:56:22 yasuoka Exp $ */ /* * Copyright (c) 2013 Internet Initiative Japan Inc. @@ -122,6 +122,7 @@ struct radius_query { int req_modified; char username[256]; /* original username */ TAILQ_ENTRY(radius_query) next; + struct radiusd_module_ref *deco; }; #ifndef nitems #define nitems(_x) (sizeof((_x)) / sizeof((_x)[0])) @@ -149,6 +150,12 @@ struct radius_query { #define MODULE_DO_ACCSREQ(_m) \ ((_m)->fd >= 0 && \ ((_m)->capabilities & RADIUSD_MODULE_CAP_ACCSREQ) != 0) +#define MODULE_DO_REQDECO(_m) \ + ((_m)->fd >= 0 && \ + ((_m)->capabilities & RADIUSD_MODULE_CAP_REQDECO) != 0) +#define MODULE_DO_RESDECO(_m) \ + ((_m)->fd >= 0 && \ + ((_m)->capabilities & RADIUSD_MODULE_CAP_RESDECO) != 0) extern struct radiusd_module mod_standard; extern struct radiusd_module mod_radius; diff --git a/usr.sbin/radiusd/radiusd_module.c b/usr.sbin/radiusd/radiusd_module.c index f38170af9..02d9b5242 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.13 2019/06/28 13:32:49 deraadt Exp $ */ +/* $OpenBSD: radiusd_module.c,v 1.14 2023/09/08 05:56:22 yasuoka Exp $ */ /* * Copyright (c) 2015 YASUOKA Masahiko @@ -46,6 +46,10 @@ static void (*module_userpass) (void *, u_int, const char *, const char *) = NULL; static void (*module_access_request) (void *, u_int, const u_char *, size_t) = NULL; +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) = NULL; struct module_base { void *ctx; @@ -73,7 +77,6 @@ static int module_imsg_handler(struct module_base *, struct imsg *); #ifdef USE_LIBEVENT static void module_on_event(int, short, void *); #endif -static void module_stop(struct module_base *); static void module_reset_event(struct module_base *); struct module_base * @@ -90,6 +93,8 @@ module_create(int sock, void *ctx, struct module_handlers *handler) module_userpass = handler->userpass; module_access_request = handler->access_request; module_config_set = handler->config_set; + module_request_decoration = handler->request_decoration; + module_response_decoration = handler->response_decoration; module_start_module = handler->start; module_stop_module = handler->stop; @@ -140,6 +145,10 @@ module_load(struct module_base *base) load.cap |= RADIUSD_MODULE_CAP_USERPASS; if (module_access_request != NULL) load.cap |= RADIUSD_MODULE_CAP_ACCSREQ; + if (module_request_decoration != NULL) + load.cap |= RADIUSD_MODULE_CAP_REQDECO; + if (module_response_decoration != NULL) + load.cap |= RADIUSD_MODULE_CAP_RESDECO; imsg_compose(&base->ibuf, IMSG_RADIUSD_MODULE_LOAD, 0, 0, -1, &load, sizeof(load)); imsg_flush(&base->ibuf); @@ -260,6 +269,22 @@ module_accsreq_aborted(struct module_base *base, u_int q_id) return (ret); } +int +module_reqdeco_done(struct module_base *base, u_int q_id, const u_char *pkt, + size_t pktlen) +{ + return (module_common_radpkt(base, IMSG_RADIUSD_MODULE_REQDECO_DONE, + q_id, pkt, pktlen)); +} + +int +module_resdeco_done(struct module_base *base, u_int q_id, const u_char *pkt, + size_t pktlen) +{ + return (module_common_radpkt(base, IMSG_RADIUSD_MODULE_RESDECO_DONE, + q_id, pkt, pktlen)); +} + static int module_common_radpkt(struct module_base *base, uint32_t imsg_type, u_int q_id, const u_char *pkt, size_t pktlen) @@ -271,19 +296,22 @@ module_common_radpkt(struct module_base *base, uint32_t imsg_type, u_int q_id, len = pktlen; ans.q_id = q_id; ans.pktlen = pktlen; - while (off < len) { + ans.final = false; + + while (!ans.final) { siz = MAX_IMSGSIZE - sizeof(ans); - if (len - off > siz) - ans.final = false; - else { + if (len - off <= siz) { ans.final = true; siz = len - off; } iov[0].iov_base = &ans; iov[0].iov_len = sizeof(ans); - iov[1].iov_base = (u_char *)pkt + off; - iov[1].iov_len = siz; - ret = imsg_composev(&base->ibuf, imsg_type, 0, 0, -1, iov, 2); + if (siz > 0) { + iov[1].iov_base = (u_char *)pkt + off; + iov[1].iov_len = siz; + } + ret = imsg_composev(&base->ibuf, imsg_type, 0, 0, -1, iov, + (siz > 0)? 2 : 1); if (ret == -1) break; off += siz; @@ -305,7 +333,6 @@ module_recv_imsg(struct module_base *base) module_stop(base); return (-1); } - for (;;) { if ((n = imsg_get(&base->ibuf, &imsg)) == -1) { syslog(LOG_ERR, "%s: imsg_get(): %m", __func__); @@ -410,19 +437,40 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg) break; } case IMSG_RADIUSD_MODULE_ACCSREQ: + case IMSG_RADIUSD_MODULE_REQDECO: + case IMSG_RADIUSD_MODULE_RESDECO: { struct radiusd_module_radpkt_arg *accessreq; int chunklen; + const char *typestr; - if (module_access_request == NULL) { - syslog(LOG_ERR, "Received ACCSREQ message, but " - "module doesn't support"); - break; + if (imsg->hdr.type == IMSG_RADIUSD_MODULE_ACCSREQ) { + if (module_access_request == NULL) { + syslog(LOG_ERR, "Received ACCSREQ message, but " + "module doesn't support"); + break; + } + typestr = "ACCSREQ"; + } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_REQDECO) { + if (module_request_decoration == NULL) { + syslog(LOG_ERR, "Received REQDECO message, but " + "module doesn't support"); + break; + } + typestr = "REQDECO"; + } else { + if (module_response_decoration == NULL) { + syslog(LOG_ERR, "Received RESDECO message, but " + "module doesn't support"); + break; + } + typestr = "RESDECO"; } + if (datalen < (ssize_t)sizeof(struct radiusd_module_radpkt_arg)) { - syslog(LOG_ERR, "Received ACCSREQ message, but " - "length is wrong"); + syslog(LOG_ERR, "Received %s message, but " + "length is wrong", typestr); break; } accessreq = (struct radiusd_module_radpkt_arg *)imsg->data; @@ -431,7 +479,7 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg) if ((nradpkt = realloc(base->radpkt, accessreq->pktlen)) == NULL) { syslog(LOG_ERR, "Could not handle received " - "ACCSREQ message: %m"); + "%s message: %m", typestr); base->radpktoff = 0; goto accsreq_out; } @@ -441,8 +489,8 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg) chunklen = datalen - sizeof(struct radiusd_module_radpkt_arg); if (chunklen > base->radpktsiz - base->radpktoff){ syslog(LOG_ERR, - "Could not handle received ACCSREQ message: " - "received length is too big"); + "Could not handle received %s message: " + "received length is too big", typestr); base->radpktoff = 0; goto accsreq_out; } @@ -453,13 +501,20 @@ module_imsg_handler(struct module_base *base, struct imsg *imsg) goto accsreq_out; if (base->radpktoff != accessreq->pktlen) { syslog(LOG_ERR, - "Could not handle received ACCSREQ " - "message: length is mismatch"); + "Could not handle received %s " + "message: length is mismatch", typestr); base->radpktoff = 0; goto accsreq_out; } - module_access_request(base->ctx, accessreq->q_id, - base->radpkt, base->radpktoff); + if (imsg->hdr.type == IMSG_RADIUSD_MODULE_ACCSREQ) + module_access_request(base->ctx, accessreq->q_id, + base->radpkt, base->radpktoff); + else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_REQDECO) + module_request_decoration(base->ctx, accessreq->q_id, + base->radpkt, base->radpktoff); + else + module_response_decoration(base->ctx, accessreq->q_id, + base->radpkt, base->radpktoff); base->radpktoff = 0; accsreq_out: break; @@ -469,7 +524,7 @@ accsreq_out: return (0); } -static void +void module_stop(struct module_base *base) { if (module_stop_module != NULL) diff --git a/usr.sbin/radiusd/radiusd_module.h b/usr.sbin/radiusd/radiusd_module.h index 647cfcf7e..42380eac2 100644 --- a/usr.sbin/radiusd/radiusd_module.h +++ b/usr.sbin/radiusd/radiusd_module.h @@ -35,8 +35,13 @@ struct module_handlers { void (*access_request)(void *ctx, u_int query_id, const u_char *pkt, size_t pktlen); - /* User-Password Attribute is encrypted if the module has the secret */ + + void (*request_decoration)(void *ctx, u_int query_id, const u_char *pkt, + size_t pktlen); + + void (*response_decoration)(void *ctx, u_int query_id, + const u_char *pkt, size_t pktlen); }; #define SYNTAX_ASSERT(_cond, _msg) \ @@ -51,6 +56,7 @@ __BEGIN_DECLS struct module_base *module_create(int, void *, struct module_handlers *); void module_start(struct module_base *); +void module_stop(struct module_base *); int module_run(struct module_base *); void module_destroy(struct module_base *); void module_load(struct module_base *); @@ -67,6 +73,10 @@ int module_userpass_fail(struct module_base *, u_int, int module_accsreq_answer(struct module_base *, u_int, const u_char *, size_t); int module_accsreq_aborted(struct module_base *, u_int); +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); __END_DECLS diff --git a/usr.sbin/radiusd/radiusd_standard.c b/usr.sbin/radiusd/radiusd_standard.c new file mode 100644 index 000000000..04052dfc5 --- /dev/null +++ b/usr.sbin/radiusd/radiusd_standard.c @@ -0,0 +1,298 @@ +/* $OpenBSD: radiusd_standard.c,v 1.1 2023/09/08 05:56:22 yasuoka Exp $ */ + +/* + * Copyright (c) 2013, 2023 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. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "radiusd.h" +#include "radiusd_module.h" + +TAILQ_HEAD(attrs,attr); + +struct attr { + uint8_t type; + uint32_t vendor; + uint32_t vtype; + TAILQ_ENTRY(attr) next; +}; + +struct module_standard { + struct module_base *base; + bool strip_atmark_realm; + bool strip_nt_domain; + struct attrs remove_reqattrs; + struct attrs remove_resattrs; +}; + +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); + +int +main(int argc, char *argv[]) +{ + struct module_standard module_standard; + struct module_handlers handlers = { + .config_set = module_standard_config_set, + .request_decoration = module_standard_reqdeco, + .response_decoration = module_standard_resdeco + }; + struct attr *attr; + + memset(&module_standard, 0, sizeof(module_standard)); + TAILQ_INIT(&module_standard.remove_reqattrs); + TAILQ_INIT(&module_standard.remove_resattrs); + + if ((module_standard.base = module_create( + STDIN_FILENO, &module_standard, &handlers)) == NULL) + err(1, "Could not create a module instance"); + + module_drop_privilege(module_standard.base); + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); + + module_load(module_standard.base); + + openlog(NULL, LOG_PID, LOG_DAEMON); + + while (module_run(module_standard.base) == 0) + ; + + module_destroy(module_standard.base); + while ((attr = TAILQ_FIRST(&module_standard.remove_reqattrs)) != NULL) { + TAILQ_REMOVE(&module_standard.remove_reqattrs, attr, next); + freezero(attr, sizeof(struct attr)); + } + while ((attr = TAILQ_FIRST(&module_standard.remove_resattrs)) != NULL) { + TAILQ_REMOVE(&module_standard.remove_resattrs, attr, next); + freezero(attr, sizeof(struct attr)); + } + + exit(EXIT_SUCCESS); +} + +static void +module_standard_config_set(void *ctx, const char *name, int argc, + char * const * argv) +{ + struct module_standard *module = ctx; + struct attr *attr; + const char *errmsg = "none"; + const char *errstr; + + if (strcmp(name, "strip-atmark-realm") == 0) { + SYNTAX_ASSERT(argc == 1, + "`strip-atmark-realm' must have only one argment"); + if (strcmp(argv[0], "true") == 0) + module->strip_atmark_realm = true; + else if (strcmp(argv[0], "false") == 0) + module->strip_atmark_realm = false; + else + SYNTAX_ASSERT(0, + "`strip-atmark-realm' must `true' or `false'"); + } else if (strcmp(name, "strip-nt-domain") == 0) { + SYNTAX_ASSERT(argc == 1, + "`strip-nt-domain' must have only one argment"); + if (strcmp(argv[0], "true") == 0) + module->strip_nt_domain = true; + else if (strcmp(argv[0], "false") == 0) + module->strip_nt_domain = false; + else + SYNTAX_ASSERT(0, + "`strip-nt-domain' must `true' or `false'"); + } else if (strcmp(name, "remove-request-attribute") == 0 || + strcmp(name, "remove-response-attribute") == 0) { + struct attrs *attrs; + + if (strcmp(name, "remove-request-attribute") == 0) { + SYNTAX_ASSERT(argc == 1 || argc == 2, + "`remove-request-attribute' must have one or two " + "argment"); + attrs = &module->remove_reqattrs; + } else { + SYNTAX_ASSERT(argc == 1 || argc == 2, + "`remove-response-attribute' must have one or two " + "argment"); + attrs = &module->remove_resattrs; + } + if ((attr = calloc(1, sizeof(struct attr))) == NULL) { + module_send_message(module->base, IMSG_NG, + "Out of memory: %s", strerror(errno)); + } + if (argc == 1) { + attr->type = strtonum(argv[0], 0, 255, &errstr); + if (errstr == NULL && + attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) { + TAILQ_INSERT_TAIL(attrs, attr, next); + attr = NULL; + } + } else { + attr->type = RADIUS_TYPE_VENDOR_SPECIFIC; + attr->vendor = strtonum(argv[0], 0, UINT32_MAX, + &errstr); + if (errstr == NULL) + attr->vtype = strtonum(argv[1], 0, 255, + &errstr); + if (errstr == NULL) { + TAILQ_INSERT_TAIL(attrs, attr, next); + attr = NULL; + } + } + freezero(attr, sizeof(struct attr)); + if (strcmp(name, "remove-request-attribute") == 0) + SYNTAX_ASSERT(attr == NULL, + "wrong number for `remove-request-attribute`"); + else + SYNTAX_ASSERT(attr == NULL, + "wrong number for `remove-response-attribute`"); + } else if (strncmp(name, "_", 1) == 0) + /* nothing */; /* ignore all internal messages */ + else { + module_send_message(module->base, IMSG_NG, + "Unknown config parameter name `%s'", name); + return; + } + module_send_message(module->base, IMSG_OK, NULL); + return; + + syntax_error: + module_send_message(module->base, IMSG_NG, "%s", errmsg); +} + +/* request message decoration */ +static void +module_standard_reqdeco(void *ctx, u_int q_id, const u_char *pkt, size_t pktlen) +{ + struct module_standard *module = ctx; + RADIUS_PACKET *radpkt = NULL; + int changed = 0; + char *ch, *username, buf[256]; + struct attr *attr; + + if (module->strip_atmark_realm || module->strip_nt_domain) { + if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { + syslog(LOG_ERR, + "%s: radius_convert_packet() failed: %m", __func__); + module_stop(module->base); + return; + } + + username = buf; + if (radius_get_string_attr(radpkt, RADIUS_TYPE_USER_NAME, + username, sizeof(buf)) != 0) { + syslog(LOG_WARNING, + "standard: q=%u could not get User-Name attribute", + q_id); + goto skip; + } + + if (module->strip_atmark_realm && + (ch = strrchr(username, '@')) != NULL) { + *ch = '\0'; + changed++; + } + if (module->strip_nt_domain && + (ch = strchr(username, '\\')) != NULL) { + username = ch + 1; + changed++; + } + if (changed > 0) { + radius_del_attr_all(radpkt, RADIUS_TYPE_USER_NAME); + radius_put_string_attr(radpkt, + RADIUS_TYPE_USER_NAME, username); + } + } + skip: + TAILQ_FOREACH(attr, &module->remove_reqattrs, next) { + if (radpkt == NULL && + (radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { + syslog(LOG_ERR, + "%s: radius_convert_packet() failed: %m", __func__); + module_stop(module->base); + return; + } + if (attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) + radius_del_attr_all(radpkt, attr->type); + else + radius_del_vs_attr_all(radpkt, attr->vendor, + attr->vtype); + } + if (radpkt == NULL) { + pkt = NULL; + pktlen = 0; + } else { + pkt = radius_get_data(radpkt); + pktlen = radius_get_length(radpkt); + } + if (module_reqdeco_done(module->base, q_id, pkt, pktlen) == -1) { + syslog(LOG_ERR, "%s: module_reqdeco_done() failed: %m", + __func__); + module_stop(module->base); + } + if (radpkt != NULL) + radius_delete_packet(radpkt); +} + +/* response message decoration */ +static void +module_standard_resdeco(void *ctx, u_int q_id, const u_char *pkt, size_t pktlen) +{ + struct module_standard *module = ctx; + RADIUS_PACKET *radpkt = NULL; + struct attr *attr; + + TAILQ_FOREACH(attr, &module->remove_reqattrs, next) { + if (radpkt == NULL && + (radpkt = radius_convert_packet(pkt, pktlen)) == NULL) { + syslog(LOG_ERR, + "%s: radius_convert_packet() failed: %m", __func__); + module_stop(module->base); + return; + } + if (attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) + radius_del_attr_all(radpkt, attr->type); + else + radius_del_vs_attr_all(radpkt, attr->vendor, + attr->vtype); + } + if (radpkt == NULL) { + pkt = NULL; + pktlen = 0; + } else { + pkt = radius_get_data(radpkt); + pktlen = radius_get_length(radpkt); + } + if (module_resdeco_done(module->base, q_id, pkt, pktlen) == -1) { + syslog(LOG_ERR, "%s: module_resdeco_done() failed: %m", + __func__); + module_stop(module->base); + } + if (radpkt != NULL) + radius_delete_packet(radpkt); +} diff --git a/usr.sbin/radiusd/radiusd_standard/Makefile b/usr.sbin/radiusd/radiusd_standard/Makefile new file mode 100644 index 000000000..5dbea5e19 --- /dev/null +++ b/usr.sbin/radiusd/radiusd_standard/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1 2023/09/08 05:56:22 yasuoka Exp $ +PROG= radiusd_standard +BINDIR= /usr/libexec/radiusd +SRCS= radiusd_standard.c radiusd_module.c +LDADD= -lutil -lradius -lcrypto +NOMAN= # + +.include