summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-01-16 23:23:45 +0000
committerDamien Miller <djm@mindrot.org>2019-01-17 11:08:13 +1100
commit60d8c84e0887514c99c9ce071965fafaa1c3d34a (patch)
tree771daf5a0f48b41115daf2b9b552e4e6d10dba7d /sftp-client.c
parentdbbc7e0eab7262f34b8e0cd6efecd1c77b905ed0 (diff)
downloadopenssh-git-60d8c84e0887514c99c9ce071965fafaa1c3d34a.tar.gz
upstream: Add "-h" flag to sftp chown/chgrp/chmod commands to
request they do not follow symlinks. Requires recently-committed lsetstat@openssh.com extension on the server side. ok markus@ dtucker@ OpenBSD-Commit-ID: f93bb3f6f7eb2fb7ef1e59126e72714f1626d604
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/sftp-client.c b/sftp-client.c
index 4986d6d8..d3f80e5a 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.130 2018/07/31 03:07:24 djm Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.131 2019/01/16 23:23:45 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -86,6 +86,7 @@ struct sftp_conn {
#define SFTP_EXT_FSTATVFS 0x00000004
#define SFTP_EXT_HARDLINK 0x00000008
#define SFTP_EXT_FSYNC 0x00000010
+#define SFTP_EXT_LSETSTAT 0x00000020
u_int exts;
u_int64_t limit_kbps;
struct bwlimit bwlimit_in, bwlimit_out;
@@ -463,6 +464,10 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
strcmp((char *)value, "1") == 0) {
ret->exts |= SFTP_EXT_FSYNC;
known = 1;
+ } else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
+ strcmp((char *)value, "1") == 0) {
+ ret->exts |= SFTP_EXT_LSETSTAT;
+ known = 1;
}
if (known) {
debug2("Server supports extension \"%s\" revision %s",
@@ -1096,7 +1101,6 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
@@ -1125,7 +1129,6 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
@@ -1138,6 +1141,38 @@ 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)
+{
+ struct sshbuf *msg;
+ u_int status, id;
+ int r;
+
+ if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
+ error("Server does not support lsetstat@openssh.com extension");
+ return -1;
+ }
+
+ id = conn->msg_id++;
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+ (r = sshbuf_put_u32(msg, id)) != 0 ||
+ (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(msg, path)) != 0 ||
+ (r = encode_attrib(msg, a)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(conn, msg);
+ sshbuf_free(msg);
+
+ status = get_status(conn, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't setstat on \"%s\": %s", path,
+ fx2txt(status));
+
+ return status == SSH2_FX_OK ? 0 : -1;
+}
+
static void
send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
u_int len, const u_char *handle, u_int handle_len)
@@ -1147,7 +1182,6 @@ send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||