From: mouring Date: Thu, 11 Jan 2001 06:20:23 +0000 (+0000) Subject: 20010112 X-Git-Tag: PRE-REORDER~59 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/f546c7809836bd6d7fce818781a88166fe50cded 20010112 - (bal) OpenBSD Sync - markus@cvs.openbsd.org 2001/01/10 22:56:22 [bufaux.h bufaux.c sftp-server.c sftp.h getput.h] cleanup sftp-server implementation: add buffer_get_int64, buffer_put_int64, GET_64BIT, PUT_64BIT parse SSH2_FILEXFER_ATTR_EXTENDED send SSH2_FX_EOF if readdir returns no more entries reply to SSH2_FXP_EXTENDED message use #defines from the draft move #definations to sftp.h more info: http://www.ietf.org/internet-drafts/draft-ietf-secsh-filexfer-00.txt - markus@cvs.openbsd.org 2001/01/10 19:43:20 [sshd.c] XXX - generate_empheral_server_key() is not safe against races, because it calls log() - markus@cvs.openbsd.org 2001/01/09 21:19:50 [packet.c] allow TCP_NDELAY for ipv6; from netbsd via itojun@ --- diff --git a/ChangeLog b/ChangeLog index 3919f779..9a92eb1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +20010112 + - (bal) OpenBSD Sync + - markus@cvs.openbsd.org 2001/01/10 22:56:22 + [bufaux.h bufaux.c sftp-server.c sftp.h getput.h] + cleanup sftp-server implementation: + add buffer_get_int64, buffer_put_int64, GET_64BIT, PUT_64BIT + parse SSH2_FILEXFER_ATTR_EXTENDED + send SSH2_FX_EOF if readdir returns no more entries + reply to SSH2_FXP_EXTENDED message + use #defines from the draft + move #definations to sftp.h + more info: + http://www.ietf.org/internet-drafts/draft-ietf-secsh-filexfer-00.txt + - markus@cvs.openbsd.org 2001/01/10 19:43:20 + [sshd.c] + XXX - generate_empheral_server_key() is not safe against races, + because it calls log() + - markus@cvs.openbsd.org 2001/01/09 21:19:50 + [packet.c] + allow TCP_NDELAY for ipv6; from netbsd via itojun@ + 20010110 - (djm) SNI/Reliant Unix needs USE_PIPES and $DISPLAY hack. Report from Bladt Norbert diff --git a/bufaux.c b/bufaux.c index 5853ee60..149677f7 100644 --- a/bufaux.c +++ b/bufaux.c @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: bufaux.c,v 1.14 2000/12/19 23:17:55 markus Exp $"); +RCSID("$OpenBSD: bufaux.c,v 1.15 2001/01/10 22:56:22 markus Exp $"); #include "ssh.h" #include @@ -152,6 +152,14 @@ buffer_get_int(Buffer *buffer) return GET_32BIT(buf); } +u_int64_t +buffer_get_int64(Buffer *buffer) +{ + u_char buf[8]; + buffer_get(buffer, (char *) buf, 8); + return GET_64BIT(buf); +} + /* * Stores an integer in the buffer in 4 bytes, msb first. */ @@ -163,6 +171,14 @@ buffer_put_int(Buffer *buffer, u_int value) buffer_append(buffer, buf, 4); } +void +buffer_put_int64(Buffer *buffer, u_int64_t value) +{ + char buf[8]; + PUT_64BIT(buf, value); + buffer_append(buffer, buf, 8); +} + /* * Returns an arbitrary binary string from the buffer. The string cannot * be longer than 256k. The returned value points to memory allocated diff --git a/bufaux.h b/bufaux.h index 6c73d4fb..ec430022 100644 --- a/bufaux.h +++ b/bufaux.h @@ -10,7 +10,7 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: bufaux.h,v 1.9 2000/12/19 23:17:55 markus Exp $"); */ +/* RCSID("$OpenBSD: bufaux.h,v 1.10 2001/01/10 22:56:22 markus Exp $"); */ #ifndef BUFAUX_H #define BUFAUX_H @@ -30,9 +30,11 @@ int buffer_get_bignum2(Buffer *buffer, BIGNUM * value); /* Returns an integer from the buffer (4 bytes, msb first). */ u_int buffer_get_int(Buffer * buffer); +u_int64_t buffer_get_int64(Buffer *buffer); /* Stores an integer in the buffer in 4 bytes, msb first. */ void buffer_put_int(Buffer * buffer, u_int value); +void buffer_put_int64(Buffer *buffer, u_int64_t value); /* Returns a character from the buffer (0 - 255). */ int buffer_get_char(Buffer * buffer); diff --git a/getput.h b/getput.h index b8e83453..1a19d22c 100644 --- a/getput.h +++ b/getput.h @@ -11,13 +11,22 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: getput.h,v 1.6 2000/12/19 23:17:56 markus Exp $"); */ +/* RCSID("$OpenBSD: getput.h,v 1.7 2001/01/10 22:56:22 markus Exp $"); */ #ifndef GETPUT_H #define GETPUT_H /*------------ macros for storing/extracting msb first words -------------*/ +#define GET_64BIT(cp) (((u_int64_t)(u_char)(cp)[0] << 56) | \ + ((u_int64_t)(u_char)(cp)[1] << 48) | \ + ((u_int64_t)(u_char)(cp)[2] << 40) | \ + ((u_int64_t)(u_char)(cp)[3] << 32) | \ + ((u_int64_t)(u_char)(cp)[4] << 24) | \ + ((u_int64_t)(u_char)(cp)[5] << 16) | \ + ((u_int64_t)(u_char)(cp)[6] << 8) | \ + ((u_int64_t)(u_char)(cp)[7])) + #define GET_32BIT(cp) (((u_long)(u_char)(cp)[0] << 24) | \ ((u_long)(u_char)(cp)[1] << 16) | \ ((u_long)(u_char)(cp)[2] << 8) | \ @@ -26,6 +35,16 @@ #define GET_16BIT(cp) (((u_long)(u_char)(cp)[0] << 8) | \ ((u_long)(u_char)(cp)[1])) +#define PUT_64BIT(cp, value) do { \ + (cp)[0] = (value) >> 56; \ + (cp)[1] = (value) >> 48; \ + (cp)[2] = (value) >> 40; \ + (cp)[3] = (value) >> 32; \ + (cp)[4] = (value) >> 24; \ + (cp)[5] = (value) >> 16; \ + (cp)[6] = (value) >> 8; \ + (cp)[7] = (value); } while (0) + #define PUT_32BIT(cp, value) do { \ (cp)[0] = (value) >> 24; \ (cp)[1] = (value) >> 16; \ @@ -36,26 +55,4 @@ (cp)[0] = (value) >> 8; \ (cp)[1] = (value); } while (0) -/*------------ macros for storing/extracting lsb first words -------------*/ - -#define GET_32BIT_LSB_FIRST(cp) \ - (((u_long)(u_char)(cp)[0]) | \ - ((u_long)(u_char)(cp)[1] << 8) | \ - ((u_long)(u_char)(cp)[2] << 16) | \ - ((u_long)(u_char)(cp)[3] << 24)) - -#define GET_16BIT_LSB_FIRST(cp) \ - (((u_long)(u_char)(cp)[0]) | \ - ((u_long)(u_char)(cp)[1] << 8)) - -#define PUT_32BIT_LSB_FIRST(cp, value) do { \ - (cp)[0] = (value); \ - (cp)[1] = (value) >> 8; \ - (cp)[2] = (value) >> 16; \ - (cp)[3] = (value) >> 24; } while (0) - -#define PUT_16BIT_LSB_FIRST(cp, value) do { \ - (cp)[0] = (value); \ - (cp)[1] = (value) >> 8; } while (0) - #endif /* GETPUT_H */ diff --git a/packet.c b/packet.c index 5435b071..cd42f2f7 100644 --- a/packet.c +++ b/packet.c @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: packet.c,v 1.41 2001/01/02 20:41:02 markus Exp $"); +RCSID("$OpenBSD: packet.c,v 1.42 2001/01/09 21:19:50 markus Exp $"); #include "xmalloc.h" #include "buffer.h" @@ -1247,25 +1247,26 @@ packet_set_interactive(int interactive, int keepalives) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); } /* - * IPTOS_LOWDELAY, TCP_NODELAY and IPTOS_THROUGHPUT are IPv4 only + * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only */ - if (!packet_connection_is_ipv4()) - return; if (interactive) { /* * Set IP options for an interactive connection. Use * IPTOS_LOWDELAY and TCP_NODELAY. */ #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) - int lowdelay = IPTOS_LOWDELAY; - if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &lowdelay, - sizeof(lowdelay)) < 0) - error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno)); + if (packet_connection_is_ipv4()) { + int lowdelay = IPTOS_LOWDELAY; + if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, + (void *) &lowdelay, sizeof(lowdelay)) < 0) + error("setsockopt IPTOS_LOWDELAY: %.100s", + strerror(errno)); + } #endif if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof(on)) < 0) error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); - } else { + } else if (packet_connection_is_ipv4()) { /* * Set IP options for a non-interactive connection. Use * IPTOS_THROUGHPUT. diff --git a/sftp-server.c b/sftp-server.c index 7113bce8..40a53531 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: sftp-server.c,v 1.9 2000/12/19 23:17:58 markus Exp $"); +RCSID("$OpenBSD: sftp-server.c,v 1.10 2001/01/10 22:56:22 markus Exp $"); #include "ssh.h" #include "buffer.h" @@ -30,65 +30,13 @@ RCSID("$OpenBSD: sftp-server.c,v 1.9 2000/12/19 23:17:58 markus Exp $"); #include "getput.h" #include "xmalloc.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 - +#include "sftp.h" /* 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 log +#define TRACE debug #ifdef HAVE___PROGNAME extern char *__progname; @@ -108,8 +56,6 @@ typedef struct Stat 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; @@ -131,25 +77,25 @@ errno_to_portable(int unixerrno) int ret = 0; switch (unixerrno) { case 0: - ret = SSH_FX_OK; + ret = SSH2_FX_OK; break; case ENOENT: case ENOTDIR: case EBADF: case ELOOP: - ret = SSH_FX_NO_SUCH_FILE; + ret = SSH2_FX_NO_SUCH_FILE; break; case EPERM: case EACCES: case EFAULT: - ret = SSH_FX_PERMISSION_DENIED; + ret = SSH2_FX_PERMISSION_DENIED; break; case ENAMETOOLONG: case EINVAL: - ret = SSH_FX_BAD_MESSAGE; + ret = SSH2_FX_BAD_MESSAGE; break; default: - ret = SSH_FX_FAILURE; + ret = SSH2_FX_FAILURE; break; } return ret; @@ -159,19 +105,19 @@ int flags_from_portable(int pflags) { int flags = 0; - if (pflags & SSH_FXF_READ && - pflags & SSH_FXF_WRITE) { + if (pflags & SSH2_FXF_READ && + pflags & SSH2_FXF_WRITE) { flags = O_RDWR; - } else if (pflags & SSH_FXF_READ) { + } else if (pflags & SSH2_FXF_READ) { flags = O_RDONLY; - } else if (pflags & SSH_FXF_WRITE) { + } else if (pflags & SSH2_FXF_WRITE) { flags = O_WRONLY; } - if (pflags & SSH_FXF_CREAT) + if (pflags & SSH2_FXF_CREAT) flags |= O_CREAT; - if (pflags & SSH_FXF_TRUNC) + if (pflags & SSH2_FXF_TRUNC) flags |= O_TRUNC; - if (pflags & SSH_FXF_EXCL) + if (pflags & SSH2_FXF_EXCL) flags |= O_EXCL; return flags; } @@ -180,8 +126,6 @@ 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; @@ -196,22 +140,32 @@ 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 & SSH2_FILEXFER_ATTR_SIZE) { + a.size = buffer_get_int64(b); } - if (a.flags & SSH_FXA_HAVE_UGID) { + if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { a.uid = buffer_get_int(b); a.gid = buffer_get_int(b); } - if (a.flags & SSH_FXA_HAVE_PERM) { + if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { a.perm = buffer_get_int(b); } - if (a.flags & SSH_FXA_HAVE_TIME) { + if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { a.atime = buffer_get_int(b); a.mtime = buffer_get_int(b); } + /* vendor-specific extensions */ + if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { + char *type, *data; + int i, count; + count = buffer_get_int(b); + for (i = 0; i < count; i++) { + type = buffer_get_string(b, NULL); + data = buffer_get_string(b, NULL); + xfree(type); + xfree(data); + } + } return &a; } @@ -219,18 +173,17 @@ 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 & SSH2_FILEXFER_ATTR_SIZE) { + buffer_put_int64(b, a->size); } - if (a->flags & SSH_FXA_HAVE_UGID) { + if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { buffer_put_int(b, a->uid); buffer_put_int(b, a->gid); } - if (a->flags & SSH_FXA_HAVE_PERM) { + if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { buffer_put_int(b, a->perm); } - if (a->flags & SSH_FXA_HAVE_TIME) { + if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { buffer_put_int(b, a->atime); buffer_put_int(b, a->mtime); } @@ -242,16 +195,14 @@ stat_to_attrib(struct stat *st) static Attrib a; attrib_clear(&a); a.flags = 0; - a.flags |= SSH_FXA_HAVE_SIZE; + a.flags |= SSH2_FILEXFER_ATTR_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.flags |= SSH2_FILEXFER_ATTR_UIDGID; a.uid = st->st_uid; a.gid = st->st_gid; - a.flags |= SSH_FXA_HAVE_PERM; + a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = st->st_mode; - a.flags |= SSH_FXA_HAVE_TIME; + a.flags |= SSH2_FILEXFER_ATTR_ACMODTIME; a.atime = st->st_atime; a.mtime = st->st_mtime; return &a; @@ -306,7 +257,8 @@ handle_new(int use, char *name, int fd, DIR *dirp) 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 @@ -381,10 +333,11 @@ int get_handle(void) { char *handle; - int val; + int val = -1; u_int hlen; handle = get_string(&hlen); - val = handle_from_string(handle, hlen); + if (hlen < 256) + val = handle_from_string(handle, hlen); xfree(handle); return val; } @@ -406,7 +359,7 @@ send_status(u_int32_t id, u_int32_t error) Buffer msg; TRACE("sent status id %d error %d", id, error); buffer_init(&msg); - buffer_put_char(&msg, SSH_FXP_STATUS); + buffer_put_char(&msg, SSH2_FXP_STATUS); buffer_put_int(&msg, id); buffer_put_int(&msg, error); send_msg(&msg); @@ -428,7 +381,7 @@ void send_data(u_int32_t id, char *data, int dlen) { TRACE("sent data id %d len %d", id, dlen); - send_data_or_handle(SSH_FXP_DATA, id, data, dlen); + send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); } void @@ -438,7 +391,7 @@ send_handle(u_int32_t id, int handle) int hlen; handle_to_string(handle, &string, &hlen); TRACE("sent handle id %d handle %d", id, handle); - send_data_or_handle(SSH_FXP_HANDLE, id, string, hlen); + send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); xfree(string); } @@ -448,7 +401,7 @@ send_names(u_int32_t id, int count, Stat *stats) Buffer msg; int i; buffer_init(&msg); - buffer_put_char(&msg, SSH_FXP_NAME); + buffer_put_char(&msg, SSH2_FXP_NAME); buffer_put_int(&msg, id); buffer_put_int(&msg, count); TRACE("sent names id %d count %d", id, count); @@ -467,7 +420,7 @@ 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, SSH_FXP_ATTRS); + buffer_put_char(&msg, SSH2_FXP_ATTRS); buffer_put_int(&msg, id); encode_attrib(&msg, a); send_msg(&msg); @@ -484,8 +437,8 @@ process_init(void) TRACE("client version %d", version); buffer_init(&msg); - buffer_put_char(&msg, SSH_FXP_VERSION); - buffer_put_int(&msg, SSH_FILEXFER_VERSION); + buffer_put_char(&msg, SSH2_FXP_VERSION); + buffer_put_int(&msg, SSH2_FILEXFER_VERSION); send_msg(&msg); buffer_free(&msg); } @@ -496,14 +449,14 @@ process_open(void) u_int32_t id, pflags; Attrib *a; char *name; - int handle, fd, flags, mode, status = SSH_FX_FAILURE; + int handle, fd, flags, mode, status = SSH2_FX_FAILURE; id = get_int(); name = get_string(NULL); - pflags = get_int(); + pflags = get_int(); /* portable flags */ a = get_attrib(); flags = flags_from_portable(pflags); - mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm : 0666; + mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? 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) { @@ -514,10 +467,10 @@ process_open(void) close(fd); } else { send_handle(id, handle); - status = SSH_FX_OK; + status = SSH2_FX_OK; } } - if (status != SSH_FX_OK) + if (status != SSH2_FX_OK) send_status(id, status); xfree(name); } @@ -526,13 +479,13 @@ void process_close(void) { u_int32_t id; - int handle, ret, status = SSH_FX_FAILURE; + int handle, ret, status = SSH2_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) : SSH_FX_OK; + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); } @@ -540,17 +493,15 @@ void process_read(void) { char buf[64*1024]; - u_int32_t id, off_high, off_low, len; - int handle, fd, ret, status = SSH_FX_FAILURE; + u_int32_t id, len; + int handle, fd, ret, status = SSH2_FX_FAILURE; u_int64_t off; id = get_int(); handle = get_handle(); - off_high = get_int(); - off_low = get_int(); + off = get_int64(); len = get_int(); - off = (((u_int64_t) off_high) << 32) + off_low; TRACE("read id %d handle %d off %lld len %d", id, handle, off, len); if (len > sizeof buf) { len = sizeof buf; @@ -566,33 +517,31 @@ process_read(void) if (ret < 0) { status = errno_to_portable(errno); } else if (ret == 0) { - status = SSH_FX_EOF; + status = SSH2_FX_EOF; } else { send_data(id, buf, ret); - status = SSH_FX_OK; + status = SSH2_FX_OK; } } } - if (status != SSH_FX_OK) + if (status != SSH2_FX_OK) send_status(id, status); } void process_write(void) { - u_int32_t id, off_high, off_low; + u_int32_t id; u_int64_t off; u_int len; - int handle, fd, ret, status = SSH_FX_FAILURE; + int handle, fd, ret, status = SSH2_FX_FAILURE; char *data; id = get_int(); handle = get_handle(); - off_high = get_int(); - off_low = get_int(); + off = get_int64(); data = get_string(&len); - off = (((u_int64_t) off_high) << 32) + off_low; TRACE("write id %d handle %d off %lld len %d", id, handle, off, len); fd = handle_to_fd(handle); if (fd >= 0) { @@ -606,7 +555,7 @@ process_write(void) error("process_write: write failed"); status = errno_to_portable(errno); } else if (ret == len) { - status = SSH_FX_OK; + status = SSH2_FX_OK; } else { log("nothing at all written"); } @@ -623,7 +572,7 @@ process_do_stat(int do_lstat) struct stat st; u_int32_t id; char *name; - int ret, status = SSH_FX_FAILURE; + int ret, status = SSH2_FX_FAILURE; id = get_int(); name = get_string(NULL); @@ -634,9 +583,9 @@ process_do_stat(int do_lstat) } else { a = stat_to_attrib(&st); send_attrib(id, a); - status = SSH_FX_OK; + status = SSH2_FX_OK; } - if (status != SSH_FX_OK) + if (status != SSH2_FX_OK) send_status(id, status); xfree(name); } @@ -659,7 +608,7 @@ process_fstat(void) Attrib *a; struct stat st; u_int32_t id; - int fd, ret, handle, status = SSH_FX_FAILURE; + int fd, ret, handle, status = SSH2_FX_FAILURE; id = get_int(); handle = get_handle(); @@ -672,10 +621,10 @@ process_fstat(void) } else { a = stat_to_attrib(&st); send_attrib(id, a); - status = SSH_FX_OK; + status = SSH2_FX_OK; } } - if (status != SSH_FX_OK) + if (status != SSH2_FX_OK) send_status(id, status); } @@ -697,18 +646,18 @@ process_setstat(void) u_int32_t id; char *name; int ret; - int status = SSH_FX_OK; + int status = SSH2_FX_OK; id = get_int(); name = get_string(NULL); a = get_attrib(); TRACE("setstat id %d name %s", id, name); - if (a->flags & SSH_FXA_HAVE_PERM) { + if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { ret = chmod(name, a->perm & 0777); if (ret == -1) status = errno_to_portable(errno); } - if (a->flags & SSH_FXA_HAVE_TIME) { + if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { ret = utimes(name, attrib_to_tv(a)); if (ret == -1) status = errno_to_portable(errno); @@ -723,7 +672,7 @@ process_fsetstat(void) Attrib *a; u_int32_t id; int handle, fd, ret; - int status = SSH_FX_OK; + int status = SSH2_FX_OK; char *name; id = get_int(); @@ -733,14 +682,14 @@ process_fsetstat(void) fd = handle_to_fd(handle); name = handle_to_name(handle); if ((fd < 0) || (name == NULL)) { - status = SSH_FX_FAILURE; + status = SSH2_FX_FAILURE; } else { - if (a->flags & SSH_FXA_HAVE_PERM) { + if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { ret = fchmod(fd, a->perm & 0777); if (ret == -1) status = errno_to_portable(errno); } - if (a->flags & SSH_FXA_HAVE_TIME) { + if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { #ifdef HAVE_FUTIMES ret = futimes(fd, attrib_to_tv(a)); #else @@ -758,7 +707,7 @@ process_opendir(void) { DIR *dirp = NULL; char *path; - int handle, status = SSH_FX_FAILURE; + int handle, status = SSH2_FX_FAILURE; u_int32_t id; id = get_int(); @@ -773,22 +722,28 @@ process_opendir(void) closedir(dirp); } else { send_handle(id, handle); - status = SSH_FX_OK; + status = SSH2_FX_OK; } } - if (status != SSH_FX_OK) + if (status != SSH2_FX_OK) send_status(id, status); xfree(path); } +/* + * XXX, draft-ietf-secsh-filexfer-00.txt says: + * The recommended format for the longname field is as follows: + * -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer + * 1234567890 123 12345678 12345678 12345678 123456789012 + */ char * ls_file(char *name, struct stat *st) { char buf[1024]; snprintf(buf, sizeof buf, "0%o %d %d %lld %d %s", - st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size,(int) st->st_mtime, - name); + st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size, + (int)st->st_mtime, name); return xstrdup(buf); } @@ -807,7 +762,7 @@ process_readdir(void) dirp = handle_to_dir(handle); path = handle_to_name(handle); if (dirp == NULL || path == NULL) { - send_status(id, SSH_FX_FAILURE); + send_status(id, SSH2_FX_FAILURE); } else { Attrib *a; struct stat st; @@ -834,10 +789,14 @@ process_readdir(void) if (count == 100) break; } - send_names(id, count, stats); - for(i = 0; i < count; i++) { - xfree(stats[i].name); - xfree(stats[i].long_name); + 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); } xfree(stats); } @@ -848,14 +807,14 @@ process_remove(void) { char *name; u_int32_t id; - int status = SSH_FX_FAILURE; + int status = SSH2_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) : SSH_FX_OK; + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); xfree(name); } @@ -866,15 +825,16 @@ process_mkdir(void) Attrib *a; u_int32_t id; char *name; - int ret, mode, status = SSH_FX_FAILURE; + int ret, mode, status = SSH2_FX_FAILURE; id = get_int(); name = get_string(NULL); a = get_attrib(); - mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm & 0777 : 0777; + mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? + 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) : SSH_FX_OK; + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); xfree(name); } @@ -890,7 +850,7 @@ process_rmdir(void) name = get_string(NULL); TRACE("rmdir id %d name %s", id, name); ret = rmdir(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); xfree(name); } @@ -932,12 +892,23 @@ process_rename(void) newpath = get_string(NULL); TRACE("rename id %d old %s new %s", id, oldpath, newpath); ret = rename(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; + 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 */ @@ -961,57 +932,60 @@ process(void) buffer_consume(&iqueue, 4); type = buffer_get_char(&iqueue); switch (type) { - case SSH_FXP_INIT: + case SSH2_FXP_INIT: process_init(); break; - case SSH_FXP_OPEN: + case SSH2_FXP_OPEN: process_open(); break; - case SSH_FXP_CLOSE: + case SSH2_FXP_CLOSE: process_close(); break; - case SSH_FXP_READ: + case SSH2_FXP_READ: process_read(); break; - case SSH_FXP_WRITE: + case SSH2_FXP_WRITE: process_write(); break; - case SSH_FXP_LSTAT: + case SSH2_FXP_LSTAT: process_lstat(); break; - case SSH_FXP_FSTAT: + case SSH2_FXP_FSTAT: process_fstat(); break; - case SSH_FXP_SETSTAT: + case SSH2_FXP_SETSTAT: process_setstat(); break; - case SSH_FXP_FSETSTAT: + case SSH2_FXP_FSETSTAT: process_fsetstat(); break; - case SSH_FXP_OPENDIR: + case SSH2_FXP_OPENDIR: process_opendir(); break; - case SSH_FXP_READDIR: + case SSH2_FXP_READDIR: process_readdir(); break; - case SSH_FXP_REMOVE: + case SSH2_FXP_REMOVE: process_remove(); break; - case SSH_FXP_MKDIR: + case SSH2_FXP_MKDIR: process_mkdir(); break; - case SSH_FXP_RMDIR: + case SSH2_FXP_RMDIR: process_rmdir(); break; - case SSH_FXP_REALPATH: + case SSH2_FXP_REALPATH: process_realpath(); break; - case SSH_FXP_STAT: + case SSH2_FXP_STAT: process_stat(); break; - case SSH_FXP_RENAME: + case SSH2_FXP_RENAME: process_rename(); break; + case SSH2_FXP_EXTENDED: + process_extended(); + break; default: error("Unknown message %d", type); break; @@ -1028,6 +1002,8 @@ main(int ac, char **av) __progname = get_progname(av[0]); handle_init(); + log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); + in = dup(STDIN_FILENO); out = dup(STDOUT_FILENO); diff --git a/sftp.h b/sftp.h new file mode 100644 index 00000000..4fdc2b6d --- /dev/null +++ b/sftp.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * draft-ietf-secsh-filexfer-00.txt + */ + +/* version */ +#define SSH2_FILEXFER_VERSION 2 + +/* client to server */ +#define SSH2_FXP_INIT 1 +#define SSH2_FXP_OPEN 3 +#define SSH2_FXP_CLOSE 4 +#define SSH2_FXP_READ 5 +#define SSH2_FXP_WRITE 6 +#define SSH2_FXP_LSTAT 7 +#define SSH2_FXP_FSTAT 8 +#define SSH2_FXP_SETSTAT 9 +#define SSH2_FXP_FSETSTAT 10 +#define SSH2_FXP_OPENDIR 11 +#define SSH2_FXP_READDIR 12 +#define SSH2_FXP_REMOVE 13 +#define SSH2_FXP_MKDIR 14 +#define SSH2_FXP_RMDIR 15 +#define SSH2_FXP_REALPATH 16 +#define SSH2_FXP_STAT 17 +#define SSH2_FXP_RENAME 18 + +/* server to client */ +#define SSH2_FXP_VERSION 2 +#define SSH2_FXP_STATUS 101 +#define SSH2_FXP_HANDLE 102 +#define SSH2_FXP_DATA 103 +#define SSH2_FXP_NAME 104 +#define SSH2_FXP_ATTRS 105 + +#define SSH2_FXP_EXTENDED 200 +#define SSH2_FXP_EXTENDED_REPLY 201 + +/* attributes */ +#define SSH2_FILEXFER_ATTR_SIZE 0x00000001 +#define SSH2_FILEXFER_ATTR_UIDGID 0x00000002 +#define SSH2_FILEXFER_ATTR_PERMISSIONS 0x00000004 +#define SSH2_FILEXFER_ATTR_ACMODTIME 0x00000008 +#define SSH2_FILEXFER_ATTR_EXTENDED 0x80000000 + +/* portable open modes */ +#define SSH2_FXF_READ 0x00000001 +#define SSH2_FXF_WRITE 0x00000002 +#define SSH2_FXF_APPEND 0x00000004 +#define SSH2_FXF_CREAT 0x00000008 +#define SSH2_FXF_TRUNC 0x00000010 +#define SSH2_FXF_EXCL 0x00000020 + +/* status messages */ +#define SSH2_FX_OK 0 +#define SSH2_FX_EOF 1 +#define SSH2_FX_NO_SUCH_FILE 2 +#define SSH2_FX_PERMISSION_DENIED 3 +#define SSH2_FX_FAILURE 4 +#define SSH2_FX_BAD_MESSAGE 5 +#define SSH2_FX_NO_CONNECTION 6 +#define SSH2_FX_CONNECTION_LOST 7 +#define SSH2_FX_OP_UNSUPPORTED 8 diff --git a/sshd.c b/sshd.c index aa7e016b..298a1b6b 100644 --- a/sshd.c +++ b/sshd.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.146 2001/01/07 11:28:07 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.147 2001/01/10 19:43:20 deraadt Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -266,8 +266,8 @@ grace_alarm_handler(int sig) * do anything with the private key or random state before forking. * Thus there should be no concurrency control/asynchronous execution * problems. + * XXX calling log() is not safe from races. */ -/* XXX do we really want this work to be done in a signal handler ? -m */ void generate_empheral_server_key(void) { @@ -279,6 +279,7 @@ generate_empheral_server_key(void) arc4random_stir(); log("RSA key generation complete."); } + void key_regeneration_alarm(int sig) {