From 7ca565d80d9e7f19544393b180cc9e1dccc247e8 Mon Sep 17 00:00:00 2001 From: Mike Kelly Date: Tue, 20 Dec 2011 10:27:51 -0500 Subject: default to erroring if we can't remap a uid/gid add a '-o nomap=ignore|error' option, which defaults to 'error' --- sshfs.1 | 11 +++++++++ sshfs.c | 83 ++++++++++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/sshfs.1 b/sshfs.1 index 9dcd8aa..27dd8bc 100644 --- a/sshfs.1 +++ b/sshfs.1 @@ -116,6 +116,17 @@ file containing username:uid mappings for \fBidmap=file\fR file containing groupname:gid mappings for \fBidmap=file\fR .RE .TP +\fB\-o\fR nomap=TYPE +with idmap=file, how to handle missing mappings +.RS 8 +.TP +ignore +don't do any re-mapping +.TP +error +return an error (default) +.RE +.TP \fB\-o\fR ssh_command=CMD execute CMD instead of 'ssh' .TP diff --git a/sshfs.c b/sshfs.c index bf7e956..749e134 100644 --- a/sshfs.c +++ b/sshfs.c @@ -201,6 +201,7 @@ struct sshfs { int no_check_root; int detect_uid; int idmap; + int nomap; char *uid_file; char *gid_file; GHashTable *uid_map; @@ -321,6 +322,11 @@ enum { IDMAP_FILE, }; +enum { + NOMAP_IGNORE, + NOMAP_ERROR, +}; + #define SSHFS_OPT(t, p, v) { t, offsetof(struct sshfs, p), v } static struct fuse_opt sshfs_opts[] = { @@ -337,6 +343,8 @@ static struct fuse_opt sshfs_opts[] = { SSHFS_OPT("idmap=file", idmap, IDMAP_FILE), SSHFS_OPT("uidfile=%s", uid_file, 0), SSHFS_OPT("gidfile=%s", gid_file, 0), + SSHFS_OPT("nomap=ignore", nomap, NOMAP_IGNORE), + SSHFS_OPT("nomap=error", nomap, NOMAP_ERROR), SSHFS_OPT("sshfs_sync", sync_write, 1), SSHFS_OPT("no_readahead", sync_read, 1), SSHFS_OPT("sshfs_debug", debug, 1), @@ -464,11 +472,20 @@ static int list_empty(const struct list_head *head) /* given a pointer to the uid/gid, and the mapping table, remap the * uid/gid, if necessary */ -static inline void translate_id(uint32_t *id, GHashTable *map) +static inline int translate_id(uint32_t *id, GHashTable *map) { gpointer id_p; - if (g_hash_table_lookup_extended(map, GUINT_TO_POINTER(*id), NULL, &id_p)) + if (g_hash_table_lookup_extended(map, GUINT_TO_POINTER(*id), NULL, &id_p)) { *id = GPOINTER_TO_UINT(id_p); + return 0; + } + switch (sshfs.nomap) { + case NOMAP_ERROR: return -1; + case NOMAP_IGNORE: return 0; + default: + fprintf(stderr, "internal error\n"); + abort(); + } } static inline void buf_init(struct buffer *buf, size_t size) @@ -672,36 +689,36 @@ static int buf_get_attrs(struct buffer *buf, struct stat *stbuf, int *flagsp) uint32_t mode = S_IFREG | 0777; if (buf_get_uint32(buf, &flags) == -1) - return -1; + return -EIO; if (flagsp) *flagsp = flags; if ((flags & SSH_FILEXFER_ATTR_SIZE) && buf_get_uint64(buf, &size) == -1) - return -1; + return -EIO; if ((flags & SSH_FILEXFER_ATTR_UIDGID) && (buf_get_uint32(buf, &uid) == -1 || buf_get_uint32(buf, &gid) == -1)) - return -1; + return -EIO; if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) && buf_get_uint32(buf, &mode) == -1) - return -1; + return -EIO; if ((flags & SSH_FILEXFER_ATTR_ACMODTIME)) { if (buf_get_uint32(buf, &atime) == -1 || buf_get_uint32(buf, &mtime) == -1) - return -1; + return -EIO; } if ((flags & SSH_FILEXFER_ATTR_EXTENDED)) { uint32_t extcount; unsigned i; if (buf_get_uint32(buf, &extcount) == -1) - return -1; + return -EIO; for (i = 0; i < extcount; i++) { struct buffer tmp; if (buf_get_data(buf, &tmp) == -1) - return -1; + return -EIO; buf_free(&tmp); if (buf_get_data(buf, &tmp) == -1) - return -1; + return -EIO; buf_free(&tmp); } } @@ -709,9 +726,11 @@ static int buf_get_attrs(struct buffer *buf, struct stat *stbuf, int *flagsp) if (sshfs.remote_uid_detected && uid == sshfs.remote_uid) uid = sshfs.local_uid; if (sshfs.idmap == IDMAP_FILE && sshfs.uid_map) - translate_id(&uid, sshfs.uid_map); + if (translate_id(&uid, sshfs.uid_map) == -1) + return -EPERM; if (sshfs.idmap == IDMAP_FILE && sshfs.gid_map) - translate_id(&gid, sshfs.gid_map); + if (translate_id(&gid, sshfs.gid_map) == -1) + return -EPERM; memset(stbuf, 0, sizeof(struct stat)); stbuf->st_mode = mode; @@ -778,7 +797,7 @@ static int buf_get_entries(struct buffer *buf, fuse_cache_dirh_t h, unsigned i; if (buf_get_uint32(buf, &count) == -1) - return -1; + return -EIO; for (i = 0; i < count; i++) { int err = -1; @@ -786,16 +805,16 @@ static int buf_get_entries(struct buffer *buf, fuse_cache_dirh_t h, char *longname; struct stat stbuf; if (buf_get_string(buf, &name) == -1) - return -1; + return -EIO; if (buf_get_string(buf, &longname) != -1) { free(longname); - if (buf_get_attrs(buf, &stbuf, NULL) != -1) { + err = buf_get_attrs(buf, &stbuf, NULL); + if (!err) { if (sshfs.follow_symlinks && S_ISLNK(stbuf.st_mode)) { stbuf.st_mode = 0; } filler(h, name, &stbuf); - err = 0; } } free(name); @@ -1552,7 +1571,7 @@ static void sftp_detect_uid() fprintf(stderr, "failed to stat home directory (%i)\n", serr); goto out; } - if (buf_get_attrs(&buf, &stbuf, &flags) == -1) + if (buf_get_attrs(&buf, &stbuf, &flags) != 0) goto out; if (!(flags & SSH_FILEXFER_ATTR_UIDGID)) @@ -1610,8 +1629,12 @@ static int sftp_check_root(const char *base_path) goto out; } - if (buf_get_attrs(&buf, &stbuf, &flags) == -1) + + int err2 = buf_get_attrs(&buf, &stbuf, &flags); + if (err2) { + err = err2; goto out; + } if (!(flags & SSH_FILEXFER_ATTR_PERMISSIONS)) goto out; @@ -1867,8 +1890,7 @@ static int sshfs_getattr(const char *path, struct stat *stbuf) err = sftp_request(sshfs.follow_symlinks ? SSH_FXP_STAT : SSH_FXP_LSTAT, &buf, SSH_FXP_ATTRS, &outbuf); if (!err) { - if (buf_get_attrs(&outbuf, stbuf, NULL) == -1) - err = -EIO; + err = buf_get_attrs(&outbuf, stbuf, NULL); buf_free(&outbuf); } buf_free(&buf); @@ -1990,8 +2012,7 @@ static int sshfs_getdir(const char *path, fuse_cache_dirh_t h, struct buffer name; err = sftp_request(SSH_FXP_READDIR, &handle, SSH_FXP_NAME, &name); if (!err) { - if (buf_get_entries(&name, h, filler) == -1) - err = -EIO; + err = buf_get_entries(&name, h, filler); buf_free(&name); } } while (!err); @@ -2190,9 +2211,11 @@ static int sshfs_chown(const char *path, uid_t uid, gid_t gid) if (sshfs.remote_uid_detected && uid == sshfs.local_uid) uid = sshfs.remote_uid; if (sshfs.idmap == IDMAP_FILE && sshfs.r_uid_map) - translate_id(&uid, sshfs.r_uid_map); + if(translate_id(&uid, sshfs.r_uid_map) == -1) + return -EPERM; if (sshfs.idmap == IDMAP_FILE && sshfs.r_gid_map) - translate_id(&gid, sshfs.r_gid_map); + if (translate_id(&gid, sshfs.r_gid_map) == -1) + return -EPERM; buf_init(&buf, 0); buf_add_path(&buf, path); @@ -2314,8 +2337,7 @@ static int sshfs_open_common(const char *path, mode_t mode, type = sshfs.follow_symlinks ? SSH_FXP_STAT : SSH_FXP_LSTAT; err2 = sftp_request(type, &buf, SSH_FXP_ATTRS, &outbuf); if (!err2) { - if (buf_get_attrs(&outbuf, &stbuf, NULL) == -1) - err2 = -EIO; + err2 = buf_get_attrs(&outbuf, &stbuf, NULL); buf_free(&outbuf); } err = sftp_request_wait(open_req, SSH_FXP_OPEN, SSH_FXP_HANDLE, @@ -2927,8 +2949,7 @@ static int sshfs_fgetattr(const char *path, struct stat *stbuf, buf_add_buf(&buf, &sf->handle); err = sftp_request(SSH_FXP_FSTAT, &buf, SSH_FXP_ATTRS, &outbuf); if (!err) { - if (buf_get_attrs(&outbuf, stbuf, NULL) == -1) - err = -EIO; + err = buf_get_attrs(&outbuf, stbuf, NULL); buf_free(&outbuf); } buf_free(&buf); @@ -3143,6 +3164,9 @@ static void usage(const char *progname) " file translate UIDs/GIDs contained in uidfile/gidfile\n" " -o uidfile=FILE file containing username:remote_uid mappings\n" " -o gidfile=FILE file containing groupname:remote_gid mappings\n" +" -o nomap=TYPE with idmap=file, how to handle missing mappings\n" +" ignore don't do any re-mapping\n" +" error return an error (default)\n" " -o ssh_command=CMD execute CMD instead of 'ssh'\n" " -o ssh_protocol=N ssh protocol to use (default: 2)\n" " -o sftp_server=SERV path to sftp server or subsystem (default: sftp)\n" @@ -3452,7 +3476,7 @@ static int ssh_connect(void) return -1; if (!sshfs.no_check_root && - sftp_check_root(sshfs.base_path) == -1) + sftp_check_root(sshfs.base_path) != 0) return -1; } @@ -3647,6 +3671,7 @@ int main(int argc, char *argv[]) sshfs.delay_connect = 0; sshfs.detect_uid = 0; sshfs.idmap = IDMAP_NONE; + sshfs.nomap = NOMAP_ERROR; ssh_add_arg("ssh"); ssh_add_arg("-x"); ssh_add_arg("-a"); -- cgit v1.2.3