mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-01-21 00:50:45 +00:00
upstream: add support for a "lsetstat@openssh.com" extension. This
replicates the functionality of the existing SSH2_FXP_SETSTAT operation but does not follow symlinks. Based on a patch from Bert Haverkamp in bz#2067 but with more attribute modifications supported. ok markus@ dtucker@ OpenBSD-Commit-ID: f7234f6e90db19655d55d936a115ee4ccb6aaf80
This commit is contained in:
parent
4a526941d3
commit
dbbc7e0eab
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-server.c,v 1.113 2019/01/01 23:10:53 djm Exp $ */
|
||||
/* $OpenBSD: sftp-server.c,v 1.114 2019/01/16 23:22:10 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -107,6 +107,7 @@ static void process_extended_statvfs(u_int32_t id);
|
||||
static void process_extended_fstatvfs(u_int32_t id);
|
||||
static void process_extended_hardlink(u_int32_t id);
|
||||
static void process_extended_fsync(u_int32_t id);
|
||||
static void process_extended_lsetstat(u_int32_t id);
|
||||
static void process_extended(u_int32_t id);
|
||||
|
||||
struct sftp_handler {
|
||||
@ -148,6 +149,7 @@ static const struct sftp_handler extended_handlers[] = {
|
||||
{ "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 },
|
||||
{ "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 },
|
||||
{ "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 },
|
||||
{ "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 },
|
||||
{ NULL, NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -666,6 +668,8 @@ process_init(void)
|
||||
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
|
||||
/* fsync extension */
|
||||
(r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
|
||||
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
|
||||
(r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
|
||||
(r = sshbuf_put_cstring(msg, "1")) != 0) /* version */
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
send_msg(msg);
|
||||
@ -889,6 +893,18 @@ attrib_to_tv(const Attrib *a)
|
||||
return tv;
|
||||
}
|
||||
|
||||
static struct timespec *
|
||||
attrib_to_ts(const Attrib *a)
|
||||
{
|
||||
static struct timespec ts[2];
|
||||
|
||||
ts[0].tv_sec = a->atime;
|
||||
ts[0].tv_nsec = 0;
|
||||
ts[1].tv_sec = a->mtime;
|
||||
ts[1].tv_nsec = 0;
|
||||
return ts;
|
||||
}
|
||||
|
||||
static void
|
||||
process_setstat(u_int32_t id)
|
||||
{
|
||||
@ -1369,6 +1385,55 @@ process_extended_fsync(u_int32_t id)
|
||||
send_status(id, status);
|
||||
}
|
||||
|
||||
static void
|
||||
process_extended_lsetstat(u_int32_t id)
|
||||
{
|
||||
Attrib a;
|
||||
char *name;
|
||||
int r, status = SSH2_FX_OK;
|
||||
|
||||
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
|
||||
(r = decode_attrib(iqueue, &a)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
|
||||
debug("request %u: lsetstat name \"%s\"", id, name);
|
||||
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
|
||||
/* nonsensical for links */
|
||||
status = SSH2_FX_BAD_MESSAGE;
|
||||
goto out;
|
||||
}
|
||||
if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
|
||||
logit("set \"%s\" mode %04o", name, a.perm);
|
||||
r = fchmodat(AT_FDCWD, name,
|
||||
a.perm & 07777, AT_SYMLINK_NOFOLLOW);
|
||||
if (r == -1)
|
||||
status = errno_to_portable(errno);
|
||||
}
|
||||
if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
|
||||
char buf[64];
|
||||
time_t t = a.mtime;
|
||||
|
||||
strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
|
||||
localtime(&t));
|
||||
logit("set \"%s\" modtime %s", name, buf);
|
||||
r = utimensat(AT_FDCWD, name,
|
||||
attrib_to_ts(&a), AT_SYMLINK_NOFOLLOW);
|
||||
if (r == -1)
|
||||
status = errno_to_portable(errno);
|
||||
}
|
||||
if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
|
||||
logit("set \"%s\" owner %lu group %lu", name,
|
||||
(u_long)a.uid, (u_long)a.gid);
|
||||
r = fchownat(AT_FDCWD, name, a.uid, a.gid,
|
||||
AT_SYMLINK_NOFOLLOW);
|
||||
if (r == -1)
|
||||
status = errno_to_portable(errno);
|
||||
}
|
||||
out:
|
||||
send_status(id, status);
|
||||
free(name);
|
||||
}
|
||||
|
||||
static void
|
||||
process_extended(u_int32_t id)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user