=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/sftp-server.c,v retrieving revision 1.6.4.3 retrieving revision 1.7 diff -u -r1.6.4.3 -r1.7 --- src/usr.bin/ssh/sftp-server.c 2001/03/21 18:53:06 1.6.4.3 +++ src/usr.bin/ssh/sftp-server.c 2000/12/09 14:08:27 1.7 @@ -22,35 +22,98 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: sftp-server.c,v 1.6.4.3 2001/03/21 18:53:06 jason Exp $"); +RCSID("$OpenBSD: sftp-server.c,v 1.7 2000/12/09 14:08:27 markus Exp $"); +#include "ssh.h" #include "buffer.h" #include "bufaux.h" #include "getput.h" -#include "log.h" #include "xmalloc.h" -#include "sftp.h" -#include "sftp-common.h" +/* version */ +#define SSH_FILEXFER_VERSION 2 +/* client to server */ +#define SSH_FXP_INIT 1 +#define SSH_FXP_OPEN 3 +#define SSH_FXP_CLOSE 4 +#define SSH_FXP_READ 5 +#define SSH_FXP_WRITE 6 +#define SSH_FXP_LSTAT 7 +#define SSH_FXP_FSTAT 8 +#define SSH_FXP_SETSTAT 9 +#define SSH_FXP_FSETSTAT 10 +#define SSH_FXP_OPENDIR 11 +#define SSH_FXP_READDIR 12 +#define SSH_FXP_REMOVE 13 +#define SSH_FXP_MKDIR 14 +#define SSH_FXP_RMDIR 15 +#define SSH_FXP_REALPATH 16 +#define SSH_FXP_STAT 17 +#define SSH_FXP_RENAME 18 + +/* server to client */ +#define SSH_FXP_VERSION 2 +#define SSH_FXP_STATUS 101 +#define SSH_FXP_HANDLE 102 +#define SSH_FXP_DATA 103 +#define SSH_FXP_NAME 104 +#define SSH_FXP_ATTRS 105 + +/* portable open modes */ +#define SSH_FXF_READ 0x01 +#define SSH_FXF_WRITE 0x02 +#define SSH_FXF_APPEND 0x04 +#define SSH_FXF_CREAT 0x08 +#define SSH_FXF_TRUNC 0x10 +#define SSH_FXF_EXCL 0x20 + +/* attributes */ +#define SSH_FXA_HAVE_SIZE 0x01 +#define SSH_FXA_HAVE_UGID 0x02 +#define SSH_FXA_HAVE_PERM 0x04 +#define SSH_FXA_HAVE_TIME 0x08 + +/* status messages */ +#define SSH_FX_OK 0x00 +#define SSH_FX_EOF 0x01 +#define SSH_FX_NO_SUCH_FILE 0x02 +#define SSH_FX_PERMISSION_DENIED 0x03 +#define SSH_FX_FAILURE 0x04 +#define SSH_FX_BAD_MESSAGE 0x05 +#define SSH_FX_NO_CONNECTION 0x06 +#define SSH_FX_CONNECTION_LOST 0x07 + + /* helper */ -#define get_int64() buffer_get_int64(&iqueue); #define get_int() buffer_get_int(&iqueue); #define get_string(lenp) buffer_get_string(&iqueue, lenp); -#define TRACE debug +#define TRACE log /* input and output queue */ Buffer iqueue; Buffer oqueue; -/* Version of client */ -int version; - /* portable attibutes, etc. */ +typedef struct Attrib Attrib; typedef struct Stat Stat; -struct Stat { +struct Attrib +{ + u_int32_t flags; + u_int32_t size_high; + u_int32_t size_low; + u_int64_t size; + u_int32_t uid; + u_int32_t gid; + u_int32_t perm; + u_int32_t atime; + u_int32_t mtime; +}; + +struct Stat +{ char *name; char *long_name; Attrib attrib; @@ -60,28 +123,27 @@ errno_to_portable(int unixerrno) { int ret = 0; - switch (unixerrno) { case 0: - ret = SSH2_FX_OK; + ret = SSH_FX_OK; break; case ENOENT: case ENOTDIR: case EBADF: case ELOOP: - ret = SSH2_FX_NO_SUCH_FILE; + ret = SSH_FX_NO_SUCH_FILE; break; case EPERM: case EACCES: case EFAULT: - ret = SSH2_FX_PERMISSION_DENIED; + ret = SSH_FX_PERMISSION_DENIED; break; case ENAMETOOLONG: case EINVAL: - ret = SSH2_FX_BAD_MESSAGE; + ret = SSH_FX_BAD_MESSAGE; break; default: - ret = SSH2_FX_FAILURE; + ret = SSH_FX_FAILURE; break; } return ret; @@ -91,25 +153,105 @@ flags_from_portable(int pflags) { int flags = 0; - - if ((pflags & SSH2_FXF_READ) && - (pflags & SSH2_FXF_WRITE)) { + if (pflags & SSH_FXF_READ && + pflags & SSH_FXF_WRITE) { flags = O_RDWR; - } else if (pflags & SSH2_FXF_READ) { + } else if (pflags & SSH_FXF_READ) { flags = O_RDONLY; - } else if (pflags & SSH2_FXF_WRITE) { + } else if (pflags & SSH_FXF_WRITE) { flags = O_WRONLY; } - if (pflags & SSH2_FXF_CREAT) + if (pflags & SSH_FXF_CREAT) flags |= O_CREAT; - if (pflags & SSH2_FXF_TRUNC) + if (pflags & SSH_FXF_TRUNC) flags |= O_TRUNC; - if (pflags & SSH2_FXF_EXCL) + if (pflags & SSH_FXF_EXCL) flags |= O_EXCL; return flags; } +void +attrib_clear(Attrib *a) +{ + a->flags = 0; + a->size_low = 0; + a->size_high = 0; + a->size = 0; + a->uid = 0; + a->gid = 0; + a->perm = 0; + a->atime = 0; + a->mtime = 0; +} + Attrib * +decode_attrib(Buffer *b) +{ + static Attrib a; + attrib_clear(&a); + a.flags = buffer_get_int(b); + if (a.flags & SSH_FXA_HAVE_SIZE) { + a.size_high = buffer_get_int(b); + a.size_low = buffer_get_int(b); + a.size = (((u_int64_t) a.size_high) << 32) + a.size_low; + } + if (a.flags & SSH_FXA_HAVE_UGID) { + a.uid = buffer_get_int(b); + a.gid = buffer_get_int(b); + } + if (a.flags & SSH_FXA_HAVE_PERM) { + a.perm = buffer_get_int(b); + } + if (a.flags & SSH_FXA_HAVE_TIME) { + a.atime = buffer_get_int(b); + a.mtime = buffer_get_int(b); + } + return &a; +} + +void +encode_attrib(Buffer *b, Attrib *a) +{ + buffer_put_int(b, a->flags); + if (a->flags & SSH_FXA_HAVE_SIZE) { + buffer_put_int(b, a->size_high); + buffer_put_int(b, a->size_low); + } + if (a->flags & SSH_FXA_HAVE_UGID) { + buffer_put_int(b, a->uid); + buffer_put_int(b, a->gid); + } + if (a->flags & SSH_FXA_HAVE_PERM) { + buffer_put_int(b, a->perm); + } + if (a->flags & SSH_FXA_HAVE_TIME) { + buffer_put_int(b, a->atime); + buffer_put_int(b, a->mtime); + } +} + +Attrib * +stat_to_attrib(struct stat *st) +{ + static Attrib a; + attrib_clear(&a); + a.flags = 0; + a.flags |= SSH_FXA_HAVE_SIZE; + a.size = st->st_size; + a.size_low = a.size; + a.size_high = (u_int32_t) (a.size >> 32); + a.flags |= SSH_FXA_HAVE_UGID; + a.uid = st->st_uid; + a.gid = st->st_gid; + a.flags |= SSH_FXA_HAVE_PERM; + a.perm = st->st_mode; + a.flags |= SSH_FXA_HAVE_TIME; + a.atime = st->st_atime; + a.mtime = st->st_mtime; + return &a; +} + +Attrib * get_attrib(void) { return decode_attrib(&iqueue); @@ -124,20 +266,17 @@ int fd; char *name; }; - enum { HANDLE_UNUSED, HANDLE_DIR, HANDLE_FILE }; - Handle handles[100]; void handle_init(void) { int i; - for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) handles[i].use = HANDLE_UNUSED; } @@ -146,7 +285,6 @@ handle_new(int use, char *name, int fd, DIR *dirp) { int i; - for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) { if (handles[i].use == HANDLE_UNUSED) { handles[i].use = use; @@ -162,29 +300,30 @@ int handle_is_ok(int i, int type) { - return i >= 0 && i < sizeof(handles)/sizeof(Handle) && - handles[i].use == type; + return i >= 0 && i < sizeof(handles)/sizeof(Handle) && handles[i].use == type; } int handle_to_string(int handle, char **stringp, int *hlenp) { + char buf[1024]; if (stringp == NULL || hlenp == NULL) return -1; - *stringp = xmalloc(sizeof(int32_t)); - PUT_32BIT(*stringp, handle); - *hlenp = sizeof(int32_t); + snprintf(buf, sizeof buf, "%d", handle); + *stringp = xstrdup(buf); + *hlenp = strlen(*stringp); return 0; } int handle_from_string(char *handle, u_int hlen) { - int val; - - if (hlen != sizeof(int32_t)) +/* XXX OVERFLOW ? */ + char *ep; + long lval = strtol(handle, &ep, 10); + int val = lval; + if (*ep != '\0') return -1; - val = GET_32BIT(handle); if (handle_is_ok(val, HANDLE_FILE) || handle_is_ok(val, HANDLE_DIR)) return val; @@ -211,7 +350,7 @@ int handle_to_fd(int handle) { - if (handle_is_ok(handle, HANDLE_FILE)) + if (handle_is_ok(handle, HANDLE_FILE)) return handles[handle].fd; return -1; } @@ -220,7 +359,6 @@ handle_close(int handle) { int ret = -1; - if (handle_is_ok(handle, HANDLE_FILE)) { ret = close(handles[handle].fd); handles[handle].use = HANDLE_UNUSED; @@ -237,12 +375,10 @@ get_handle(void) { char *handle; - int val = -1; + int val; u_int hlen; - handle = get_string(&hlen); - if (hlen < 256) - val = handle_from_string(handle, hlen); + val = handle_from_string(handle, hlen); xfree(handle); return val; } @@ -253,7 +389,6 @@ send_msg(Buffer *m) { int mlen = buffer_len(m); - buffer_put_int(&oqueue, mlen); buffer_append(&oqueue, buffer_ptr(m), mlen); buffer_consume(m, mlen); @@ -263,29 +398,11 @@ send_status(u_int32_t id, u_int32_t error) { Buffer msg; - const char *status_messages[] = { - "Success", /* SSH_FX_OK */ - "End of file", /* SSH_FX_EOF */ - "No such file", /* SSH_FX_NO_SUCH_FILE */ - "Permission denied", /* SSH_FX_PERMISSION_DENIED */ - "Failure", /* SSH_FX_FAILURE */ - "Bad message", /* SSH_FX_BAD_MESSAGE */ - "No connection", /* SSH_FX_NO_CONNECTION */ - "Connection lost", /* SSH_FX_CONNECTION_LOST */ - "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ - "Unknown error" /* Others */ - }; - TRACE("sent status id %d error %d", id, error); buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_STATUS); + buffer_put_char(&msg, SSH_FXP_STATUS); buffer_put_int(&msg, id); buffer_put_int(&msg, error); - if (version >= 3) { - buffer_put_cstring(&msg, - status_messages[MIN(error,SSH2_FX_MAX)]); - buffer_put_cstring(&msg, ""); - } send_msg(&msg); buffer_free(&msg); } @@ -293,7 +410,6 @@ send_data_or_handle(char type, u_int32_t id, char *data, int dlen) { Buffer msg; - buffer_init(&msg); buffer_put_char(&msg, type); buffer_put_int(&msg, id); @@ -306,7 +422,7 @@ send_data(u_int32_t id, char *data, int dlen) { TRACE("sent data id %d len %d", id, dlen); - send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); + send_data_or_handle(SSH_FXP_DATA, id, data, dlen); } void @@ -314,10 +430,9 @@ { char *string; int hlen; - handle_to_string(handle, &string, &hlen); TRACE("sent handle id %d handle %d", id, handle); - send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); + send_data_or_handle(SSH_FXP_HANDLE, id, string, hlen); xfree(string); } @@ -326,9 +441,8 @@ { Buffer msg; int i; - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_NAME); + buffer_put_char(&msg, SSH_FXP_NAME); buffer_put_int(&msg, id); buffer_put_int(&msg, count); TRACE("sent names id %d count %d", id, count); @@ -345,10 +459,9 @@ send_attrib(u_int32_t id, Attrib *a) { Buffer msg; - TRACE("sent attrib id %d have 0x%x", id, a->flags); buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_ATTRS); + buffer_put_char(&msg, SSH_FXP_ATTRS); buffer_put_int(&msg, id); encode_attrib(&msg, a); send_msg(&msg); @@ -361,12 +474,12 @@ process_init(void) { Buffer msg; + int version = buffer_get_int(&iqueue); - version = buffer_get_int(&iqueue); TRACE("client version %d", version); buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_VERSION); - buffer_put_int(&msg, SSH2_FILEXFER_VERSION); + buffer_put_char(&msg, SSH_FXP_VERSION); + buffer_put_int(&msg, SSH_FILEXFER_VERSION); send_msg(&msg); buffer_free(&msg); } @@ -377,14 +490,14 @@ u_int32_t id, pflags; Attrib *a; char *name; - int handle, fd, flags, mode, status = SSH2_FX_FAILURE; + int handle, fd, flags, mode, status = SSH_FX_FAILURE; id = get_int(); name = get_string(NULL); - pflags = get_int(); /* portable flags */ + pflags = get_int(); a = get_attrib(); flags = flags_from_portable(pflags); - mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; + mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm : 0666; TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode); fd = open(name, flags, mode); if (fd < 0) { @@ -395,10 +508,10 @@ close(fd); } else { send_handle(id, handle); - status = SSH2_FX_OK; + status = SSH_FX_OK; } } - if (status != SSH2_FX_OK) + if (status != SSH_FX_OK) send_status(id, status); xfree(name); } @@ -407,13 +520,13 @@ process_close(void) { u_int32_t id; - int handle, ret, status = SSH2_FX_FAILURE; + int handle, ret, status = SSH_FX_FAILURE; id = get_int(); handle = get_handle(); TRACE("close id %d handle %d", id, handle); ret = handle_close(handle); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; send_status(id, status); } @@ -421,17 +534,18 @@ process_read(void) { char buf[64*1024]; - u_int32_t id, len; - int handle, fd, ret, status = SSH2_FX_FAILURE; + u_int32_t id, off_high, off_low, len; + int handle, fd, ret, status = SSH_FX_FAILURE; u_int64_t off; id = get_int(); handle = get_handle(); - off = get_int64(); + off_high = get_int(); + off_low = get_int(); len = get_int(); - TRACE("read id %d handle %d off %llu len %d", id, handle, - (unsigned long long)off, len); + off = (((u_int64_t) off_high) << 32) + off_low; + TRACE("read id %d handle %d off %qd len %d", id, handle, off, len); if (len > sizeof buf) { len = sizeof buf; log("read change len %d", len); @@ -446,33 +560,34 @@ if (ret < 0) { status = errno_to_portable(errno); } else if (ret == 0) { - status = SSH2_FX_EOF; + status = SSH_FX_EOF; } else { send_data(id, buf, ret); - status = SSH2_FX_OK; + status = SSH_FX_OK; } } } - if (status != SSH2_FX_OK) + if (status != SSH_FX_OK) send_status(id, status); } void process_write(void) { - u_int32_t id; + u_int32_t id, off_high, off_low; u_int64_t off; u_int len; - int handle, fd, ret, status = SSH2_FX_FAILURE; + int handle, fd, ret, status = SSH_FX_FAILURE; char *data; id = get_int(); handle = get_handle(); - off = get_int64(); + off_high = get_int(); + off_low = get_int(); data = get_string(&len); - TRACE("write id %d handle %d off %llu len %d", id, handle, - (unsigned long long)off, len); + off = (((u_int64_t) off_high) << 32) + off_low; + TRACE("write id %d handle %d off %qd len %d", id, handle, off, len); fd = handle_to_fd(handle); if (fd >= 0) { if (lseek(fd, off, SEEK_SET) < 0) { @@ -485,7 +600,7 @@ error("process_write: write failed"); status = errno_to_portable(errno); } else if (ret == len) { - status = SSH2_FX_OK; + status = SSH_FX_OK; } else { log("nothing at all written"); } @@ -498,11 +613,11 @@ void process_do_stat(int do_lstat) { - Attrib a; + Attrib *a; struct stat st; u_int32_t id; char *name; - int ret, status = SSH2_FX_FAILURE; + int ret, status = SSH_FX_FAILURE; id = get_int(); name = get_string(NULL); @@ -511,11 +626,11 @@ if (ret < 0) { status = errno_to_portable(errno); } else { - stat_to_attrib(&st, &a); - send_attrib(id, &a); - status = SSH2_FX_OK; + a = stat_to_attrib(&st); + send_attrib(id, a); + status = SSH_FX_OK; } - if (status != SSH2_FX_OK) + if (status != SSH_FX_OK) send_status(id, status); xfree(name); } @@ -535,10 +650,10 @@ void process_fstat(void) { - Attrib a; + Attrib *a; struct stat st; u_int32_t id; - int fd, ret, handle, status = SSH2_FX_FAILURE; + int fd, ret, handle, status = SSH_FX_FAILURE; id = get_int(); handle = get_handle(); @@ -549,12 +664,12 @@ if (ret < 0) { status = errno_to_portable(errno); } else { - stat_to_attrib(&st, &a); - send_attrib(id, &a); - status = SSH2_FX_OK; + a = stat_to_attrib(&st); + send_attrib(id, a); + status = SSH_FX_OK; } } - if (status != SSH2_FX_OK) + if (status != SSH_FX_OK) send_status(id, status); } @@ -562,7 +677,6 @@ attrib_to_tv(Attrib *a) { static struct timeval tv[2]; - tv[0].tv_sec = a->atime; tv[0].tv_usec = 0; tv[1].tv_sec = a->mtime; @@ -577,27 +691,22 @@ u_int32_t id; char *name; int ret; - int status = SSH2_FX_OK; + int status = SSH_FX_OK; id = get_int(); name = get_string(NULL); a = get_attrib(); TRACE("setstat id %d name %s", id, name); - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { + if (a->flags & SSH_FXA_HAVE_PERM) { ret = chmod(name, a->perm & 0777); if (ret == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { + if (a->flags & SSH_FXA_HAVE_TIME) { ret = utimes(name, attrib_to_tv(a)); if (ret == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { - ret = chown(name, a->uid, a->gid); - if (ret == -1) - status = errno_to_portable(errno); - } send_status(id, status); xfree(name); } @@ -608,7 +717,7 @@ Attrib *a; u_int32_t id; int handle, fd, ret; - int status = SSH2_FX_OK; + int status = SSH_FX_OK; id = get_int(); handle = get_handle(); @@ -616,23 +725,18 @@ TRACE("fsetstat id %d handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) { - status = SSH2_FX_FAILURE; + status = SSH_FX_FAILURE; } else { - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { + if (a->flags & SSH_FXA_HAVE_PERM) { ret = fchmod(fd, a->perm & 0777); if (ret == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { + if (a->flags & SSH_FXA_HAVE_TIME) { ret = futimes(fd, attrib_to_tv(a)); if (ret == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { - ret = fchown(fd, a->uid, a->gid); - if (ret == -1) - status = errno_to_portable(errno); - } } send_status(id, status); } @@ -642,13 +746,13 @@ { DIR *dirp = NULL; char *path; - int handle, status = SSH2_FX_FAILURE; + int handle, status = SSH_FX_FAILURE; u_int32_t id; id = get_int(); path = get_string(NULL); TRACE("opendir id %d path %s", id, path); - dirp = opendir(path); + dirp = opendir(path); if (dirp == NULL) { status = errno_to_portable(errno); } else { @@ -657,51 +761,22 @@ closedir(dirp); } else { send_handle(id, handle); - status = SSH2_FX_OK; + status = SSH_FX_OK; } - + } - if (status != SSH2_FX_OK) + if (status != SSH_FX_OK) send_status(id, status); xfree(path); } -/* - * drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh - */ char * ls_file(char *name, struct stat *st) { - int sz = 0; - struct passwd *pw; - struct group *gr; - struct tm *ltime = localtime(&st->st_mtime); - char *user, *group; - char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1]; - - strmode(st->st_mode, mode); - if ((pw = getpwuid(st->st_uid)) != NULL) { - user = pw->pw_name; - } else { - snprintf(ubuf, sizeof ubuf, "%d", st->st_uid); - user = ubuf; - } - if ((gr = getgrgid(st->st_gid)) != NULL) { - group = gr->gr_name; - } else { - snprintf(gbuf, sizeof gbuf, "%d", st->st_gid); - group = gbuf; - } - if (ltime != NULL) { - if (time(NULL) - st->st_mtime < (365*24*60*60)/2) - sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime); - else - sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime); - } - if (sz == 0) - tbuf[0] = '\0'; - snprintf(buf, sizeof buf, "%s %3d %-8.8s %-8.8s %8llu %s %s", mode, - st->st_nlink, user, group, (unsigned long long)st->st_size, tbuf, name); + char buf[1024]; + snprintf(buf, sizeof buf, "0%o %d %d %qd %d %s", + st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size,(int) st->st_mtime, + name); return xstrdup(buf); } @@ -720,8 +795,9 @@ dirp = handle_to_dir(handle); path = handle_to_name(handle); if (dirp == NULL || path == NULL) { - send_status(id, SSH2_FX_FAILURE); + send_status(id, SSH_FX_FAILURE); } else { + Attrib *a; struct stat st; char pathname[1024]; Stat *stats; @@ -737,23 +813,19 @@ "%s/%s", path, dp->d_name); if (lstat(pathname, &st) < 0) continue; - stat_to_attrib(&st, &(stats[count].attrib)); + a = stat_to_attrib(&st); + stats[count].attrib = *a; stats[count].name = xstrdup(dp->d_name); stats[count].long_name = ls_file(dp->d_name, &st); count++; /* send up to 100 entries in one message */ - /* XXX check packet size instead */ if (count == 100) break; } - if (count > 0) { - send_names(id, count, stats); - for(i = 0; i < count; i++) { - xfree(stats[i].name); - xfree(stats[i].long_name); - } - } else { - send_status(id, SSH2_FX_EOF); + send_names(id, count, stats); + for(i = 0; i < count; i++) { + xfree(stats[i].name); + xfree(stats[i].long_name); } xfree(stats); } @@ -764,14 +836,14 @@ { char *name; u_int32_t id; - int status = SSH2_FX_FAILURE; + int status = SSH_FX_FAILURE; int ret; id = get_int(); name = get_string(NULL); TRACE("remove id %d name %s", id, name); - ret = unlink(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + ret = remove(name); + status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; send_status(id, status); xfree(name); } @@ -782,16 +854,15 @@ Attrib *a; u_int32_t id; char *name; - int ret, mode, status = SSH2_FX_FAILURE; + int ret, mode, status = SSH_FX_FAILURE; id = get_int(); name = get_string(NULL); a = get_attrib(); - mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? - a->perm & 0777 : 0777; + mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm & 0777 : 0777; TRACE("mkdir id %d name %s mode 0%o", id, name, mode); ret = mkdir(name, mode); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; send_status(id, status); xfree(name); } @@ -807,7 +878,7 @@ name = get_string(NULL); TRACE("rmdir id %d name %s", id, name); ret = rmdir(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; send_status(id, status); xfree(name); } @@ -841,93 +912,33 @@ process_rename(void) { u_int32_t id; - struct stat st; char *oldpath, *newpath; - int ret, status = SSH2_FX_FAILURE; + int ret, status; id = get_int(); oldpath = get_string(NULL); newpath = get_string(NULL); TRACE("rename id %d old %s new %s", id, oldpath, newpath); - /* fail if 'newpath' exists */ - if (stat(newpath, &st) == -1) { - ret = rename(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - } + ret = rename(oldpath, newpath); + status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; send_status(id, status); xfree(oldpath); xfree(newpath); } -void -process_readlink(void) -{ - u_int32_t id; - char link[MAXPATHLEN]; - char *path; - id = get_int(); - path = get_string(NULL); - TRACE("readlink id %d path %s", id, path); - if (readlink(path, link, sizeof(link) - 1) == -1) - send_status(id, errno_to_portable(errno)); - else { - Stat s; - - link[sizeof(link) - 1] = '\0'; - attrib_clear(&s.attrib); - s.name = s.long_name = link; - send_names(id, 1, &s); - } - xfree(path); -} - -void -process_symlink(void) -{ - u_int32_t id; - struct stat st; - char *oldpath, *newpath; - int ret, status = SSH2_FX_FAILURE; - - id = get_int(); - oldpath = get_string(NULL); - newpath = get_string(NULL); - TRACE("symlink id %d old %s new %s", id, oldpath, newpath); - /* fail if 'newpath' exists */ - if (stat(newpath, &st) == -1) { - ret = symlink(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; - } - send_status(id, status); - xfree(oldpath); - xfree(newpath); -} - -void -process_extended(void) -{ - u_int32_t id; - char *request; - - id = get_int(); - request = get_string(NULL); - send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ - xfree(request); -} - /* stolen from ssh-agent */ void process(void) { - u_int msg_len; - u_int type; - u_char *cp; + unsigned int msg_len; + unsigned int type; + unsigned char *cp; if (buffer_len(&iqueue) < 5) return; /* Incomplete message. */ - cp = (u_char *) buffer_ptr(&iqueue); + cp = (unsigned char *) buffer_ptr(&iqueue); msg_len = GET_32BIT(cp); if (msg_len > 256 * 1024) { error("bad message "); @@ -938,66 +949,57 @@ buffer_consume(&iqueue, 4); type = buffer_get_char(&iqueue); switch (type) { - case SSH2_FXP_INIT: + case SSH_FXP_INIT: process_init(); break; - case SSH2_FXP_OPEN: + case SSH_FXP_OPEN: process_open(); break; - case SSH2_FXP_CLOSE: + case SSH_FXP_CLOSE: process_close(); break; - case SSH2_FXP_READ: + case SSH_FXP_READ: process_read(); break; - case SSH2_FXP_WRITE: + case SSH_FXP_WRITE: process_write(); break; - case SSH2_FXP_LSTAT: + case SSH_FXP_LSTAT: process_lstat(); break; - case SSH2_FXP_FSTAT: + case SSH_FXP_FSTAT: process_fstat(); break; - case SSH2_FXP_SETSTAT: + case SSH_FXP_SETSTAT: process_setstat(); break; - case SSH2_FXP_FSETSTAT: + case SSH_FXP_FSETSTAT: process_fsetstat(); break; - case SSH2_FXP_OPENDIR: + case SSH_FXP_OPENDIR: process_opendir(); break; - case SSH2_FXP_READDIR: + case SSH_FXP_READDIR: process_readdir(); break; - case SSH2_FXP_REMOVE: + case SSH_FXP_REMOVE: process_remove(); break; - case SSH2_FXP_MKDIR: + case SSH_FXP_MKDIR: process_mkdir(); break; - case SSH2_FXP_RMDIR: + case SSH_FXP_RMDIR: process_rmdir(); break; - case SSH2_FXP_REALPATH: + case SSH_FXP_REALPATH: process_realpath(); break; - case SSH2_FXP_STAT: + case SSH_FXP_STAT: process_stat(); break; - case SSH2_FXP_RENAME: + case SSH_FXP_RENAME: process_rename(); break; - case SSH2_FXP_READLINK: - process_readlink(); - break; - case SSH2_FXP_SYMLINK: - process_symlink(); - break; - case SSH2_FXP_EXTENDED: - process_extended(); - break; default: error("Unknown message %d", type); break; @@ -1007,18 +1009,12 @@ int main(int ac, char **av) { - fd_set *rset, *wset; + fd_set rset, wset; int in, out, max; - ssize_t len, olen, set_size; + ssize_t len, olen; - /* XXX should use getopt */ - handle_init(); -#ifdef DEBUG_SFTP_SERVER - log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); -#endif - in = dup(STDIN_FILENO); out = dup(STDOUT_FILENO); @@ -1031,27 +1027,23 @@ buffer_init(&iqueue); buffer_init(&oqueue); - set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); - rset = (fd_set *)xmalloc(set_size); - wset = (fd_set *)xmalloc(set_size); - for (;;) { - memset(rset, 0, set_size); - memset(wset, 0, set_size); + FD_ZERO(&rset); + FD_ZERO(&wset); - FD_SET(in, rset); + FD_SET(in, &rset); olen = buffer_len(&oqueue); if (olen > 0) - FD_SET(out, wset); + FD_SET(out, &wset); - if (select(max+1, rset, wset, NULL, NULL) < 0) { + if (select(max+1, &rset, &wset, NULL, NULL) < 0) { if (errno == EINTR) continue; exit(2); } /* copy stdin to iqueue */ - if (FD_ISSET(in, rset)) { + if (FD_ISSET(in, &rset)) { char buf[4*4096]; len = read(in, buf, sizeof buf); if (len == 0) { @@ -1065,7 +1057,7 @@ } } /* send oqueue to stdout */ - if (FD_ISSET(out, wset)) { + if (FD_ISSET(out, &wset)) { len = write(out, buffer_ptr(&oqueue), olen); if (len < 0) { error("write error");