diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | bufaux.c | 18 | ||||
-rw-r--r-- | bufaux.h | 4 | ||||
-rw-r--r-- | getput.h | 43 | ||||
-rw-r--r-- | packet.c | 19 | ||||
-rw-r--r-- | sftp-server.c | 314 | ||||
-rw-r--r-- | sftp.h | 86 | ||||
-rw-r--r-- | sshd.c | 5 |
8 files changed, 305 insertions, 205 deletions
@@ -1,3 +1,24 @@ | |||
1 | 20010112 | ||
2 | - (bal) OpenBSD Sync | ||
3 | - markus@cvs.openbsd.org 2001/01/10 22:56:22 | ||
4 | [bufaux.h bufaux.c sftp-server.c sftp.h getput.h] | ||
5 | cleanup sftp-server implementation: | ||
6 | add buffer_get_int64, buffer_put_int64, GET_64BIT, PUT_64BIT | ||
7 | parse SSH2_FILEXFER_ATTR_EXTENDED | ||
8 | send SSH2_FX_EOF if readdir returns no more entries | ||
9 | reply to SSH2_FXP_EXTENDED message | ||
10 | use #defines from the draft | ||
11 | move #definations to sftp.h | ||
12 | more info: | ||
13 | http://www.ietf.org/internet-drafts/draft-ietf-secsh-filexfer-00.txt | ||
14 | - markus@cvs.openbsd.org 2001/01/10 19:43:20 | ||
15 | [sshd.c] | ||
16 | XXX - generate_empheral_server_key() is not safe against races, | ||
17 | because it calls log() | ||
18 | - markus@cvs.openbsd.org 2001/01/09 21:19:50 | ||
19 | [packet.c] | ||
20 | allow TCP_NDELAY for ipv6; from netbsd via itojun@ | ||
21 | |||
1 | 20010110 | 22 | 20010110 |
2 | - (djm) SNI/Reliant Unix needs USE_PIPES and $DISPLAY hack. Report from | 23 | - (djm) SNI/Reliant Unix needs USE_PIPES and $DISPLAY hack. Report from |
3 | Bladt Norbert <Norbert.Bladt@adi.ch> | 24 | Bladt Norbert <Norbert.Bladt@adi.ch> |
@@ -37,7 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include "includes.h" | 39 | #include "includes.h" |
40 | RCSID("$OpenBSD: bufaux.c,v 1.14 2000/12/19 23:17:55 markus Exp $"); | 40 | RCSID("$OpenBSD: bufaux.c,v 1.15 2001/01/10 22:56:22 markus Exp $"); |
41 | 41 | ||
42 | #include "ssh.h" | 42 | #include "ssh.h" |
43 | #include <openssl/bn.h> | 43 | #include <openssl/bn.h> |
@@ -152,6 +152,14 @@ buffer_get_int(Buffer *buffer) | |||
152 | return GET_32BIT(buf); | 152 | return GET_32BIT(buf); |
153 | } | 153 | } |
154 | 154 | ||
155 | u_int64_t | ||
156 | buffer_get_int64(Buffer *buffer) | ||
157 | { | ||
158 | u_char buf[8]; | ||
159 | buffer_get(buffer, (char *) buf, 8); | ||
160 | return GET_64BIT(buf); | ||
161 | } | ||
162 | |||
155 | /* | 163 | /* |
156 | * Stores an integer in the buffer in 4 bytes, msb first. | 164 | * Stores an integer in the buffer in 4 bytes, msb first. |
157 | */ | 165 | */ |
@@ -163,6 +171,14 @@ buffer_put_int(Buffer *buffer, u_int value) | |||
163 | buffer_append(buffer, buf, 4); | 171 | buffer_append(buffer, buf, 4); |
164 | } | 172 | } |
165 | 173 | ||
174 | void | ||
175 | buffer_put_int64(Buffer *buffer, u_int64_t value) | ||
176 | { | ||
177 | char buf[8]; | ||
178 | PUT_64BIT(buf, value); | ||
179 | buffer_append(buffer, buf, 8); | ||
180 | } | ||
181 | |||
166 | /* | 182 | /* |
167 | * Returns an arbitrary binary string from the buffer. The string cannot | 183 | * Returns an arbitrary binary string from the buffer. The string cannot |
168 | * be longer than 256k. The returned value points to memory allocated | 184 | * be longer than 256k. The returned value points to memory allocated |
@@ -10,7 +10,7 @@ | |||
10 | * called by a name other than "ssh" or "Secure Shell". | 10 | * called by a name other than "ssh" or "Secure Shell". |
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* RCSID("$OpenBSD: bufaux.h,v 1.9 2000/12/19 23:17:55 markus Exp $"); */ | 13 | /* RCSID("$OpenBSD: bufaux.h,v 1.10 2001/01/10 22:56:22 markus Exp $"); */ |
14 | 14 | ||
15 | #ifndef BUFAUX_H | 15 | #ifndef BUFAUX_H |
16 | #define BUFAUX_H | 16 | #define BUFAUX_H |
@@ -30,9 +30,11 @@ int buffer_get_bignum2(Buffer *buffer, BIGNUM * value); | |||
30 | 30 | ||
31 | /* Returns an integer from the buffer (4 bytes, msb first). */ | 31 | /* Returns an integer from the buffer (4 bytes, msb first). */ |
32 | u_int buffer_get_int(Buffer * buffer); | 32 | u_int buffer_get_int(Buffer * buffer); |
33 | u_int64_t buffer_get_int64(Buffer *buffer); | ||
33 | 34 | ||
34 | /* Stores an integer in the buffer in 4 bytes, msb first. */ | 35 | /* Stores an integer in the buffer in 4 bytes, msb first. */ |
35 | void buffer_put_int(Buffer * buffer, u_int value); | 36 | void buffer_put_int(Buffer * buffer, u_int value); |
37 | void buffer_put_int64(Buffer *buffer, u_int64_t value); | ||
36 | 38 | ||
37 | /* Returns a character from the buffer (0 - 255). */ | 39 | /* Returns a character from the buffer (0 - 255). */ |
38 | int buffer_get_char(Buffer * buffer); | 40 | int buffer_get_char(Buffer * buffer); |
@@ -11,13 +11,22 @@ | |||
11 | * called by a name other than "ssh" or "Secure Shell". | 11 | * called by a name other than "ssh" or "Secure Shell". |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /* RCSID("$OpenBSD: getput.h,v 1.6 2000/12/19 23:17:56 markus Exp $"); */ | 14 | /* RCSID("$OpenBSD: getput.h,v 1.7 2001/01/10 22:56:22 markus Exp $"); */ |
15 | 15 | ||
16 | #ifndef GETPUT_H | 16 | #ifndef GETPUT_H |
17 | #define GETPUT_H | 17 | #define GETPUT_H |
18 | 18 | ||
19 | /*------------ macros for storing/extracting msb first words -------------*/ | 19 | /*------------ macros for storing/extracting msb first words -------------*/ |
20 | 20 | ||
21 | #define GET_64BIT(cp) (((u_int64_t)(u_char)(cp)[0] << 56) | \ | ||
22 | ((u_int64_t)(u_char)(cp)[1] << 48) | \ | ||
23 | ((u_int64_t)(u_char)(cp)[2] << 40) | \ | ||
24 | ((u_int64_t)(u_char)(cp)[3] << 32) | \ | ||
25 | ((u_int64_t)(u_char)(cp)[4] << 24) | \ | ||
26 | ((u_int64_t)(u_char)(cp)[5] << 16) | \ | ||
27 | ((u_int64_t)(u_char)(cp)[6] << 8) | \ | ||
28 | ((u_int64_t)(u_char)(cp)[7])) | ||
29 | |||
21 | #define GET_32BIT(cp) (((u_long)(u_char)(cp)[0] << 24) | \ | 30 | #define GET_32BIT(cp) (((u_long)(u_char)(cp)[0] << 24) | \ |
22 | ((u_long)(u_char)(cp)[1] << 16) | \ | 31 | ((u_long)(u_char)(cp)[1] << 16) | \ |
23 | ((u_long)(u_char)(cp)[2] << 8) | \ | 32 | ((u_long)(u_char)(cp)[2] << 8) | \ |
@@ -26,6 +35,16 @@ | |||
26 | #define GET_16BIT(cp) (((u_long)(u_char)(cp)[0] << 8) | \ | 35 | #define GET_16BIT(cp) (((u_long)(u_char)(cp)[0] << 8) | \ |
27 | ((u_long)(u_char)(cp)[1])) | 36 | ((u_long)(u_char)(cp)[1])) |
28 | 37 | ||
38 | #define PUT_64BIT(cp, value) do { \ | ||
39 | (cp)[0] = (value) >> 56; \ | ||
40 | (cp)[1] = (value) >> 48; \ | ||
41 | (cp)[2] = (value) >> 40; \ | ||
42 | (cp)[3] = (value) >> 32; \ | ||
43 | (cp)[4] = (value) >> 24; \ | ||
44 | (cp)[5] = (value) >> 16; \ | ||
45 | (cp)[6] = (value) >> 8; \ | ||
46 | (cp)[7] = (value); } while (0) | ||
47 | |||
29 | #define PUT_32BIT(cp, value) do { \ | 48 | #define PUT_32BIT(cp, value) do { \ |
30 | (cp)[0] = (value) >> 24; \ | 49 | (cp)[0] = (value) >> 24; \ |
31 | (cp)[1] = (value) >> 16; \ | 50 | (cp)[1] = (value) >> 16; \ |
@@ -36,26 +55,4 @@ | |||
36 | (cp)[0] = (value) >> 8; \ | 55 | (cp)[0] = (value) >> 8; \ |
37 | (cp)[1] = (value); } while (0) | 56 | (cp)[1] = (value); } while (0) |
38 | 57 | ||
39 | /*------------ macros for storing/extracting lsb first words -------------*/ | ||
40 | |||
41 | #define GET_32BIT_LSB_FIRST(cp) \ | ||
42 | (((u_long)(u_char)(cp)[0]) | \ | ||
43 | ((u_long)(u_char)(cp)[1] << 8) | \ | ||
44 | ((u_long)(u_char)(cp)[2] << 16) | \ | ||
45 | ((u_long)(u_char)(cp)[3] << 24)) | ||
46 | |||
47 | #define GET_16BIT_LSB_FIRST(cp) \ | ||
48 | (((u_long)(u_char)(cp)[0]) | \ | ||
49 | ((u_long)(u_char)(cp)[1] << 8)) | ||
50 | |||
51 | #define PUT_32BIT_LSB_FIRST(cp, value) do { \ | ||
52 | (cp)[0] = (value); \ | ||
53 | (cp)[1] = (value) >> 8; \ | ||
54 | (cp)[2] = (value) >> 16; \ | ||
55 | (cp)[3] = (value) >> 24; } while (0) | ||
56 | |||
57 | #define PUT_16BIT_LSB_FIRST(cp, value) do { \ | ||
58 | (cp)[0] = (value); \ | ||
59 | (cp)[1] = (value) >> 8; } while (0) | ||
60 | |||
61 | #endif /* GETPUT_H */ | 58 | #endif /* GETPUT_H */ |
@@ -37,7 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include "includes.h" | 39 | #include "includes.h" |
40 | RCSID("$OpenBSD: packet.c,v 1.41 2001/01/02 20:41:02 markus Exp $"); | 40 | RCSID("$OpenBSD: packet.c,v 1.42 2001/01/09 21:19:50 markus Exp $"); |
41 | 41 | ||
42 | #include "xmalloc.h" | 42 | #include "xmalloc.h" |
43 | #include "buffer.h" | 43 | #include "buffer.h" |
@@ -1247,25 +1247,26 @@ packet_set_interactive(int interactive, int keepalives) | |||
1247 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 1247 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
1248 | } | 1248 | } |
1249 | /* | 1249 | /* |
1250 | * IPTOS_LOWDELAY, TCP_NODELAY and IPTOS_THROUGHPUT are IPv4 only | 1250 | * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only |
1251 | */ | 1251 | */ |
1252 | if (!packet_connection_is_ipv4()) | ||
1253 | return; | ||
1254 | if (interactive) { | 1252 | if (interactive) { |
1255 | /* | 1253 | /* |
1256 | * Set IP options for an interactive connection. Use | 1254 | * Set IP options for an interactive connection. Use |
1257 | * IPTOS_LOWDELAY and TCP_NODELAY. | 1255 | * IPTOS_LOWDELAY and TCP_NODELAY. |
1258 | */ | 1256 | */ |
1259 | #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) | 1257 | #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) |
1260 | int lowdelay = IPTOS_LOWDELAY; | 1258 | if (packet_connection_is_ipv4()) { |
1261 | if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &lowdelay, | 1259 | int lowdelay = IPTOS_LOWDELAY; |
1262 | sizeof(lowdelay)) < 0) | 1260 | if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, |
1263 | error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno)); | 1261 | (void *) &lowdelay, sizeof(lowdelay)) < 0) |
1262 | error("setsockopt IPTOS_LOWDELAY: %.100s", | ||
1263 | strerror(errno)); | ||
1264 | } | ||
1264 | #endif | 1265 | #endif |
1265 | if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *) &on, | 1266 | if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *) &on, |
1266 | sizeof(on)) < 0) | 1267 | sizeof(on)) < 0) |
1267 | error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); | 1268 | error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); |
1268 | } else { | 1269 | } else if (packet_connection_is_ipv4()) { |
1269 | /* | 1270 | /* |
1270 | * Set IP options for a non-interactive connection. Use | 1271 | * Set IP options for a non-interactive connection. Use |
1271 | * IPTOS_THROUGHPUT. | 1272 | * IPTOS_THROUGHPUT. |
diff --git a/sftp-server.c b/sftp-server.c index 7113bce82..40a535314 100644 --- a/sftp-server.c +++ b/sftp-server.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 | */ | 23 | */ |
24 | #include "includes.h" | 24 | #include "includes.h" |
25 | RCSID("$OpenBSD: sftp-server.c,v 1.9 2000/12/19 23:17:58 markus Exp $"); | 25 | RCSID("$OpenBSD: sftp-server.c,v 1.10 2001/01/10 22:56:22 markus Exp $"); |
26 | 26 | ||
27 | #include "ssh.h" | 27 | #include "ssh.h" |
28 | #include "buffer.h" | 28 | #include "buffer.h" |
@@ -30,65 +30,13 @@ RCSID("$OpenBSD: sftp-server.c,v 1.9 2000/12/19 23:17:58 markus Exp $"); | |||
30 | #include "getput.h" | 30 | #include "getput.h" |
31 | #include "xmalloc.h" | 31 | #include "xmalloc.h" |
32 | 32 | ||
33 | /* version */ | 33 | #include "sftp.h" |
34 | #define SSH_FILEXFER_VERSION 2 | ||
35 | |||
36 | /* client to server */ | ||
37 | #define SSH_FXP_INIT 1 | ||
38 | #define SSH_FXP_OPEN 3 | ||
39 | #define SSH_FXP_CLOSE 4 | ||
40 | #define SSH_FXP_READ 5 | ||
41 | #define SSH_FXP_WRITE 6 | ||
42 | #define SSH_FXP_LSTAT 7 | ||
43 | #define SSH_FXP_FSTAT 8 | ||
44 | #define SSH_FXP_SETSTAT 9 | ||
45 | #define SSH_FXP_FSETSTAT 10 | ||
46 | #define SSH_FXP_OPENDIR 11 | ||
47 | #define SSH_FXP_READDIR 12 | ||
48 | #define SSH_FXP_REMOVE 13 | ||
49 | #define SSH_FXP_MKDIR 14 | ||
50 | #define SSH_FXP_RMDIR 15 | ||
51 | #define SSH_FXP_REALPATH 16 | ||
52 | #define SSH_FXP_STAT 17 | ||
53 | #define SSH_FXP_RENAME 18 | ||
54 | |||
55 | /* server to client */ | ||
56 | #define SSH_FXP_VERSION 2 | ||
57 | #define SSH_FXP_STATUS 101 | ||
58 | #define SSH_FXP_HANDLE 102 | ||
59 | #define SSH_FXP_DATA 103 | ||
60 | #define SSH_FXP_NAME 104 | ||
61 | #define SSH_FXP_ATTRS 105 | ||
62 | |||
63 | /* portable open modes */ | ||
64 | #define SSH_FXF_READ 0x01 | ||
65 | #define SSH_FXF_WRITE 0x02 | ||
66 | #define SSH_FXF_APPEND 0x04 | ||
67 | #define SSH_FXF_CREAT 0x08 | ||
68 | #define SSH_FXF_TRUNC 0x10 | ||
69 | #define SSH_FXF_EXCL 0x20 | ||
70 | |||
71 | /* attributes */ | ||
72 | #define SSH_FXA_HAVE_SIZE 0x01 | ||
73 | #define SSH_FXA_HAVE_UGID 0x02 | ||
74 | #define SSH_FXA_HAVE_PERM 0x04 | ||
75 | #define SSH_FXA_HAVE_TIME 0x08 | ||
76 | |||
77 | /* status messages */ | ||
78 | #define SSH_FX_OK 0x00 | ||
79 | #define SSH_FX_EOF 0x01 | ||
80 | #define SSH_FX_NO_SUCH_FILE 0x02 | ||
81 | #define SSH_FX_PERMISSION_DENIED 0x03 | ||
82 | #define SSH_FX_FAILURE 0x04 | ||
83 | #define SSH_FX_BAD_MESSAGE 0x05 | ||
84 | #define SSH_FX_NO_CONNECTION 0x06 | ||
85 | #define SSH_FX_CONNECTION_LOST 0x07 | ||
86 | |||
87 | 34 | ||
88 | /* helper */ | 35 | /* helper */ |
36 | #define get_int64() buffer_get_int64(&iqueue); | ||
89 | #define get_int() buffer_get_int(&iqueue); | 37 | #define get_int() buffer_get_int(&iqueue); |
90 | #define get_string(lenp) buffer_get_string(&iqueue, lenp); | 38 | #define get_string(lenp) buffer_get_string(&iqueue, lenp); |
91 | #define TRACE log | 39 | #define TRACE debug |
92 | 40 | ||
93 | #ifdef HAVE___PROGNAME | 41 | #ifdef HAVE___PROGNAME |
94 | extern char *__progname; | 42 | extern char *__progname; |
@@ -108,8 +56,6 @@ typedef struct Stat Stat; | |||
108 | struct Attrib | 56 | struct Attrib |
109 | { | 57 | { |
110 | u_int32_t flags; | 58 | u_int32_t flags; |
111 | u_int32_t size_high; | ||
112 | u_int32_t size_low; | ||
113 | u_int64_t size; | 59 | u_int64_t size; |
114 | u_int32_t uid; | 60 | u_int32_t uid; |
115 | u_int32_t gid; | 61 | u_int32_t gid; |
@@ -131,25 +77,25 @@ errno_to_portable(int unixerrno) | |||
131 | int ret = 0; | 77 | int ret = 0; |
132 | switch (unixerrno) { | 78 | switch (unixerrno) { |
133 | case 0: | 79 | case 0: |
134 | ret = SSH_FX_OK; | 80 | ret = SSH2_FX_OK; |
135 | break; | 81 | break; |
136 | case ENOENT: | 82 | case ENOENT: |
137 | case ENOTDIR: | 83 | case ENOTDIR: |
138 | case EBADF: | 84 | case EBADF: |
139 | case ELOOP: | 85 | case ELOOP: |
140 | ret = SSH_FX_NO_SUCH_FILE; | 86 | ret = SSH2_FX_NO_SUCH_FILE; |
141 | break; | 87 | break; |
142 | case EPERM: | 88 | case EPERM: |
143 | case EACCES: | 89 | case EACCES: |
144 | case EFAULT: | 90 | case EFAULT: |
145 | ret = SSH_FX_PERMISSION_DENIED; | 91 | ret = SSH2_FX_PERMISSION_DENIED; |
146 | break; | 92 | break; |
147 | case ENAMETOOLONG: | 93 | case ENAMETOOLONG: |
148 | case EINVAL: | 94 | case EINVAL: |
149 | ret = SSH_FX_BAD_MESSAGE; | 95 | ret = SSH2_FX_BAD_MESSAGE; |
150 | break; | 96 | break; |
151 | default: | 97 | default: |
152 | ret = SSH_FX_FAILURE; | 98 | ret = SSH2_FX_FAILURE; |
153 | break; | 99 | break; |
154 | } | 100 | } |
155 | return ret; | 101 | return ret; |
@@ -159,19 +105,19 @@ int | |||
159 | flags_from_portable(int pflags) | 105 | flags_from_portable(int pflags) |
160 | { | 106 | { |
161 | int flags = 0; | 107 | int flags = 0; |
162 | if (pflags & SSH_FXF_READ && | 108 | if (pflags & SSH2_FXF_READ && |
163 | pflags & SSH_FXF_WRITE) { | 109 | pflags & SSH2_FXF_WRITE) { |
164 | flags = O_RDWR; | 110 | flags = O_RDWR; |
165 | } else if (pflags & SSH_FXF_READ) { | 111 | } else if (pflags & SSH2_FXF_READ) { |
166 | flags = O_RDONLY; | 112 | flags = O_RDONLY; |
167 | } else if (pflags & SSH_FXF_WRITE) { | 113 | } else if (pflags & SSH2_FXF_WRITE) { |
168 | flags = O_WRONLY; | 114 | flags = O_WRONLY; |
169 | } | 115 | } |
170 | if (pflags & SSH_FXF_CREAT) | 116 | if (pflags & SSH2_FXF_CREAT) |
171 | flags |= O_CREAT; | 117 | flags |= O_CREAT; |
172 | if (pflags & SSH_FXF_TRUNC) | 118 | if (pflags & SSH2_FXF_TRUNC) |
173 | flags |= O_TRUNC; | 119 | flags |= O_TRUNC; |
174 | if (pflags & SSH_FXF_EXCL) | 120 | if (pflags & SSH2_FXF_EXCL) |
175 | flags |= O_EXCL; | 121 | flags |= O_EXCL; |
176 | return flags; | 122 | return flags; |
177 | } | 123 | } |
@@ -180,8 +126,6 @@ void | |||
180 | attrib_clear(Attrib *a) | 126 | attrib_clear(Attrib *a) |
181 | { | 127 | { |
182 | a->flags = 0; | 128 | a->flags = 0; |
183 | a->size_low = 0; | ||
184 | a->size_high = 0; | ||
185 | a->size = 0; | 129 | a->size = 0; |
186 | a->uid = 0; | 130 | a->uid = 0; |
187 | a->gid = 0; | 131 | a->gid = 0; |
@@ -196,22 +140,32 @@ decode_attrib(Buffer *b) | |||
196 | static Attrib a; | 140 | static Attrib a; |
197 | attrib_clear(&a); | 141 | attrib_clear(&a); |
198 | a.flags = buffer_get_int(b); | 142 | a.flags = buffer_get_int(b); |
199 | if (a.flags & SSH_FXA_HAVE_SIZE) { | 143 | if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { |
200 | a.size_high = buffer_get_int(b); | 144 | a.size = buffer_get_int64(b); |
201 | a.size_low = buffer_get_int(b); | ||
202 | a.size = (((u_int64_t) a.size_high) << 32) + a.size_low; | ||
203 | } | 145 | } |
204 | if (a.flags & SSH_FXA_HAVE_UGID) { | 146 | if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { |
205 | a.uid = buffer_get_int(b); | 147 | a.uid = buffer_get_int(b); |
206 | a.gid = buffer_get_int(b); | 148 | a.gid = buffer_get_int(b); |
207 | } | 149 | } |
208 | if (a.flags & SSH_FXA_HAVE_PERM) { | 150 | if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
209 | a.perm = buffer_get_int(b); | 151 | a.perm = buffer_get_int(b); |
210 | } | 152 | } |
211 | if (a.flags & SSH_FXA_HAVE_TIME) { | 153 | if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
212 | a.atime = buffer_get_int(b); | 154 | a.atime = buffer_get_int(b); |
213 | a.mtime = buffer_get_int(b); | 155 | a.mtime = buffer_get_int(b); |
214 | } | 156 | } |
157 | /* vendor-specific extensions */ | ||
158 | if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { | ||
159 | char *type, *data; | ||
160 | int i, count; | ||
161 | count = buffer_get_int(b); | ||
162 | for (i = 0; i < count; i++) { | ||
163 | type = buffer_get_string(b, NULL); | ||
164 | data = buffer_get_string(b, NULL); | ||
165 | xfree(type); | ||
166 | xfree(data); | ||
167 | } | ||
168 | } | ||
215 | return &a; | 169 | return &a; |
216 | } | 170 | } |
217 | 171 | ||
@@ -219,18 +173,17 @@ void | |||
219 | encode_attrib(Buffer *b, Attrib *a) | 173 | encode_attrib(Buffer *b, Attrib *a) |
220 | { | 174 | { |
221 | buffer_put_int(b, a->flags); | 175 | buffer_put_int(b, a->flags); |
222 | if (a->flags & SSH_FXA_HAVE_SIZE) { | 176 | if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
223 | buffer_put_int(b, a->size_high); | 177 | buffer_put_int64(b, a->size); |
224 | buffer_put_int(b, a->size_low); | ||
225 | } | 178 | } |
226 | if (a->flags & SSH_FXA_HAVE_UGID) { | 179 | if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
227 | buffer_put_int(b, a->uid); | 180 | buffer_put_int(b, a->uid); |
228 | buffer_put_int(b, a->gid); | 181 | buffer_put_int(b, a->gid); |
229 | } | 182 | } |
230 | if (a->flags & SSH_FXA_HAVE_PERM) { | 183 | if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
231 | buffer_put_int(b, a->perm); | 184 | buffer_put_int(b, a->perm); |
232 | } | 185 | } |
233 | if (a->flags & SSH_FXA_HAVE_TIME) { | 186 | if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
234 | buffer_put_int(b, a->atime); | 187 | buffer_put_int(b, a->atime); |
235 | buffer_put_int(b, a->mtime); | 188 | buffer_put_int(b, a->mtime); |
236 | } | 189 | } |
@@ -242,16 +195,14 @@ stat_to_attrib(struct stat *st) | |||
242 | static Attrib a; | 195 | static Attrib a; |
243 | attrib_clear(&a); | 196 | attrib_clear(&a); |
244 | a.flags = 0; | 197 | a.flags = 0; |
245 | a.flags |= SSH_FXA_HAVE_SIZE; | 198 | a.flags |= SSH2_FILEXFER_ATTR_SIZE; |
246 | a.size = st->st_size; | 199 | a.size = st->st_size; |
247 | a.size_low = a.size; | 200 | a.flags |= SSH2_FILEXFER_ATTR_UIDGID; |
248 | a.size_high = (u_int32_t) (a.size >> 32); | ||
249 | a.flags |= SSH_FXA_HAVE_UGID; | ||
250 | a.uid = st->st_uid; | 201 | a.uid = st->st_uid; |
251 | a.gid = st->st_gid; | 202 | a.gid = st->st_gid; |
252 | a.flags |= SSH_FXA_HAVE_PERM; | 203 | a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; |
253 | a.perm = st->st_mode; | 204 | a.perm = st->st_mode; |
254 | a.flags |= SSH_FXA_HAVE_TIME; | 205 | a.flags |= SSH2_FILEXFER_ATTR_ACMODTIME; |
255 | a.atime = st->st_atime; | 206 | a.atime = st->st_atime; |
256 | a.mtime = st->st_mtime; | 207 | a.mtime = st->st_mtime; |
257 | return &a; | 208 | return &a; |
@@ -306,7 +257,8 @@ handle_new(int use, char *name, int fd, DIR *dirp) | |||
306 | int | 257 | int |
307 | handle_is_ok(int i, int type) | 258 | handle_is_ok(int i, int type) |
308 | { | 259 | { |
309 | return i >= 0 && i < sizeof(handles)/sizeof(Handle) && handles[i].use == type; | 260 | return i >= 0 && i < sizeof(handles)/sizeof(Handle) && |
261 | handles[i].use == type; | ||
310 | } | 262 | } |
311 | 263 | ||
312 | int | 264 | int |
@@ -381,10 +333,11 @@ int | |||
381 | get_handle(void) | 333 | get_handle(void) |
382 | { | 334 | { |
383 | char *handle; | 335 | char *handle; |
384 | int val; | 336 | int val = -1; |
385 | u_int hlen; | 337 | u_int hlen; |
386 | handle = get_string(&hlen); | 338 | handle = get_string(&hlen); |
387 | val = handle_from_string(handle, hlen); | 339 | if (hlen < 256) |
340 | val = handle_from_string(handle, hlen); | ||
388 | xfree(handle); | 341 | xfree(handle); |
389 | return val; | 342 | return val; |
390 | } | 343 | } |
@@ -406,7 +359,7 @@ send_status(u_int32_t id, u_int32_t error) | |||
406 | Buffer msg; | 359 | Buffer msg; |
407 | TRACE("sent status id %d error %d", id, error); | 360 | TRACE("sent status id %d error %d", id, error); |
408 | buffer_init(&msg); | 361 | buffer_init(&msg); |
409 | buffer_put_char(&msg, SSH_FXP_STATUS); | 362 | buffer_put_char(&msg, SSH2_FXP_STATUS); |
410 | buffer_put_int(&msg, id); | 363 | buffer_put_int(&msg, id); |
411 | buffer_put_int(&msg, error); | 364 | buffer_put_int(&msg, error); |
412 | send_msg(&msg); | 365 | send_msg(&msg); |
@@ -428,7 +381,7 @@ void | |||
428 | send_data(u_int32_t id, char *data, int dlen) | 381 | send_data(u_int32_t id, char *data, int dlen) |
429 | { | 382 | { |
430 | TRACE("sent data id %d len %d", id, dlen); | 383 | TRACE("sent data id %d len %d", id, dlen); |
431 | send_data_or_handle(SSH_FXP_DATA, id, data, dlen); | 384 | send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); |
432 | } | 385 | } |
433 | 386 | ||
434 | void | 387 | void |
@@ -438,7 +391,7 @@ send_handle(u_int32_t id, int handle) | |||
438 | int hlen; | 391 | int hlen; |
439 | handle_to_string(handle, &string, &hlen); | 392 | handle_to_string(handle, &string, &hlen); |
440 | TRACE("sent handle id %d handle %d", id, handle); | 393 | TRACE("sent handle id %d handle %d", id, handle); |
441 | send_data_or_handle(SSH_FXP_HANDLE, id, string, hlen); | 394 | send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); |
442 | xfree(string); | 395 | xfree(string); |
443 | } | 396 | } |
444 | 397 | ||
@@ -448,7 +401,7 @@ send_names(u_int32_t id, int count, Stat *stats) | |||
448 | Buffer msg; | 401 | Buffer msg; |
449 | int i; | 402 | int i; |
450 | buffer_init(&msg); | 403 | buffer_init(&msg); |
451 | buffer_put_char(&msg, SSH_FXP_NAME); | 404 | buffer_put_char(&msg, SSH2_FXP_NAME); |
452 | buffer_put_int(&msg, id); | 405 | buffer_put_int(&msg, id); |
453 | buffer_put_int(&msg, count); | 406 | buffer_put_int(&msg, count); |
454 | TRACE("sent names id %d count %d", id, count); | 407 | TRACE("sent names id %d count %d", id, count); |
@@ -467,7 +420,7 @@ send_attrib(u_int32_t id, Attrib *a) | |||
467 | Buffer msg; | 420 | Buffer msg; |
468 | TRACE("sent attrib id %d have 0x%x", id, a->flags); | 421 | TRACE("sent attrib id %d have 0x%x", id, a->flags); |
469 | buffer_init(&msg); | 422 | buffer_init(&msg); |
470 | buffer_put_char(&msg, SSH_FXP_ATTRS); | 423 | buffer_put_char(&msg, SSH2_FXP_ATTRS); |
471 | buffer_put_int(&msg, id); | 424 | buffer_put_int(&msg, id); |
472 | encode_attrib(&msg, a); | 425 | encode_attrib(&msg, a); |
473 | send_msg(&msg); | 426 | send_msg(&msg); |
@@ -484,8 +437,8 @@ process_init(void) | |||
484 | 437 | ||
485 | TRACE("client version %d", version); | 438 | TRACE("client version %d", version); |
486 | buffer_init(&msg); | 439 | buffer_init(&msg); |
487 | buffer_put_char(&msg, SSH_FXP_VERSION); | 440 | buffer_put_char(&msg, SSH2_FXP_VERSION); |
488 | buffer_put_int(&msg, SSH_FILEXFER_VERSION); | 441 | buffer_put_int(&msg, SSH2_FILEXFER_VERSION); |
489 | send_msg(&msg); | 442 | send_msg(&msg); |
490 | buffer_free(&msg); | 443 | buffer_free(&msg); |
491 | } | 444 | } |
@@ -496,14 +449,14 @@ process_open(void) | |||
496 | u_int32_t id, pflags; | 449 | u_int32_t id, pflags; |
497 | Attrib *a; | 450 | Attrib *a; |
498 | char *name; | 451 | char *name; |
499 | int handle, fd, flags, mode, status = SSH_FX_FAILURE; | 452 | int handle, fd, flags, mode, status = SSH2_FX_FAILURE; |
500 | 453 | ||
501 | id = get_int(); | 454 | id = get_int(); |
502 | name = get_string(NULL); | 455 | name = get_string(NULL); |
503 | pflags = get_int(); | 456 | pflags = get_int(); /* portable flags */ |
504 | a = get_attrib(); | 457 | a = get_attrib(); |
505 | flags = flags_from_portable(pflags); | 458 | flags = flags_from_portable(pflags); |
506 | mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm : 0666; | 459 | mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; |
507 | TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode); | 460 | TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode); |
508 | fd = open(name, flags, mode); | 461 | fd = open(name, flags, mode); |
509 | if (fd < 0) { | 462 | if (fd < 0) { |
@@ -514,10 +467,10 @@ process_open(void) | |||
514 | close(fd); | 467 | close(fd); |
515 | } else { | 468 | } else { |
516 | send_handle(id, handle); | 469 | send_handle(id, handle); |
517 | status = SSH_FX_OK; | 470 | status = SSH2_FX_OK; |
518 | } | 471 | } |
519 | } | 472 | } |
520 | if (status != SSH_FX_OK) | 473 | if (status != SSH2_FX_OK) |
521 | send_status(id, status); | 474 | send_status(id, status); |
522 | xfree(name); | 475 | xfree(name); |
523 | } | 476 | } |
@@ -526,13 +479,13 @@ void | |||
526 | process_close(void) | 479 | process_close(void) |
527 | { | 480 | { |
528 | u_int32_t id; | 481 | u_int32_t id; |
529 | int handle, ret, status = SSH_FX_FAILURE; | 482 | int handle, ret, status = SSH2_FX_FAILURE; |
530 | 483 | ||
531 | id = get_int(); | 484 | id = get_int(); |
532 | handle = get_handle(); | 485 | handle = get_handle(); |
533 | TRACE("close id %d handle %d", id, handle); | 486 | TRACE("close id %d handle %d", id, handle); |
534 | ret = handle_close(handle); | 487 | ret = handle_close(handle); |
535 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | 488 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
536 | send_status(id, status); | 489 | send_status(id, status); |
537 | } | 490 | } |
538 | 491 | ||
@@ -540,17 +493,15 @@ void | |||
540 | process_read(void) | 493 | process_read(void) |
541 | { | 494 | { |
542 | char buf[64*1024]; | 495 | char buf[64*1024]; |
543 | u_int32_t id, off_high, off_low, len; | 496 | u_int32_t id, len; |
544 | int handle, fd, ret, status = SSH_FX_FAILURE; | 497 | int handle, fd, ret, status = SSH2_FX_FAILURE; |
545 | u_int64_t off; | 498 | u_int64_t off; |
546 | 499 | ||
547 | id = get_int(); | 500 | id = get_int(); |
548 | handle = get_handle(); | 501 | handle = get_handle(); |
549 | off_high = get_int(); | 502 | off = get_int64(); |
550 | off_low = get_int(); | ||
551 | len = get_int(); | 503 | len = get_int(); |
552 | 504 | ||
553 | off = (((u_int64_t) off_high) << 32) + off_low; | ||
554 | TRACE("read id %d handle %d off %lld len %d", id, handle, off, len); | 505 | TRACE("read id %d handle %d off %lld len %d", id, handle, off, len); |
555 | if (len > sizeof buf) { | 506 | if (len > sizeof buf) { |
556 | len = sizeof buf; | 507 | len = sizeof buf; |
@@ -566,33 +517,31 @@ process_read(void) | |||
566 | if (ret < 0) { | 517 | if (ret < 0) { |
567 | status = errno_to_portable(errno); | 518 | status = errno_to_portable(errno); |
568 | } else if (ret == 0) { | 519 | } else if (ret == 0) { |
569 | status = SSH_FX_EOF; | 520 | status = SSH2_FX_EOF; |
570 | } else { | 521 | } else { |
571 | send_data(id, buf, ret); | 522 | send_data(id, buf, ret); |
572 | status = SSH_FX_OK; | 523 | status = SSH2_FX_OK; |
573 | } | 524 | } |
574 | } | 525 | } |
575 | } | 526 | } |
576 | if (status != SSH_FX_OK) | 527 | if (status != SSH2_FX_OK) |
577 | send_status(id, status); | 528 | send_status(id, status); |
578 | } | 529 | } |
579 | 530 | ||
580 | void | 531 | void |
581 | process_write(void) | 532 | process_write(void) |
582 | { | 533 | { |
583 | u_int32_t id, off_high, off_low; | 534 | u_int32_t id; |
584 | u_int64_t off; | 535 | u_int64_t off; |
585 | u_int len; | 536 | u_int len; |
586 | int handle, fd, ret, status = SSH_FX_FAILURE; | 537 | int handle, fd, ret, status = SSH2_FX_FAILURE; |
587 | char *data; | 538 | char *data; |
588 | 539 | ||
589 | id = get_int(); | 540 | id = get_int(); |
590 | handle = get_handle(); | 541 | handle = get_handle(); |
591 | off_high = get_int(); | 542 | off = get_int64(); |
592 | off_low = get_int(); | ||
593 | data = get_string(&len); | 543 | data = get_string(&len); |
594 | 544 | ||
595 | off = (((u_int64_t) off_high) << 32) + off_low; | ||
596 | TRACE("write id %d handle %d off %lld len %d", id, handle, off, len); | 545 | TRACE("write id %d handle %d off %lld len %d", id, handle, off, len); |
597 | fd = handle_to_fd(handle); | 546 | fd = handle_to_fd(handle); |
598 | if (fd >= 0) { | 547 | if (fd >= 0) { |
@@ -606,7 +555,7 @@ process_write(void) | |||
606 | error("process_write: write failed"); | 555 | error("process_write: write failed"); |
607 | status = errno_to_portable(errno); | 556 | status = errno_to_portable(errno); |
608 | } else if (ret == len) { | 557 | } else if (ret == len) { |
609 | status = SSH_FX_OK; | 558 | status = SSH2_FX_OK; |
610 | } else { | 559 | } else { |
611 | log("nothing at all written"); | 560 | log("nothing at all written"); |
612 | } | 561 | } |
@@ -623,7 +572,7 @@ process_do_stat(int do_lstat) | |||
623 | struct stat st; | 572 | struct stat st; |
624 | u_int32_t id; | 573 | u_int32_t id; |
625 | char *name; | 574 | char *name; |
626 | int ret, status = SSH_FX_FAILURE; | 575 | int ret, status = SSH2_FX_FAILURE; |
627 | 576 | ||
628 | id = get_int(); | 577 | id = get_int(); |
629 | name = get_string(NULL); | 578 | name = get_string(NULL); |
@@ -634,9 +583,9 @@ process_do_stat(int do_lstat) | |||
634 | } else { | 583 | } else { |
635 | a = stat_to_attrib(&st); | 584 | a = stat_to_attrib(&st); |
636 | send_attrib(id, a); | 585 | send_attrib(id, a); |
637 | status = SSH_FX_OK; | 586 | status = SSH2_FX_OK; |
638 | } | 587 | } |
639 | if (status != SSH_FX_OK) | 588 | if (status != SSH2_FX_OK) |
640 | send_status(id, status); | 589 | send_status(id, status); |
641 | xfree(name); | 590 | xfree(name); |
642 | } | 591 | } |
@@ -659,7 +608,7 @@ process_fstat(void) | |||
659 | Attrib *a; | 608 | Attrib *a; |
660 | struct stat st; | 609 | struct stat st; |
661 | u_int32_t id; | 610 | u_int32_t id; |
662 | int fd, ret, handle, status = SSH_FX_FAILURE; | 611 | int fd, ret, handle, status = SSH2_FX_FAILURE; |
663 | 612 | ||
664 | id = get_int(); | 613 | id = get_int(); |
665 | handle = get_handle(); | 614 | handle = get_handle(); |
@@ -672,10 +621,10 @@ process_fstat(void) | |||
672 | } else { | 621 | } else { |
673 | a = stat_to_attrib(&st); | 622 | a = stat_to_attrib(&st); |
674 | send_attrib(id, a); | 623 | send_attrib(id, a); |
675 | status = SSH_FX_OK; | 624 | status = SSH2_FX_OK; |
676 | } | 625 | } |
677 | } | 626 | } |
678 | if (status != SSH_FX_OK) | 627 | if (status != SSH2_FX_OK) |
679 | send_status(id, status); | 628 | send_status(id, status); |
680 | } | 629 | } |
681 | 630 | ||
@@ -697,18 +646,18 @@ process_setstat(void) | |||
697 | u_int32_t id; | 646 | u_int32_t id; |
698 | char *name; | 647 | char *name; |
699 | int ret; | 648 | int ret; |
700 | int status = SSH_FX_OK; | 649 | int status = SSH2_FX_OK; |
701 | 650 | ||
702 | id = get_int(); | 651 | id = get_int(); |
703 | name = get_string(NULL); | 652 | name = get_string(NULL); |
704 | a = get_attrib(); | 653 | a = get_attrib(); |
705 | TRACE("setstat id %d name %s", id, name); | 654 | TRACE("setstat id %d name %s", id, name); |
706 | if (a->flags & SSH_FXA_HAVE_PERM) { | 655 | if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
707 | ret = chmod(name, a->perm & 0777); | 656 | ret = chmod(name, a->perm & 0777); |
708 | if (ret == -1) | 657 | if (ret == -1) |
709 | status = errno_to_portable(errno); | 658 | status = errno_to_portable(errno); |
710 | } | 659 | } |
711 | if (a->flags & SSH_FXA_HAVE_TIME) { | 660 | if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
712 | ret = utimes(name, attrib_to_tv(a)); | 661 | ret = utimes(name, attrib_to_tv(a)); |
713 | if (ret == -1) | 662 | if (ret == -1) |
714 | status = errno_to_portable(errno); | 663 | status = errno_to_portable(errno); |
@@ -723,7 +672,7 @@ process_fsetstat(void) | |||
723 | Attrib *a; | 672 | Attrib *a; |
724 | u_int32_t id; | 673 | u_int32_t id; |
725 | int handle, fd, ret; | 674 | int handle, fd, ret; |
726 | int status = SSH_FX_OK; | 675 | int status = SSH2_FX_OK; |
727 | char *name; | 676 | char *name; |
728 | 677 | ||
729 | id = get_int(); | 678 | id = get_int(); |
@@ -733,14 +682,14 @@ process_fsetstat(void) | |||
733 | fd = handle_to_fd(handle); | 682 | fd = handle_to_fd(handle); |
734 | name = handle_to_name(handle); | 683 | name = handle_to_name(handle); |
735 | if ((fd < 0) || (name == NULL)) { | 684 | if ((fd < 0) || (name == NULL)) { |
736 | status = SSH_FX_FAILURE; | 685 | status = SSH2_FX_FAILURE; |
737 | } else { | 686 | } else { |
738 | if (a->flags & SSH_FXA_HAVE_PERM) { | 687 | if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
739 | ret = fchmod(fd, a->perm & 0777); | 688 | ret = fchmod(fd, a->perm & 0777); |
740 | if (ret == -1) | 689 | if (ret == -1) |
741 | status = errno_to_portable(errno); | 690 | status = errno_to_portable(errno); |
742 | } | 691 | } |
743 | if (a->flags & SSH_FXA_HAVE_TIME) { | 692 | if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
744 | #ifdef HAVE_FUTIMES | 693 | #ifdef HAVE_FUTIMES |
745 | ret = futimes(fd, attrib_to_tv(a)); | 694 | ret = futimes(fd, attrib_to_tv(a)); |
746 | #else | 695 | #else |
@@ -758,7 +707,7 @@ process_opendir(void) | |||
758 | { | 707 | { |
759 | DIR *dirp = NULL; | 708 | DIR *dirp = NULL; |
760 | char *path; | 709 | char *path; |
761 | int handle, status = SSH_FX_FAILURE; | 710 | int handle, status = SSH2_FX_FAILURE; |
762 | u_int32_t id; | 711 | u_int32_t id; |
763 | 712 | ||
764 | id = get_int(); | 713 | id = get_int(); |
@@ -773,22 +722,28 @@ process_opendir(void) | |||
773 | closedir(dirp); | 722 | closedir(dirp); |
774 | } else { | 723 | } else { |
775 | send_handle(id, handle); | 724 | send_handle(id, handle); |
776 | status = SSH_FX_OK; | 725 | status = SSH2_FX_OK; |
777 | } | 726 | } |
778 | 727 | ||
779 | } | 728 | } |
780 | if (status != SSH_FX_OK) | 729 | if (status != SSH2_FX_OK) |
781 | send_status(id, status); | 730 | send_status(id, status); |
782 | xfree(path); | 731 | xfree(path); |
783 | } | 732 | } |
784 | 733 | ||
734 | /* | ||
735 | * XXX, draft-ietf-secsh-filexfer-00.txt says: | ||
736 | * The recommended format for the longname field is as follows: | ||
737 | * -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer | ||
738 | * 1234567890 123 12345678 12345678 12345678 123456789012 | ||
739 | */ | ||
785 | char * | 740 | char * |
786 | ls_file(char *name, struct stat *st) | 741 | ls_file(char *name, struct stat *st) |
787 | { | 742 | { |
788 | char buf[1024]; | 743 | char buf[1024]; |
789 | snprintf(buf, sizeof buf, "0%o %d %d %lld %d %s", | 744 | snprintf(buf, sizeof buf, "0%o %d %d %lld %d %s", |
790 | st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size,(int) st->st_mtime, | 745 | st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size, |
791 | name); | 746 | (int)st->st_mtime, name); |
792 | return xstrdup(buf); | 747 | return xstrdup(buf); |
793 | } | 748 | } |
794 | 749 | ||
@@ -807,7 +762,7 @@ process_readdir(void) | |||
807 | dirp = handle_to_dir(handle); | 762 | dirp = handle_to_dir(handle); |
808 | path = handle_to_name(handle); | 763 | path = handle_to_name(handle); |
809 | if (dirp == NULL || path == NULL) { | 764 | if (dirp == NULL || path == NULL) { |
810 | send_status(id, SSH_FX_FAILURE); | 765 | send_status(id, SSH2_FX_FAILURE); |
811 | } else { | 766 | } else { |
812 | Attrib *a; | 767 | Attrib *a; |
813 | struct stat st; | 768 | struct stat st; |
@@ -834,10 +789,14 @@ process_readdir(void) | |||
834 | if (count == 100) | 789 | if (count == 100) |
835 | break; | 790 | break; |
836 | } | 791 | } |
837 | send_names(id, count, stats); | 792 | if (count > 0) { |
838 | for(i = 0; i < count; i++) { | 793 | send_names(id, count, stats); |
839 | xfree(stats[i].name); | 794 | for(i = 0; i < count; i++) { |
840 | xfree(stats[i].long_name); | 795 | xfree(stats[i].name); |
796 | xfree(stats[i].long_name); | ||
797 | } | ||
798 | } else { | ||
799 | send_status(id, SSH2_FX_EOF); | ||
841 | } | 800 | } |
842 | xfree(stats); | 801 | xfree(stats); |
843 | } | 802 | } |
@@ -848,14 +807,14 @@ process_remove(void) | |||
848 | { | 807 | { |
849 | char *name; | 808 | char *name; |
850 | u_int32_t id; | 809 | u_int32_t id; |
851 | int status = SSH_FX_FAILURE; | 810 | int status = SSH2_FX_FAILURE; |
852 | int ret; | 811 | int ret; |
853 | 812 | ||
854 | id = get_int(); | 813 | id = get_int(); |
855 | name = get_string(NULL); | 814 | name = get_string(NULL); |
856 | TRACE("remove id %d name %s", id, name); | 815 | TRACE("remove id %d name %s", id, name); |
857 | ret = unlink(name); | 816 | ret = unlink(name); |
858 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | 817 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
859 | send_status(id, status); | 818 | send_status(id, status); |
860 | xfree(name); | 819 | xfree(name); |
861 | } | 820 | } |
@@ -866,15 +825,16 @@ process_mkdir(void) | |||
866 | Attrib *a; | 825 | Attrib *a; |
867 | u_int32_t id; | 826 | u_int32_t id; |
868 | char *name; | 827 | char *name; |
869 | int ret, mode, status = SSH_FX_FAILURE; | 828 | int ret, mode, status = SSH2_FX_FAILURE; |
870 | 829 | ||
871 | id = get_int(); | 830 | id = get_int(); |
872 | name = get_string(NULL); | 831 | name = get_string(NULL); |
873 | a = get_attrib(); | 832 | a = get_attrib(); |
874 | mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm & 0777 : 0777; | 833 | mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? |
834 | a->perm & 0777 : 0777; | ||
875 | TRACE("mkdir id %d name %s mode 0%o", id, name, mode); | 835 | TRACE("mkdir id %d name %s mode 0%o", id, name, mode); |
876 | ret = mkdir(name, mode); | 836 | ret = mkdir(name, mode); |
877 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | 837 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
878 | send_status(id, status); | 838 | send_status(id, status); |
879 | xfree(name); | 839 | xfree(name); |
880 | } | 840 | } |
@@ -890,7 +850,7 @@ process_rmdir(void) | |||
890 | name = get_string(NULL); | 850 | name = get_string(NULL); |
891 | TRACE("rmdir id %d name %s", id, name); | 851 | TRACE("rmdir id %d name %s", id, name); |
892 | ret = rmdir(name); | 852 | ret = rmdir(name); |
893 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | 853 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
894 | send_status(id, status); | 854 | send_status(id, status); |
895 | xfree(name); | 855 | xfree(name); |
896 | } | 856 | } |
@@ -932,12 +892,23 @@ process_rename(void) | |||
932 | newpath = get_string(NULL); | 892 | newpath = get_string(NULL); |
933 | TRACE("rename id %d old %s new %s", id, oldpath, newpath); | 893 | TRACE("rename id %d old %s new %s", id, oldpath, newpath); |
934 | ret = rename(oldpath, newpath); | 894 | ret = rename(oldpath, newpath); |
935 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | 895 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
936 | send_status(id, status); | 896 | send_status(id, status); |
937 | xfree(oldpath); | 897 | xfree(oldpath); |
938 | xfree(newpath); | 898 | xfree(newpath); |
939 | } | 899 | } |
940 | 900 | ||
901 | void | ||
902 | process_extended(void) | ||
903 | { | ||
904 | u_int32_t id; | ||
905 | char *request; | ||
906 | |||
907 | id = get_int(); | ||
908 | request = get_string(NULL); | ||
909 | send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ | ||
910 | xfree(request); | ||
911 | } | ||
941 | 912 | ||
942 | /* stolen from ssh-agent */ | 913 | /* stolen from ssh-agent */ |
943 | 914 | ||
@@ -961,57 +932,60 @@ process(void) | |||
961 | buffer_consume(&iqueue, 4); | 932 | buffer_consume(&iqueue, 4); |
962 | type = buffer_get_char(&iqueue); | 933 | type = buffer_get_char(&iqueue); |
963 | switch (type) { | 934 | switch (type) { |
964 | case SSH_FXP_INIT: | 935 | case SSH2_FXP_INIT: |
965 | process_init(); | 936 | process_init(); |
966 | break; | 937 | break; |
967 | case SSH_FXP_OPEN: | 938 | case SSH2_FXP_OPEN: |
968 | process_open(); | 939 | process_open(); |
969 | break; | 940 | break; |
970 | case SSH_FXP_CLOSE: | 941 | case SSH2_FXP_CLOSE: |
971 | process_close(); | 942 | process_close(); |
972 | break; | 943 | break; |
973 | case SSH_FXP_READ: | 944 | case SSH2_FXP_READ: |
974 | process_read(); | 945 | process_read(); |
975 | break; | 946 | break; |
976 | case SSH_FXP_WRITE: | 947 | case SSH2_FXP_WRITE: |
977 | process_write(); | 948 | process_write(); |
978 | break; | 949 | break; |
979 | case SSH_FXP_LSTAT: | 950 | case SSH2_FXP_LSTAT: |
980 | process_lstat(); | 951 | process_lstat(); |
981 | break; | 952 | break; |
982 | case SSH_FXP_FSTAT: | 953 | case SSH2_FXP_FSTAT: |
983 | process_fstat(); | 954 | process_fstat(); |
984 | break; | 955 | break; |
985 | case SSH_FXP_SETSTAT: | 956 | case SSH2_FXP_SETSTAT: |
986 | process_setstat(); | 957 | process_setstat(); |
987 | break; | 958 | break; |
988 | case SSH_FXP_FSETSTAT: | 959 | case SSH2_FXP_FSETSTAT: |
989 | process_fsetstat(); | 960 | process_fsetstat(); |
990 | break; | 961 | break; |
991 | case SSH_FXP_OPENDIR: | 962 | case SSH2_FXP_OPENDIR: |
992 | process_opendir(); | 963 | process_opendir(); |
993 | break; | 964 | break; |
994 | case SSH_FXP_READDIR: | 965 | case SSH2_FXP_READDIR: |
995 | process_readdir(); | 966 | process_readdir(); |
996 | break; | 967 | break; |
997 | case SSH_FXP_REMOVE: | 968 | case SSH2_FXP_REMOVE: |
998 | process_remove(); | 969 | process_remove(); |
999 | break; | 970 | break; |
1000 | case SSH_FXP_MKDIR: | 971 | case SSH2_FXP_MKDIR: |
1001 | process_mkdir(); | 972 | process_mkdir(); |
1002 | break; | 973 | break; |
1003 | case SSH_FXP_RMDIR: | 974 | case SSH2_FXP_RMDIR: |
1004 | process_rmdir(); | 975 | process_rmdir(); |
1005 | break; | 976 | break; |
1006 | case SSH_FXP_REALPATH: | 977 | case SSH2_FXP_REALPATH: |
1007 | process_realpath(); | 978 | process_realpath(); |
1008 | break; | 979 | break; |
1009 | case SSH_FXP_STAT: | 980 | case SSH2_FXP_STAT: |
1010 | process_stat(); | 981 | process_stat(); |
1011 | break; | 982 | break; |
1012 | case SSH_FXP_RENAME: | 983 | case SSH2_FXP_RENAME: |
1013 | process_rename(); | 984 | process_rename(); |
1014 | break; | 985 | break; |
986 | case SSH2_FXP_EXTENDED: | ||
987 | process_extended(); | ||
988 | break; | ||
1015 | default: | 989 | default: |
1016 | error("Unknown message %d", type); | 990 | error("Unknown message %d", type); |
1017 | break; | 991 | break; |
@@ -1028,6 +1002,8 @@ main(int ac, char **av) | |||
1028 | __progname = get_progname(av[0]); | 1002 | __progname = get_progname(av[0]); |
1029 | handle_init(); | 1003 | handle_init(); |
1030 | 1004 | ||
1005 | log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); | ||
1006 | |||
1031 | in = dup(STDIN_FILENO); | 1007 | in = dup(STDIN_FILENO); |
1032 | out = dup(STDOUT_FILENO); | 1008 | out = dup(STDOUT_FILENO); |
1033 | 1009 | ||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | ||
3 | * | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * 1. Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * 2. Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * | ||
13 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
14 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
15 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
16 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
17 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
18 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
19 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
20 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * draft-ietf-secsh-filexfer-00.txt | ||
27 | */ | ||
28 | |||
29 | /* version */ | ||
30 | #define SSH2_FILEXFER_VERSION 2 | ||
31 | |||
32 | /* client to server */ | ||
33 | #define SSH2_FXP_INIT 1 | ||
34 | #define SSH2_FXP_OPEN 3 | ||
35 | #define SSH2_FXP_CLOSE 4 | ||
36 | #define SSH2_FXP_READ 5 | ||
37 | #define SSH2_FXP_WRITE 6 | ||
38 | #define SSH2_FXP_LSTAT 7 | ||
39 | #define SSH2_FXP_FSTAT 8 | ||
40 | #define SSH2_FXP_SETSTAT 9 | ||
41 | #define SSH2_FXP_FSETSTAT 10 | ||
42 | #define SSH2_FXP_OPENDIR 11 | ||
43 | #define SSH2_FXP_READDIR 12 | ||
44 | #define SSH2_FXP_REMOVE 13 | ||
45 | #define SSH2_FXP_MKDIR 14 | ||
46 | #define SSH2_FXP_RMDIR 15 | ||
47 | #define SSH2_FXP_REALPATH 16 | ||
48 | #define SSH2_FXP_STAT 17 | ||
49 | #define SSH2_FXP_RENAME 18 | ||
50 | |||
51 | /* server to client */ | ||
52 | #define SSH2_FXP_VERSION 2 | ||
53 | #define SSH2_FXP_STATUS 101 | ||
54 | #define SSH2_FXP_HANDLE 102 | ||
55 | #define SSH2_FXP_DATA 103 | ||
56 | #define SSH2_FXP_NAME 104 | ||
57 | #define SSH2_FXP_ATTRS 105 | ||
58 | |||
59 | #define SSH2_FXP_EXTENDED 200 | ||
60 | #define SSH2_FXP_EXTENDED_REPLY 201 | ||
61 | |||
62 | /* attributes */ | ||
63 | #define SSH2_FILEXFER_ATTR_SIZE 0x00000001 | ||
64 | #define SSH2_FILEXFER_ATTR_UIDGID 0x00000002 | ||
65 | #define SSH2_FILEXFER_ATTR_PERMISSIONS 0x00000004 | ||
66 | #define SSH2_FILEXFER_ATTR_ACMODTIME 0x00000008 | ||
67 | #define SSH2_FILEXFER_ATTR_EXTENDED 0x80000000 | ||
68 | |||
69 | /* portable open modes */ | ||
70 | #define SSH2_FXF_READ 0x00000001 | ||
71 | #define SSH2_FXF_WRITE 0x00000002 | ||
72 | #define SSH2_FXF_APPEND 0x00000004 | ||
73 | #define SSH2_FXF_CREAT 0x00000008 | ||
74 | #define SSH2_FXF_TRUNC 0x00000010 | ||
75 | #define SSH2_FXF_EXCL 0x00000020 | ||
76 | |||
77 | /* status messages */ | ||
78 | #define SSH2_FX_OK 0 | ||
79 | #define SSH2_FX_EOF 1 | ||
80 | #define SSH2_FX_NO_SUCH_FILE 2 | ||
81 | #define SSH2_FX_PERMISSION_DENIED 3 | ||
82 | #define SSH2_FX_FAILURE 4 | ||
83 | #define SSH2_FX_BAD_MESSAGE 5 | ||
84 | #define SSH2_FX_NO_CONNECTION 6 | ||
85 | #define SSH2_FX_CONNECTION_LOST 7 | ||
86 | #define SSH2_FX_OP_UNSUPPORTED 8 | ||
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: sshd.c,v 1.146 2001/01/07 11:28:07 markus Exp $"); | 43 | RCSID("$OpenBSD: sshd.c,v 1.147 2001/01/10 19:43:20 deraadt Exp $"); |
44 | 44 | ||
45 | #include "xmalloc.h" | 45 | #include "xmalloc.h" |
46 | #include "rsa.h" | 46 | #include "rsa.h" |
@@ -266,8 +266,8 @@ grace_alarm_handler(int sig) | |||
266 | * do anything with the private key or random state before forking. | 266 | * do anything with the private key or random state before forking. |
267 | * Thus there should be no concurrency control/asynchronous execution | 267 | * Thus there should be no concurrency control/asynchronous execution |
268 | * problems. | 268 | * problems. |
269 | * XXX calling log() is not safe from races. | ||
269 | */ | 270 | */ |
270 | /* XXX do we really want this work to be done in a signal handler ? -m */ | ||
271 | void | 271 | void |
272 | generate_empheral_server_key(void) | 272 | generate_empheral_server_key(void) |
273 | { | 273 | { |
@@ -279,6 +279,7 @@ generate_empheral_server_key(void) | |||
279 | arc4random_stir(); | 279 | arc4random_stir(); |
280 | log("RSA key generation complete."); | 280 | log("RSA key generation complete."); |
281 | } | 281 | } |
282 | |||
282 | void | 283 | void |
283 | key_regeneration_alarm(int sig) | 284 | key_regeneration_alarm(int sig) |
284 | { | 285 | { |