mirror of git://anongit.mindrot.org/openssh.git
upstream: sftp client library support for
users-groups-by-id@openssh.com; ok markus@ OpenBSD-Commit-ID: ddb2f33a2da6349a9a89a8b5bcb9ca7c999394de
This commit is contained in:
parent
488f6e1c58
commit
8ff680368b
140
sftp-client.c
140
sftp-client.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sftp-client.c,v 1.164 2022/05/15 23:47:21 djm Exp $ */
|
/* $OpenBSD: sftp-client.c,v 1.165 2022/09/19 10:43:12 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
|
@ -95,15 +95,16 @@ struct sftp_conn {
|
||||||
u_int num_requests;
|
u_int num_requests;
|
||||||
u_int version;
|
u_int version;
|
||||||
u_int msg_id;
|
u_int msg_id;
|
||||||
#define SFTP_EXT_POSIX_RENAME 0x00000001
|
#define SFTP_EXT_POSIX_RENAME 0x00000001
|
||||||
#define SFTP_EXT_STATVFS 0x00000002
|
#define SFTP_EXT_STATVFS 0x00000002
|
||||||
#define SFTP_EXT_FSTATVFS 0x00000004
|
#define SFTP_EXT_FSTATVFS 0x00000004
|
||||||
#define SFTP_EXT_HARDLINK 0x00000008
|
#define SFTP_EXT_HARDLINK 0x00000008
|
||||||
#define SFTP_EXT_FSYNC 0x00000010
|
#define SFTP_EXT_FSYNC 0x00000010
|
||||||
#define SFTP_EXT_LSETSTAT 0x00000020
|
#define SFTP_EXT_LSETSTAT 0x00000020
|
||||||
#define SFTP_EXT_LIMITS 0x00000040
|
#define SFTP_EXT_LIMITS 0x00000040
|
||||||
#define SFTP_EXT_PATH_EXPAND 0x00000080
|
#define SFTP_EXT_PATH_EXPAND 0x00000080
|
||||||
#define SFTP_EXT_COPY_DATA 0x00000100
|
#define SFTP_EXT_COPY_DATA 0x00000100
|
||||||
|
#define SFTP_EXT_GETUSERSGROUPS_BY_ID 0x00000200
|
||||||
u_int exts;
|
u_int exts;
|
||||||
u_int64_t limit_kbps;
|
u_int64_t limit_kbps;
|
||||||
struct bwlimit bwlimit_in, bwlimit_out;
|
struct bwlimit bwlimit_in, bwlimit_out;
|
||||||
|
@ -539,6 +540,11 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
|
||||||
strcmp((char *)value, "1") == 0) {
|
strcmp((char *)value, "1") == 0) {
|
||||||
ret->exts |= SFTP_EXT_COPY_DATA;
|
ret->exts |= SFTP_EXT_COPY_DATA;
|
||||||
known = 1;
|
known = 1;
|
||||||
|
} else if (strcmp(name,
|
||||||
|
"users-groups-by-id@openssh.com") == 0 &&
|
||||||
|
strcmp((char *)value, "1") == 0) {
|
||||||
|
ret->exts |= SFTP_EXT_GETUSERSGROUPS_BY_ID;
|
||||||
|
known = 1;
|
||||||
}
|
}
|
||||||
if (known) {
|
if (known) {
|
||||||
debug2("Server supports extension \"%s\" revision %s",
|
debug2("Server supports extension \"%s\" revision %s",
|
||||||
|
@ -2752,6 +2758,120 @@ crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
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,
|
||||||
|
const u_int *uids, u_int nuids,
|
||||||
|
const u_int *gids, u_int ngids,
|
||||||
|
char ***usernamesp, char ***groupnamesp)
|
||||||
|
{
|
||||||
|
struct sshbuf *msg, *uidbuf, *gidbuf;
|
||||||
|
u_int i, expected_id, id;
|
||||||
|
char *name, **usernames = NULL, **groupnames = NULL;
|
||||||
|
u_char type;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
*usernamesp = *groupnamesp = NULL;
|
||||||
|
if (!can_get_users_groups_by_id(conn))
|
||||||
|
return SSH_ERR_FEATURE_UNSUPPORTED;
|
||||||
|
|
||||||
|
if ((msg = sshbuf_new()) == NULL ||
|
||||||
|
(uidbuf = sshbuf_new()) == NULL ||
|
||||||
|
(gidbuf = sshbuf_new()) == NULL)
|
||||||
|
fatal_f("sshbuf_new failed");
|
||||||
|
expected_id = id = conn->msg_id++;
|
||||||
|
debug2("Sending SSH2_FXP_EXTENDED(users-groups-by-id@openssh.com)");
|
||||||
|
for (i = 0; i < nuids; i++) {
|
||||||
|
if ((r = sshbuf_put_u32(uidbuf, uids[i])) != 0)
|
||||||
|
fatal_fr(r, "compose uids");
|
||||||
|
}
|
||||||
|
for (i = 0; i < ngids; i++) {
|
||||||
|
if ((r = sshbuf_put_u32(gidbuf, gids[i])) != 0)
|
||||||
|
fatal_fr(r, "compose gids");
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
|
||||||
|
(r = sshbuf_put_u32(msg, id)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(msg,
|
||||||
|
"users-groups-by-id@openssh.com")) != 0 ||
|
||||||
|
(r = sshbuf_put_stringb(msg, uidbuf)) != 0 ||
|
||||||
|
(r = sshbuf_put_stringb(msg, gidbuf)) != 0)
|
||||||
|
fatal_fr(r, "compose");
|
||||||
|
send_msg(conn, msg);
|
||||||
|
get_msg(conn, msg);
|
||||||
|
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
|
||||||
|
(r = sshbuf_get_u32(msg, &id)) != 0)
|
||||||
|
fatal_fr(r, "parse");
|
||||||
|
if (id != expected_id)
|
||||||
|
fatal("ID mismatch (%u != %u)", id, expected_id);
|
||||||
|
if (type == SSH2_FXP_STATUS) {
|
||||||
|
u_int status;
|
||||||
|
char *errmsg;
|
||||||
|
|
||||||
|
if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
|
||||||
|
(r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
|
||||||
|
fatal_fr(r, "parse status");
|
||||||
|
error("users-groups-by-id %s",
|
||||||
|
*errmsg == '\0' ? fx2txt(status) : errmsg);
|
||||||
|
free(errmsg);
|
||||||
|
sshbuf_free(msg);
|
||||||
|
sshbuf_free(uidbuf);
|
||||||
|
sshbuf_free(gidbuf);
|
||||||
|
return -1;
|
||||||
|
} else if (type != SSH2_FXP_EXTENDED_REPLY)
|
||||||
|
fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
|
||||||
|
SSH2_FXP_EXTENDED_REPLY, type);
|
||||||
|
|
||||||
|
/* reuse */
|
||||||
|
sshbuf_free(uidbuf);
|
||||||
|
sshbuf_free(gidbuf);
|
||||||
|
uidbuf = gidbuf = NULL;
|
||||||
|
if ((r = sshbuf_froms(msg, &uidbuf)) != 0 ||
|
||||||
|
(r = sshbuf_froms(msg, &gidbuf)) != 0)
|
||||||
|
fatal_fr(r, "parse response");
|
||||||
|
if (nuids > 0) {
|
||||||
|
usernames = xcalloc(nuids, sizeof(*usernames));
|
||||||
|
for (i = 0; i < nuids; i++) {
|
||||||
|
if ((r = sshbuf_get_cstring(uidbuf, &name, NULL)) != 0)
|
||||||
|
fatal_fr(r, "parse user name");
|
||||||
|
/* Handle unresolved names */
|
||||||
|
if (*name == '\0') {
|
||||||
|
free(name);
|
||||||
|
name = NULL;
|
||||||
|
}
|
||||||
|
usernames[i] = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ngids > 0) {
|
||||||
|
groupnames = xcalloc(ngids, sizeof(*groupnames));
|
||||||
|
for (i = 0; i < ngids; i++) {
|
||||||
|
if ((r = sshbuf_get_cstring(gidbuf, &name, NULL)) != 0)
|
||||||
|
fatal_fr(r, "parse user name");
|
||||||
|
/* Handle unresolved names */
|
||||||
|
if (*name == '\0') {
|
||||||
|
free(name);
|
||||||
|
name = NULL;
|
||||||
|
}
|
||||||
|
groupnames[i] = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sshbuf_len(uidbuf) != 0)
|
||||||
|
fatal_f("unexpected extra username data");
|
||||||
|
if (sshbuf_len(gidbuf) != 0)
|
||||||
|
fatal_f("unexpected extra groupname data");
|
||||||
|
sshbuf_free(uidbuf);
|
||||||
|
sshbuf_free(gidbuf);
|
||||||
|
sshbuf_free(msg);
|
||||||
|
/* success */
|
||||||
|
*usernamesp = usernames;
|
||||||
|
*groupnamesp = groupnames;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
path_append(const char *p1, const char *p2)
|
path_append(const char *p1, const char *p2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sftp-client.h,v 1.37 2022/05/13 06:31:50 djm Exp $ */
|
/* $OpenBSD: sftp-client.h,v 1.38 2022/09/19 10:43:12 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||||
|
@ -183,6 +183,15 @@ int crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
Attrib *dirattrib, int preserve_flag, int print_flag,
|
Attrib *dirattrib, int preserve_flag, int print_flag,
|
||||||
int follow_link_flag);
|
int follow_link_flag);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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,
|
||||||
|
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. */
|
/* Concatenate paths, taking care of slashes. Caller must free result. */
|
||||||
char *path_append(const char *, const char *);
|
char *path_append(const char *, const char *);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue