aboutsummaryrefslogtreecommitdiff
path: root/sshfs.c
diff options
context:
space:
mode:
authorMike Kelly <mike@pair.com>2011-12-20 10:27:51 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2011-12-21 10:05:08 +0100
commit7ca565d80d9e7f19544393b180cc9e1dccc247e8 (patch)
tree643c23f5192f762da390cd6384092e0eece13a5c /sshfs.c
parent301cc5218b36cb6f15602191eb2394877cdc930c (diff)
downloadsshfs-7ca565d80d9e7f19544393b180cc9e1dccc247e8.tar
sshfs-7ca565d80d9e7f19544393b180cc9e1dccc247e8.tar.gz
sshfs-7ca565d80d9e7f19544393b180cc9e1dccc247e8.tar.bz2
sshfs-7ca565d80d9e7f19544393b180cc9e1dccc247e8.zip
default to erroring if we can't remap a uid/gid
add a '-o nomap=ignore|error' option, which defaults to 'error'
Diffstat (limited to 'sshfs.c')
-rw-r--r--sshfs.c83
1 files changed, 54 insertions, 29 deletions
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");