1 /*
2 * ProFTPD - mod_sftp sftp
3 * Copyright (c) 2008-2020 TJ Saunders
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 *
19 * As a special exemption, TJ Saunders and other respective copyright holders
20 * give permission to link this program with OpenSSL, and distribute the
21 * resulting executable, without including the source code for OpenSSL in the
22 * source distribution.
23 */
24
25 #include "mod_sftp.h"
26 #include "ssh2.h"
27 #include "msg.h"
28 #include "crypto.h"
29 #include "packet.h"
30 #include "disconnect.h"
31 #include "channel.h"
32 #include "auth.h"
33 #include "display.h"
34 #include "fxp.h"
35 #include "utf8.h"
36 #include "misc.h"
37
38 /* FXP_NAME file attribute flags */
39 #define SSH2_FX_ATTR_SIZE 0x00000001
40 #define SSH2_FX_ATTR_UIDGID 0x00000002
41 #define SSH2_FX_ATTR_PERMISSIONS 0x00000004
42 #define SSH2_FX_ATTR_ACMODTIME 0x00000008
43 #define SSH2_FX_ATTR_ACCESSTIME SSH2_FX_ATTR_ACMODTIME
44 #define SSH2_FX_ATTR_CREATETIME 0x00000010
45 #define SSH2_FX_ATTR_MODIFYTIME 0x00000020
46 #define SSH2_FX_ATTR_ACL 0x00000040
47 #define SSH2_FX_ATTR_OWNERGROUP 0x00000080
48 #define SSH2_FX_ATTR_SUBSECOND_TIMES 0x00000100
49 #define SSH2_FX_ATTR_BITS 0x00000200
50
51 /* Note that these attributes were added in draft-ietf-secsh-filexfer-06,
52 * which is SFTP protocol version 6.
53 */
54 #define SSH2_FX_ATTR_ALLOCATION_SIZE 0x00000400
55 #define SSH2_FX_ATTR_TEXT_HINT 0x00000800
56 #define SSH2_FX_ATTR_MIME_TYPE 0x00001000
57 #define SSH2_FX_ATTR_LINK_COUNT 0x00002000
58 #define SSH2_FX_ATTR_UNTRANSLATED_NAME 0x00004000
59
60 #define SSH2_FX_ATTR_CTIME 0x00008000
61
62 /* The EXTENDED attribute was defined in draft-ietf-secsh-filexfer-02,
63 * which is SFTP protocol version 3.
64 */
65 #define SSH2_FX_ATTR_EXTENDED 0x80000000
66
67 /* FX_ATTR_BITS values (see draft-ietf-secsh-filexfer-13, Section 7.9) */
68 #define SSH2_FX_ATTR_BIT_FL_READONLY 0x00000001
69 #define SSH2_FX_ATTR_BIT_FL_SYSTEM 0x00000002
70 #define SSH2_FX_ATTR_BIT_FL_HIDDEN 0x00000004
71 #define SSH2_FX_ATTR_BIT_FL_CASE_INSENSITIVE 0x00000008
72 #define SSH2_FX_ATTR_BIT_FL_ARCHIVE 0x00000010
73 #define SSH2_FX_ATTR_BIT_FL_ENCRYPTED 0x00000020
74 #define SSH2_FX_ATTR_BIT_FL_COMPRESSED 0x00000040
75 #define SSH2_FX_ATTR_BIT_FL_SPARSE 0x00000080
76 #define SSH2_FX_ATTR_BIT_FL_APPEND_ONLY 0x00000100
77 #define SSH2_FX_ATTR_BIT_FL_IMMUTABLE 0x00000200
78 #define SSH2_FX_ATTR_BIT_FL_SYNC 0x00000400
79 #define SSH2_FX_ATTR_BIT_FL_TRANSLATION_ERR 0x00000800
80
81 /* FX_ATTR_TEXT_HINT values (see draft-ietf-secsh-filexfer-13, Section 7.10) */
82 #define SSH2_FX_ATTR_KNOWN_TEXT 0x00
83 #define SSH2_FX_ATTR_GUESSED_TEXT 0x01
84 #define SSH2_FX_ATTR_KNOWN_BINARY 0x02
85 #define SSH2_FX_ATTR_GUESSED_BINARY 0x03
86
87 /* FXP_ATTRS file types */
88 #define SSH2_FX_ATTR_FTYPE_REGULAR 1
89 #define SSH2_FX_ATTR_FTYPE_DIRECTORY 2
90 #define SSH2_FX_ATTR_FTYPE_SYMLINK 3
91 #define SSH2_FX_ATTR_FTYPE_SPECIAL 4
92 #define SSH2_FX_ATTR_FTYPE_UNKNOWN 5
93 #define SSH2_FX_ATTR_FTYPE_SOCKET 6
94 #define SSH2_FX_ATTR_FTYPE_CHAR_DEVICE 7
95 #define SSH2_FX_ATTR_FTYPE_BLOCK_DEVICE 8
96 #define SSH2_FX_ATTR_FTYPE_FIFO 9
97
98 /* FXP_LOCK/FXP_UNLOCK flags */
99 #define SSH2_FXL_READ 0x00000040
100 #define SSH2_FXL_WRITE 0x00000080
101 #define SSH2_FXL_DELETE 0x00000100
102
103 /* FXP_OPEN flags (prior to version 5) */
104 #define SSH2_FXF_READ 0x00000001
105 #define SSH2_FXF_WRITE 0x00000002
106 #define SSH2_FXF_APPEND 0x00000004
107 #define SSH2_FXF_CREAT 0x00000008
108 #define SSH2_FXF_TRUNC 0x00000010
109 #define SSH2_FXF_EXCL 0x00000020
110 #define SSH2_FXF_TEXT 0x00000040
111
112 /* FXP_OPEN flags (version 5 and higher) */
113 #define SSH2_FXF_WANT_READ_DATA 0x00000001
114 #define SSH2_FXF_WANT_WRITE_DATA 0x00000002
115 #define SSH2_FXF_WANT_APPEND_DATA 0x00000004
116 #define SSH2_FXF_WANT_READ_NAMED_ATTRS 0x00000008
117 #define SSH2_FXF_WANT_WRITE_NAMED_ATTRS 0x00000010
118 #define SSH2_FXF_WANT_READ_ATTRIBUTES 0x00000080
119 #define SSH2_FXF_WANT_WRITE_ATTRIBUTES 0x00000100
120 #define SSH2_FXF_WANT_READ_ACL 0x00020000
121 #define SSH2_FXF_WANT_WRITE_ACL 0x00040000
122 #define SSH2_FXF_WANT_WRITE_OWNER 0x00080000
123
124 #define SSH2_FXF_CREATE_NEW 0x00000000
125 #define SSH2_FXF_CREATE_TRUNCATE 0x00000001
126 #define SSH2_FXF_OPEN_EXISTING 0x00000002
127 #define SSH2_FXF_OPEN_OR_CREATE 0x00000003
128 #define SSH2_FXF_TRUNCATE_EXISTING 0x00000004
129 #define SSH2_FXF_ACCESS_APPEND_DATA 0x00000008
130 #define SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC 0x00000010
131 #define SSH2_FXF_ACCESS_TEXT_MODE 0x00000020
132
133 /* These are the BLOCK_{READ,WRITE,DELETE} values from Section 8.1.1.3 of
134 * the SFTP Draft.
135 */
136 #define SSH2_FXF_ACCESS_READ_LOCK 0x00000040
137 #define SSH2_FXF_ACCESS_WRITE_LOCK 0x00000080
138 #define SSH2_FXF_ACCESS_DELETE_LOCK 0x00000100
139
140 /* FXP_REALPATH control values */
141 #define SSH2_FXRP_NO_CHECK 0x00000001
142 #define SSH2_FXRP_STAT_IF 0x00000002
143 #define SSH2_FXRP_STAT_ALWAYS 0x00000003
144
145 /* FXP_RENAME flags */
146 #define SSH2_FXR_OVERWRITE 0x00000001
147 #define SSH2_FXR_ATOMIC 0x00000002
148 #define SSH2_FXR_NATIVE 0x00000004
149
150 /* FXP_STATUS codes */
151 #define SSH2_FX_OK 0
152 #define SSH2_FX_EOF 1
153 #define SSH2_FX_NO_SUCH_FILE 2
154 #define SSH2_FX_PERMISSION_DENIED 3
155 #define SSH2_FX_FAILURE 4
156 #define SSH2_FX_BAD_MESSAGE 5
157 #define SSH2_FX_NO_CONNECTION 6
158 #define SSH2_FX_CONNECTION_LOST 7
159 #define SSH2_FX_OP_UNSUPPORTED 8
160 #define SSH2_FX_INVALID_HANDLE 9
161 #define SSH2_FX_NO_SUCH_PATH 10
162 #define SSH2_FX_FILE_ALREADY_EXISTS 11
163 #define SSH2_FX_WRITE_PROTECT 12
164 #define SSH2_FX_NO_MEDIA 13
165 #define SSH2_FX_NO_SPACE_ON_FILESYSTEM 14
166 #define SSH2_FX_QUOTA_EXCEEDED 15
167 #define SSH2_FX_UNKNOWN_PRINCIPAL 16
168 #define SSH2_FX_LOCK_CONFLICT 17
169 #define SSH2_FX_DIR_NOT_EMPTY 18
170 #define SSH2_FX_NOT_A_DIRECTORY 19
171 #define SSH2_FX_INVALID_FILENAME 20
172 #define SSH2_FX_LINK_LOOP 21
173 #define SSH2_FX_CANNOT_DELETE 22
174 #define SSH2_FX_INVALID_PARAMETER 23
175 #define SSH2_FX_FILE_IS_A_DIRECTORY 24
176 #define SSH2_FX_BYTE_RANGE_LOCK_CONFLICT 25
177 #define SSH2_FX_BYTE_RANGE_LOCK_REFUSED 26
178 #define SSH2_FX_DELETE_PENDING 27
179 #define SSH2_FX_FILE_CORRUPT 28
180 #define SSH2_FX_OWNER_INVALID 29
181 #define SSH2_FX_GROUP_INVALID 30
182 #define SSH2_FX_NO_MATCHING_BYTE_RANGE_LOCK 31
183
184 /* statvfs@openssh.com extension flags */
185 #define SSH2_FXE_STATVFS_ST_RDONLY 0x1
186 #define SSH2_FXE_STATVFS_ST_NOSUID 0x2
187
188 /* xattr@proftpd.org extension flags */
189 #define SSH2_FXE_XATTR_CREATE 0x1
190 #define SSH2_FXE_XATTR_REPLACE 0x2
191
192 extern pr_response_t *resp_list, *resp_err_list;
193
194 struct fxp_dirent {
195 const char *client_path;
196 const char *real_path;
197 struct stat *st;
198 };
199
200 struct fxp_handle {
201 pool *pool;
202 const char *name;
203
204 pr_fh_t *fh;
205 int fh_flags;
206
207 /* For indicating whether the file existed prior to being opened/created. */
208 int fh_existed;
209
210 /* For supporting the HiddenStores directive */
211 char *fh_real_path;
212
213 /* For referencing information about the opened file; NOTE THAT THIS MAY
214 * BE STALE.
215 */
216 struct stat *fh_st;
217
218 /* For tracking the number of bytes transferred for this file; for
219 * better TransferLog tracking.
220 */
221 size_t fh_bytes_xferred;
222
223 void *dirh;
224 const char *dir;
225 };
226
227 struct fxp_packet {
228 pool *pool;
229 uint32_t channel_id;
230 uint32_t packet_len;
231 unsigned char request_type;
232 uint32_t request_id;
233 uint32_t payload_sz;
234 unsigned char *payload;
235 uint32_t payload_len;
236
237 unsigned int state;
238 };
239
240 struct fxp_buffer {
241 /* Pointer to the start of the buffer */
242 unsigned char *ptr;
243
244 /* Total size of the buffer */
245 uint32_t bufsz;
246
247 /* Current pointer */
248 unsigned char *buf;
249
250 /* Length of buffer remaining */
251 uint32_t buflen;
252 };
253
254 #define FXP_PACKET_HAVE_PACKET_LEN 0x0001
255 #define FXP_PACKET_HAVE_REQUEST_TYPE 0x0002
256 #define FXP_PACKET_HAVE_REQUEST_ID 0x0004
257 #define FXP_PACKET_HAVE_PAYLOAD_SIZE 0x0008
258 #define FXP_PACKET_HAVE_PAYLOAD 0x0010
259
260 /* After 32K of allocation from the scratch SFTP payload pool, destroy the
261 * pool and create a new one. This will prevent unbounded allocation
262 * from the pool.
263 */
264 #define FXP_PACKET_DATA_ALLOC_MAX_SZ (1024 * 32)
265 static size_t fxp_packet_data_allocsz = 0;
266
267 #define FXP_PACKET_DATA_DEFAULT_SZ (1024 * 16)
268 #define FXP_RESPONSE_DATA_DEFAULT_SZ 512
269
270 #ifdef PR_USE_XATTR
271 /* Allocate larger buffers for extended attributes */
272 # define FXP_RESPONSE_NAME_DEFAULT_SZ (1024 * 4)
273 #endif /* PR_USE_XATTR */
274
275 #ifndef FXP_RESPONSE_NAME_DEFAULT_SZ
276 # define FXP_RESPONSE_NAME_DEFAULT_SZ FXP_RESPONSE_DATA_DEFAULT_SZ
277 #endif
278
279 #define FXP_MAX_PACKET_LEN (1024 * 512)
280
281 /* Maximum number of SFTP extended attributes we accept at one time. */
282 #ifndef FXP_MAX_EXTENDED_ATTRIBUTES
283 # define FXP_MAX_EXTENDED_ATTRIBUTES 100
284 #endif
285
286 /* Maximum length of SFTP extended attribute name OR value. */
287 #ifndef FXP_MAX_EXTENDED_ATTR_LEN
288 # define FXP_MAX_EXTENDED_ATTR_LEN 1024
289 #endif
290
291 struct fxp_extpair {
292 char *ext_name;
293 uint32_t ext_datalen;
294 unsigned char *ext_data;
295 };
296
297 static pool *fxp_pool = NULL;
298 static int fxp_use_gmt = TRUE;
299
300 /* FSOptions */
301 static unsigned long fxp_fsio_opts = 0UL;
302 static unsigned int fxp_min_client_version = 1;
303 static unsigned int fxp_max_client_version = 6;
304 static unsigned int fxp_utf8_protocol_version = 4;
305 static unsigned long fxp_ext_flags = SFTP_FXP_EXT_DEFAULT;
306
307 static pr_fh_t *fxp_displaylogin_fh = NULL;
308 static int fxp_sent_display_login_file = FALSE;
309
310 /* For handling "version-select" requests properly (or rejecting them as
311 * necessary.
312 */
313 static int allow_version_select = FALSE;
314
315 /* Use a struct to maintain the per-channel FXP-specific values. */
316 struct fxp_session {
317 struct fxp_session *next, *prev;
318
319 pool *pool;
320 uint32_t channel_id;
321 uint32_t client_version;
322 pr_table_t *handle_tab;
323 };
324
325 static struct fxp_session *fxp_session = NULL, *fxp_sessions = NULL;
326
327 static const char *trace_channel = "sftp";
328
329 /* Necessary prototypes */
330 static struct fxp_handle *fxp_handle_get(const char *);
331 static struct fxp_packet *fxp_packet_create(pool *, uint32_t);
332 static int fxp_packet_write(struct fxp_packet *);
333
fxp_get_session(uint32_t channel_id)334 static struct fxp_session *fxp_get_session(uint32_t channel_id) {
335 struct fxp_session *sess;
336
337 sess = fxp_sessions;
338 while (sess) {
339 pr_signals_handle();
340
341 if (sess->channel_id == channel_id) {
342 return sess;
343 }
344
345 sess = sess->next;
346 }
347
348 errno = ENOENT;
349 return NULL;
350 }
351
fxp_timeout_stalled_cb(CALLBACK_FRAME)352 static int fxp_timeout_stalled_cb(CALLBACK_FRAME) {
353 pr_event_generate("core.timeout-stalled", NULL);
354
355 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
356 "SFTP data transfer stalled timeout (%d secs) reached",
357 pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED));
358 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION,
359 "data stalled timeout reached");
360
361 return 0;
362 }
363
fxp_cmd_alloc(pool * p,const char * name,char * arg)364 static cmd_rec *fxp_cmd_alloc(pool *p, const char *name, char *arg) {
365 cmd_rec *cmd;
366
367 cmd = pr_cmd_alloc(p, 2, pstrdup(p, name), arg ? arg : "");
368 cmd->arg = arg;
369
370 return cmd;
371 }
372
fxp_strerror(uint32_t status)373 static const char *fxp_strerror(uint32_t status) {
374 switch (status) {
375 case SSH2_FX_OK:
376 return "OK";
377
378 case SSH2_FX_EOF:
379 return "End of file";
380
381 case SSH2_FX_NO_SUCH_FILE:
382 return "No such file";
383
384 case SSH2_FX_PERMISSION_DENIED:
385 return "Permission denied";
386
387 case SSH2_FX_BAD_MESSAGE:
388 return "Bad message";
389
390 case SSH2_FX_OP_UNSUPPORTED:
391 return "Unsupported operation";
392
393 case SSH2_FX_INVALID_HANDLE:
394 return "Invalid handle";
395
396 case SSH2_FX_NO_SUCH_PATH:
397 return "No such path";
398
399 case SSH2_FX_FILE_ALREADY_EXISTS:
400 return "File already exists";
401
402 case SSH2_FX_NO_SPACE_ON_FILESYSTEM:
403 return "Out of disk space";
404
405 case SSH2_FX_QUOTA_EXCEEDED:
406 return "Quota exceeded";
407
408 case SSH2_FX_UNKNOWN_PRINCIPAL:
409 return "Unknown principal";
410
411 case SSH2_FX_LOCK_CONFLICT:
412 return "Lock conflict";
413
414 case SSH2_FX_DIR_NOT_EMPTY:
415 return "Directory is not empty";
416
417 case SSH2_FX_NOT_A_DIRECTORY:
418 return "Not a directory";
419
420 case SSH2_FX_INVALID_FILENAME:
421 return "Invalid filename";
422
423 case SSH2_FX_LINK_LOOP:
424 return "Link loop";
425
426 case SSH2_FX_INVALID_PARAMETER:
427 return "Invalid parameter";
428
429 case SSH2_FX_FILE_IS_A_DIRECTORY:
430 return "File is a directory";
431
432 case SSH2_FX_OWNER_INVALID:
433 return "Invalid owner";
434
435 case SSH2_FX_GROUP_INVALID:
436 return "Invalid group";
437 }
438
439 return "Failure";
440 }
441
fxp_errno2status(int xerrno,const char ** reason)442 static uint32_t fxp_errno2status(int xerrno, const char **reason) {
443 uint32_t status_code = SSH2_FX_FAILURE;
444
445 /* Provide a default reason string; it will be overwritten below by a
446 * more appropriate string as necessary.
447 */
448 if (reason) {
449 *reason = fxp_strerror(status_code);
450 }
451
452 switch (xerrno) {
453 case 0:
454 status_code = SSH2_FX_OK;
455 if (reason) {
456 *reason = fxp_strerror(status_code);
457 }
458 break;
459
460 case EOF:
461 status_code = SSH2_FX_EOF;
462 if (reason) {
463 *reason = fxp_strerror(status_code);
464 }
465 break;
466
467 case EBADF:
468 case ENOENT:
469 #ifdef ENXIO
470 case ENXIO:
471 #endif
472 #if defined(ENODATA)
473 case ENODATA:
474 #endif
475 #if defined(ENOATTR) && defined(ENODATA) && ENOATTR != ENODATA
476 case ENOATTR:
477 #endif
478 status_code = SSH2_FX_NO_SUCH_FILE;
479 if (reason) {
480 *reason = fxp_strerror(status_code);
481 }
482 break;
483
484 case EACCES:
485 case EPERM:
486 status_code = SSH2_FX_PERMISSION_DENIED;
487 if (reason) {
488 *reason = fxp_strerror(status_code);
489 }
490 break;
491
492 case EIO:
493 case EXDEV:
494 if (reason) {
495 *reason = strerror(xerrno);
496 }
497 break;
498
499 case ENOSYS:
500 #ifdef ENOTSUP
501 case ENOTSUP:
502 #endif
503 status_code = SSH2_FX_OP_UNSUPPORTED;
504 if (reason) {
505 *reason = fxp_strerror(status_code);
506 }
507 break;
508
509 case EFAULT:
510 case EINVAL:
511 #ifdef E2BIG
512 case E2BIG:
513 #endif
514 #ifdef ERANGE
515 case ERANGE:
516 #endif
517 if (reason) {
518 *reason = fxp_strerror(SSH2_FX_INVALID_PARAMETER);
519 }
520
521 if (fxp_session->client_version > 5) {
522 status_code = SSH2_FX_INVALID_PARAMETER;
523
524 } else {
525 status_code = SSH2_FX_OP_UNSUPPORTED;
526 }
527 break;
528
529 case EEXIST:
530 if (reason) {
531 *reason = fxp_strerror(SSH2_FX_FILE_ALREADY_EXISTS);
532 }
533
534 if (fxp_session->client_version > 3) {
535 status_code = SSH2_FX_FILE_ALREADY_EXISTS;
536 }
537 break;
538
539 #ifdef EDQUOT
540 case EDQUOT:
541 if (reason) {
542 *reason = fxp_strerror(SSH2_FX_QUOTA_EXCEEDED);
543 }
544
545 if (fxp_session->client_version > 4) {
546 status_code = SSH2_FX_QUOTA_EXCEEDED;
547 }
548 break;
549 #endif
550
551 #ifdef EFBIG
552 case EFBIG:
553 #endif
554 #ifdef ENOSPC
555 case ENOSPC:
556 #endif
557 if (reason) {
558 *reason = fxp_strerror(SSH2_FX_NO_SPACE_ON_FILESYSTEM);
559 }
560
561 if (fxp_session->client_version > 4) {
562 status_code = SSH2_FX_NO_SPACE_ON_FILESYSTEM;
563 }
564 break;
565
566 case EISDIR:
567 if (reason) {
568 *reason = fxp_strerror(SSH2_FX_FILE_IS_A_DIRECTORY);
569 }
570
571 if (fxp_session->client_version > 5) {
572 status_code = SSH2_FX_FILE_IS_A_DIRECTORY;
573 }
574 break;
575
576 case ENOTDIR:
577 if (reason) {
578 *reason = fxp_strerror(SSH2_FX_NOT_A_DIRECTORY);
579 }
580
581 if (fxp_session->client_version > 5) {
582 status_code = SSH2_FX_NOT_A_DIRECTORY;
583 }
584 break;
585
586 case ELOOP:
587 if (reason) {
588 *reason = fxp_strerror(SSH2_FX_LINK_LOOP);
589 }
590
591 if (fxp_session->client_version > 5) {
592 status_code = SSH2_FX_LINK_LOOP;
593 }
594 break;
595
596 #ifdef ENAMETOOLONG
597 case ENAMETOOLONG:
598 if (reason) {
599 *reason = fxp_strerror(SSH2_FX_INVALID_FILENAME);
600 }
601
602 if (fxp_session->client_version > 5) {
603 status_code = SSH2_FX_INVALID_FILENAME;
604 }
605 break;
606 #endif
607
608 /* On AIX5, ENOTEMPTY and EEXIST are defined to be the same value.
609 * And using the same value multiple times in a switch statement
610 * causes compiler grief. See:
611 *
612 * http://forums.proftpd.org/smf/index.php/topic,3971.0.html
613 *
614 * To handle this, then, we only use ENOTEMPTY if it is defined to
615 * be a different value than EEXIST. We'll have an AIX-specific
616 * check for this particular error case in the fxp_handle_rmdir()
617 * function.
618 */
619 #if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST
620 case ENOTEMPTY:
621 if (reason) {
622 *reason = fxp_strerror(SSH2_FX_DIR_NOT_EMPTY);
623 }
624
625 if (fxp_session->client_version > 5) {
626 status_code = SSH2_FX_DIR_NOT_EMPTY;
627 }
628 break;
629 #endif
630 }
631
632 return status_code;
633 }
634
fxp_set_filehandle_note(cmd_rec * cmd,struct fxp_handle * fxh)635 static void fxp_set_filehandle_note(cmd_rec *cmd, struct fxp_handle *fxh) {
636 if (pr_table_add(cmd->notes, "sftp.file-handle", (char *) fxh->name, 0) < 0) {
637 int xerrno = errno;
638
639 if (xerrno != EEXIST) {
640 pr_trace_msg(trace_channel, 8,
641 "error setting 'sftp.file-handle' note: %s", strerror(xerrno));
642 }
643 }
644 }
645
fxp_trace_v3_open_flags(pool * p,uint32_t flags)646 static void fxp_trace_v3_open_flags(pool *p, uint32_t flags) {
647 char *flags_str = "";
648 int trace_level = 15;
649
650 if (pr_trace_get_level(trace_channel) < trace_level) {
651 return;
652 }
653
654 if (flags & SSH2_FXF_READ) {
655 flags_str = pstrcat(p, flags_str, "FXF_READ", NULL);
656 }
657
658 if (flags & SSH2_FXF_WRITE) {
659 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
660 "FXF_WRITE", NULL);
661 }
662
663 if (flags & SSH2_FXF_APPEND) {
664 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
665 "FXF_APPEND", NULL);
666 }
667
668 if (flags & SSH2_FXF_CREAT) {
669 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
670 "FXF_CREAT", NULL);
671 }
672
673 if (flags & SSH2_FXF_TRUNC) {
674 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
675 "FXF_TRUNC", NULL);
676 }
677
678 if (flags & SSH2_FXF_EXCL) {
679 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
680 "FXF_EXCL", NULL);
681 }
682
683 if (flags & SSH2_FXF_TEXT) {
684 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
685 "FXF_TEXT", NULL);
686 }
687
688 pr_trace_msg(trace_channel, trace_level, "OPEN flags = %s", flags_str);
689 }
690
691 /* Map the FXP_OPEN flags to POSIX flags. */
fxp_get_v3_open_flags(uint32_t flags)692 static int fxp_get_v3_open_flags(uint32_t flags) {
693 int res = 0;
694
695 if (flags & SSH2_FXF_READ) {
696 if (flags & SSH2_FXF_WRITE) {
697 res = O_RDWR;
698
699 #ifdef O_APPEND
700 if (flags & SSH2_FXF_APPEND) {
701 res |= O_APPEND;
702 }
703 #endif
704
705 } else {
706 res = O_RDONLY;
707 }
708
709 } else if (flags & SSH2_FXF_WRITE) {
710 res = O_WRONLY;
711
712 #ifdef O_APPEND
713 if (flags & SSH2_FXF_APPEND) {
714 res |= O_APPEND;
715 }
716 #endif
717
718 } else if (flags & SSH2_FXF_APPEND) {
719 /* Assume FXF_WRITE, since the client didn't explicitly provide either
720 * FXF_READ or FXF_WRITE.
721 */
722 res = O_WRONLY|O_APPEND;
723 }
724
725 if (flags & SSH2_FXF_CREAT) {
726 res |= O_CREAT;
727
728 /* Since the behavior of open(2) when O_EXCL is set and O_CREAT is not
729 * set is undefined, we avoid that situation, and only check for the
730 * FXF_EXCL SSH flag if the FXF_CREAT flag is set.
731 */
732 if (flags & SSH2_FXF_EXCL) {
733 res |= O_EXCL;
734 }
735 }
736
737 if (flags & SSH2_FXF_TRUNC) {
738 res |= O_TRUNC;
739 }
740
741 return res;
742 }
743
fxp_trace_v5_bit_flags(pool * p,uint32_t attr_bits,uint32_t attr_valid_bits)744 static void fxp_trace_v5_bit_flags(pool *p, uint32_t attr_bits,
745 uint32_t attr_valid_bits) {
746 uint32_t flags;
747 char *flags_str = "";
748 int trace_level = 15;
749
750 if (pr_trace_get_level(trace_channel) < trace_level) {
751 return;
752 }
753
754 /* We're only interested in which, of the valid bits, are turned on/enabled
755 * in the bits value, for logging.
756 */
757
758 flags = (attr_bits & attr_valid_bits);
759
760 if (flags & SSH2_FX_ATTR_BIT_FL_READONLY) {
761 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
762 "FLAGS_READONLY", NULL);
763 }
764
765 if (flags & SSH2_FX_ATTR_BIT_FL_SYSTEM) {
766 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
767 "FLAGS_SYSTEM", NULL);
768 }
769
770 if (flags & SSH2_FX_ATTR_BIT_FL_HIDDEN) {
771 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
772 "FLAGS_HIDDEN", NULL);
773 }
774
775 if (flags & SSH2_FX_ATTR_BIT_FL_CASE_INSENSITIVE) {
776 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
777 "FLAGS_CASE_INSENSITIVE", NULL);
778 }
779
780 if (flags & SSH2_FX_ATTR_BIT_FL_ARCHIVE) {
781 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
782 "FLAGS_ARCHIVE", NULL);
783 }
784
785 if (flags & SSH2_FX_ATTR_BIT_FL_ENCRYPTED) {
786 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
787 "FLAGS_ENCRYPTED", NULL);
788 }
789
790 if (flags & SSH2_FX_ATTR_BIT_FL_COMPRESSED) {
791 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
792 "FLAGS_COMPRESSED", NULL);
793 }
794
795 if (flags & SSH2_FX_ATTR_BIT_FL_SPARSE) {
796 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
797 "FLAGS_SPARSE", NULL);
798 }
799
800 if (flags & SSH2_FX_ATTR_BIT_FL_APPEND_ONLY) {
801 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
802 "FLAGS_APPEND_ONLY", NULL);
803 }
804
805 if (flags & SSH2_FX_ATTR_BIT_FL_IMMUTABLE) {
806 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
807 "FLAGS_IMMUTABLE", NULL);
808 }
809
810 if (flags & SSH2_FX_ATTR_BIT_FL_SYNC) {
811 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
812 "FLAGS_SYNC", NULL);
813 }
814
815 if (flags & SSH2_FX_ATTR_BIT_FL_TRANSLATION_ERR) {
816 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
817 "FLAGS_TRANSLATION_ERR", NULL);
818 }
819
820 pr_trace_msg(trace_channel, 15,
821 "protocol version %lu: read BITS attribute: bits %s requested",
822 (unsigned long) fxp_session->client_version, flags_str);
823 }
824
fxp_trace_v5_open_flags(pool * p,uint32_t desired_access,uint32_t flags)825 static void fxp_trace_v5_open_flags(pool *p, uint32_t desired_access,
826 uint32_t flags) {
827 uint32_t base_flag;
828 char *access_str = "", *flags_str = "";
829 int trace_level = 15;
830
831 if (pr_trace_get_level(trace_channel) < trace_level) {
832 return;
833 }
834
835 /* The flags value, in the case of v5 (and later) OPEN requests, has
836 * a "base" value, along with some modifying bits masked in.
837 */
838
839 base_flag = (flags &~ (SSH2_FXF_ACCESS_APPEND_DATA|SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC|SSH2_FXF_ACCESS_TEXT_MODE));
840
841 switch (base_flag) {
842 case SSH2_FXF_CREATE_NEW:
843 flags_str = pstrcat(p, flags_str, "FXF_CREATE_NEW", NULL);
844 break;
845
846 case SSH2_FXF_CREATE_TRUNCATE:
847 flags_str = pstrcat(p, flags_str, "FXF_CREATE_TRUNCATE", NULL);
848 break;
849
850 case SSH2_FXF_OPEN_EXISTING:
851 flags_str = pstrcat(p, flags_str, "FXF_OPEN_EXISTING", NULL);
852 break;
853
854 case SSH2_FXF_OPEN_OR_CREATE:
855 flags_str = pstrcat(p, flags_str, "FXF_OPEN_OR_CREATE", NULL);
856 break;
857
858 case SSH2_FXF_TRUNCATE_EXISTING:
859 flags_str = pstrcat(p, flags_str, "FXF_TRUNCATE_EXISTING", NULL);
860 break;
861
862 default:
863 flags_str = pstrcat(p, flags_str, "<unknown>", NULL);
864 }
865
866 if (flags & SSH2_FXF_ACCESS_APPEND_DATA) {
867 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
868 "FXF_ACCESS_APPEND_DATA", NULL);
869 }
870
871 if (flags & SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC) {
872 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
873 "FXF_ACCESS_APPEND_DATA_ATOMIC", NULL);
874 }
875
876 if (flags & SSH2_FXF_ACCESS_TEXT_MODE) {
877 flags_str = pstrcat(p, flags_str, *flags_str ? "|" : "",
878 "FXF_ACCESS_TEXT_MODE", NULL);
879 }
880
881 if (desired_access & SSH2_FXF_WANT_READ_DATA) {
882 access_str = pstrcat(p, access_str, "FXF_WANT_READ_DATA", NULL);
883 }
884
885 if (desired_access & SSH2_FXF_WANT_WRITE_DATA) {
886 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
887 "FXF_WANT_WRITE_DATA", NULL);
888 }
889
890 if (desired_access & SSH2_FXF_WANT_APPEND_DATA) {
891 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
892 "FXF_WANT_APPEND_DATA", NULL);
893 }
894
895 if (desired_access & SSH2_FXF_WANT_READ_NAMED_ATTRS) {
896 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
897 "FXF_WANT_READ_NAMED_ATTRS", NULL);
898 }
899
900 if (desired_access & SSH2_FXF_WANT_WRITE_NAMED_ATTRS) {
901 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
902 "FXF_WANT_WRITE_NAMED_ATTRS", NULL);
903 }
904
905 if (desired_access & SSH2_FXF_WANT_WRITE_ATTRIBUTES) {
906 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
907 "FXF_WANT_WRITE_ATTRS", NULL);
908 }
909
910 if (desired_access & SSH2_FXF_WANT_READ_ACL) {
911 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
912 "FXF_WANT_READ_ACL", NULL);
913 }
914
915 if (desired_access & SSH2_FXF_WANT_WRITE_ACL) {
916 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
917 "FXF_WANT_WRITE_ACL", NULL);
918 }
919
920 if (desired_access & SSH2_FXF_WANT_WRITE_OWNER) {
921 access_str = pstrcat(p, access_str, *access_str ? "|" : "",
922 "FXF_WANT_WRITE_OWNER", NULL);
923 }
924
925 pr_trace_msg(trace_channel, trace_level,
926 "OPEN flags = %s, desired access = %s", flags_str, access_str);
927 }
928
fxp_get_v5_open_flags(uint32_t desired_access,uint32_t flags)929 static int fxp_get_v5_open_flags(uint32_t desired_access, uint32_t flags) {
930 uint32_t base_flag;
931
932 /* Assume that the desired flag is read-only by default. */
933 int res = O_RDONLY;
934
935 /* These mappings are found in draft-ietf-secsh-filexfer-05.txt,
936 * section 6.3.1.
937 */
938
939 if ((desired_access & SSH2_FXF_WANT_READ_DATA) ||
940 (desired_access & SSH2_FXF_WANT_READ_ATTRIBUTES)) {
941
942 if ((desired_access & SSH2_FXF_WANT_WRITE_DATA) ||
943 (desired_access & SSH2_FXF_WANT_WRITE_ATTRIBUTES)) {
944 res = O_RDWR;
945
946 #ifdef O_APPEND
947 if ((desired_access & SSH2_FXF_WANT_APPEND_DATA) &&
948 ((flags & SSH2_FXF_ACCESS_APPEND_DATA) ||
949 (flags & SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC))) {
950 res |= O_APPEND;
951 }
952 #endif
953
954 } else {
955 res = O_RDONLY;
956 }
957
958 } else if ((desired_access & SSH2_FXF_WANT_WRITE_DATA) ||
959 (desired_access & SSH2_FXF_WANT_WRITE_ATTRIBUTES)) {
960 res = O_WRONLY;
961
962 #ifdef O_APPEND
963 if ((desired_access & SSH2_FXF_WANT_APPEND_DATA) &&
964 ((flags & SSH2_FXF_ACCESS_APPEND_DATA) ||
965 (flags & SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC))) {
966 res |= O_APPEND;
967 }
968 #endif
969 }
970
971 /* The flags value, in the case of v5 (and later) OPEN requests, has
972 * a "base" value, along with some modifying bits masked in.
973 */
974 base_flag = (flags &~ (SSH2_FXF_ACCESS_APPEND_DATA|SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC|SSH2_FXF_ACCESS_TEXT_MODE));
975
976 switch (base_flag) {
977 case SSH2_FXF_CREATE_NEW:
978 res |= O_CREAT|O_EXCL;
979 break;
980
981 case SSH2_FXF_CREATE_TRUNCATE:
982 if (res == O_RDONLY) {
983 /* A truncate is a write. */
984 res = O_WRONLY;
985 }
986 res |= O_CREAT|O_TRUNC;
987 break;
988
989 case SSH2_FXF_OPEN_EXISTING:
990 break;
991
992 case SSH2_FXF_OPEN_OR_CREATE:
993 res |= O_CREAT;
994 break;
995
996 case SSH2_FXF_TRUNCATE_EXISTING:
997 if (res == O_RDONLY) {
998 /* A truncate is a write. */
999 res = O_WRONLY;
1000 }
1001 res |= O_TRUNC;
1002 break;
1003
1004 default:
1005 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1006 "unknown OPEN base flag value (%lu), defaulting to O_RDONLY",
1007 (unsigned long) base_flag);
1008 break;
1009 }
1010
1011 return res;
1012 }
1013
fxp_strtime(pool * p,time_t t)1014 static const char *fxp_strtime(pool *p, time_t t) {
1015 return pr_strtime3(p, t, TRUE);
1016 }
1017
fxp_cmd_dispatch(cmd_rec * cmd)1018 static void fxp_cmd_dispatch(cmd_rec *cmd) {
1019 pr_cmd_dispatch_phase(cmd, POST_CMD, 0);
1020 pr_cmd_dispatch_phase(cmd, LOG_CMD, 0);
1021 pr_response_clear(&resp_list);
1022 }
1023
fxp_cmd_dispatch_err(cmd_rec * cmd)1024 static void fxp_cmd_dispatch_err(cmd_rec *cmd) {
1025 pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
1026 pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
1027 pr_response_clear(&resp_err_list);
1028 }
1029
fxp_cmd_note_file_status(cmd_rec * cmd,const char * status)1030 static void fxp_cmd_note_file_status(cmd_rec *cmd, const char *status) {
1031 if (pr_table_add(cmd->notes, "mod_sftp.file-status",
1032 pstrdup(cmd->pool, status), 0) < 0) {
1033 if (errno != EEXIST) {
1034 pr_trace_msg(trace_channel, 3,
1035 "error stashing file status in command notes: %s", strerror(errno));
1036 }
1037 }
1038 }
1039
fxp_get_request_type_desc(unsigned char request_type)1040 static const char *fxp_get_request_type_desc(unsigned char request_type) {
1041 switch (request_type) {
1042 case SFTP_SSH2_FXP_INIT:
1043 return "INIT";
1044
1045 case SFTP_SSH2_FXP_VERSION:
1046 /* XXX We should never receive this type of message from the client. */
1047 return "VERSION";
1048
1049 case SFTP_SSH2_FXP_OPEN:
1050 return "OPEN";
1051
1052 case SFTP_SSH2_FXP_CLOSE:
1053 return "CLOSE";
1054
1055 case SFTP_SSH2_FXP_READ:
1056 return "READ";
1057
1058 case SFTP_SSH2_FXP_WRITE:
1059 return "WRITE";
1060
1061 case SFTP_SSH2_FXP_LSTAT:
1062 return "LSTAT";
1063
1064 case SFTP_SSH2_FXP_FSTAT:
1065 return "FSTAT";
1066
1067 case SFTP_SSH2_FXP_SETSTAT:
1068 return "SETSTAT";
1069
1070 case SFTP_SSH2_FXP_FSETSTAT:
1071 return "FSETSTAT";
1072
1073 case SFTP_SSH2_FXP_OPENDIR:
1074 return "OPENDIR";
1075
1076 case SFTP_SSH2_FXP_READDIR:
1077 return "READDIR";
1078
1079 case SFTP_SSH2_FXP_REMOVE:
1080 return "REMOVE";
1081
1082 case SFTP_SSH2_FXP_MKDIR:
1083 return "MKDIR";
1084
1085 case SFTP_SSH2_FXP_RMDIR:
1086 return "RMDIR";
1087
1088 case SFTP_SSH2_FXP_REALPATH:
1089 return "REALPATH";
1090
1091 case SFTP_SSH2_FXP_STAT:
1092 return "STAT";
1093
1094 case SFTP_SSH2_FXP_RENAME:
1095 return "RENAME";
1096
1097 case SFTP_SSH2_FXP_READLINK:
1098 return "READLINK";
1099
1100 case SFTP_SSH2_FXP_LINK:
1101 return "LINK";
1102
1103 case SFTP_SSH2_FXP_SYMLINK:
1104 return "SYMLINK";
1105
1106 case SFTP_SSH2_FXP_LOCK:
1107 return "LOCK";
1108
1109 case SFTP_SSH2_FXP_UNLOCK:
1110 return "UNLOCK";
1111
1112 case SFTP_SSH2_FXP_STATUS:
1113 return "STATUS";
1114
1115 case SFTP_SSH2_FXP_HANDLE:
1116 return "HANDLE";
1117
1118 case SFTP_SSH2_FXP_DATA:
1119 return "DATA";
1120
1121 case SFTP_SSH2_FXP_NAME:
1122 return "NAME";
1123
1124 case SFTP_SSH2_FXP_ATTRS:
1125 return "ATTRS";
1126
1127 case SFTP_SSH2_FXP_EXTENDED:
1128 return "EXTENDED";
1129
1130 case SFTP_SSH2_FXP_EXTENDED_REPLY:
1131 return "EXTENDED_REPLY";
1132 }
1133
1134 return "(unknown)";
1135 }
1136
fxp_path_pass_regex_filters(pool * p,const char * request,const char * path)1137 static int fxp_path_pass_regex_filters(pool *p, const char *request,
1138 const char *path) {
1139 int res;
1140 xaset_t *set;
1141
1142 set = get_dir_ctxt(p, (char *) path);
1143
1144 res = pr_filter_allow_path(set, path);
1145 switch (res) {
1146 case 0:
1147 break;
1148
1149 case PR_FILTER_ERR_FAILS_ALLOW_FILTER:
1150 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1151 "path '%s' for %s denied by PathAllowFilter", path, request);
1152 errno = EACCES;
1153 return -1;
1154
1155 case PR_FILTER_ERR_FAILS_DENY_FILTER:
1156 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1157 "path '%s' for %s denied by PathDenyFilter", path, request);
1158 errno = EACCES;
1159 return -1;
1160 }
1161
1162 return 0;
1163 }
1164
1165 /* FXP_STATUS messages */
fxp_status_write(pool * p,unsigned char ** buf,uint32_t * buflen,uint32_t request_id,uint32_t status_code,const char * status_msg,const char * extra_data)1166 static void fxp_status_write(pool *p, unsigned char **buf, uint32_t *buflen,
1167 uint32_t request_id, uint32_t status_code, const char *status_msg,
1168 const char *extra_data) {
1169 char num[32];
1170
1171 /* Add a fake response to the response chain, for use by mod_log's
1172 * logging, e.g. for supporting the %S/%s LogFormat variables.
1173 */
1174
1175 pr_response_clear(&resp_list);
1176 pr_response_clear(&resp_err_list);
1177
1178 memset(num, '\0', sizeof(num));
1179 pr_snprintf(num, sizeof(num)-1, "%lu", (unsigned long) status_code);
1180 num[sizeof(num)-1] = '\0';
1181 pr_response_add(pstrdup(p, num), "%s", status_msg);
1182
1183 sftp_msg_write_byte(buf, buflen, SFTP_SSH2_FXP_STATUS);
1184 sftp_msg_write_int(buf, buflen, request_id);
1185 sftp_msg_write_int(buf, buflen, status_code);
1186
1187 if (fxp_session->client_version >= 3) {
1188 sftp_msg_write_string(buf, buflen, status_msg);
1189 /* XXX localization */
1190 sftp_msg_write_string(buf, buflen, "en-US");
1191
1192 if (fxp_session->client_version >= 5 &&
1193 extra_data) {
1194 /* Used specifically for UNKNOWN_PRINCIPAL errors */
1195 sftp_msg_write_string(buf, buflen, extra_data);
1196 }
1197 }
1198 }
1199
1200 /* The SFTP subsystem Draft defines a few new data types. */
1201
1202 #if 0
1203 /* XXX Not really used for messages from clients. */
1204 static uint16_t fxp_msg_read_short(pool *p, char **buf, uint32_t *buflen) {
1205 uint16_t val;
1206
1207 (void) p;
1208
1209 if (*buflen < sizeof(uint16_t)) {
1210 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1211 "SFTP message format error: unable to read short (buflen = %lu)",
1212 (unsigned long) *buflen);
1213 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
1214 }
1215
1216 memcpy(&val, *buf, sizeof(uint16_t));
1217 (*buf) += sizeof(uint16_t);
1218 (*buflen) -= sizeof(uint16_t);
1219
1220 val = ntohs(val);
1221 return val;
1222 }
1223 #endif
1224
fxp_msg_read_extpair(pool * p,unsigned char ** buf,uint32_t * buflen)1225 static struct fxp_extpair *fxp_msg_read_extpair(pool *p, unsigned char **buf,
1226 uint32_t *buflen) {
1227 uint32_t namelen, datalen;
1228 unsigned char *name, *data;
1229 struct fxp_extpair *extpair;
1230
1231 namelen = sftp_msg_read_int(p, buf, buflen);
1232 if (*buflen < namelen) {
1233 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1234 "SFTP message format error: unable to read %lu bytes of extpair name "
1235 "data (buflen = %lu)", (unsigned long) namelen, (unsigned long) *buflen);
1236 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
1237 }
1238
1239 if (namelen > FXP_MAX_EXTENDED_ATTR_LEN) {
1240 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1241 "received too-long extended attribute name (%lu > max %lu), ignoring",
1242 (unsigned long) namelen, (unsigned long) FXP_MAX_EXTENDED_ATTR_LEN);
1243 errno = EINVAL;
1244 return NULL;
1245 }
1246
1247 name = palloc(p, namelen + 1);
1248 memcpy(name, *buf, namelen);
1249 (*buf) += namelen;
1250 (*buflen) -= namelen;
1251 name[namelen] = '\0';
1252
1253 datalen = sftp_msg_read_int(p, buf, buflen);
1254 if (datalen > 0) {
1255 if (datalen > FXP_MAX_EXTENDED_ATTR_LEN) {
1256 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1257 "received too-long extended attribute '%s' value (%lu > max %lu), "
1258 "ignoring", name, (unsigned long) datalen,
1259 (unsigned long) FXP_MAX_EXTENDED_ATTR_LEN);
1260 errno = EINVAL;
1261 return NULL;
1262 }
1263
1264 data = sftp_msg_read_data(p, buf, buflen, datalen);
1265
1266 } else {
1267 data = NULL;
1268 }
1269
1270 extpair = palloc(p, sizeof(struct fxp_extpair));
1271 extpair->ext_name = (char *) name;
1272 extpair->ext_datalen = datalen;
1273 extpair->ext_data = data;
1274
1275 return extpair;
1276 }
1277
fxp_msg_write_short(unsigned char ** buf,uint32_t * buflen,uint16_t val)1278 static uint32_t fxp_msg_write_short(unsigned char **buf, uint32_t *buflen,
1279 uint16_t val) {
1280 uint32_t len = 0;
1281
1282 if (*buflen < sizeof(uint16_t)) {
1283 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1284 "SFTP message format error: unable to write short (buflen = %lu)",
1285 (unsigned long) *buflen);
1286 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
1287 }
1288
1289 len = sizeof(uint16_t);
1290
1291 val = htons(val);
1292 memcpy(*buf, &val, len);
1293 (*buf) += len;
1294 (*buflen) -= len;
1295
1296 return len;
1297 }
1298
fxp_msg_write_extpair(unsigned char ** buf,uint32_t * buflen,struct fxp_extpair * extpair)1299 static void fxp_msg_write_extpair(unsigned char **buf, uint32_t *buflen,
1300 struct fxp_extpair *extpair) {
1301 uint32_t len;
1302
1303 len = strlen(extpair->ext_name);
1304 sftp_msg_write_data(buf, buflen, (unsigned char *) extpair->ext_name, len,
1305 TRUE);
1306 sftp_msg_write_data(buf, buflen, extpair->ext_data, extpair->ext_datalen,
1307 TRUE);
1308 }
1309
fxp_attrs_clear_unsupported(uint32_t attr_flags)1310 static uint32_t fxp_attrs_clear_unsupported(uint32_t attr_flags) {
1311
1312 /* Clear any unsupported/ignored flags. */
1313
1314 if (attr_flags & SSH2_FX_ATTR_ALLOCATION_SIZE) {
1315 pr_trace_msg(trace_channel, 17,
1316 "clearing unsupported ALLOCATION_SIZE attribute flag");
1317 attr_flags &= ~SSH2_FX_ATTR_ALLOCATION_SIZE;
1318 }
1319
1320 if (attr_flags & SSH2_FX_ATTR_SUBSECOND_TIMES) {
1321 pr_trace_msg(trace_channel, 17,
1322 "clearing unsupported SUBSECOND_TIMES attribute flag");
1323 attr_flags &= ~SSH2_FX_ATTR_SUBSECOND_TIMES;
1324 }
1325
1326 if (attr_flags & SSH2_FX_ATTR_CREATETIME) {
1327 pr_trace_msg(trace_channel, 17,
1328 "clearing unsupported CREATETIME attribute flag");
1329 attr_flags &= ~SSH2_FX_ATTR_CREATETIME;
1330 }
1331
1332 if (attr_flags & SSH2_FX_ATTR_ACL) {
1333 pr_trace_msg(trace_channel, 17,
1334 "clearing unsupported ACL attribute flag");
1335 attr_flags &= ~SSH2_FX_ATTR_ACL;
1336 }
1337
1338 if (attr_flags & SSH2_FX_ATTR_BITS) {
1339 pr_trace_msg(trace_channel, 17,
1340 "clearing unsupported BITS attribute flag");
1341 attr_flags &= ~SSH2_FX_ATTR_BITS;
1342 }
1343
1344 if (attr_flags & SSH2_FX_ATTR_TEXT_HINT) {
1345 pr_trace_msg(trace_channel, 17,
1346 "clearing unsupported TEXT_HINT attribute flag");
1347 attr_flags &= ~SSH2_FX_ATTR_TEXT_HINT;
1348 }
1349
1350 if (attr_flags & SSH2_FX_ATTR_MIME_TYPE) {
1351 pr_trace_msg(trace_channel, 17,
1352 "clearing unsupported MIME_TYPE attribute flag");
1353 attr_flags &= ~SSH2_FX_ATTR_MIME_TYPE;
1354 }
1355
1356 if (attr_flags & SSH2_FX_ATTR_UNTRANSLATED_NAME) {
1357 pr_trace_msg(trace_channel, 17,
1358 "clearing unsupported UNTRANSLATED_NAME attribute flag");
1359 attr_flags &= ~SSH2_FX_ATTR_UNTRANSLATED_NAME;
1360 }
1361
1362 if (attr_flags & SSH2_FX_ATTR_CTIME) {
1363 pr_trace_msg(trace_channel, 17,
1364 "clearing unsupported CTIME attribute flag");
1365 attr_flags &= ~SSH2_FX_ATTR_CTIME;
1366 }
1367
1368 return attr_flags;
1369 }
1370
fxp_attrs_set(pr_fh_t * fh,const char * path,struct stat * attrs,uint32_t attr_flags,array_header * xattrs,unsigned char ** buf,uint32_t * buflen,struct fxp_packet * fxp)1371 static int fxp_attrs_set(pr_fh_t *fh, const char *path, struct stat *attrs,
1372 uint32_t attr_flags, array_header *xattrs, unsigned char **buf,
1373 uint32_t *buflen, struct fxp_packet *fxp) {
1374 struct stat st;
1375 int res;
1376
1377 /* Note: path is never null; it is always passed by the caller. fh MAY be
1378 * null, depending on whether the caller already has a file handle or not.
1379 */
1380
1381 if (fh != NULL) {
1382 res = pr_fsio_fstat(fh, &st);
1383
1384 } else {
1385 pr_fs_clear_cache2(path);
1386 res = pr_fsio_lstat(path, &st);
1387 }
1388
1389 if (res < 0) {
1390 uint32_t status_code;
1391 const char *reason;
1392 int xerrno = errno;
1393
1394 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1395 "error checking '%s': %s", path, strerror(xerrno));
1396
1397 status_code = fxp_errno2status(xerrno, &reason);
1398
1399 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1400 "('%s' [%d])", (unsigned long) status_code, reason,
1401 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
1402
1403 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id, status_code,
1404 reason, NULL);
1405
1406 errno = xerrno;
1407 return -1;
1408 }
1409
1410 if (attr_flags & SSH2_FX_ATTR_PERMISSIONS) {
1411 if (attrs->st_mode &&
1412 st.st_mode != attrs->st_mode) {
1413 cmd_rec *cmd;
1414
1415 cmd = fxp_cmd_alloc(fxp->pool, "SITE_CHMOD", pstrdup(fxp->pool, path));
1416 if (!dir_check(fxp->pool, cmd, G_WRITE, (char *) path, NULL)) {
1417 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1418 "chmod of '%s' blocked by <Limit> configuration", path);
1419
1420 errno = EACCES;
1421 res = -1;
1422
1423 } else {
1424 if (fh != NULL) {
1425 res = pr_fsio_fchmod(fh, attrs->st_mode);
1426
1427 } else {
1428 res = pr_fsio_chmod(path, attrs->st_mode);
1429 }
1430 }
1431
1432 if (res < 0) {
1433 uint32_t status_code;
1434 const char *reason;
1435 int xerrno = errno;
1436
1437 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1438 "error changing permissions of '%s' to 0%o: %s", path,
1439 (unsigned int) attrs->st_mode, strerror(xerrno));
1440
1441 status_code = fxp_errno2status(xerrno, &reason);
1442
1443 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1444 "('%s' [%d])", (unsigned long) status_code, reason,
1445 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
1446
1447 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id, status_code,
1448 reason, NULL);
1449
1450 errno = xerrno;
1451 return -1;
1452 }
1453
1454 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1455 "client set permissions on '%s' to 0%o", path,
1456 (unsigned int) (attrs->st_mode & ~S_IFMT));
1457 }
1458 }
1459
1460 if ((attr_flags & SSH2_FX_ATTR_UIDGID) ||
1461 (attr_flags & SSH2_FX_ATTR_OWNERGROUP)) {
1462 int do_chown = FALSE;
1463 uid_t client_uid = (uid_t) -1;
1464 gid_t client_gid = (gid_t) -1;
1465
1466 if (st.st_uid != attrs->st_uid) {
1467 client_uid = attrs->st_uid;
1468 do_chown = TRUE;
1469 }
1470
1471 if (st.st_gid != attrs->st_gid) {
1472 client_gid = attrs->st_gid;
1473 do_chown = TRUE;
1474 }
1475
1476 if (do_chown) {
1477 cmd_rec *cmd;
1478
1479 cmd = fxp_cmd_alloc(fxp->pool, "SITE_CHGRP", pstrdup(fxp->pool, path));
1480 if (!dir_check(fxp->pool, cmd, G_WRITE, (char *) path, NULL)) {
1481 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1482 "chown of '%s' blocked by <Limit> configuration", path);
1483
1484 errno = EACCES;
1485 res = -1;
1486
1487 } else {
1488 if (fh != NULL) {
1489 res = pr_fsio_fchown(fh, client_uid, client_gid);
1490
1491 } else {
1492 res = pr_fsio_chown(path, client_uid, client_gid);
1493 }
1494 }
1495
1496 if (res < 0) {
1497 uint32_t status_code;
1498 const char *reason;
1499 int xerrno = errno;
1500
1501 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1502 "error changing ownership of '%s' to UID %s, GID %s: %s",
1503 path, pr_uid2str(fxp->pool, client_uid),
1504 pr_gid2str(fxp->pool, client_gid), strerror(xerrno));
1505
1506 status_code = fxp_errno2status(xerrno, &reason);
1507
1508 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1509 "('%s' [%d])", (unsigned long) status_code, reason,
1510 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
1511
1512 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id, status_code,
1513 reason, NULL);
1514
1515 errno = xerrno;
1516 return -1;
1517 }
1518
1519 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1520 "client set ownership of '%s' to UID %s, GID %s",
1521 path, pr_uid2str(fxp->pool, client_uid),
1522 pr_gid2str(fxp->pool, client_gid));
1523 }
1524 }
1525
1526 if (attr_flags & SSH2_FX_ATTR_SIZE) {
1527 if (attrs->st_size &&
1528 st.st_size != attrs->st_size) {
1529
1530 /* If we're dealing with a FIFO, just pretend that the truncate(2)
1531 * succeeded; FIFOs don't handle truncation well. And it won't
1532 * necessarily matter to the client, right?
1533 */
1534 if (S_ISREG(st.st_mode)) {
1535 if (fh != NULL) {
1536 res = pr_fsio_ftruncate(fh, attrs->st_size);
1537
1538 } else {
1539 res = pr_fsio_truncate(path, attrs->st_size);
1540 }
1541
1542 } else {
1543 res = 0;
1544 }
1545
1546 if (res < 0) {
1547 uint32_t status_code;
1548 const char *reason;
1549 int xerrno = errno;
1550
1551 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1552 "error changing size of '%s' from %" PR_LU " bytes to %" PR_LU
1553 " bytes: %s", path, (pr_off_t) st.st_size, (pr_off_t) attrs->st_size,
1554 strerror(xerrno));
1555
1556 status_code = fxp_errno2status(xerrno, &reason);
1557
1558 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1559 "('%s' [%d])", (unsigned long) status_code, reason,
1560 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
1561
1562 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id, status_code,
1563 reason, NULL);
1564
1565 errno = xerrno;
1566 return -1;
1567 }
1568
1569 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1570 "client set size of '%s' to %" PR_LU " bytes", path,
1571 (pr_off_t) attrs->st_size);
1572 }
1573 }
1574
1575 if (fxp_session->client_version <= 3 &&
1576 attr_flags & SSH2_FX_ATTR_ACMODTIME) {
1577 if (st.st_atime != attrs->st_atime ||
1578 st.st_mtime != attrs->st_mtime) {
1579 struct timeval tvs[2];
1580
1581 tvs[0].tv_sec = attrs->st_atime;
1582 tvs[0].tv_usec = 0;
1583
1584 tvs[1].tv_sec = attrs->st_mtime;
1585 tvs[1].tv_usec = 0;
1586
1587 if (fh != NULL) {
1588 res = pr_fsio_futimes(fh, tvs);
1589
1590 } else {
1591 res = pr_fsio_utimes(path, tvs);
1592 }
1593
1594 if (res < 0) {
1595 uint32_t status_code;
1596 const char *reason;
1597 int xerrno = errno;
1598
1599 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1600 "error changing access/modification times '%s': %s", path,
1601 strerror(xerrno));
1602
1603 status_code = fxp_errno2status(xerrno, &reason);
1604
1605 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1606 "('%s' [%d])", (unsigned long) status_code, reason,
1607 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
1608
1609 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id, status_code,
1610 reason, NULL);
1611
1612 errno = xerrno;
1613 return -1;
1614 }
1615
1616 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1617 "client set access time of '%s' to %s, modification time to %s",
1618 path, fxp_strtime(fxp->pool, attrs->st_atime),
1619 fxp_strtime(fxp->pool, attrs->st_mtime));
1620 }
1621 }
1622
1623 if (fxp_session->client_version > 3) {
1624 /* Note: we handle the xattrs FIRST, before the timestamps, so that
1625 * setting the xattrs does not change the expected timestamps, thus
1626 * preserving the principle of least surprise.
1627 */
1628 if (attr_flags & SSH2_FX_ATTR_EXTENDED) {
1629 #ifdef PR_USE_XATTR
1630 if (xattrs != NULL &&
1631 xattrs->nelts > 0) {
1632 register unsigned int i;
1633 struct fxp_extpair **ext_pairs;
1634
1635 ext_pairs = xattrs->elts;
1636 for (i = 0; i < xattrs->nelts; i++) {
1637 struct fxp_extpair *xattr;
1638 const char *xattr_name;
1639 void *xattr_val;
1640 size_t xattr_valsz;
1641
1642 xattr = ext_pairs[i];
1643 xattr_name = xattr->ext_name;
1644 xattr_val = xattr->ext_data;
1645 xattr_valsz = (size_t) xattr->ext_datalen;
1646
1647 if (fh != NULL) {
1648 res = pr_fsio_fsetxattr(fxp->pool, fh, xattr_name, xattr_val,
1649 xattr_valsz, 0);
1650
1651 } else {
1652 res = pr_fsio_lsetxattr(fxp->pool, path, xattr_name, xattr_val,
1653 xattr_valsz, 0);
1654 }
1655
1656 if (res < 0) {
1657 uint32_t status_code;
1658 const char *reason;
1659 int xerrno = errno;
1660
1661 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1662 "error setting xattr '%s' (%lu bytes) on '%s': %s", xattr_name,
1663 (unsigned long) xattr_valsz, path, strerror(xerrno));
1664
1665 status_code = fxp_errno2status(xerrno, &reason);
1666
1667 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1668 "('%s' [%d])", (unsigned long) status_code, reason,
1669 strerror(xerrno), xerrno);
1670
1671 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id,
1672 status_code, reason, NULL);
1673
1674 errno = xerrno;
1675 return -1;
1676 }
1677 }
1678 }
1679 #else
1680 (void) xattrs;
1681 #endif /* PR_USE_XATTR */
1682 }
1683
1684 if (attr_flags & SSH2_FX_ATTR_ACCESSTIME) {
1685 if (st.st_atime != attrs->st_atime) {
1686 struct timeval tvs[2];
1687
1688 tvs[0].tv_sec = attrs->st_atime;
1689 tvs[0].tv_usec = 0;
1690
1691 tvs[1].tv_sec = st.st_mtime;
1692 tvs[1].tv_usec = 0;
1693
1694 if (fh != NULL) {
1695 res = pr_fsio_futimes(fh, tvs);
1696
1697 } else {
1698 res = pr_fsio_utimes(path, tvs);
1699 }
1700
1701 if (res < 0) {
1702 uint32_t status_code;
1703 const char *reason;
1704 int xerrno = errno;
1705
1706 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1707 "error changing access time '%s': %s", path, strerror(xerrno));
1708
1709 status_code = fxp_errno2status(xerrno, &reason);
1710
1711 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1712 "('%s' [%d])", (unsigned long) status_code, reason,
1713 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
1714
1715 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id, status_code,
1716 reason, NULL);
1717
1718 errno = xerrno;
1719 return -1;
1720 }
1721
1722 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1723 "client set access time of '%s' to %s", path,
1724 fxp_strtime(fxp->pool, attrs->st_atime));
1725 }
1726 }
1727
1728 if (attr_flags & SSH2_FX_ATTR_MODIFYTIME) {
1729 if (st.st_mtime != attrs->st_mtime) {
1730 struct timeval tvs[2];
1731
1732 tvs[0].tv_sec = st.st_atime;
1733 tvs[0].tv_usec = 0;
1734
1735 tvs[1].tv_sec = attrs->st_mtime;
1736 tvs[1].tv_usec = 0;
1737
1738 if (fh != NULL) {
1739 res = pr_fsio_futimes(fh, tvs);
1740
1741 } else {
1742 res = pr_fsio_utimes(path, tvs);
1743 }
1744
1745 if (res < 0) {
1746 uint32_t status_code;
1747 const char *reason;
1748 int xerrno = errno;
1749
1750 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1751 "error changing modification time '%s': %s", path,
1752 strerror(xerrno));
1753
1754 status_code = fxp_errno2status(xerrno, &reason);
1755
1756 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
1757 "('%s' [%d])", (unsigned long) status_code, reason,
1758 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
1759
1760 fxp_status_write(fxp->pool, buf, buflen, fxp->request_id, status_code,
1761 reason, NULL);
1762
1763 errno = xerrno;
1764 return -1;
1765 }
1766
1767 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
1768 "client set modification time of '%s' to %s", path,
1769 fxp_strtime(fxp->pool, attrs->st_mtime));
1770 }
1771 }
1772 }
1773
1774 return 0;
1775 }
1776
1777 /* Provide a stringified representation of attributes sent by clients. */
1778
fxp_strftype(mode_t mode)1779 static const char *fxp_strftype(mode_t mode) {
1780 if (S_ISREG(mode)) {
1781 return "file";
1782 }
1783
1784 if (S_ISDIR(mode)) {
1785 return "dir";
1786 }
1787
1788 if (S_ISLNK(mode)) {
1789 return "symlink";
1790 }
1791
1792 if (S_ISSOCK(mode)) {
1793 return "socket";
1794 }
1795
1796 #ifdef S_ISFIFO
1797 if (S_ISFIFO(mode)) {
1798 return "fifo";
1799 }
1800 #endif
1801
1802 #ifdef S_ISCHR
1803 if (S_ISCHR(mode)) {
1804 return "dev/char";
1805 }
1806 #endif
1807
1808 #ifdef S_ISBLK
1809 if (S_ISBLK(mode)) {
1810 return "dev/block";
1811 }
1812 #endif
1813
1814 return "unknown";
1815 }
1816
fxp_strattrs(pool * p,struct stat * st,uint32_t * attr_flags)1817 static char *fxp_strattrs(pool *p, struct stat *st, uint32_t *attr_flags) {
1818 char buf[PR_TUNABLE_BUFFER_SIZE], *ptr;
1819 size_t buflen = 0, bufsz;
1820 uint32_t flags = 0;
1821
1822 buflen = 0;
1823 bufsz = sizeof(buf);
1824 memset(buf, '\0', bufsz);
1825
1826 ptr = buf;
1827
1828 if (attr_flags != NULL) {
1829 flags = *attr_flags;
1830
1831 } else {
1832 if (fxp_session->client_version <= 3) {
1833 flags = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_UIDGID|SSH2_FX_ATTR_PERMISSIONS|
1834 SSH2_FX_ATTR_ACMODTIME;
1835
1836 } else {
1837 flags = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_PERMISSIONS|
1838 SSH2_FX_ATTR_ACCESSTIME|SSH2_FX_ATTR_MODIFYTIME|
1839 SSH2_FX_ATTR_OWNERGROUP;
1840
1841 if (fxp_session->client_version >= 6) {
1842 flags |= SSH2_FX_ATTR_LINK_COUNT;
1843 #ifdef PR_USE_XATTR
1844 flags |= SSH2_FX_ATTR_EXTENDED;
1845 #endif /* PR_USE_XATTR */
1846 }
1847 }
1848 }
1849
1850 pr_snprintf(ptr, bufsz - buflen, "type=%s;", fxp_strftype(st->st_mode));
1851 buflen = strlen(buf);
1852 ptr = buf + buflen;
1853
1854 if (flags & SSH2_FX_ATTR_SIZE) {
1855 pr_snprintf(ptr, bufsz - buflen, "size=%" PR_LU ";",
1856 (pr_off_t) st->st_size);
1857 buflen = strlen(buf);
1858 ptr = buf + buflen;
1859 }
1860
1861 if ((flags & SSH2_FX_ATTR_UIDGID) ||
1862 (flags & SSH2_FX_ATTR_OWNERGROUP)) {
1863 pr_snprintf(ptr, bufsz - buflen, "UNIX.owner=%s;",
1864 pr_uid2str(NULL, st->st_uid));
1865 buflen = strlen(buf);
1866 ptr = buf + buflen;
1867
1868 pr_snprintf(ptr, bufsz - buflen, "UNIX.group=%s;",
1869 pr_gid2str(NULL, st->st_gid));
1870 buflen = strlen(buf);
1871 ptr = buf + buflen;
1872 }
1873
1874 if (flags & SSH2_FX_ATTR_PERMISSIONS) {
1875 pr_snprintf(ptr, bufsz - buflen, "UNIX.mode=%04o;",
1876 (unsigned int) st->st_mode & 07777);
1877 buflen = strlen(buf);
1878 ptr = buf + buflen;
1879 }
1880
1881 if (fxp_session->client_version <= 3) {
1882 if (flags & SSH2_FX_ATTR_ACMODTIME) {
1883 struct tm *tm;
1884
1885 tm = pr_gmtime(p, (const time_t *) &st->st_atime);
1886 if (tm != NULL) {
1887 pr_snprintf(ptr, bufsz - buflen, "access=%04d%02d%02d%02d%02d%02d;",
1888 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min,
1889 tm->tm_sec);
1890 buflen = strlen(buf);
1891 ptr = buf + buflen;
1892
1893 } else {
1894 pr_trace_msg(trace_channel, 1,
1895 "error obtaining st_atime GMT timestamp: %s", strerror(errno));
1896 }
1897
1898 tm = pr_gmtime(p, (const time_t *) &st->st_mtime);
1899 if (tm != NULL) {
1900 pr_snprintf(ptr, bufsz - buflen, "modify=%04d%02d%02d%02d%02d%02d;",
1901 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min,
1902 tm->tm_sec);
1903
1904 } else {
1905 pr_trace_msg(trace_channel, 1,
1906 "error obtaining st_mtime GMT timestamp: %s", strerror(errno));
1907 }
1908
1909 buflen = strlen(buf);
1910 ptr = buf + buflen;
1911 }
1912
1913 } else {
1914 if (flags & SSH2_FX_ATTR_ACCESSTIME) {
1915 struct tm *tm;
1916
1917 tm = pr_gmtime(p, (const time_t *) &st->st_atime);
1918 if (tm != NULL) {
1919 pr_snprintf(ptr, bufsz - buflen, "access=%04d%02d%02d%02d%02d%02d;",
1920 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min,
1921 tm->tm_sec);
1922
1923 } else {
1924 pr_trace_msg(trace_channel, 1,
1925 "error obtaining st_atime GMT timestamp: %s", strerror(errno));
1926 }
1927
1928 buflen = strlen(buf);
1929 ptr = buf + buflen;
1930 }
1931
1932 if (flags & SSH2_FX_ATTR_MODIFYTIME) {
1933 struct tm *tm;
1934
1935 tm = pr_gmtime(p, (const time_t *) &st->st_mtime);
1936 if (tm != NULL) {
1937 pr_snprintf(ptr, bufsz - buflen, "modify=%04d%02d%02d%02d%02d%02d;",
1938 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min,
1939 tm->tm_sec);
1940
1941 } else {
1942 pr_trace_msg(trace_channel, 1,
1943 "error obtaining st_mtime GMT timestamp: %s", strerror(errno));
1944 }
1945
1946 buflen = strlen(buf);
1947 ptr = buf + buflen;
1948 }
1949
1950 if (flags & SSH2_FX_ATTR_LINK_COUNT) {
1951 pr_snprintf(ptr, bufsz - buflen, "UNIX.nlink=%lu;",
1952 (unsigned long) st->st_nlink);
1953 buflen = strlen(buf);
1954 ptr = buf + buflen;
1955 }
1956 }
1957
1958 return pstrdup(p, buf);
1959 }
1960
fxp_strattrflags(pool * p,uint32_t flags)1961 static char *fxp_strattrflags(pool *p, uint32_t flags) {
1962 char *str = "";
1963
1964 if (flags & SSH2_FX_ATTR_SIZE) {
1965 str = pstrcat(p, str, *str ? ";" : "", "size", NULL);
1966 }
1967
1968 if ((flags & SSH2_FX_ATTR_UIDGID) ||
1969 (flags & SSH2_FX_ATTR_OWNERGROUP)) {
1970 str = pstrcat(p, str, *str ? ";" : "", "UNIX.owner", NULL);
1971 str = pstrcat(p, str, *str ? ";" : "", "UNIX.group", NULL);
1972 }
1973
1974 if (flags & SSH2_FX_ATTR_PERMISSIONS) {
1975 str = pstrcat(p, str, *str ? ";" : "", "UNIX.mode", NULL);
1976 }
1977
1978 if (fxp_session->client_version <= 3) {
1979 if (flags & SSH2_FX_ATTR_ACMODTIME) {
1980 str = pstrcat(p, str, *str ? ";" : "", "access", NULL);
1981 str = pstrcat(p, str, *str ? ";" : "", "modify", NULL);
1982 }
1983
1984 } else {
1985 if (flags & SSH2_FX_ATTR_ACCESSTIME) {
1986 str = pstrcat(p, str, *str ? ";" : "", "access", NULL);
1987 }
1988
1989 if (flags & SSH2_FX_ATTR_MODIFYTIME) {
1990 str = pstrcat(p, str, *str ? ";" : "", "modify", NULL);
1991 }
1992 }
1993
1994 return str;
1995 }
1996
fxp_stroflags(pool * p,int flags)1997 static char *fxp_stroflags(pool *p, int flags) {
1998 char *str = "";
1999
2000 if (flags == O_RDONLY) {
2001 str = pstrcat(p, str, "O_RDONLY", NULL);
2002
2003 } else if (flags & O_RDWR) {
2004 str = pstrcat(p, str, "O_RDWR", NULL);
2005
2006 } else if (flags & O_WRONLY) {
2007 str = pstrcat(p, str, "O_WRONLY", NULL);
2008 }
2009
2010 #ifdef O_APPEND
2011 if (flags & O_APPEND) {
2012 str = pstrcat(p, str, *str ? "|" : "", "O_APPEND", NULL);
2013 }
2014 #endif
2015
2016 if (flags & O_CREAT) {
2017 str = pstrcat(p, str, *str ? "|" : "", "O_CREAT", NULL);
2018 }
2019
2020 if (flags & O_TRUNC) {
2021 str = pstrcat(p, str, *str ? "|" : "", "O_TRUNC", NULL);
2022 }
2023
2024 if (flags & O_EXCL) {
2025 str = pstrcat(p, str, *str ? "|" : "", "O_EXCL", NULL);
2026 }
2027
2028 return str;
2029 }
2030
fxp_xattrs_read(pool * p,unsigned char ** buf,uint32_t * buflen)2031 static array_header *fxp_xattrs_read(pool *p, unsigned char **buf,
2032 uint32_t *buflen) {
2033 register unsigned int i;
2034 uint32_t extpair_count;
2035 array_header *xattrs = NULL;
2036
2037 extpair_count = sftp_msg_read_int(p, buf, buflen);
2038 pr_trace_msg(trace_channel, 15,
2039 "protocol version %lu: read EXTENDED attribute: %lu extensions",
2040 (unsigned long) fxp_session->client_version,
2041 (unsigned long) extpair_count);
2042
2043 if (extpair_count > FXP_MAX_EXTENDED_ATTRIBUTES) {
2044 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2045 "received too many EXTENDED attributes (%lu > max %lu), "
2046 "truncating to max", (unsigned long) extpair_count,
2047 (unsigned long) FXP_MAX_EXTENDED_ATTRIBUTES);
2048 extpair_count = FXP_MAX_EXTENDED_ATTRIBUTES;
2049 }
2050
2051 xattrs = make_array(p, 1, sizeof(struct fxp_extpair *));
2052
2053 for (i = 0; i < extpair_count; i++) {
2054 struct fxp_extpair *ext;
2055
2056 ext = fxp_msg_read_extpair(p, buf, buflen);
2057 if (ext != NULL) {
2058 pr_trace_msg(trace_channel, 15,
2059 "protocol version %lu: read EXTENDED attribute: "
2060 "extension '%s' (%lu bytes of data)",
2061 (unsigned long) fxp_session->client_version, ext->ext_name,
2062 (unsigned long) ext->ext_datalen);
2063
2064 *((struct fxp_extpair **) push_array(xattrs)) = ext;
2065 }
2066 }
2067
2068 return xattrs;
2069 }
2070
fxp_attrs_read(struct fxp_packet * fxp,unsigned char ** buf,uint32_t * buflen,uint32_t * flags,array_header ** xattrs)2071 static struct stat *fxp_attrs_read(struct fxp_packet *fxp, unsigned char **buf,
2072 uint32_t *buflen, uint32_t *flags, array_header **xattrs) {
2073 struct stat *st;
2074
2075 st = pcalloc(fxp->pool, sizeof(struct stat));
2076
2077 *flags = sftp_msg_read_int(fxp->pool, buf, buflen);
2078
2079 if (fxp_session->client_version <= 3) {
2080 if (*flags & SSH2_FX_ATTR_SIZE) {
2081 st->st_size = sftp_msg_read_long(fxp->pool, buf, buflen);
2082 }
2083
2084 if (*flags & SSH2_FX_ATTR_UIDGID) {
2085 st->st_uid = sftp_msg_read_int(fxp->pool, buf, buflen);
2086 st->st_gid = sftp_msg_read_int(fxp->pool, buf, buflen);
2087 }
2088
2089 if (*flags & SSH2_FX_ATTR_PERMISSIONS) {
2090 st->st_mode |= sftp_msg_read_int(fxp->pool, buf, buflen);
2091 }
2092
2093 if (*flags & SSH2_FX_ATTR_ACMODTIME) {
2094 st->st_atime = sftp_msg_read_int(fxp->pool, buf, buflen);
2095 st->st_mtime = sftp_msg_read_int(fxp->pool, buf, buflen);
2096 }
2097
2098 } else {
2099 char file_type;
2100
2101 /* XXX Use this to create different types of files? E.g. what if the client
2102 * wants to OPEN a socket, or a fifo?
2103 */
2104 file_type = sftp_msg_read_byte(fxp->pool, buf, buflen);
2105 switch (file_type) {
2106 case SSH2_FX_ATTR_FTYPE_REGULAR:
2107 st->st_mode |= S_IFREG;
2108 break;
2109
2110 case SSH2_FX_ATTR_FTYPE_DIRECTORY:
2111 st->st_mode |= S_IFDIR;
2112 break;
2113
2114 case SSH2_FX_ATTR_FTYPE_SYMLINK:
2115 st->st_mode |= S_IFLNK;
2116 break;
2117
2118 case SSH2_FX_ATTR_FTYPE_SPECIAL:
2119 /* Default to marking this as a character special device, rather than
2120 * block special.
2121 */
2122 st->st_mode |= S_IFCHR;
2123 break;
2124
2125 case SSH2_FX_ATTR_FTYPE_UNKNOWN:
2126 /* Nothing to do here; leave st->st_mode alone. */
2127 break;
2128
2129 case SSH2_FX_ATTR_FTYPE_SOCKET:
2130 st->st_mode |= S_IFSOCK;
2131 break;
2132
2133 case SSH2_FX_ATTR_FTYPE_CHAR_DEVICE:
2134 st->st_mode |= S_IFCHR;
2135 break;
2136
2137 case SSH2_FX_ATTR_FTYPE_BLOCK_DEVICE:
2138 st->st_mode |= S_IFBLK;
2139 break;
2140
2141 #ifdef S_IFIFO
2142 case SSH2_FX_ATTR_FTYPE_FIFO:
2143 st->st_mode |= S_IFIFO;
2144 break;
2145 #endif /* S_IFIFO */
2146
2147 default:
2148 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2149 "unrecognized file type %d requested (protocol version %d)",
2150 file_type, fxp_session->client_version);
2151 }
2152
2153 if (*flags & SSH2_FX_ATTR_SIZE) {
2154 st->st_size = sftp_msg_read_long(fxp->pool, buf, buflen);
2155 }
2156
2157 if (*flags & SSH2_FX_ATTR_ALLOCATION_SIZE) {
2158 /* Read (and ignore) any allocation size attribute. */
2159 uint64_t allosz;
2160
2161 allosz = sftp_msg_read_long(fxp->pool, buf, buflen);
2162 pr_trace_msg(trace_channel, 15,
2163 "protocol version %lu: read ALLOCATION_SIZE attribute: %" PR_LU,
2164 (unsigned long) fxp_session->client_version, (pr_off_t) allosz);
2165 }
2166
2167 if (*flags & SSH2_FX_ATTR_OWNERGROUP) {
2168 char *name;
2169 uid_t uid;
2170 gid_t gid;
2171
2172 name = sftp_msg_read_string(fxp->pool, buf, buflen);
2173 uid = pr_auth_name2uid(fxp->pool, name);
2174 if (uid == (uid_t) -1) {
2175 unsigned char *buf2, *ptr2;
2176 uint32_t buflen2, bufsz2, status_code;
2177 struct fxp_packet *resp;
2178
2179 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2180 "unable to translate user name '%s' to UID, UNKNOWN_PRINCIPAL error",
2181 name);
2182
2183 buflen2 = bufsz2 = FXP_RESPONSE_DATA_DEFAULT_SZ;
2184 buf2 = ptr2 = palloc(fxp->pool, bufsz2);
2185
2186 status_code = SSH2_FX_UNKNOWN_PRINCIPAL;
2187
2188 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
2189 (unsigned long) status_code, fxp_strerror(status_code));
2190
2191 fxp_status_write(fxp->pool, &buf2, &buflen2, fxp->request_id,
2192 status_code, fxp_strerror(status_code), name);
2193
2194 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
2195 resp->payload = ptr2;
2196 resp->payload_sz = (bufsz2 - buflen2);
2197
2198 if (fxp_packet_write(resp) < 0) {
2199 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2200 "error sending UNKNOWN_PRINCIPAL status: %s", strerror(errno));
2201 }
2202
2203 return NULL;
2204 }
2205
2206 st->st_uid = uid;
2207
2208 name = sftp_msg_read_string(fxp->pool, buf, buflen);
2209 gid = pr_auth_name2gid(fxp->pool, name);
2210 if (gid == (gid_t) -1) {
2211 unsigned char *buf2, *ptr2;
2212 uint32_t buflen2, bufsz2, status_code;
2213 struct fxp_packet *resp;
2214
2215 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2216 "unable to translate group name '%s' to GID, UNKNOWN_PRINCIPAL error",
2217 name);
2218
2219 buflen2 = bufsz2 = FXP_RESPONSE_DATA_DEFAULT_SZ;
2220 buf2 = ptr2 = palloc(fxp->pool, bufsz2);
2221
2222 status_code = SSH2_FX_UNKNOWN_PRINCIPAL;
2223
2224 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
2225 (unsigned long) status_code, fxp_strerror(status_code));
2226
2227 fxp_status_write(fxp->pool, &buf2, &buflen2, fxp->request_id,
2228 status_code, fxp_strerror(status_code), name);
2229
2230 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
2231 resp->payload = ptr2;
2232 resp->payload_sz = (bufsz2 - buflen2);
2233
2234 if (fxp_packet_write(resp) < 0) {
2235 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2236 "error sending UNKNOWN_PRINCIPAL status: %s", strerror(errno));
2237 }
2238
2239 return NULL;
2240 }
2241
2242 st->st_gid = gid;
2243 }
2244
2245 if (*flags & SSH2_FX_ATTR_PERMISSIONS) {
2246 st->st_mode |= sftp_msg_read_int(fxp->pool, buf, buflen);
2247 }
2248
2249 if (*flags & SSH2_FX_ATTR_ACCESSTIME) {
2250 st->st_atime = sftp_msg_read_long(fxp->pool, buf, buflen);
2251
2252 if (*flags & SSH2_FX_ATTR_SUBSECOND_TIMES) {
2253 /* Read (and ignore) the nanoseconds field. */
2254 uint32_t nanosecs;
2255
2256 nanosecs = sftp_msg_read_int(fxp->pool, buf, buflen);
2257 pr_trace_msg(trace_channel, 15,
2258 "protocol version %lu: read ACCESSTIME SUBSECOND attribute: %lu",
2259 (unsigned long) fxp_session->client_version,
2260 (unsigned long) nanosecs);
2261 }
2262 }
2263
2264 if (*flags & SSH2_FX_ATTR_CREATETIME) {
2265 /* Read (and ignore) the create time attribute. */
2266 uint64_t create_time;
2267
2268 create_time = sftp_msg_read_long(fxp->pool, buf, buflen);
2269 pr_trace_msg(trace_channel, 15,
2270 "protocol version %lu: read CREATETIME attribute: %" PR_LU,
2271 (unsigned long) fxp_session->client_version, (pr_off_t) create_time);
2272
2273 if (*flags & SSH2_FX_ATTR_SUBSECOND_TIMES) {
2274 /* Read (and ignore) the nanoseconds field. */
2275 uint32_t nanosecs;
2276
2277 nanosecs = sftp_msg_read_int(fxp->pool, buf, buflen);
2278 pr_trace_msg(trace_channel, 15,
2279 "protocol version %lu: read CREATETIME SUBSECOND attribute: %lu",
2280 (unsigned long) fxp_session->client_version,
2281 (unsigned long) nanosecs);
2282 }
2283 }
2284
2285 if (*flags & SSH2_FX_ATTR_MODIFYTIME) {
2286 st->st_mtime = sftp_msg_read_long(fxp->pool, buf, buflen);
2287
2288 if (*flags & SSH2_FX_ATTR_SUBSECOND_TIMES) {
2289 /* Read (and ignore) the nanoseconds field. */
2290 uint32_t nanosecs;
2291
2292 nanosecs = sftp_msg_read_int(fxp->pool, buf, buflen);
2293 pr_trace_msg(trace_channel, 15,
2294 "protocol version %lu: read MOTIFYTIME SUBSECOND attribute: %lu",
2295 (unsigned long) fxp_session->client_version,
2296 (unsigned long) nanosecs);
2297 }
2298 }
2299
2300 if (*flags & SSH2_FX_ATTR_CTIME) {
2301 /* Read (and ignore) the ctime attribute. */
2302 uint64_t change_time;
2303
2304 change_time = sftp_msg_read_long(fxp->pool, buf, buflen);
2305 pr_trace_msg(trace_channel, 15,
2306 "protocol version %lu: read CTIME attribute: %" PR_LU,
2307 (unsigned long) fxp_session->client_version, (pr_off_t) change_time);
2308
2309 if (*flags & SSH2_FX_ATTR_SUBSECOND_TIMES) {
2310 /* Read (and ignore) the nanoseconds field. */
2311 uint32_t nanosecs;
2312
2313 nanosecs = sftp_msg_read_int(fxp->pool, buf, buflen);
2314 pr_trace_msg(trace_channel, 15,
2315 "protocol version %lu: read CTIME SUBSECOND attribute: %lu",
2316 (unsigned long) fxp_session->client_version,
2317 (unsigned long) nanosecs);
2318 }
2319 }
2320
2321 if (*flags & SSH2_FX_ATTR_ACL) {
2322 /* Read (and ignore) the ACL attribute. */
2323 char *acl;
2324
2325 acl = sftp_msg_read_string(fxp->pool, buf, buflen);
2326 pr_trace_msg(trace_channel, 15,
2327 "protocol version %lu: read ACL attribute: '%s'",
2328 (unsigned long) fxp_session->client_version, acl ? acl : "(nil)");
2329 }
2330
2331 if (*flags & SSH2_FX_ATTR_BITS) {
2332 /* Read (and ignore) the BITS attributes. */
2333 uint32_t attr_bits, attr_valid_bits;
2334
2335 attr_bits = sftp_msg_read_int(fxp->pool, buf, buflen);
2336 attr_valid_bits = sftp_msg_read_int(fxp->pool, buf, buflen);
2337
2338 fxp_trace_v5_bit_flags(fxp->pool, attr_bits, attr_valid_bits);
2339 }
2340
2341 if (*flags & SSH2_FX_ATTR_TEXT_HINT) {
2342 /* Read (and ignore) the TEXT_HINT attribute. */
2343 char hint, *hint_type;
2344
2345 hint = sftp_msg_read_byte(fxp->pool, buf, buflen);
2346 switch (hint) {
2347 case SSH2_FX_ATTR_KNOWN_TEXT:
2348 hint_type = "KNOWN_TEXT";
2349 break;
2350
2351 case SSH2_FX_ATTR_GUESSED_TEXT:
2352 hint_type = "GUESSED_TEXT";
2353 break;
2354
2355 case SSH2_FX_ATTR_KNOWN_BINARY:
2356 hint_type = "KNOWN_BINARY";
2357 break;
2358
2359 case SSH2_FX_ATTR_GUESSED_BINARY:
2360 hint_type = "GUESSED_BINARY";
2361 break;
2362
2363 default:
2364 hint_type = "(unknown)";
2365 break;
2366 }
2367
2368 pr_trace_msg(trace_channel, 15,
2369 "protocol version %lu: read TEXT_HINT attribute: '%s'",
2370 (unsigned long) fxp_session->client_version, hint_type);
2371 }
2372
2373 if (*flags & SSH2_FX_ATTR_MIME_TYPE) {
2374 /* Read (and ignore) the MIME_TYPE attribute. */
2375 char *mime_type;
2376
2377 mime_type = sftp_msg_read_string(fxp->pool, buf, buflen);
2378 pr_trace_msg(trace_channel, 15,
2379 "protocol version %lu: read MIME_TYPE attribute: '%s'",
2380 (unsigned long) fxp_session->client_version,
2381 mime_type ? mime_type : "(nil)");
2382 }
2383
2384 if (*flags & SSH2_FX_ATTR_LINK_COUNT) {
2385 uint32_t link_count;
2386
2387 link_count = sftp_msg_read_int(fxp->pool, buf, buflen);
2388 pr_trace_msg(trace_channel, 15,
2389 "protocol version %lu: read LINK_COUNT attribute: %lu",
2390 (unsigned long) fxp_session->client_version,
2391 (unsigned long) link_count);
2392 }
2393
2394 if (*flags & SSH2_FX_ATTR_UNTRANSLATED_NAME) {
2395 /* Read (and ignore) the UNTRANSLATED_NAME attribute. */
2396 char *untranslated;
2397
2398 untranslated = sftp_msg_read_string(fxp->pool, buf, buflen);
2399 pr_trace_msg(trace_channel, 15,
2400 "protocol version %lu: read UNTRANSLATED_NAME attribute: '%s'",
2401 (unsigned long) fxp_session->client_version,
2402 untranslated ? untranslated : "(nil)");
2403 }
2404 }
2405
2406 if (*flags & SSH2_FX_ATTR_EXTENDED) {
2407 array_header *ext_attrs;
2408
2409 /* Read the EXTENDED attribute. */
2410 ext_attrs = fxp_xattrs_read(fxp->pool, buf, buflen);
2411 if (xattrs != NULL) {
2412 *xattrs = ext_attrs;
2413 }
2414 }
2415
2416 return st;
2417 }
2418
fxp_get_file_type(mode_t mode)2419 static char fxp_get_file_type(mode_t mode) {
2420 if (S_ISREG(mode)) {
2421 return SSH2_FX_ATTR_FTYPE_REGULAR;
2422 }
2423
2424 if (S_ISDIR(mode)) {
2425 return SSH2_FX_ATTR_FTYPE_DIRECTORY;
2426 }
2427
2428 if (S_ISLNK(mode)) {
2429 return SSH2_FX_ATTR_FTYPE_SYMLINK;
2430 }
2431
2432 if (S_ISSOCK(mode)) {
2433 if (fxp_session->client_version <= 4) {
2434 return SSH2_FX_ATTR_FTYPE_SPECIAL;
2435 }
2436
2437 return SSH2_FX_ATTR_FTYPE_SOCKET;
2438 }
2439
2440 #ifdef S_ISFIFO
2441 if (S_ISFIFO(mode)) {
2442 if (fxp_session->client_version <= 4) {
2443 return SSH2_FX_ATTR_FTYPE_SPECIAL;
2444 }
2445
2446 return SSH2_FX_ATTR_FTYPE_FIFO;
2447 }
2448 #endif
2449
2450 #ifdef S_ISCHR
2451 if (S_ISCHR(mode)) {
2452 if (fxp_session->client_version <= 4) {
2453 return SSH2_FX_ATTR_FTYPE_SPECIAL;
2454 }
2455
2456 return SSH2_FX_ATTR_FTYPE_CHAR_DEVICE;
2457 }
2458 #endif
2459
2460 #ifdef S_ISBLK
2461 if (S_ISBLK(mode)) {
2462 if (fxp_session->client_version <= 4) {
2463 return SSH2_FX_ATTR_FTYPE_SPECIAL;
2464 }
2465
2466 return SSH2_FX_ATTR_FTYPE_BLOCK_DEVICE;
2467 }
2468 #endif
2469
2470 return SSH2_FX_ATTR_FTYPE_UNKNOWN;
2471 }
2472
fxp_xattrs_write(pool * p,struct fxp_buffer * fxb,const char * path)2473 static uint32_t fxp_xattrs_write(pool *p, struct fxp_buffer *fxb,
2474 const char *path) {
2475 uint32_t len = 0;
2476
2477 #ifdef PR_USE_XATTR
2478 int res;
2479 array_header *names = NULL;
2480
2481 res = pr_fsio_llistxattr(p, path, &names);
2482 if (res > 0) {
2483 register unsigned int i;
2484 pool *sub_pool;
2485 uint32_t xattrsz = 0;
2486 array_header *vals;
2487
2488 sub_pool = make_sub_pool(p);
2489 pr_pool_tag(sub_pool, "listxattr pool");
2490
2491 vals = make_array(sub_pool, names->nelts, sizeof(pr_buffer_t *));
2492 xattrsz = sizeof(uint32_t);
2493
2494 for (i = 0; i < names->nelts; i++) {
2495 const char *name;
2496 pr_buffer_t *val;
2497 ssize_t valsz;
2498
2499 name = ((const char **) names->elts)[i];
2500 xattrsz += (sizeof(uint32_t) + strlen(name));
2501
2502 val = pcalloc(sub_pool, sizeof(pr_buffer_t));
2503
2504 valsz = pr_fsio_lgetxattr(p, path, name, NULL, 0);
2505 if (valsz > 0) {
2506 xattrsz += (sizeof(uint32_t) + valsz);
2507
2508 val->buflen = valsz;
2509 val->buf = palloc(sub_pool, valsz);
2510
2511 valsz = pr_fsio_lgetxattr(p, path, name, val->buf, valsz);
2512 if (valsz > 0) {
2513 *((pr_buffer_t **) push_array(vals)) = val;
2514 }
2515 } else {
2516 /* Push the empty buffer into the list, so that the vals list
2517 * lines up with the names list.
2518 */
2519 *((pr_buffer_t **) push_array(vals)) = val;
2520 }
2521 }
2522
2523 if (fxb->buflen < xattrsz) {
2524 unsigned char *ptr;
2525 uint32_t bufsz, resp_len;
2526
2527 resp_len = fxb->bufsz - fxb->buflen;
2528
2529 /* Allocate a buffer large enough for the xattrs */
2530 pr_trace_msg(trace_channel, 3,
2531 "allocating larger response buffer (have %lu bytes, need %lu bytes)",
2532 (unsigned long) fxb->bufsz, (unsigned long) fxb->bufsz + xattrsz);
2533
2534 bufsz = fxb->bufsz + xattrsz;
2535 ptr = palloc(p, bufsz);
2536
2537 /* Copy over our existing response data into the new buffer. */
2538 memcpy(ptr, fxb->ptr, resp_len);
2539 fxb->ptr = ptr;
2540 fxb->bufsz = bufsz;
2541 fxb->buf = ptr + resp_len;
2542 fxb->buflen = bufsz - resp_len;
2543 }
2544
2545 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), names->nelts);
2546 for (i = 0; i < names->nelts; i++) {
2547 const char *name;
2548 pr_buffer_t *val;
2549
2550 name = ((const char **) names->elts)[i];
2551 val = ((pr_buffer_t **) vals->elts)[i];
2552
2553 len += sftp_msg_write_string(&(fxb->buf), &(fxb->buflen), name);
2554 len += sftp_msg_write_data(&(fxb->buf), &(fxb->buflen),
2555 (const unsigned char *) val->buf, (size_t) val->buflen, TRUE);
2556 }
2557
2558 destroy_pool(sub_pool);
2559
2560 } else {
2561 /* Have to write an extended count of zero. */
2562 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), 0);
2563 }
2564 #endif /* PR_USE_XATTR */
2565
2566 return len;
2567 }
2568
fxp_attrs_write(pool * p,struct fxp_buffer * fxb,const char * path,struct stat * st,uint32_t flags,const char * user_owner,const char * group_owner)2569 static uint32_t fxp_attrs_write(pool *p, struct fxp_buffer *fxb,
2570 const char *path, struct stat *st, uint32_t flags,
2571 const char *user_owner, const char *group_owner) {
2572 uint32_t len = 0;
2573 mode_t perms;
2574
2575 if (fxp_session->client_version <= 3) {
2576 perms = st->st_mode;
2577
2578 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), flags);
2579
2580 if (flags & SSH2_FX_ATTR_SIZE) {
2581 len += sftp_msg_write_long(&(fxb->buf), &(fxb->buflen), st->st_size);
2582 }
2583
2584 if (flags & SSH2_FX_ATTR_UIDGID) {
2585 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), st->st_uid);
2586 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), st->st_gid);
2587 }
2588
2589 if (flags & SSH2_FX_ATTR_PERMISSIONS) {
2590 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), perms);
2591 }
2592
2593 if (flags & SSH2_FX_ATTR_ACMODTIME) {
2594 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), st->st_atime);
2595 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), st->st_mtime);
2596 }
2597
2598 if (flags & SSH2_FX_ATTR_EXTENDED) {
2599 len += fxp_xattrs_write(p, fxb, path);
2600 }
2601
2602 } else {
2603 char file_type;
2604
2605 perms = st->st_mode;
2606
2607 /* Make sure that we do not include the file type bits when sending the
2608 * permission bits of the st_mode field.
2609 */
2610 perms &= ~S_IFMT;
2611
2612 file_type = fxp_get_file_type(st->st_mode);
2613
2614 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), flags);
2615 len += sftp_msg_write_byte(&(fxb->buf), &(fxb->buflen), file_type);
2616
2617 if (flags & SSH2_FX_ATTR_SIZE) {
2618 len += sftp_msg_write_long(&(fxb->buf), &(fxb->buflen), st->st_size);
2619 }
2620
2621 if (flags & SSH2_FX_ATTR_OWNERGROUP) {
2622 const char *user_name, *group_name;
2623
2624 if (user_owner == NULL) {
2625 user_name = pr_auth_uid2name(p, st->st_uid);
2626
2627 } else {
2628 user_name = user_owner;
2629 }
2630
2631 if (group_owner == NULL) {
2632 group_name = pr_auth_gid2name(p, st->st_gid);
2633
2634 } else {
2635 group_name = group_owner;
2636 }
2637
2638 len += sftp_msg_write_string(&(fxb->buf), &(fxb->buflen), user_name);
2639 len += sftp_msg_write_string(&(fxb->buf), &(fxb->buflen), group_name);
2640 }
2641
2642 if (flags & SSH2_FX_ATTR_PERMISSIONS) {
2643 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), perms);
2644 }
2645
2646 if (flags & SSH2_FX_ATTR_ACCESSTIME) {
2647 len += sftp_msg_write_long(&(fxb->buf), &(fxb->buflen), st->st_atime);
2648 }
2649
2650 if (flags & SSH2_FX_ATTR_MODIFYTIME) {
2651 len += sftp_msg_write_long(&(fxb->buf), &(fxb->buflen), st->st_mtime);
2652 }
2653
2654 if (flags & SSH2_FX_ATTR_LINK_COUNT) {
2655 len += sftp_msg_write_int(&(fxb->buf), &(fxb->buflen), st->st_nlink);
2656 }
2657
2658 if (flags & SSH2_FX_ATTR_EXTENDED) {
2659 len += fxp_xattrs_write(p, fxb, path);
2660 }
2661 }
2662
2663 return len;
2664 }
2665
2666 /* The strmode(3) function appears in some BSDs, but is not portable. */
fxp_strmode(pool * p,mode_t mode)2667 static char *fxp_strmode(pool *p, mode_t mode) {
2668 char mode_str[12];
2669
2670 memset(mode_str, '\0', sizeof(mode_str));
2671 sstrncpy(mode_str, "?--------- ", sizeof(mode_str));
2672
2673 switch (mode & S_IFMT) {
2674 case S_IFREG:
2675 mode_str[0] = '-';
2676 break;
2677
2678 case S_IFDIR:
2679 mode_str[0] = 'd';
2680 break;
2681
2682 case S_IFLNK:
2683 mode_str[0] = 'l';
2684 break;
2685
2686 #ifdef S_IFSOCK
2687 case S_IFSOCK:
2688 mode_str[0] = 's';
2689 break;
2690 #endif
2691
2692 case S_IFIFO:
2693 mode_str[0] = 'p';
2694 break;
2695
2696 case S_IFBLK:
2697 mode_str[0] = 'b';
2698 break;
2699
2700 case S_IFCHR:
2701 mode_str[0] = 'c';
2702 break;
2703 }
2704
2705 if (mode_str[0] != '?') {
2706 /* User perms */
2707 mode_str[1] = (mode & S_IRUSR) ? 'r' : '-';
2708 mode_str[2] = (mode & S_IWUSR) ? 'w' : '-';
2709 mode_str[3] = (mode & S_IXUSR) ?
2710 ((mode & S_ISUID) ? 's' : 'x') : ((mode & S_ISUID) ? 'S' : '-');
2711
2712 /* Group perms */
2713 mode_str[4] = (mode & S_IRGRP) ? 'r' : '-';
2714 mode_str[5] = (mode & S_IWGRP) ? 'w' : '-';
2715 mode_str[6] = (mode & S_IXGRP) ?
2716 ((mode & S_ISGID) ? 's' : 'x') : ((mode & S_ISGID) ? 'S' : '-');
2717
2718 /* World perms */
2719 mode_str[7] = (mode & S_IROTH) ? 'r' : '-';
2720 mode_str[8] = (mode & S_IWOTH) ? 'w' : '-';
2721 mode_str[9] = (mode & S_IXOTH) ?
2722 ((mode & S_ISVTX) ? 't' : 'x') : ((mode & S_ISVTX) ? 'T' : '-');
2723 }
2724
2725 return pstrdup(p, mode_str);
2726 }
2727
fxp_get_path_listing(pool * p,const char * path,struct stat * st,const char * user_owner,const char * group_owner)2728 static char *fxp_get_path_listing(pool *p, const char *path, struct stat *st,
2729 const char *user_owner, const char *group_owner) {
2730 const char *user, *group;
2731 char listing[1024], *mode_str, time_str[64];
2732 struct tm *t;
2733 int user_len, group_len;
2734 size_t time_strlen;
2735 time_t now = time(NULL);
2736
2737 memset(listing, '\0', sizeof(listing));
2738 memset(time_str, '\0', sizeof(time_str));
2739
2740 mode_str = fxp_strmode(p, st->st_mode);
2741
2742 if (fxp_use_gmt) {
2743 t = pr_gmtime(p, (const time_t *) &st->st_mtime);
2744
2745 } else {
2746 t = pr_localtime(p, (const time_t *) &st->st_mtime);
2747 }
2748
2749 /* Use strftime(3) to format the time entry for us. Seems some SFTP clients
2750 * are *very* particular about this formatting. Understandable, since
2751 * the SFTP Drafts for protocol version 3 did not actually define a format;
2752 * now most clients conform to the format used by OpenSSH.
2753 */
2754
2755 if ((now - st->st_mtime) > (180 * 24 * 60 * 60)) {
2756 time_strlen = strftime(time_str, sizeof(time_str), "%b %e %Y", t);
2757
2758 } else {
2759 time_strlen = strftime(time_str, sizeof(time_str), "%b %e %H:%M", t);
2760 }
2761
2762 if (time_strlen == 0) {
2763 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "%s",
2764 "warning: strftime(3) returned 0");
2765 }
2766
2767 if (user_owner == NULL) {
2768 user = pr_auth_uid2name(p, st->st_uid);
2769
2770 } else {
2771 user = user_owner;
2772 }
2773
2774 user_len = MAX(strlen(user), 8);
2775
2776 if (group_owner == NULL) {
2777 group = pr_auth_gid2name(p, st->st_gid);
2778
2779 } else {
2780 group = group_owner;
2781 }
2782
2783 group_len = MAX(strlen(group), 8);
2784
2785 pr_snprintf(listing, sizeof(listing)-1,
2786 "%s %3u %-*s %-*s %8" PR_LU " %s %s", mode_str,
2787 (unsigned int) st->st_nlink, user_len, user, group_len, group,
2788 (pr_off_t) st->st_size, time_str, path);
2789 return pstrdup(p, listing);
2790 }
2791
fxp_get_dirent(pool * p,cmd_rec * cmd,const char * real_path,mode_t * fake_mode)2792 static struct fxp_dirent *fxp_get_dirent(pool *p, cmd_rec *cmd,
2793 const char *real_path, mode_t *fake_mode) {
2794 struct fxp_dirent *fxd;
2795 struct stat st;
2796 int hidden = 0, res;
2797
2798 pr_fs_clear_cache2(real_path);
2799 if (pr_fsio_lstat(real_path, &st) < 0) {
2800 return NULL;
2801 }
2802
2803 res = dir_check(p, cmd, G_DIRS, real_path, &hidden);
2804 if (res == 0 ||
2805 hidden == TRUE) {
2806 errno = EACCES;
2807 return NULL;
2808 }
2809
2810 if (fake_mode != NULL) {
2811 mode_t mode;
2812
2813 mode = *fake_mode;
2814 mode |= (st.st_mode & S_IFMT);
2815
2816 if (S_ISDIR(st.st_mode)) {
2817 if (st.st_mode & S_IROTH) {
2818 mode |= S_IXOTH;
2819 }
2820
2821 if (st.st_mode & S_IRGRP) {
2822 mode |= S_IXGRP;
2823 }
2824
2825 if (st.st_mode & S_IRUSR) {
2826 mode |= S_IXUSR;
2827 }
2828 }
2829
2830 st.st_mode = mode;
2831 }
2832
2833 fxd = pcalloc(p, sizeof(struct fxp_dirent));
2834 fxd->real_path = real_path;
2835 fxd->st = pcalloc(p, sizeof(struct stat));
2836 memcpy(fxd->st, &st, sizeof(struct stat));
2837
2838 return fxd;
2839 }
2840
fxp_name_write(pool * p,struct fxp_buffer * fxb,const char * path,struct stat * st,uint32_t attr_flags,const char * user_owner,const char * group_owner)2841 static uint32_t fxp_name_write(pool *p, struct fxp_buffer *fxb,
2842 const char *path, struct stat *st, uint32_t attr_flags,
2843 const char *user_owner, const char *group_owner) {
2844 uint32_t len = 0;
2845 const char *encoded_path;
2846
2847 encoded_path = path;
2848 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
2849 encoded_path = sftp_utf8_encode_str(p, encoded_path);
2850 }
2851
2852 len += sftp_msg_write_string(&(fxb->buf), &(fxb->buflen), encoded_path);
2853
2854 if (fxp_session->client_version <= 3) {
2855 char *path_desc;
2856
2857 path_desc = fxp_get_path_listing(p, path, st, user_owner, group_owner);
2858 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
2859 path_desc = sftp_utf8_encode_str(p, path_desc);
2860 }
2861
2862 len += sftp_msg_write_string(&(fxb->buf), &(fxb->buflen), path_desc);
2863 }
2864
2865 len += fxp_attrs_write(p, fxb, path, st, attr_flags, user_owner, group_owner);
2866 return len;
2867 }
2868
2869 /* FX Handle Mgmt */
2870
fxp_handle_add(uint32_t channel_id,struct fxp_handle * fxh)2871 static int fxp_handle_add(uint32_t channel_id, struct fxp_handle *fxh) {
2872 int res;
2873
2874 if (fxp_session->handle_tab == NULL) {
2875 fxp_session->handle_tab = pr_table_alloc(fxp_session->pool, 0);
2876 }
2877
2878 res = pr_table_add(fxp_session->handle_tab, fxh->name, fxh, sizeof(void *));
2879 if (res < 0) {
2880 if (errno != EEXIST) {
2881 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2882 "error stashing handle: %s", strerror(errno));
2883 }
2884 }
2885
2886 return res;
2887 }
2888
fxp_handle_create(pool * p)2889 static struct fxp_handle *fxp_handle_create(pool *p) {
2890 unsigned char *data;
2891 char *handle;
2892 size_t data_len;
2893 pool *sub_pool;
2894 struct fxp_handle *fxh;
2895
2896 sub_pool = make_sub_pool(p);
2897 pr_pool_tag(sub_pool, "SFTP file handle pool");
2898 fxh = pcalloc(sub_pool, sizeof(struct fxp_handle));
2899 fxh->pool = sub_pool;
2900
2901 /* Use 8 random bytes for our handle, which means 16 bytes as hex-encoded
2902 * characters.
2903 */
2904 data_len = 8;
2905 data = palloc(p, data_len);
2906
2907 while (TRUE) {
2908 /* Keep trying until mktemp(3) returns a string that we haven't used
2909 * yet. We need to avoid collisions.
2910 */
2911 pr_signals_handle();
2912
2913 RAND_bytes(data, data_len);
2914
2915 /* Encode the data as hex to create the handle ID. */
2916 handle = pr_str_bin2hex(fxh->pool, data, data_len, PR_STR_FL_HEX_USE_LC);
2917
2918 if (fxp_handle_get(handle) == NULL) {
2919 fxh->name = handle;
2920 fxh->fh_st = pcalloc(fxh->pool, sizeof(struct stat));
2921 break;
2922 }
2923
2924 pr_trace_msg(trace_channel, 4,
2925 "handle '%s' already used, generating another", handle);
2926 }
2927
2928 return fxh;
2929 }
2930
2931 /* NOTE: this function is ONLY called when the session is closed, for
2932 * "aborting" any file handles still left open by the client.
2933 */
fxp_handle_abort(const void * key_data,size_t key_datasz,const void * value_data,size_t value_datasz,void * user_data)2934 static int fxp_handle_abort(const void *key_data, size_t key_datasz,
2935 const void *value_data, size_t value_datasz, void *user_data) {
2936 struct fxp_handle *fxh;
2937 char *abs_path, *curr_path = NULL, *real_path = NULL;
2938 char direction;
2939 unsigned char *delete_aborted_stores = NULL;
2940 cmd_rec *cmd = NULL;
2941
2942 fxh = (struct fxp_handle *) value_data;
2943 delete_aborted_stores = user_data;
2944
2945 /* Is this a file or a directory handle? */
2946 if (fxh->dirh != NULL) {
2947 cmd = fxp_cmd_alloc(fxh->pool, C_MLSD, (char *) fxh->dir);
2948 cmd->cmd_class = CL_DIRS;
2949 cmd->cmd_id = pr_cmd_get_id(C_MLSD);
2950
2951 if (pr_fsio_closedir(fxh->dirh) < 0) {
2952 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2953 "error closing aborted directory '%s': %s", fxh->dir, strerror(errno));
2954 }
2955
2956 pr_response_clear(&resp_list);
2957 pr_response_clear(&resp_err_list);
2958 fxp_cmd_dispatch_err(cmd);
2959
2960 fxh->dirh = NULL;
2961 return 0;
2962 }
2963
2964 /* This filehandle may already have been closed. If so, just move on to
2965 * the next one.
2966 */
2967 if (fxh->fh == NULL) {
2968 return 0;
2969 }
2970
2971 curr_path = pstrdup(fxh->pool, fxh->fh->fh_path);
2972 real_path = curr_path;
2973 if (fxh->fh_real_path) {
2974 real_path = fxh->fh_real_path;
2975 }
2976
2977 /* Write an 'incomplete' TransferLog entry for this. */
2978 abs_path = sftp_misc_vroot_abs_path(fxh->pool, real_path, TRUE);
2979
2980 if (fxh->fh_flags == O_RDONLY) {
2981 direction = 'o';
2982
2983 } else {
2984 direction = 'i';
2985 }
2986
2987 if (fxh->fh_flags & O_APPEND) {
2988 cmd = fxp_cmd_alloc(fxh->pool, C_APPE, pstrdup(fxh->pool, curr_path));
2989 cmd->cmd_class = CL_WRITE;
2990 session.curr_cmd = C_APPE;
2991
2992 if (pr_table_add(cmd->notes, "mod_xfer.store-path",
2993 pstrdup(fxh->pool, curr_path), 0) < 0) {
2994 if (errno != EEXIST) {
2995 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
2996 "error adding 'mod_xfer.store-path' note: %s", strerror(errno));
2997 }
2998 }
2999
3000 } else if ((fxh->fh_flags & O_WRONLY) ||
3001 (fxh->fh_flags & O_RDWR)) {
3002 cmd = fxp_cmd_alloc(fxh->pool, C_STOR, pstrdup(fxh->pool, curr_path));
3003 cmd->cmd_class = CL_WRITE;
3004 session.curr_cmd = C_STOR;
3005
3006 if (pr_table_add(cmd->notes, "mod_xfer.store-path",
3007 pstrdup(fxh->pool, curr_path), 0) < 0) {
3008 if (errno != EEXIST) {
3009 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3010 "error adding 'mod_xfer.store-path' note: %s", strerror(errno));
3011 }
3012 }
3013
3014 } else if (fxh->fh_flags == O_RDONLY) {
3015 cmd = fxp_cmd_alloc(fxh->pool, C_RETR, pstrdup(fxh->pool, curr_path));
3016 cmd->cmd_class = CL_READ;
3017 session.curr_cmd = C_RETR;
3018
3019 if (pr_table_add(cmd->notes, "mod_xfer.retr-path",
3020 pstrdup(fxh->pool, curr_path), 0) < 0) {
3021 if (errno != EEXIST) {
3022 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3023 "error adding 'mod_xfer.retr-path' note: %s", strerror(errno));
3024 }
3025 }
3026 }
3027
3028 if (cmd != NULL) {
3029 /* Add a note indicating that this is a failed transfer. */
3030 fxp_cmd_note_file_status(cmd, "failed");
3031 }
3032
3033 xferlog_write(0, pr_netaddr_get_sess_remote_name(), fxh->fh_bytes_xferred,
3034 abs_path, 'b', direction, 'r', session.user, 'i', "_");
3035
3036 if (cmd) {
3037 pr_response_clear(&resp_list);
3038 pr_response_clear(&resp_err_list);
3039
3040 pr_response_add_err(R_451, "%s: %s", cmd->arg, strerror(ECONNRESET));
3041 fxp_cmd_dispatch_err(cmd);
3042 }
3043
3044 if (pr_fsio_close(fxh->fh) < 0) {
3045 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3046 "error writing aborted file '%s': %s", fxh->fh->fh_path, strerror(errno));
3047 }
3048
3049 fxh->fh = NULL;
3050
3051 if (fxh->fh_flags != O_RDONLY) {
3052 if (fxh->fh_real_path) {
3053 /* This is a HiddenStores file. */
3054 if (delete_aborted_stores == NULL ||
3055 *delete_aborted_stores == TRUE) {
3056 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3057 "removing aborted uploaded file '%s'", curr_path);
3058
3059 if (pr_fsio_unlink(curr_path) < 0) {
3060 if (errno != ENOENT) {
3061 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3062 "error unlinking file '%s': %s", curr_path,
3063 strerror(errno));
3064 }
3065 }
3066 }
3067 }
3068 }
3069
3070 return 0;
3071 }
3072
fxp_handle_delete(struct fxp_handle * fxh)3073 static int fxp_handle_delete(struct fxp_handle *fxh) {
3074 if (fxp_session->handle_tab == NULL) {
3075 errno = EPERM;
3076 return -1;
3077 }
3078
3079 (void) pr_table_remove(fxp_session->handle_tab, fxh->name, NULL);
3080 return 0;
3081 }
3082
fxp_handle_get(const char * handle)3083 static struct fxp_handle *fxp_handle_get(const char *handle) {
3084 struct fxp_handle *fxh;
3085
3086 if (fxp_session->handle_tab == NULL) {
3087 errno = EPERM;
3088 return NULL;
3089 }
3090
3091 fxh = (struct fxp_handle *) pr_table_get(fxp_session->handle_tab, handle,
3092 NULL);
3093 return fxh;
3094 }
3095
3096 /* FX Message I/O */
3097
fxp_packet_create(pool * p,uint32_t channel_id)3098 static struct fxp_packet *fxp_packet_create(pool *p, uint32_t channel_id) {
3099 pool *sub_pool;
3100 struct fxp_packet *fxp;
3101
3102 sub_pool = make_sub_pool(p);
3103 pr_pool_tag(sub_pool, "SFTP packet pool");
3104 fxp = pcalloc(sub_pool, sizeof(struct fxp_packet));
3105 fxp->pool = sub_pool;
3106 fxp->channel_id = channel_id;
3107
3108 return fxp;
3109 }
3110
3111 static pool *curr_buf_pool = NULL;
3112 static unsigned char *curr_buf = NULL;
3113 static uint32_t curr_buflen = 0, curr_bufsz = 0;
3114 static struct fxp_packet *curr_pkt = NULL;
3115
fxp_packet_get_packet(uint32_t channel_id)3116 static struct fxp_packet *fxp_packet_get_packet(uint32_t channel_id) {
3117 struct fxp_packet *fxp;
3118
3119 if (curr_pkt) {
3120 return curr_pkt;
3121 }
3122
3123 fxp = fxp_packet_create(fxp_pool, channel_id);
3124 return fxp;
3125 }
3126
fxp_packet_set_packet(struct fxp_packet * pkt)3127 static void fxp_packet_set_packet(struct fxp_packet *pkt) {
3128 curr_pkt = pkt;
3129 }
3130
fxp_packet_clear_cache(void)3131 static void fxp_packet_clear_cache(void) {
3132 curr_buflen = 0;
3133 }
3134
fxp_packet_get_cache(unsigned char ** data)3135 static uint32_t fxp_packet_get_cache(unsigned char **data) {
3136 *data = curr_buf;
3137 return curr_buflen;
3138 }
3139
fxp_packet_add_cache(unsigned char * data,uint32_t datalen)3140 static void fxp_packet_add_cache(unsigned char *data, uint32_t datalen) {
3141 if (curr_buf_pool == NULL) {
3142 curr_buf_pool = make_sub_pool(fxp_pool);
3143 pr_pool_tag(curr_buf_pool, "SFTP packet buffer pool");
3144
3145 curr_buf = palloc(curr_buf_pool, FXP_PACKET_DATA_DEFAULT_SZ);
3146 curr_bufsz = fxp_packet_data_allocsz = FXP_PACKET_DATA_DEFAULT_SZ;
3147 }
3148
3149 if (data == NULL ||
3150 datalen == 0) {
3151 return;
3152 }
3153
3154 if (curr_buflen == 0) {
3155 if (curr_bufsz >= datalen) {
3156 /* We already have a buffer with enough space. Nice. */
3157
3158 } else {
3159 /* We need a larger buffer. Round up to the nearest 1K size. */
3160 size_t sz;
3161
3162 sz = sftp_crypto_get_size(datalen+1, 1024);
3163
3164 if (fxp_packet_data_allocsz > FXP_PACKET_DATA_ALLOC_MAX_SZ) {
3165 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3166 "renewing SFTP packet data pool");
3167 destroy_pool(curr_buf_pool);
3168
3169 curr_buf_pool = make_sub_pool(fxp_pool);
3170 pr_pool_tag(curr_buf_pool, "SFTP packet buffer pool");
3171
3172 curr_bufsz = 0;
3173 }
3174
3175 curr_bufsz = sz;
3176 curr_buf = palloc(curr_buf_pool, curr_bufsz);
3177 fxp_packet_data_allocsz += sz;
3178 }
3179
3180 /* We explicitly want to use memmove(3) here rather than memcpy(3),
3181 * since it is possible (and likely) that after reading data out
3182 * of this buffer, there will be leftover data which is put back into
3183 * the buffer, only at a different offset. This means that the
3184 * source and destination pointers CAN overlap; using memcpy(3) would
3185 * lead to subtle memory copy issue (e.g. Bug#3743).
3186 *
3187 * This manifested as hard-to-reproduce SFTP upload/download stalls,
3188 * segfaults, etc, due to corrupted memory being read out as
3189 * packet lengths and such.
3190 */
3191 memmove(curr_buf, data, datalen);
3192 curr_buflen = datalen;
3193
3194 return;
3195 }
3196
3197 if (curr_buflen > 0) {
3198 if (curr_bufsz >= (curr_buflen + datalen)) {
3199 /* We already have a buffer with enough space. Nice. */
3200
3201 } else {
3202 /* We need a larger buffer. Round up to the nearest 1K size. */
3203 size_t sz;
3204
3205 sz = sftp_crypto_get_size(curr_buflen + datalen + 1, 1024);
3206
3207 if (fxp_packet_data_allocsz > FXP_PACKET_DATA_ALLOC_MAX_SZ) {
3208 pool *tmp_pool;
3209 char *tmp_data;
3210 uint32_t tmp_datalen;
3211
3212 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3213 "renewing SFTP packet data pool");
3214
3215 tmp_pool = make_sub_pool(fxp_pool);
3216 tmp_datalen = curr_buflen;
3217 tmp_data = palloc(tmp_pool, tmp_datalen);
3218 memcpy(tmp_data, curr_buf, tmp_datalen);
3219
3220 destroy_pool(curr_buf_pool);
3221
3222 curr_buf_pool = make_sub_pool(fxp_pool);
3223 pr_pool_tag(curr_buf_pool, "SFTP packet buffer pool");
3224
3225 curr_bufsz = sz;
3226 curr_buf = palloc(curr_buf_pool, curr_bufsz);
3227 fxp_packet_data_allocsz += sz;
3228
3229 memcpy(curr_buf, tmp_data, tmp_datalen);
3230 curr_buflen = tmp_datalen;
3231
3232 destroy_pool(tmp_pool);
3233 }
3234 }
3235
3236 /* Append the SSH2 data to the current unconsumed buffer.
3237 *
3238 * We explicitly want to use memmove(3) here rather than memcpy(3),
3239 * since it is possible (and likely) that after reading data out
3240 * of this buffer, there will be leftover data which is put back into
3241 * the buffer, only at a different offset. This means that the
3242 * source and destination pointers CAN overlap; using memcpy(3) would
3243 * lead to subtle memory copy issue (e.g. Bug#3743).
3244 *
3245 * This manifested as hard-to-reproduce SFTP upload/download stalls,
3246 * segfaults, etc, due to corrupted memory being read out as
3247 * packet lengths and such.
3248 */
3249 memmove(curr_buf + curr_buflen, data, datalen);
3250 curr_buflen += datalen;
3251 }
3252
3253 return;
3254 }
3255
fxp_packet_read(uint32_t channel_id,unsigned char ** data,uint32_t * datalen,int * have_cache)3256 static struct fxp_packet *fxp_packet_read(uint32_t channel_id,
3257 unsigned char **data, uint32_t *datalen, int *have_cache) {
3258 struct fxp_packet *fxp;
3259 unsigned char *buf;
3260 uint32_t buflen;
3261
3262 if (datalen) {
3263 pr_trace_msg(trace_channel, 9,
3264 "reading SFTP data from SSH2 packet buffer (%lu bytes)",
3265 (unsigned long) *datalen);
3266 fxp_packet_add_cache(*data, *datalen);
3267 }
3268
3269 buflen = fxp_packet_get_cache(&buf);
3270 pr_trace_msg(trace_channel, 19,
3271 "using %lu bytes of SSH2 packet buffer data", (unsigned long) buflen);
3272
3273 fxp = fxp_packet_get_packet(channel_id);
3274
3275 if (!(fxp->state & FXP_PACKET_HAVE_PACKET_LEN)) {
3276 /* Make sure we have enough data in the buffer to cover the packet len. */
3277 if (buflen < sizeof(uint32_t)) {
3278 fxp_packet_set_packet(fxp);
3279
3280 /* We didn't consume any data, so no need to call
3281 * clear_cache()/add_cache().
3282 */
3283 *have_cache = TRUE;
3284
3285 return NULL;
3286 }
3287
3288 fxp->packet_len = sftp_msg_read_int(fxp->pool, &buf, &buflen);
3289 fxp->state |= FXP_PACKET_HAVE_PACKET_LEN;
3290
3291 pr_trace_msg(trace_channel, 19,
3292 "read SFTP request packet len %lu from SSH2 packet buffer "
3293 "(%lu bytes remaining in buffer)", (unsigned long) fxp->packet_len,
3294 (unsigned long) buflen);
3295
3296 if (buflen == 0) {
3297 fxp_packet_set_packet(fxp);
3298 fxp_packet_clear_cache();
3299 *have_cache = FALSE;
3300
3301 return NULL;
3302 }
3303
3304 } else {
3305 pr_trace_msg(trace_channel, 19,
3306 "already have SFTP request packet len %lu from previous buffer data",
3307 (unsigned long) fxp->packet_len);
3308 }
3309
3310 if (!(fxp->state & FXP_PACKET_HAVE_REQUEST_TYPE)) {
3311 /* Make sure we have enough data in the buffer to cover the request type. */
3312 if (buflen < sizeof(char)) {
3313 fxp_packet_set_packet(fxp);
3314 fxp_packet_clear_cache();
3315 fxp_packet_add_cache(buf, buflen);
3316 *have_cache = TRUE;
3317
3318 return NULL;
3319 }
3320
3321 fxp->request_type = sftp_msg_read_byte(fxp->pool, &buf, &buflen);
3322 fxp->state |= FXP_PACKET_HAVE_REQUEST_TYPE;
3323
3324 pr_trace_msg(trace_channel, 19,
3325 "read SFTP request type %d from SSH2 packet buffer "
3326 "(%lu bytes remaining in buffer)", (int) fxp->request_type,
3327 (unsigned long) buflen);
3328
3329 if (buflen == 0) {
3330 fxp_packet_set_packet(fxp);
3331 fxp_packet_clear_cache();
3332 *have_cache = FALSE;
3333
3334 return NULL;
3335 }
3336
3337 } else {
3338 pr_trace_msg(trace_channel, 19,
3339 "already have SFTP request type %d from previous buffer data",
3340 fxp->request_type);
3341 }
3342
3343 if (!(fxp->state & FXP_PACKET_HAVE_PAYLOAD_SIZE)) {
3344 /* And take back one byte for whose request_type this is... */
3345 fxp->payload_sz = fxp->packet_len - 1;
3346 fxp->state |= FXP_PACKET_HAVE_PAYLOAD_SIZE;
3347
3348 pr_trace_msg(trace_channel, 19,
3349 "read SFTP request payload size %lu from SSH2 packet buffer "
3350 "(%lu bytes remaining in buffer)", (unsigned long) fxp->payload_sz,
3351 (unsigned long) buflen);
3352
3353 } else {
3354 pr_trace_msg(trace_channel, 19,
3355 "already have SFTP request payload size %lu from previous buffer data",
3356 (unsigned long) fxp->payload_sz);
3357 }
3358
3359 if (!(fxp->state & FXP_PACKET_HAVE_REQUEST_ID)) {
3360 if (fxp->request_type != SFTP_SSH2_FXP_INIT) {
3361 /* Make sure we have enough data in the buffer to cover the request ID. */
3362 if (buflen < sizeof(uint32_t)) {
3363 fxp_packet_set_packet(fxp);
3364 fxp_packet_clear_cache();
3365 fxp_packet_add_cache(buf, buflen);
3366 *have_cache = TRUE;
3367
3368 return NULL;
3369 }
3370
3371 /* The INIT and VERSION requests do not use request IDs. */
3372 fxp->request_id = sftp_msg_read_int(fxp->pool, &buf, &buflen);
3373 fxp->payload_sz -= sizeof(uint32_t);
3374
3375 pr_trace_msg(trace_channel, 19,
3376 "read SFTP request ID %lu from SSH2 packet buffer "
3377 "(%lu bytes remaining in buffer)", (unsigned long) fxp->request_id,
3378 (unsigned long) buflen);
3379 }
3380
3381 fxp->state |= FXP_PACKET_HAVE_REQUEST_ID;
3382
3383 if (buflen == 0) {
3384 fxp_packet_set_packet(fxp);
3385 fxp_packet_clear_cache();
3386 *have_cache = FALSE;
3387
3388 return NULL;
3389 }
3390
3391 } else {
3392 pr_trace_msg(trace_channel, 19,
3393 "already have SFTP request ID %lu from previous buffer data",
3394 (unsigned long) fxp->request_id);
3395 }
3396
3397 if (!(fxp->state & FXP_PACKET_HAVE_PAYLOAD)) {
3398 uint32_t payload_remaining;
3399
3400 /* The first question is: do we have any existing payload data?
3401 *
3402 * 1. Have no payload data:
3403 * a. Packet buffer is exactly size of needed payload data.
3404 * This means that we will get the full payload, and there will be
3405 * no data left over in the packet buffer.
3406 *
3407 * b. Packet buffer is larger than size of needed payload data.
3408 * This means that we will get the full payload, and there will be
3409 * data left over in the packet buffer.
3410 *
3411 * c. Packet buffer is smaller than size of needed payload data.
3412 * This means that we will get only a partial payload, and there will
3413 * be no data left over in the packet buffer.
3414 *
3415 * 2. Have existing payload data:
3416 * a. Packet buffer is exactly size of remaining payload data.
3417 * This means that we will get the full payload, and there will be
3418 * no data left over in the packet buffer.
3419 *
3420 * b. Packet buffer is larger than size of remaining payload data.
3421 * This means that we will get the full payload, and there will be
3422 * data left over in the packet buffer.
3423 *
3424 * c. Packet buffer is smaller than size of remaining payload data.
3425 * This means that we will get only a partial payload, and there will
3426 * be no data left over in the packet buffer.
3427 *
3428 * To simplify the code, we can say that if we have no payload data,
3429 * it can be handled the same as a partial payload of length zero.
3430 */
3431
3432 if (fxp->payload == NULL) {
3433 /* Make sure we have a payload buffer allocated. */
3434 fxp->payload = pcalloc(fxp->pool, fxp->payload_sz);
3435 fxp->payload_len = 0;
3436 }
3437
3438 /* Now determine the amount of bytes remaining before we have the full
3439 * payload.
3440 */
3441 payload_remaining = fxp->payload_sz - fxp->payload_len;
3442
3443 /* First case: the packet buffer is exactly the size of the remaining
3444 * payload data.
3445 */
3446 if (buflen == payload_remaining) {
3447 pr_trace_msg(trace_channel, 19,
3448 "filling remaining SFTP request payload (%lu of %lu total bytes) "
3449 "from SSH2 packet buffer (%lu bytes in buffer)",
3450 (unsigned long) payload_remaining, (unsigned long) fxp->payload_sz,
3451 (unsigned long) buflen);
3452
3453 memcpy(fxp->payload + fxp->payload_len, buf, buflen);
3454 fxp->payload_len = buflen;
3455 fxp->state |= FXP_PACKET_HAVE_PAYLOAD;
3456
3457 fxp_packet_set_packet(NULL);
3458 fxp_packet_clear_cache();
3459 *have_cache = FALSE;
3460
3461 pr_trace_msg(trace_channel, 19, "completely filled payload of %lu bytes "
3462 "(0 bytes remaining in buffer)", (unsigned long) fxp->payload_sz);
3463 return fxp;
3464 }
3465
3466 /* Second case: the packet buffer is larger than the size of the remaining
3467 * payload data.
3468 */
3469 if (buflen > payload_remaining) {
3470 pr_trace_msg(trace_channel, 19,
3471 "filling remaining SFTP request payload (%lu of %lu total bytes) "
3472 "from SSH2 packet buffer (%lu bytes in buffer)",
3473 (unsigned long) payload_remaining, (unsigned long) fxp->payload_sz,
3474 (unsigned long) buflen);
3475
3476 memcpy(fxp->payload + fxp->payload_len, buf, payload_remaining);
3477 fxp->payload_len += payload_remaining;
3478 fxp->state |= FXP_PACKET_HAVE_PAYLOAD;
3479
3480 buflen -= payload_remaining;
3481 buf += payload_remaining;
3482
3483 fxp_packet_set_packet(NULL);
3484 fxp_packet_clear_cache();
3485 fxp_packet_add_cache(buf, buflen);
3486 *have_cache = TRUE;
3487
3488 pr_trace_msg(trace_channel, 19, "completely filled payload of %lu bytes "
3489 "(%lu bytes remaining in buffer)", (unsigned long) fxp->payload_sz,
3490 (unsigned long) buflen);
3491 return fxp;
3492 }
3493
3494 /* Third (and remaining) case: the packet buffer is smaller than the size
3495 * of the remaining payload data.
3496 */
3497 pr_trace_msg(trace_channel, 19,
3498 "filling remaining SFTP request payload (%lu of %lu total bytes) "
3499 "from SSH2 packet buffer (%lu bytes in buffer)",
3500 (unsigned long) payload_remaining, (unsigned long) fxp->payload_sz,
3501 (unsigned long) buflen);
3502
3503 memcpy(fxp->payload + fxp->payload_len, buf, buflen);
3504 fxp->payload_len += buflen;
3505
3506 fxp_packet_set_packet(fxp);
3507 fxp_packet_clear_cache();
3508 *have_cache = FALSE;
3509
3510 } else {
3511 pr_trace_msg(trace_channel, 19,
3512 "already have SFTP payload (%lu bytes) from previous buffer data",
3513 (unsigned long) fxp->payload_sz);
3514 }
3515
3516 return NULL;
3517 }
3518
fxp_packet_write(struct fxp_packet * fxp)3519 static int fxp_packet_write(struct fxp_packet *fxp) {
3520 unsigned char *buf, *ptr;
3521 uint32_t buflen, bufsz;
3522 int res;
3523
3524 /* Use a buffer that's a little larger than the FX packet size */
3525 buflen = bufsz = fxp->payload_sz + 32;
3526 buf = ptr = palloc(fxp->pool, bufsz);
3527
3528 sftp_msg_write_data(&buf, &buflen, fxp->payload, fxp->payload_sz, TRUE);
3529
3530 res = sftp_channel_write_data(fxp->pool, fxp->channel_id, ptr,
3531 (bufsz - buflen));
3532 return res;
3533 }
3534
3535 /* Miscellaneous */
3536
fxp_version_add_vendor_id_ext(pool * p,unsigned char ** buf,uint32_t * buflen)3537 static void fxp_version_add_vendor_id_ext(pool *p, unsigned char **buf,
3538 uint32_t *buflen) {
3539 unsigned char *buf2, *ptr2;
3540 const char *vendor_name, *product_name, *product_version;
3541 uint32_t bufsz2, buflen2;
3542 uint64_t build_number;
3543 struct fxp_extpair ext;
3544
3545 bufsz2 = buflen2 = 512;
3546 ptr2 = buf2 = sftp_msg_getbuf(p, bufsz2);
3547
3548 vendor_name = "ProFTPD Project";
3549 product_name = "mod_sftp";
3550 product_version = MOD_SFTP_VERSION;
3551 build_number = pr_version_get_number();
3552
3553 sftp_msg_write_string(&buf2, &buflen2, vendor_name);
3554 sftp_msg_write_string(&buf2, &buflen2, product_name);
3555 sftp_msg_write_string(&buf2, &buflen2, product_version);
3556 sftp_msg_write_long(&buf2, &buflen2, build_number);
3557
3558 ext.ext_name = "vendor-id";
3559 ext.ext_data = ptr2;
3560 ext.ext_datalen = (bufsz2 - buflen2);
3561
3562 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = "
3563 "{ vendorName = '%s', productName = '%s', productVersion = '%s', "
3564 "buildNumber = %" PR_LU " }", ext.ext_name, vendor_name, product_name,
3565 product_version, (pr_off_t) build_number);
3566
3567 fxp_msg_write_extpair(buf, buflen, &ext);
3568 }
3569
fxp_version_add_version_ext(pool * p,unsigned char ** buf,uint32_t * buflen)3570 static void fxp_version_add_version_ext(pool *p, unsigned char **buf,
3571 uint32_t *buflen) {
3572 register unsigned int i;
3573 struct fxp_extpair ext;
3574 char *versions_str = "";
3575
3576 if (!(fxp_ext_flags & SFTP_FXP_EXT_VERSION_SELECT)) {
3577 return;
3578 }
3579
3580 ext.ext_name = "versions";
3581
3582 /* The versions we report to the client depend on the min/max client
3583 * versions, which may have been configured differently via SFTPClientMatch.
3584 */
3585
3586 for (i = fxp_min_client_version; i <= fxp_max_client_version; i++) {
3587 switch (i) {
3588 case 1:
3589 /* Skip version 1; it is not in the list of version strings defined
3590 * in Section 4.6 of the SFTP Draft.
3591 */
3592 break;
3593
3594 case 2:
3595 versions_str = pstrcat(p, versions_str, *versions_str ? "," : "",
3596 "2", NULL);
3597 break;
3598
3599 case 3:
3600 versions_str = pstrcat(p, versions_str, *versions_str ? "," : "",
3601 "3", NULL);
3602 break;
3603
3604 #ifdef PR_USE_NLS
3605 /* We can only advertise support for these protocol versions if
3606 * --enable-nls has been used, as they require UTF8 support.
3607 */
3608 case 4:
3609 versions_str = pstrcat(p, versions_str, *versions_str ? "," : "",
3610 "4", NULL);
3611 break;
3612
3613 case 5:
3614 versions_str = pstrcat(p, versions_str, *versions_str ? "," : "",
3615 "5", NULL);
3616 break;
3617
3618 case 6:
3619 versions_str = pstrcat(p, versions_str, *versions_str ? "," : "",
3620 "6", NULL);
3621 break;
3622 #endif
3623 }
3624 }
3625
3626 ext.ext_data = (unsigned char *) versions_str;
3627 ext.ext_datalen = strlen(versions_str);
3628
3629 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '%s'", ext.ext_name,
3630 ext.ext_data);
3631 fxp_msg_write_extpair(buf, buflen, &ext);
3632
3633 /* The sending of this extension is necessary in order to support any
3634 * 'version-select' requests from the client, as per Section 4.6 of the
3635 * SFTP Draft. That is, if we don't send the 'versions' extension and the
3636 * client tries to send us a 'version-select', then we MUST close the
3637 * connection.
3638 */
3639 allow_version_select = TRUE;
3640 }
3641
fxp_version_add_openssh_exts(pool * p,unsigned char ** buf,uint32_t * buflen)3642 static void fxp_version_add_openssh_exts(pool *p, unsigned char **buf,
3643 uint32_t *buflen) {
3644 (void) p;
3645
3646 /* These are OpenSSH-specific SFTP extensions. */
3647
3648 if (fxp_ext_flags & SFTP_FXP_EXT_FSYNC) {
3649 struct fxp_extpair ext;
3650
3651 ext.ext_name = "fsync@openssh.com";
3652 ext.ext_data = (unsigned char *) "1";
3653 ext.ext_datalen = 1;
3654
3655 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '%s'", ext.ext_name,
3656 ext.ext_data);
3657 fxp_msg_write_extpair(buf, buflen, &ext);
3658 }
3659
3660 if (fxp_ext_flags & SFTP_FXP_EXT_POSIX_RENAME) {
3661 struct fxp_extpair ext;
3662
3663 ext.ext_name = "posix-rename@openssh.com";
3664 ext.ext_data = (unsigned char *) "1";
3665 ext.ext_datalen = 1;
3666
3667 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '%s'", ext.ext_name,
3668 ext.ext_data);
3669 fxp_msg_write_extpair(buf, buflen, &ext);
3670 }
3671
3672 #ifdef HAVE_SYS_STATVFS_H
3673 if (fxp_ext_flags & SFTP_FXP_EXT_STATVFS) {
3674 struct fxp_extpair ext;
3675
3676 ext.ext_name = "statvfs@openssh.com";
3677 ext.ext_data = (unsigned char *) "2";
3678 ext.ext_datalen = 1;
3679
3680 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '%s'", ext.ext_name,
3681 ext.ext_data);
3682 fxp_msg_write_extpair(buf, buflen, &ext);
3683
3684 ext.ext_name = "fstatvfs@openssh.com";
3685 ext.ext_data = (unsigned char *) "2";
3686 ext.ext_datalen = 1;
3687
3688 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '%s'",
3689 ext.ext_name, ext.ext_data);
3690 fxp_msg_write_extpair(buf, buflen, &ext);
3691 }
3692 #endif
3693
3694 if (fxp_ext_flags & SFTP_FXP_EXT_HARDLINK) {
3695 struct fxp_extpair ext;
3696
3697 ext.ext_name = "hardlink@openssh.com";
3698 ext.ext_data = (unsigned char *) "1";
3699 ext.ext_datalen = 1;
3700
3701 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '%s'", ext.ext_name,
3702 ext.ext_data);
3703 fxp_msg_write_extpair(buf, buflen, &ext);
3704 }
3705
3706 if (fxp_ext_flags & SFTP_FXP_EXT_XATTR) {
3707 struct fxp_extpair ext;
3708
3709 ext.ext_name = "xattr@proftpd.org";
3710 ext.ext_data = (unsigned char *) "1";
3711 ext.ext_datalen = 1;
3712
3713 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '%s'", ext.ext_name,
3714 ext.ext_data);
3715 fxp_msg_write_extpair(buf, buflen, &ext);
3716 }
3717 }
3718
fxp_version_add_newline_ext(pool * p,unsigned char ** buf,uint32_t * buflen)3719 static void fxp_version_add_newline_ext(pool *p, unsigned char **buf,
3720 uint32_t *buflen) {
3721 struct fxp_extpair ext;
3722
3723 (void) p;
3724
3725 ext.ext_name = "newline";
3726 ext.ext_data = (unsigned char *) "\n";
3727 ext.ext_datalen = 1;
3728
3729 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s = '\n'", ext.ext_name);
3730 fxp_msg_write_extpair(buf, buflen, &ext);
3731 }
3732
fxp_version_add_supported_ext(pool * p,unsigned char ** buf,uint32_t * buflen)3733 static void fxp_version_add_supported_ext(pool *p, unsigned char **buf,
3734 uint32_t *buflen) {
3735 struct fxp_extpair ext;
3736 uint32_t attrs_len, attrs_sz, exts_len, exts_sz;
3737 unsigned char *attrs_buf, *attrs_ptr, *exts_buf, *exts_ptr;
3738 uint32_t file_mask, bits_mask, open_mask, access_mask, max_read_size;
3739 unsigned int ext_count;
3740
3741 ext.ext_name = "supported";
3742
3743 attrs_sz = attrs_len = 1024;
3744 attrs_ptr = attrs_buf = sftp_msg_getbuf(p, attrs_sz);
3745
3746 file_mask = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_PERMISSIONS|
3747 SSH2_FX_ATTR_ACCESSTIME|SSH2_FX_ATTR_MODIFYTIME|SSH2_FX_ATTR_OWNERGROUP;
3748
3749 bits_mask = 0;
3750
3751 open_mask = SSH2_FXF_WANT_READ_DATA|SSH2_FXF_WANT_WRITE_DATA|
3752 SSH2_FXF_WANT_APPEND_DATA|SSH2_FXF_WANT_READ_ATTRIBUTES|
3753 SSH2_FXF_WANT_WRITE_ATTRIBUTES;
3754
3755 access_mask = SSH2_FXF_CREATE_NEW|SSH2_FXF_CREATE_TRUNCATE|
3756 SSH2_FXF_OPEN_EXISTING|SSH2_FXF_OPEN_OR_CREATE|
3757 SSH2_FXF_TRUNCATE_EXISTING|SSH2_FXF_ACCESS_APPEND_DATA|
3758 SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC;
3759
3760 max_read_size = 0;
3761
3762 sftp_msg_write_int(&attrs_buf, &attrs_len, file_mask);
3763 sftp_msg_write_int(&attrs_buf, &attrs_len, bits_mask);
3764 sftp_msg_write_int(&attrs_buf, &attrs_len, open_mask);
3765 sftp_msg_write_int(&attrs_buf, &attrs_len, access_mask);
3766 sftp_msg_write_int(&attrs_buf, &attrs_len, max_read_size);
3767
3768 /* The possible extensions to advertise here are:
3769 *
3770 * check-file
3771 * copy-file
3772 * space-available
3773 * vendor-id
3774 */
3775
3776 ext_count = 4;
3777
3778 if (!(fxp_ext_flags & SFTP_FXP_EXT_CHECK_FILE)) {
3779 ext_count--;
3780 }
3781
3782 if (!(fxp_ext_flags & SFTP_FXP_EXT_COPY_FILE)) {
3783 ext_count--;
3784 }
3785
3786 if (!(fxp_ext_flags & SFTP_FXP_EXT_SPACE_AVAIL)) {
3787 ext_count--;
3788 }
3789
3790 /* We don't decrement the extension count if the 'vendor-id' extension
3791 * is disabled. By advertisting the 'vendor-id' extension here, we are
3792 * telling the client that it can send us its vendor information.
3793 */
3794
3795 exts_len = exts_sz = 256;
3796 exts_buf = exts_ptr = palloc(p, exts_sz);
3797
3798 if (fxp_ext_flags & SFTP_FXP_EXT_CHECK_FILE) {
3799 pr_trace_msg(trace_channel, 11, "%s", "+ SFTP extension: check-file");
3800 sftp_msg_write_string(&exts_buf, &exts_len, "check-file");
3801 }
3802
3803 if (fxp_ext_flags & SFTP_FXP_EXT_COPY_FILE) {
3804 pr_trace_msg(trace_channel, 11, "%s", "+ SFTP extension: copy-file");
3805 sftp_msg_write_string(&exts_buf, &exts_len, "copy-file");
3806 }
3807
3808 if (fxp_ext_flags & SFTP_FXP_EXT_SPACE_AVAIL) {
3809 pr_trace_msg(trace_channel, 11, "%s",
3810 "+ SFTP extension: space-available");
3811 sftp_msg_write_string(&exts_buf, &exts_len, "space-available");
3812 }
3813
3814 /* We always send the 'vendor-id' extension; it lets the client know
3815 * that it can send its vendor information to us.
3816 */
3817 pr_trace_msg(trace_channel, 11, "%s", "+ SFTP extension: vendor-id");
3818 sftp_msg_write_string(&exts_buf, &exts_len, "vendor-id");
3819
3820 sftp_msg_write_data(&attrs_buf, &attrs_len, exts_ptr, (exts_sz - exts_len),
3821 FALSE);
3822
3823 ext.ext_data = attrs_ptr;
3824 ext.ext_datalen = (attrs_sz - attrs_len);
3825
3826 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s", ext.ext_name);
3827 fxp_msg_write_extpair(buf, buflen, &ext);
3828 }
3829
fxp_version_add_supported2_ext(pool * p,unsigned char ** buf,uint32_t * buflen)3830 static void fxp_version_add_supported2_ext(pool *p, unsigned char **buf,
3831 uint32_t *buflen) {
3832 struct fxp_extpair ext;
3833 uint32_t attrs_len, attrs_sz;
3834 unsigned char *attrs_buf, *attrs_ptr;
3835 uint32_t file_mask, bits_mask, open_mask, access_mask, max_read_size;
3836 uint16_t open_lock_mask, lock_mask;
3837 unsigned int ext_count;
3838
3839 ext.ext_name = "supported2";
3840
3841 attrs_sz = attrs_len = 1024;
3842 attrs_ptr = attrs_buf = sftp_msg_getbuf(p, attrs_sz);
3843
3844 file_mask = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_PERMISSIONS|
3845 SSH2_FX_ATTR_ACCESSTIME|SSH2_FX_ATTR_MODIFYTIME|SSH2_FX_ATTR_OWNERGROUP;
3846 #ifdef PR_USE_XATTR
3847 file_mask |= SSH2_FX_ATTR_EXTENDED;
3848 #endif /* PR_USE_XATTR */
3849
3850 bits_mask = 0;
3851
3852 open_mask = SSH2_FXF_WANT_READ_DATA|SSH2_FXF_WANT_WRITE_DATA|
3853 SSH2_FXF_WANT_APPEND_DATA|SSH2_FXF_WANT_READ_ATTRIBUTES|
3854 SSH2_FXF_WANT_WRITE_ATTRIBUTES;
3855
3856 access_mask = SSH2_FXF_CREATE_NEW|SSH2_FXF_CREATE_TRUNCATE|
3857 SSH2_FXF_OPEN_EXISTING|SSH2_FXF_OPEN_OR_CREATE|
3858 SSH2_FXF_TRUNCATE_EXISTING|SSH2_FXF_ACCESS_APPEND_DATA|
3859 SSH2_FXF_ACCESS_APPEND_DATA_ATOMIC;
3860
3861 max_read_size = 0;
3862
3863 /* Set only one bit, to indicate that locking is not supported for
3864 * OPEN commands.
3865 */
3866 open_lock_mask = 0x0001;
3867
3868 /* Indicate that we support the classic locks: READ+WRITE+ADVISORY and
3869 * WRITE+ADVISORY. Note that we do not need to include DELETE, since this
3870 * mask is only for LOCK commands, not UNLOCK commands.
3871 */
3872 lock_mask = 0x0c01;
3873
3874 sftp_msg_write_int(&attrs_buf, &attrs_len, file_mask);
3875 sftp_msg_write_int(&attrs_buf, &attrs_len, bits_mask);
3876 sftp_msg_write_int(&attrs_buf, &attrs_len, open_mask);
3877 sftp_msg_write_int(&attrs_buf, &attrs_len, access_mask);
3878 sftp_msg_write_int(&attrs_buf, &attrs_len, max_read_size);
3879 fxp_msg_write_short(&attrs_buf, &attrs_len, open_lock_mask);
3880 fxp_msg_write_short(&attrs_buf, &attrs_len, lock_mask);
3881
3882 /* Attribute extensions */
3883 sftp_msg_write_int(&attrs_buf, &attrs_len, 0);
3884
3885 /* The possible extensions to advertise here are:
3886 *
3887 * check-file
3888 * copy-file
3889 * space-available
3890 * vendor-id
3891 *
3892 * Note that we don't have to advertise the @openssh.com extensions, since
3893 * they occur for protocol versions which don't support 'supported2'. And
3894 * we don't have to list 'version-select', since the sending of the
3895 * 'versions' extension in our VERSION automatically enables use of this
3896 * extension by the client.
3897 */
3898 ext_count = 4;
3899
3900 if (!(fxp_ext_flags & SFTP_FXP_EXT_CHECK_FILE)) {
3901 ext_count--;
3902 }
3903
3904 if (!(fxp_ext_flags & SFTP_FXP_EXT_COPY_FILE)) {
3905 ext_count--;
3906 }
3907
3908 if (!(fxp_ext_flags & SFTP_FXP_EXT_SPACE_AVAIL)) {
3909 ext_count--;
3910 }
3911
3912 /* We don't decrement the extension count if the 'vendor-id' extension
3913 * is disabled. By advertisting the 'vendor-id' extension here, we are
3914 * telling the client that it can send us its vendor information.
3915 */
3916
3917 /* Additional protocol extensions (why these appear in 'supported2' is
3918 * confusing to me, too).
3919 */
3920 sftp_msg_write_int(&attrs_buf, &attrs_len, ext_count);
3921
3922 if (fxp_ext_flags & SFTP_FXP_EXT_CHECK_FILE) {
3923 pr_trace_msg(trace_channel, 11, "%s", "+ SFTP extension: check-file");
3924 sftp_msg_write_string(&attrs_buf, &attrs_len, "check-file");
3925 }
3926
3927 if (fxp_ext_flags & SFTP_FXP_EXT_COPY_FILE) {
3928 pr_trace_msg(trace_channel, 11, "%s", "+ SFTP extension: copy-file");
3929 sftp_msg_write_string(&attrs_buf, &attrs_len, "copy-file");
3930 }
3931
3932 if (fxp_ext_flags & SFTP_FXP_EXT_SPACE_AVAIL) {
3933 pr_trace_msg(trace_channel, 11, "%s",
3934 "+ SFTP extension: space-available");
3935 sftp_msg_write_string(&attrs_buf, &attrs_len, "space-available");
3936 }
3937
3938 /* We always send the 'vendor-id' extension; it lets the client know
3939 * that it can send its vendor information to us.
3940 */
3941 pr_trace_msg(trace_channel, 11, "%s", "+ SFTP extension: vendor-id");
3942 sftp_msg_write_string(&attrs_buf, &attrs_len, "vendor-id");
3943
3944 ext.ext_data = attrs_ptr;
3945 ext.ext_datalen = (attrs_sz - attrs_len);
3946
3947 pr_trace_msg(trace_channel, 11, "+ SFTP extension: %s", ext.ext_name);
3948 fxp_msg_write_extpair(buf, buflen, &ext);
3949 }
3950
3951 /* SFTP Extension handlers */
3952
fxp_handle_ext_check_file(struct fxp_packet * fxp,char * digest_list,char * path,off_t offset,off_t len,uint32_t blocksz)3953 static int fxp_handle_ext_check_file(struct fxp_packet *fxp, char *digest_list,
3954 char *path, off_t offset, off_t len, uint32_t blocksz) {
3955 unsigned char *buf, *ptr;
3956 char *supported_digests;
3957 const char *digest_name, *reason;
3958 uint32_t buflen, bufsz, expected_buflen, status_code;
3959 struct fxp_packet *resp;
3960 int data_len, res, xerrno = 0;
3961 struct stat st;
3962 pr_fh_t *fh;
3963 cmd_rec *cmd;
3964 unsigned long nblocks;
3965 off_t range_len, total_len = 0;
3966 void *data;
3967 BIO *bio;
3968 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
3969 defined(HAVE_LIBRESSL)
3970 EVP_MD_CTX md_ctx;
3971 #endif /* prior to OpenSSL-1.1.0 */
3972 EVP_MD_CTX *pctx;
3973 const EVP_MD *md;
3974
3975 pr_trace_msg(trace_channel, 8, "client sent check-file request: "
3976 "path = '%s', digests = '%s', offset = %" PR_LU ", len = %" PR_LU
3977 ", block size = %lu", path, digest_list, (pr_off_t) offset, (pr_off_t) len,
3978 (unsigned long) blocksz);
3979
3980 /* We could end up with lots of digests to write, if the file is large
3981 * and/or the block size is small. Be prepared.
3982 */
3983 buflen = bufsz = (FXP_RESPONSE_DATA_DEFAULT_SZ * 2);
3984 buf = ptr = palloc(fxp->pool, bufsz);
3985
3986 /* The minimum block size required by this extension is 256 bytes. */
3987 if (blocksz != 0 &&
3988 blocksz < 256) {
3989 xerrno = EINVAL;
3990
3991 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
3992 "SFTP client check-file request sent invalid block size "
3993 "(%lu bytes <= 256)", (unsigned long) blocksz);
3994
3995 status_code = fxp_errno2status(xerrno, &reason);
3996
3997 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
3998 (unsigned long) status_code, reason);
3999
4000 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4001 reason, NULL);
4002
4003 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4004 resp->payload = ptr;
4005 resp->payload_sz = (bufsz - buflen);
4006
4007 return fxp_packet_write(resp);
4008 }
4009
4010 pr_fs_clear_cache2(path);
4011 if (pr_fsio_lstat(path, &st) == 0) {
4012 if (S_ISLNK(st.st_mode)) {
4013 char link_path[PR_TUNABLE_PATH_MAX];
4014 int link_len;
4015
4016 memset(link_path, '\0', sizeof(link_path));
4017 link_len = dir_readlink(fxp->pool, path, link_path, sizeof(link_path)-1,
4018 PR_DIR_READLINK_FL_HANDLE_REL_PATH);
4019 if (link_len > 0) {
4020 link_path[link_len] = '\0';
4021 path = pstrdup(fxp->pool, link_path);
4022 }
4023 }
4024 }
4025
4026 pr_fs_clear_cache2(path);
4027 res = pr_fsio_lstat(path, &st);
4028 if (res < 0) {
4029 xerrno = errno;
4030
4031 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4032 "unable to lstat path '%s': %s", path, strerror(xerrno));
4033
4034 status_code = fxp_errno2status(xerrno, &reason);
4035
4036 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4037 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4038 xerrno);
4039
4040 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4041 reason, NULL);
4042
4043 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4044 resp->payload = ptr;
4045 resp->payload_sz = (bufsz - buflen);
4046
4047 return fxp_packet_write(resp);
4048 }
4049
4050 if (S_ISDIR(st.st_mode)) {
4051 xerrno = EISDIR;
4052
4053 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4054 "SFTP client check-file requested on a directory, denying");
4055
4056 status_code = fxp_errno2status(xerrno, &reason);
4057
4058 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4059 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4060 xerrno);
4061
4062 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4063 reason, NULL);
4064
4065 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4066 resp->payload = ptr;
4067 resp->payload_sz = (bufsz - buflen);
4068
4069 return fxp_packet_write(resp);
4070 }
4071
4072 if (!S_ISREG(st.st_mode) &&
4073 !S_ISLNK(st.st_mode)) {
4074 xerrno = EINVAL;
4075
4076 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4077 "SFTP client check-file request not for file or symlink, denying");
4078
4079 status_code = fxp_errno2status(xerrno, &reason);
4080
4081 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4082 (unsigned long) status_code, reason);
4083
4084 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4085 reason, NULL);
4086
4087 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4088 resp->payload = ptr;
4089 resp->payload_sz = (bufsz - buflen);
4090
4091 return fxp_packet_write(resp);
4092 }
4093
4094 if (offset >= st.st_size) {
4095 xerrno = EINVAL;
4096
4097 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4098 "client check-file request sent invalid offset (%" PR_LU
4099 " >= %" PR_LU " file size)", (pr_off_t) offset, (pr_off_t) st.st_size);
4100
4101 status_code = fxp_errno2status(xerrno, &reason);
4102
4103 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4104 (unsigned long) status_code, reason);
4105
4106 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4107 reason, NULL);
4108
4109 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4110 resp->payload = ptr;
4111 resp->payload_sz = (bufsz - buflen);
4112
4113 return fxp_packet_write(resp);
4114 }
4115
4116 cmd = fxp_cmd_alloc(fxp->pool, "SITE_DIGEST", pstrdup(fxp->pool, path));
4117 if (!dir_check(fxp->pool, cmd, "READ", path, NULL)) {
4118 xerrno = EACCES;
4119
4120 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4121 "'check-file' of '%s' blocked by <Limit> configuration", path);
4122
4123 status_code = fxp_errno2status(xerrno, &reason);
4124
4125 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4126 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4127 xerrno);
4128
4129 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4130 reason, NULL);
4131
4132 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4133 resp->payload = ptr;
4134 resp->payload_sz = (bufsz - buflen);
4135
4136 return fxp_packet_write(resp);
4137 }
4138
4139 supported_digests = "md5,sha1";
4140 #ifdef HAVE_SHA256_OPENSSL
4141 supported_digests = pstrcat(fxp->pool, supported_digests, ",sha224,sha256",
4142 NULL);
4143 #endif
4144 #ifdef HAVE_SHA512_OPENSSL
4145 supported_digests = pstrcat(fxp->pool, supported_digests, ",sha384,sha512",
4146 NULL);
4147 #endif
4148
4149 digest_name = sftp_misc_namelist_shared(fxp->pool, digest_list,
4150 supported_digests);
4151 if (digest_name == NULL) {
4152 xerrno = EINVAL;
4153
4154 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4155 "no supported digests in client check-file request "
4156 "(client sent '%s', server supports '%s')", digest_list,
4157 supported_digests);
4158
4159 status_code = fxp_errno2status(xerrno, &reason);
4160
4161 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4162 (unsigned long) status_code, reason);
4163
4164 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4165 reason, NULL);
4166
4167 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4168 resp->payload = ptr;
4169 resp->payload_sz = (bufsz - buflen);
4170
4171 return fxp_packet_write(resp);
4172 }
4173
4174 if (len == 0) {
4175 range_len = st.st_size - offset;
4176
4177 } else {
4178 range_len = offset + len;
4179 }
4180
4181 if (blocksz == 0) {
4182 nblocks = 1;
4183
4184 } else {
4185 nblocks = (unsigned long) (range_len / blocksz);
4186 if (range_len % blocksz != 0) {
4187 nblocks++;
4188 }
4189 }
4190
4191 pr_trace_msg(trace_channel, 15, "for check-file request on '%s', "
4192 "calculate %s digest of %lu %s", path, digest_name, nblocks,
4193 nblocks == 1 ? "block/checksum" : "nblocks/checksums");
4194
4195 fh = pr_fsio_open(path, O_RDONLY|O_NONBLOCK);
4196 if (fh == NULL) {
4197 xerrno = errno;
4198
4199 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4200 "unable to open path '%s': %s", path, strerror(xerrno));
4201
4202 status_code = fxp_errno2status(xerrno, &reason);
4203
4204 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4205 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4206 xerrno);
4207
4208 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4209 reason, NULL);
4210
4211 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4212 resp->payload = ptr;
4213 resp->payload_sz = (bufsz - buflen);
4214
4215 return fxp_packet_write(resp);
4216 }
4217
4218 if (pr_fsio_set_block(fh) < 0) {
4219 pr_trace_msg(trace_channel, 3,
4220 "error setting fd %d (file '%s') as blocking: %s", fh->fh_fd,
4221 fh->fh_path, strerror(errno));
4222 }
4223
4224 if (pr_fsio_lseek(fh, offset, SEEK_SET) < 0) {
4225 xerrno = errno;
4226
4227 pr_fsio_close(fh);
4228
4229 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4230 "unable to seek to offset %" PR_LU " in '%s': %s", (pr_off_t) offset,
4231 path, strerror(xerrno));
4232
4233 status_code = fxp_errno2status(xerrno, &reason);
4234
4235 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4236 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4237 xerrno);
4238
4239 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4240 reason, NULL);
4241
4242 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4243 resp->payload = ptr;
4244 resp->payload_sz = (bufsz - buflen);
4245
4246 return fxp_packet_write(resp);
4247 }
4248
4249 md = EVP_get_digestbyname(digest_name);
4250 if (md == NULL) {
4251 xerrno = EINVAL;
4252
4253 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4254 "unable to support %s digests: %s", digest_name,
4255 sftp_crypto_get_errors());
4256
4257 pr_fsio_close(fh);
4258
4259 status_code = fxp_errno2status(xerrno, &reason);
4260
4261 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4262 (unsigned long) status_code, reason);
4263
4264 /* Since we already started writing the EXTENDED_REPLY, we have
4265 * to reset the pointers and overwrite the existing message.
4266 */
4267 buf = ptr;
4268 buflen = bufsz;
4269
4270 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4271 reason, NULL);
4272
4273 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4274 resp->payload = ptr;
4275 resp->payload_sz = (bufsz - buflen);
4276
4277 return fxp_packet_write(resp);
4278 }
4279
4280 /* Calculate the size of the response buffer, based on the number of blocks.
4281 * Our already-allocated response buffer might be too small (see Issue #576).
4282 *
4283 * Each block needs at most EVP_MAX_MD_SIZE bytes, plus 4 bytes for the
4284 * length prefix.
4285 */
4286 expected_buflen = FXP_RESPONSE_DATA_DEFAULT_SZ +
4287 (nblocks * (EVP_MAX_MD_SIZE + 4));
4288 if (buflen < expected_buflen) {
4289 pr_trace_msg(trace_channel, 15, "allocated larger buffer (%lu bytes) for "
4290 "check-file request on '%s', %s digest, %lu %s",
4291 (unsigned long) expected_buflen, path, digest_name, nblocks,
4292 nblocks == 1 ? "block/checksum" : "nblocks/checksums");
4293
4294 buflen = bufsz = expected_buflen;
4295 buf = ptr = palloc(fxp->pool, bufsz);
4296 }
4297
4298 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
4299 defined(HAVE_LIBRESSL)
4300 pctx = &md_ctx;
4301 EVP_MD_CTX_init(pctx);
4302 #else
4303 pctx = EVP_MD_CTX_new();
4304 #endif /* prior to OpenSSL-1.1.0 */
4305
4306 bio = BIO_new(BIO_s_fd());
4307 BIO_set_fd(bio, PR_FH_FD(fh), BIO_NOCLOSE);
4308
4309 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
4310 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
4311 sftp_msg_write_string(&buf, &buflen, digest_name);
4312
4313 pr_trace_msg(trace_channel, 8,
4314 "sending response: EXTENDED_REPLY %s digest of %lu %s", digest_name,
4315 nblocks, nblocks == 1 ? "block" : "blocks");
4316
4317 if (blocksz == 0) {
4318 data_len = st.st_blksize;
4319
4320 } else {
4321 data_len = blocksz;
4322 }
4323
4324 data = palloc(fxp->pool, data_len);
4325
4326 while (TRUE) {
4327 pr_signals_handle();
4328
4329 res = BIO_read(bio, data, data_len);
4330 if (res < 0) {
4331 if (BIO_should_read(bio)) {
4332 continue;
4333 }
4334
4335 /* error */
4336 xerrno = errno;
4337
4338 pr_fsio_close(fh);
4339
4340 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4341 "error reading from '%s': %s", path, strerror(xerrno));
4342
4343 status_code = fxp_errno2status(xerrno, &reason);
4344
4345 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4346 "('%s' [%d])", (unsigned long) status_code, reason,
4347 strerror(xerrno), xerrno);
4348
4349 /* Since we already started writing the EXTENDED_REPLY, we have
4350 * to reset the pointers and overwrite the existing message.
4351 */
4352 buf = ptr;
4353 buflen = bufsz;
4354
4355 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4356 reason, NULL);
4357
4358 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4359 resp->payload = ptr;
4360 resp->payload_sz = (bufsz - buflen);
4361
4362 /* Cleanup. */
4363 BIO_free(bio);
4364
4365 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
4366 defined(HAVE_LIBRESSL)
4367 EVP_MD_CTX_cleanup(pctx);
4368 #else
4369 EVP_MD_CTX_free(pctx);
4370 #endif /* prior to OpenSSL-1.1.0 */
4371
4372 return fxp_packet_write(resp);
4373
4374 } else if (res == 0) {
4375 if (BIO_should_retry(bio) != 0) {
4376 continue;
4377 }
4378
4379 /* EOF */
4380 break;
4381 }
4382
4383 if (blocksz != 0) {
4384 unsigned char digest[EVP_MAX_MD_SIZE];
4385 unsigned int digest_len = 0;
4386
4387 EVP_DigestInit(pctx, md);
4388 EVP_DigestUpdate(pctx, data, res);
4389 EVP_DigestFinal(pctx, digest, &digest_len);
4390
4391 sftp_msg_write_data(&buf, &buflen, digest, digest_len, FALSE);
4392
4393 total_len += res;
4394 if (len > 0 &&
4395 total_len >= len) {
4396 break;
4397 }
4398 }
4399 }
4400
4401 if (blocksz == 0) {
4402 unsigned char digest[EVP_MAX_MD_SIZE];
4403 unsigned int digest_len = 0;
4404
4405 EVP_DigestInit(pctx, md);
4406 EVP_DigestUpdate(pctx, data, res);
4407 EVP_DigestFinal(pctx, digest, &digest_len);
4408
4409 sftp_msg_write_data(&buf, &buflen, digest, digest_len, FALSE);
4410 }
4411
4412 /* Cleanup. */
4413 BIO_free(bio);
4414 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
4415 defined(HAVE_LIBRESSL)
4416 EVP_MD_CTX_cleanup(pctx);
4417 #else
4418 EVP_MD_CTX_free(pctx);
4419 #endif /* prior to OpenSSL-1.1.0 */
4420 pr_fsio_close(fh);
4421
4422 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4423 resp->payload = ptr;
4424 resp->payload_sz = (bufsz - buflen);
4425
4426 return fxp_packet_write(resp);
4427 }
4428
fxp_handle_ext_copy_file(struct fxp_packet * fxp,char * src,char * dst,int overwrite)4429 static int fxp_handle_ext_copy_file(struct fxp_packet *fxp, char *src,
4430 char *dst, int overwrite) {
4431 char *abs_path, *args, *tmp;
4432 unsigned char *buf, *ptr;
4433 const char *reason;
4434 uint32_t buflen, bufsz, status_code;
4435 struct fxp_packet *resp;
4436 cmd_rec *cmd, *cmd2;
4437 int res, xerrno;
4438 struct stat st;
4439
4440 args = pstrcat(fxp->pool, src, " ", dst, NULL);
4441
4442 /* We need to provide an actual argv in this COPY cmd_rec, so we can't
4443 * use fxp_cmd_alloc(); we have to allocate the cmd_rec ourselves.
4444 */
4445 cmd = pr_cmd_alloc(fxp->pool, 4, pstrdup(fxp->pool, "SITE"),
4446 pstrdup(fxp->pool, "COPY"), src, dst);
4447 cmd->arg = pstrcat(fxp->pool, "COPY ", src, " ", dst, NULL);
4448 cmd->cmd_class = CL_WRITE;
4449
4450 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
4451 buf = ptr = palloc(fxp->pool, bufsz);
4452
4453 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
4454 status_code = SSH2_FX_PERMISSION_DENIED;
4455
4456 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4457 "COPY of '%s' to '%s' blocked by '%s' handler", src, dst,
4458 (char *) cmd->argv[0]);
4459
4460 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4461 (unsigned long) status_code, fxp_strerror(status_code));
4462
4463 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4464 fxp_strerror(status_code), NULL);
4465
4466 fxp_cmd_dispatch_err(cmd);
4467
4468 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4469 resp->payload = ptr;
4470 resp->payload_sz = (bufsz - buflen);
4471
4472 return fxp_packet_write(resp);
4473 }
4474
4475 tmp = src;
4476 src = dir_best_path(fxp->pool, tmp);
4477 if (src == NULL) {
4478 status_code = SSH2_FX_PERMISSION_DENIED;
4479
4480 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4481 "COPY request denied: unable to access path '%s'", tmp);
4482
4483 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4484 (unsigned long) status_code, fxp_strerror(status_code));
4485
4486 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4487 fxp_strerror(status_code), NULL);
4488
4489 fxp_cmd_dispatch_err(cmd);
4490
4491 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4492 resp->payload = ptr;
4493 resp->payload_sz = (bufsz - buflen);
4494
4495 return fxp_packet_write(resp);
4496 }
4497
4498 tmp = dst;
4499 dst = dir_best_path(fxp->pool, tmp);
4500 if (dst == NULL) {
4501 status_code = SSH2_FX_PERMISSION_DENIED;
4502
4503 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4504 "COPY request denied: unable to access path '%s'", tmp);
4505
4506 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4507 (unsigned long) status_code, fxp_strerror(status_code));
4508
4509 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4510 fxp_strerror(status_code), NULL);
4511
4512 fxp_cmd_dispatch_err(cmd);
4513
4514 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4515 resp->payload = ptr;
4516 resp->payload_sz = (bufsz - buflen);
4517
4518 return fxp_packet_write(resp);
4519 }
4520
4521 if (strcmp(src, dst) == 0) {
4522 xerrno = EEXIST;
4523
4524 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4525 "COPY of '%s' to same path '%s', rejecting", src, dst);
4526
4527 status_code = fxp_errno2status(xerrno, &reason);
4528
4529 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4530 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4531 xerrno);
4532
4533 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4534 reason, NULL);
4535
4536 fxp_cmd_dispatch_err(cmd);
4537
4538 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4539 resp->payload = ptr;
4540 resp->payload_sz = (bufsz - buflen);
4541
4542 return fxp_packet_write(resp);
4543 }
4544
4545 pr_fs_clear_cache2(dst);
4546 res = pr_fsio_stat(dst, &st);
4547 if (res == 0) {
4548 unsigned char *allow_overwrite = NULL;
4549 int limit_allow;
4550
4551 allow_overwrite = get_param_ptr(get_dir_ctxt(fxp->pool, dst),
4552 "AllowOverwrite", FALSE);
4553
4554 cmd2 = pr_cmd_alloc(fxp->pool, 3, "SITE_COPY", src, dst);
4555 cmd2->arg = pstrdup(fxp->pool, args);
4556 limit_allow = dir_check(fxp->pool, cmd2, "WRITE", dst, NULL);
4557
4558 if (!overwrite ||
4559 (allow_overwrite == NULL ||
4560 *allow_overwrite == FALSE) ||
4561 !limit_allow) {
4562 xerrno = EACCES;
4563
4564 if (!overwrite) {
4565 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4566 "'%s' exists and client did not request COPY overwrites", dst);
4567
4568 } else if (!limit_allow) {
4569 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4570 "COPY to '%s' blocked by <Limit> configuration", dst);
4571
4572 } else {
4573 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4574 "AllowOverwrite permission denied for '%s'", dst);
4575 }
4576
4577 status_code = fxp_errno2status(xerrno, &reason);
4578
4579 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4580 (unsigned long) status_code, reason);
4581
4582 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4583 reason, NULL);
4584
4585 fxp_cmd_dispatch_err(cmd);
4586
4587 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4588 resp->payload = ptr;
4589 resp->payload_sz = (bufsz - buflen);
4590
4591 return fxp_packet_write(resp);
4592 }
4593 }
4594
4595 if (fxp_path_pass_regex_filters(fxp->pool, "COPY", src) < 0 ||
4596 fxp_path_pass_regex_filters(fxp->pool, "COPY", dst) < 0) {
4597 xerrno = errno;
4598
4599 status_code = fxp_errno2status(xerrno, &reason);
4600
4601 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4602 (unsigned long) status_code, reason);
4603
4604 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4605 reason, NULL);
4606
4607 fxp_cmd_dispatch_err(cmd);
4608
4609 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4610 resp->payload = ptr;
4611 resp->payload_sz = (bufsz - buflen);
4612
4613 return fxp_packet_write(resp);
4614 }
4615
4616 cmd2 = pr_cmd_alloc(fxp->pool, 3, "SITE_COPY", src, dst);
4617 cmd2->arg = pstrdup(fxp->pool, args);
4618 if (!dir_check(fxp->pool, cmd2, "READ", src, NULL)) {
4619 xerrno = EACCES;
4620
4621 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4622 "COPY of '%s' blocked by <Limit> configuration", src);
4623
4624 status_code = fxp_errno2status(xerrno, &reason);
4625
4626 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4627 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4628 xerrno);
4629
4630 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4631 reason, NULL);
4632
4633 fxp_cmd_dispatch_err(cmd);
4634
4635 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4636 resp->payload = ptr;
4637 resp->payload_sz = (bufsz - buflen);
4638
4639 return fxp_packet_write(resp);
4640 }
4641
4642 res = pr_fs_copy_file2(src, dst, 0, NULL);
4643 if (res < 0) {
4644 xerrno = errno;
4645
4646 status_code = fxp_errno2status(xerrno, &reason);
4647
4648 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4649 "error copying '%s' to '%s': %s", src, dst, strerror(xerrno));
4650
4651 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4652 (unsigned long) status_code, reason);
4653
4654 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4655 reason, NULL);
4656
4657 fxp_cmd_dispatch_err(cmd);
4658
4659 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4660 resp->payload = ptr;
4661 resp->payload_sz = (bufsz - buflen);
4662
4663 return fxp_packet_write(resp);
4664 }
4665
4666 /* No errors. */
4667 xerrno = errno = 0;
4668
4669 pr_fs_clear_cache2(dst);
4670 pr_fsio_stat(dst, &st);
4671
4672 fxp_cmd_dispatch(cmd);
4673
4674 /* Write a TransferLog entry as well. */
4675 abs_path = sftp_misc_vroot_abs_path(fxp->pool, dst, TRUE);
4676 xferlog_write(0, session.c->remote_name, st.st_size, abs_path, 'b', 'i',
4677 'r', session.user, 'c', "_");
4678
4679 status_code = fxp_errno2status(xerrno, &reason);
4680
4681 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4682 (unsigned long) status_code, reason);
4683
4684 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4685 reason, NULL);
4686
4687 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4688 resp->payload = ptr;
4689 resp->payload_sz = (bufsz - buflen);
4690
4691 return fxp_packet_write(resp);
4692 }
4693
fxp_handle_ext_fsync(struct fxp_packet * fxp,struct fxp_handle * fxh)4694 static int fxp_handle_ext_fsync(struct fxp_packet *fxp,
4695 struct fxp_handle *fxh) {
4696 unsigned char *buf, *ptr;
4697 char *args;
4698 const char *path, *reason;
4699 uint32_t buflen, bufsz, status_code;
4700 struct fxp_packet *resp;
4701 cmd_rec *cmd;
4702 int res, xerrno;
4703
4704 path = fxh->fh->fh_path;
4705 args = pstrdup(fxp->pool, path);
4706
4707 cmd = fxp_cmd_alloc(fxp->pool, "FSYNC", args);
4708 cmd->cmd_class = CL_MISC|CL_SFTP;
4709 pr_cmd_dispatch_phase(cmd, PRE_CMD, 0);
4710
4711 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
4712 buf = ptr = palloc(fxp->pool, bufsz);
4713
4714 res = fsync(PR_FH_FD(fxh->fh));
4715 if (res < 0) {
4716 xerrno = errno;
4717
4718 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4719 "error calling fsync(2) on '%s': %s", path, strerror(xerrno));
4720
4721 errno = xerrno;
4722
4723 } else {
4724 /* No errors. */
4725 xerrno = errno = 0;
4726 }
4727
4728 status_code = fxp_errno2status(xerrno, &reason);
4729
4730 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4731 "('%s' [%d])", (unsigned long) status_code, reason,
4732 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
4733
4734 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4735 reason, NULL);
4736
4737 if (xerrno == 0) {
4738 fxp_cmd_dispatch(cmd);
4739
4740 } else {
4741 fxp_cmd_dispatch_err(cmd);
4742 }
4743
4744 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4745 resp->payload = ptr;
4746 resp->payload_sz = (bufsz - buflen);
4747
4748 return fxp_packet_write(resp);
4749 }
4750
fxp_handle_ext_hardlink(struct fxp_packet * fxp,char * src,char * dst)4751 static int fxp_handle_ext_hardlink(struct fxp_packet *fxp, char *src,
4752 char *dst) {
4753 unsigned char *buf, *ptr;
4754 char *args, *path;
4755 const char *reason;
4756 uint32_t buflen, bufsz, status_code;
4757 struct fxp_packet *resp;
4758 cmd_rec *cmd = NULL;
4759 int res, xerrno = 0;
4760
4761 args = pstrcat(fxp->pool, src, " ", dst, NULL);
4762
4763 pr_scoreboard_entry_update(session.pid,
4764 PR_SCORE_CMD, "%s", "HARDLINK", NULL, NULL);
4765 pr_scoreboard_entry_update(session.pid,
4766 PR_SCORE_CMD_ARG, "%s", args, NULL, NULL);
4767
4768 pr_proctitle_set("%s - %s: HARDLINK %s %s", session.user, session.proc_prefix,
4769 src, dst);
4770
4771 cmd = fxp_cmd_alloc(fxp->pool, "HARDLINK", args);
4772 cmd->cmd_class = CL_MISC|CL_SFTP;
4773
4774 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
4775 buf = ptr = palloc(fxp->pool, bufsz);
4776
4777 path = dir_best_path(fxp->pool, src);
4778 if (path == NULL) {
4779 status_code = SSH2_FX_PERMISSION_DENIED;
4780
4781 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4782 "hardlink request denied: unable to access path '%s'", src);
4783
4784 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4785 (unsigned long) status_code, fxp_strerror(status_code));
4786
4787 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4788 fxp_strerror(status_code), NULL);
4789
4790 fxp_cmd_dispatch_err(cmd);
4791
4792 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4793 resp->payload = ptr;
4794 resp->payload_sz = (bufsz - buflen);
4795
4796 return fxp_packet_write(resp);
4797 }
4798 src = path;
4799
4800 path = dir_best_path(fxp->pool, dst);
4801 if (path == NULL) {
4802 status_code = SSH2_FX_PERMISSION_DENIED;
4803
4804 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4805 "hardlink request denied: unable to access path '%s'", dst);
4806
4807 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4808 (unsigned long) status_code, fxp_strerror(status_code));
4809
4810 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4811 fxp_strerror(status_code), NULL);
4812
4813 fxp_cmd_dispatch_err(cmd);
4814
4815 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4816 resp->payload = ptr;
4817 resp->payload_sz = (bufsz - buflen);
4818
4819 return fxp_packet_write(resp);
4820 }
4821 dst = path;
4822
4823 if (!dir_check(fxp->pool, cmd, G_DIRS, src, NULL) ||
4824 !dir_check(fxp->pool, cmd, G_WRITE, dst, NULL)) {
4825 status_code = SSH2_FX_PERMISSION_DENIED;
4826
4827 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4828 "HARDLINK of '%s' to '%s' blocked by <Limit> configuration",
4829 src, dst);
4830
4831 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4832 (unsigned long) status_code, fxp_strerror(status_code));
4833
4834 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4835 fxp_strerror(status_code), NULL);
4836
4837 fxp_cmd_dispatch_err(cmd);
4838
4839 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4840 resp->payload = ptr;
4841 resp->payload_sz = (bufsz - buflen);
4842
4843 return fxp_packet_write(resp);
4844 }
4845
4846 if (strcmp(src, dst) == 0) {
4847 xerrno = EEXIST;
4848
4849 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4850 "HARDLINK of '%s' to same path '%s', rejecting", src, dst);
4851
4852 status_code = fxp_errno2status(xerrno, &reason);
4853
4854 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4855 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4856 xerrno);
4857
4858 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4859 reason, NULL);
4860
4861 fxp_cmd_dispatch_err(cmd);
4862
4863 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4864 resp->payload = ptr;
4865 resp->payload_sz = (bufsz - buflen);
4866
4867 return fxp_packet_write(resp);
4868 }
4869
4870 if (fxp_path_pass_regex_filters(fxp->pool, "HARDLINK", src) < 0 ||
4871 fxp_path_pass_regex_filters(fxp->pool, "HARDLINK", dst) < 0) {
4872 xerrno = errno;
4873
4874 status_code = fxp_errno2status(xerrno, &reason);
4875
4876 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4877 (unsigned long) status_code, fxp_strerror(status_code));
4878
4879 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4880 fxp_strerror(status_code), NULL);
4881
4882 fxp_cmd_dispatch_err(cmd);
4883
4884 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4885 resp->payload = ptr;
4886 resp->payload_sz = (bufsz - buflen);
4887
4888 return fxp_packet_write(resp);
4889 }
4890
4891 res = pr_fsio_link(src, dst);
4892 if (res < 0) {
4893 xerrno = errno;
4894
4895 (void) pr_trace_msg("fileperms", 1, "HARDLINK, user '%s' (UID %s, "
4896 "GID %s): error hardlinking '%s' to '%s': %s", session.user,
4897 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
4898 src, dst, strerror(xerrno));
4899
4900 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4901 "error hardlinking '%s' to '%s': %s", src, dst, strerror(xerrno));
4902
4903 errno = xerrno;
4904
4905 } else {
4906 /* No errors. */
4907 xerrno = errno = 0;
4908 }
4909
4910 status_code = fxp_errno2status(xerrno, &reason);
4911
4912 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
4913 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
4914 xerrno);
4915
4916 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4917 reason, NULL);
4918
4919 if (xerrno == 0) {
4920 fxp_cmd_dispatch(cmd);
4921
4922 } else {
4923 fxp_cmd_dispatch_err(cmd);
4924 }
4925
4926 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4927 resp->payload = ptr;
4928 resp->payload_sz = (bufsz - buflen);
4929
4930 return fxp_packet_write(resp);
4931 }
4932
fxp_handle_ext_posix_rename(struct fxp_packet * fxp,char * src,char * dst)4933 static int fxp_handle_ext_posix_rename(struct fxp_packet *fxp, char *src,
4934 char *dst) {
4935 unsigned char *buf, *ptr;
4936 char *args;
4937 const char *reason;
4938 uint32_t buflen, bufsz, status_code;
4939 struct fxp_packet *resp;
4940 cmd_rec *cmd = NULL, *cmd2 = NULL, *cmd3 = NULL;
4941 int res, xerrno = 0;
4942
4943 args = pstrcat(fxp->pool, src, " ", dst, NULL);
4944
4945 pr_scoreboard_entry_update(session.pid,
4946 PR_SCORE_CMD, "%s", "RENAME", NULL, NULL);
4947 pr_scoreboard_entry_update(session.pid,
4948 PR_SCORE_CMD_ARG, "%s", args, NULL, NULL);
4949
4950 pr_proctitle_set("%s - %s: RENAME %s %s", session.user, session.proc_prefix,
4951 src, dst);
4952
4953 cmd = fxp_cmd_alloc(fxp->pool, "RENAME", args);
4954 cmd->cmd_class = CL_MISC|CL_SFTP;
4955
4956 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
4957 buf = ptr = palloc(fxp->pool, bufsz);
4958
4959 cmd2 = fxp_cmd_alloc(fxp->pool, C_RNFR, src);
4960 cmd2->cmd_class = CL_MISC|CL_WRITE;
4961 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) < 0) {
4962 status_code = SSH2_FX_PERMISSION_DENIED;
4963
4964 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4965 "RENAME from '%s' blocked by '%s' handler", src, (char *) cmd2->argv[0]);
4966
4967 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4968 (unsigned long) status_code, fxp_strerror(status_code));
4969
4970 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
4971 fxp_cmd_dispatch_err(cmd2);
4972
4973 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4974 fxp_strerror(status_code), NULL);
4975
4976 fxp_cmd_dispatch_err(cmd);
4977
4978 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
4979 resp->payload = ptr;
4980 resp->payload_sz = (bufsz - buflen);
4981
4982 return fxp_packet_write(resp);
4983 }
4984
4985 src = dir_best_path(fxp->pool, cmd2->arg);
4986 if (src == NULL) {
4987 status_code = SSH2_FX_PERMISSION_DENIED;
4988
4989 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
4990 "posix-rename request denied: unable to access path '%s'", cmd2->arg);
4991
4992 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
4993 (unsigned long) status_code, fxp_strerror(status_code));
4994
4995 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
4996 fxp_strerror(status_code), NULL);
4997
4998 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
4999 fxp_cmd_dispatch_err(cmd2);
5000
5001 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5002 fxp_strerror(status_code), NULL);
5003
5004 fxp_cmd_dispatch_err(cmd);
5005
5006 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5007 resp->payload = ptr;
5008 resp->payload_sz = (bufsz - buflen);
5009
5010 return fxp_packet_write(resp);
5011 }
5012
5013 if (pr_table_add(session.notes, "mod_core.rnfr-path",
5014 pstrdup(session.pool, src), 0) < 0) {
5015 if (errno != EEXIST) {
5016 pr_trace_msg(trace_channel, 8,
5017 "error setting 'mod_core.rnfr-path' note: %s", strerror(errno));
5018 }
5019 }
5020
5021 cmd3 = fxp_cmd_alloc(fxp->pool, C_RNTO, dst);
5022 cmd3->cmd_class = CL_MISC|CL_WRITE;
5023 if (pr_cmd_dispatch_phase(cmd3, PRE_CMD, 0) < 0) {
5024 status_code = SSH2_FX_PERMISSION_DENIED;
5025
5026 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5027 "RENAME to '%s' blocked by '%s' handler", dst, (char *) cmd3->argv[0]);
5028
5029 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5030 (unsigned long) status_code, fxp_strerror(status_code));
5031
5032 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(EACCES));
5033 fxp_cmd_dispatch_err(cmd3);
5034
5035 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
5036 fxp_cmd_dispatch_err(cmd2);
5037
5038 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5039 fxp_strerror(status_code), NULL);
5040
5041 fxp_cmd_dispatch_err(cmd);
5042
5043 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5044 resp->payload = ptr;
5045 resp->payload_sz = (bufsz - buflen);
5046
5047 return fxp_packet_write(resp);
5048 }
5049
5050 dst = dir_best_path(fxp->pool, cmd3->arg);
5051 if (dst == NULL) {
5052 status_code = SSH2_FX_PERMISSION_DENIED;
5053
5054 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5055 "posix-rename request denied: unable to access path '%s'", cmd2->arg);
5056
5057 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5058 (unsigned long) status_code, fxp_strerror(status_code));
5059
5060 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5061 fxp_strerror(status_code), NULL);
5062
5063 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(EACCES));
5064 fxp_cmd_dispatch_err(cmd3);
5065
5066 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
5067 fxp_cmd_dispatch_err(cmd2);
5068
5069 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5070 fxp_strerror(status_code), NULL);
5071
5072 fxp_cmd_dispatch_err(cmd);
5073
5074 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5075 resp->payload = ptr;
5076 resp->payload_sz = (bufsz - buflen);
5077
5078 return fxp_packet_write(resp);
5079 }
5080
5081 if (!dir_check(fxp->pool, cmd2, G_DIRS, src, NULL) ||
5082 !dir_check(fxp->pool, cmd3, G_WRITE, dst, NULL)) {
5083 status_code = SSH2_FX_PERMISSION_DENIED;
5084
5085 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5086 "RENAME of '%s' to '%s' blocked by <Limit> configuration",
5087 src, dst);
5088
5089 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5090 (unsigned long) status_code, fxp_strerror(status_code));
5091
5092 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(EACCES));
5093 fxp_cmd_dispatch_err(cmd3);
5094
5095 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
5096 fxp_cmd_dispatch_err(cmd2);
5097
5098 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5099 fxp_strerror(status_code), NULL);
5100
5101 fxp_cmd_dispatch_err(cmd);
5102
5103 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5104 resp->payload = ptr;
5105 resp->payload_sz = (bufsz - buflen);
5106
5107 return fxp_packet_write(resp);
5108 }
5109
5110 if (strcmp(src, dst) == 0) {
5111 xerrno = EEXIST;
5112
5113 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5114 "RENAME of '%s' to same path '%s', rejecting", src, dst);
5115
5116 status_code = fxp_errno2status(xerrno, &reason);
5117
5118 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5119 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
5120 xerrno);
5121
5122 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(EEXIST));
5123 fxp_cmd_dispatch_err(cmd3);
5124
5125 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(EEXIST));
5126 fxp_cmd_dispatch_err(cmd2);
5127
5128 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5129 reason, NULL);
5130
5131 fxp_cmd_dispatch_err(cmd);
5132
5133 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5134 resp->payload = ptr;
5135 resp->payload_sz = (bufsz - buflen);
5136
5137 return fxp_packet_write(resp);
5138 }
5139
5140 if (fxp_path_pass_regex_filters(fxp->pool, "RENAME", src) < 0 ||
5141 fxp_path_pass_regex_filters(fxp->pool, "RENAME", dst) < 0) {
5142 xerrno = errno;
5143
5144 status_code = fxp_errno2status(xerrno, &reason);
5145
5146 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5147 (unsigned long) status_code, fxp_strerror(status_code));
5148
5149 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(xerrno));
5150 fxp_cmd_dispatch_err(cmd3);
5151
5152 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
5153 fxp_cmd_dispatch_err(cmd2);
5154
5155 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5156 fxp_strerror(status_code), NULL);
5157
5158 fxp_cmd_dispatch_err(cmd);
5159
5160 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5161 resp->payload = ptr;
5162 resp->payload_sz = (bufsz - buflen);
5163
5164 return fxp_packet_write(resp);
5165 }
5166
5167 res = pr_fsio_rename(src, dst);
5168 if (res < 0) {
5169 if (errno != EXDEV) {
5170 xerrno = errno;
5171
5172 (void) pr_trace_msg("fileperms", 1, "RENAME, user '%s' (UID %s, "
5173 "GID %s): error renaming '%s' to '%s': %s", session.user,
5174 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
5175 src, dst, strerror(xerrno));
5176
5177 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5178 "error renaming '%s' to '%s': %s", src, dst, strerror(xerrno));
5179
5180 errno = xerrno;
5181
5182 } else {
5183 /* In this case, we should manually copy the file from the source
5184 * path to the destination path.
5185 */
5186 errno = 0;
5187
5188 res = pr_fs_copy_file2(src, dst, 0, NULL);
5189 if (res < 0) {
5190 xerrno = errno;
5191
5192 (void) pr_trace_msg("fileperms", 1, "RENAME, user '%s' (UID %s, "
5193 "GID %s): error copying '%s' to '%s': %s", session.user,
5194 pr_uid2str(fxp->pool, session.uid),
5195 pr_gid2str(fxp->pool, session.gid),
5196 src, dst, strerror(xerrno));
5197
5198 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5199 "error copying '%s' to '%s': %s", src, dst, strerror(xerrno));
5200
5201 errno = xerrno;
5202
5203 } else {
5204 /* Once copied, remove the original path. */
5205 if (pr_fsio_unlink(src) < 0) {
5206 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5207 "error deleting '%s': %s", src, strerror(errno));
5208 }
5209
5210 xerrno = errno = 0;
5211 }
5212 }
5213
5214 } else {
5215 /* No errors. */
5216 xerrno = errno = 0;
5217 }
5218
5219 status_code = fxp_errno2status(xerrno, &reason);
5220
5221 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5222 "('%s' [%d])", (unsigned long) status_code, reason,
5223 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
5224
5225 /* Clear out any transfer-specific data. */
5226 if (session.xfer.p) {
5227 destroy_pool(session.xfer.p);
5228 }
5229 memset(&session.xfer, 0, sizeof(session.xfer));
5230
5231 /* The timing of these steps may look peculiar, but it's deliberate,
5232 * in order to get the expected log messages in an ExtendedLog.
5233 */
5234
5235 session.xfer.p = make_sub_pool(fxp_pool);
5236 pr_pool_tag(session.xfer.p, "SFTP session transfer pool");
5237 memset(&session.xfer.start_time, 0, sizeof(session.xfer.start_time));
5238 gettimeofday(&session.xfer.start_time, NULL);
5239
5240 session.xfer.path = pstrdup(session.xfer.p, src);
5241
5242 if (xerrno == 0) {
5243 pr_response_add(R_350,
5244 "File or directory exists, ready for destination name");
5245 fxp_cmd_dispatch(cmd2);
5246
5247 } else {
5248 pr_response_add_err(R_550, "%s: %s", (char *) cmd2->argv[0],
5249 strerror(xerrno));
5250 fxp_cmd_dispatch_err(cmd2);
5251 }
5252
5253 session.xfer.path = pstrdup(session.xfer.p, dst);
5254
5255 if (xerrno == 0) {
5256 pr_response_add(R_250, "Rename successful");
5257 fxp_cmd_dispatch(cmd3);
5258
5259 } else {
5260 pr_response_add_err(R_550, "%s: %s", (char *) cmd3->argv[0],
5261 strerror(xerrno));
5262 fxp_cmd_dispatch_err(cmd3);
5263 }
5264
5265 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5266 reason, NULL);
5267 if (xerrno == 0) {
5268 fxp_cmd_dispatch(cmd);
5269
5270 } else {
5271 fxp_cmd_dispatch_err(cmd);
5272 }
5273
5274 /* Clear out any transfer-specific data. */
5275 if (session.xfer.p) {
5276 destroy_pool(session.xfer.p);
5277 }
5278 memset(&session.xfer, 0, sizeof(session.xfer));
5279
5280 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5281 resp->payload = ptr;
5282 resp->payload_sz = (bufsz - buflen);
5283
5284 return fxp_packet_write(resp);
5285 }
5286
5287 #ifdef HAVE_SYS_STATVFS_H
5288
get_fs_bytes_total(void * ptr)5289 static off_t get_fs_bytes_total(void *ptr) {
5290 # if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && \
5291 defined(SOLARIS2) && !defined(SOLARIS2_5_1) && !defined(SOLARIS2_6) && \
5292 !defined(SOLARIS2_7)
5293 /* Note: somewhere along the way, Sun decided that the prototype for
5294 * its statvfs64(2) function would include a statvfs64_t rather than
5295 * struct statvfs64. In 2.6 and 2.7, it's struct statvfs64, and
5296 * in 8, 9 it's statvfs64_t. This should silence compiler warnings.
5297 * (The statvfs_t will be redefined to a statvfs64_t as appropriate on
5298 * LFS systems).
5299 */
5300 statvfs_t *fs = ptr;
5301 # else
5302 struct statvfs *fs = ptr;
5303 # endif /* LFS && !Solaris 2.5.1 && !Solaris 2.6 && !Solaris 2.7 */
5304
5305 return ((off_t) fs->f_blocks * (off_t) fs->f_frsize);
5306 }
5307
get_fs_bytes_unused(void * ptr)5308 static off_t get_fs_bytes_unused(void *ptr) {
5309 # if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && \
5310 defined(SOLARIS2) && !defined(SOLARIS2_5_1) && !defined(SOLARIS2_6) && \
5311 !defined(SOLARIS2_7)
5312 /* Note: somewhere along the way, Sun decided that the prototype for
5313 * its statvfs64(2) function would include a statvfs64_t rather than
5314 * struct statvfs64. In 2.6 and 2.7, it's struct statvfs64, and
5315 * in 8, 9 it's statvfs64_t. This should silence compiler warnings.
5316 * (The statvfs_t will be redefined to a statvfs64_t as appropriate on
5317 * LFS systems).
5318 */
5319 statvfs_t *fs = ptr;
5320 # else
5321 struct statvfs *fs = ptr;
5322 # endif /* LFS && !Solaris 2.5.1 && !Solaris 2.6 && !Solaris 2.7 */
5323
5324 return ((off_t) fs->f_bavail * (off_t) fs->f_frsize);
5325 }
5326
get_user_bytes_avail(void * ptr)5327 static off_t get_user_bytes_avail(void *ptr) {
5328 # if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && \
5329 defined(SOLARIS2) && !defined(SOLARIS2_5_1) && !defined(SOLARIS2_6) && \
5330 !defined(SOLARIS2_7)
5331 /* Note: somewhere along the way, Sun decided that the prototype for
5332 * its statvfs64(2) function would include a statvfs64_t rather than
5333 * struct statvfs64. In 2.6 and 2.7, it's struct statvfs64, and
5334 * in 8, 9 it's statvfs64_t. This should silence compiler warnings.
5335 * (The statvfs_t will be redefined to a statvfs64_t as appropriate on
5336 * LFS systems).
5337 */
5338 statvfs_t *fs = ptr;
5339 # else
5340 struct statvfs *fs = ptr;
5341 # endif /* LFS && !Solaris 2.5.1 && !Solaris 2.6 && !Solaris 2.7 */
5342
5343 /* XXX This should use mod_quotatab as well, for user-specific limits/
5344 * tallies.
5345 */
5346
5347 /* Take the total number of blocks, and subtract the difference between
5348 * the total free blocks and the non-root free blocks. That difference
5349 * provides the number of blocks reserved for root. So subtracting those
5350 * reserved blocks from the total blocks yields the user-available blocks.
5351 */
5352 return (((off_t) fs->f_blocks - ((off_t) fs->f_bfree) - (off_t) fs->f_bavail) * (off_t) fs->f_frsize);
5353 }
5354
get_user_bytes_unused(void * ptr)5355 static off_t get_user_bytes_unused(void *ptr) {
5356 # if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && \
5357 defined(SOLARIS2) && !defined(SOLARIS2_5_1) && !defined(SOLARIS2_6) && \
5358 !defined(SOLARIS2_7)
5359 /* Note: somewhere along the way, Sun decided that the prototype for
5360 * its statvfs64(2) function would include a statvfs64_t rather than
5361 * struct statvfs64. In 2.6 and 2.7, it's struct statvfs64, and
5362 * in 8, 9 it's statvfs64_t. This should silence compiler warnings.
5363 * (The statvfs_t will be redefined to a statvfs64_t as appropriate on
5364 * LFS systems).
5365 */
5366 statvfs_t *fs = ptr;
5367 # else
5368 struct statvfs *fs = ptr;
5369 # endif /* LFS && !Solaris 2.5.1 && !Solaris 2.6 && !Solaris 2.7 */
5370
5371 /* XXX This should use mod_quotatab as well, for user-specific limits/
5372 * tallies.
5373 */
5374
5375 return ((off_t) fs->f_bavail * (off_t) fs->f_frsize);
5376 }
5377
fxp_handle_ext_space_avail(struct fxp_packet * fxp,char * path)5378 static int fxp_handle_ext_space_avail(struct fxp_packet *fxp, char *path) {
5379 unsigned char *buf, *ptr;
5380 const char *reason;
5381 uint32_t buflen, bufsz, status_code;
5382 struct fxp_packet *resp;
5383
5384 # if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && \
5385 defined(SOLARIS2) && !defined(SOLARIS2_5_1) && !defined(SOLARIS2_6) && \
5386 !defined(SOLARIS2_7)
5387 /* Note: somewhere along the way, Sun decided that the prototype for
5388 * its statvfs64(2) function would include a statvfs64_t rather than
5389 * struct statvfs64. In 2.6 and 2.7, it's struct statvfs64, and
5390 * in 8, 9 it's statvfs64_t. This should silence compiler warnings.
5391 * (The statvfs_t will be redefined to a statvfs64_t as appropriate on
5392 * LFS systems).
5393 */
5394 statvfs_t fs;
5395 # else
5396 struct statvfs fs;
5397 # endif /* LFS && !Solaris 2.5.1 && !Solaris 2.6 && !Solaris 2.7 */
5398
5399 pr_trace_msg(trace_channel, 8, "client sent space-available request: "
5400 "path = '%s'", path);
5401
5402 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
5403 buf = ptr = palloc(fxp->pool, bufsz);
5404
5405 if (statvfs(path, &fs) < 0) {
5406 int xerrno = errno;
5407
5408 pr_trace_msg(trace_channel, 3, "statvfs() error using '%s': %s",
5409 path, strerror(xerrno));
5410
5411 status_code = fxp_errno2status(xerrno, &reason);
5412
5413 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5414 "('%s' [%d])", (unsigned long) status_code, reason,
5415 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
5416
5417 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5418 reason, NULL);
5419
5420 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5421 resp->payload = ptr;
5422 resp->payload_sz = (bufsz - buflen);
5423
5424 return fxp_packet_write(resp);
5425 }
5426
5427 pr_trace_msg(trace_channel, 8,
5428 "sending response: EXTENDED_REPLY <space-avail data of '%s'>", path);
5429
5430 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
5431 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
5432
5433 /* Total bytes on device */
5434 sftp_msg_write_long(&buf, &buflen, (uint64_t) get_fs_bytes_total(&fs));
5435
5436 /* Unused bytes on device. */
5437 sftp_msg_write_long(&buf, &buflen, (uint64_t) get_fs_bytes_unused(&fs));
5438
5439 /* Total bytes available to user. */
5440 sftp_msg_write_long(&buf, &buflen, (uint64_t) get_user_bytes_avail(&fs));
5441
5442 /* Unused bytes available to user. */
5443 sftp_msg_write_long(&buf, &buflen, (uint64_t) get_user_bytes_unused(&fs));
5444
5445 sftp_msg_write_int(&buf, &buflen, (uint32_t) fs.f_frsize);
5446
5447 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5448 resp->payload = ptr;
5449 resp->payload_sz = (bufsz - buflen);
5450
5451 return fxp_packet_write(resp);
5452 }
5453
fxp_handle_ext_statvfs(struct fxp_packet * fxp,const char * path)5454 static int fxp_handle_ext_statvfs(struct fxp_packet *fxp, const char *path) {
5455 unsigned char *buf, *ptr;
5456 const char *reason;
5457 uint32_t buflen, bufsz, status_code;
5458 struct fxp_packet *resp;
5459 uint64_t fs_id = 0, fs_flags = 0;
5460
5461 # if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && \
5462 defined(SOLARIS2) && !defined(SOLARIS2_5_1) && !defined(SOLARIS2_6) && \
5463 !defined(SOLARIS2_7)
5464 /* Note: somewhere along the way, Sun decided that the prototype for
5465 * its statvfs64(2) function would include a statvfs64_t rather than
5466 * struct statvfs64. In 2.6 and 2.7, it's struct statvfs64, and
5467 * in 8, 9 it's statvfs64_t. This should silence compiler warnings.
5468 * (The statvfs_t will be redefined to a statvfs64_t as appropriate on
5469 * LFS systems).
5470 */
5471 statvfs_t fs;
5472 # else
5473 struct statvfs fs;
5474 # endif /* LFS && !Solaris 2.5.1 && !Solaris 2.6 && !Solaris 2.7 */
5475
5476 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
5477 buf = ptr = palloc(fxp->pool, bufsz);
5478
5479 if (statvfs(path, &fs) < 0) {
5480 int xerrno = errno;
5481
5482 pr_trace_msg(trace_channel, 3, "statvfs() error using '%s': %s",
5483 path, strerror(xerrno));
5484
5485 status_code = fxp_errno2status(xerrno, &reason);
5486
5487 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5488 "('%s' [%d])", (unsigned long) status_code, reason,
5489 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
5490
5491 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5492 reason, NULL);
5493
5494 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5495 resp->payload = ptr;
5496 resp->payload_sz = (bufsz - buflen);
5497
5498 return fxp_packet_write(resp);
5499 }
5500
5501 pr_trace_msg(trace_channel, 8,
5502 "sending response: EXTENDED_REPLY <statvfs data of '%s'>", path);
5503
5504 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
5505 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
5506 sftp_msg_write_long(&buf, &buflen, fs.f_bsize);
5507 sftp_msg_write_long(&buf, &buflen, fs.f_frsize);
5508 sftp_msg_write_long(&buf, &buflen, fs.f_blocks);
5509 sftp_msg_write_long(&buf, &buflen, fs.f_bfree);
5510 sftp_msg_write_long(&buf, &buflen, fs.f_bavail);
5511 sftp_msg_write_long(&buf, &buflen, fs.f_files);
5512 sftp_msg_write_long(&buf, &buflen, fs.f_ffree);
5513 sftp_msg_write_long(&buf, &buflen, fs.f_favail);
5514
5515 /* AIX requires this machination because a) its statvfs struct has
5516 * non-standard data types for the fsid value:
5517 *
5518 * https://lists.dulug.duke.edu/pipermail/rpm-devel/2006-July/001236.html
5519 * https://lists.dulug.duke.edu/pipermail/rpm-devel/2006-July/001264.html
5520 * https://lists.dulug.duke.edu/pipermail/rpm-devel/2006-July/001265.html
5521 * https://lists.dulug.duke.edu/pipermail/rpm-devel/2006-July/001268.html
5522 *
5523 * and b) it does not really matter what value is written; the client is
5524 * not going to be able to do much with this value anyway. From that
5525 * perspective, I'm not sure why the OpenSSH extension even includes the
5526 * value in the response (*shrug*).
5527 */
5528 #if !defined(AIX4) && !defined(AIX5)
5529 memcpy(&fs_id, &(fs.f_fsid), sizeof(fs_id));
5530 #endif
5531 sftp_msg_write_long(&buf, &buflen, fs_id);
5532
5533 /* These flags and values are defined by OpenSSH's PROTOCOL document.
5534 *
5535 * Other platforms support more fs.f_flag values than just ST_RDONLY
5536 * and ST_NOSUID, but those are the only two flags handled by OpenSSH;
5537 * thus we cannot simply send fs.f_flag directly to the client as is.
5538 */
5539 #ifdef ST_RDONLY
5540 if (fs.f_flag & ST_RDONLY) {
5541 fs_flags |= SSH2_FXE_STATVFS_ST_RDONLY;
5542 }
5543 #endif
5544
5545 #ifdef ST_NOSUID
5546 if (fs.f_flag & ST_NOSUID) {
5547 fs_flags |= SSH2_FXE_STATVFS_ST_NOSUID;
5548 }
5549 #endif
5550
5551 sftp_msg_write_long(&buf, &buflen, fs_flags);
5552 sftp_msg_write_long(&buf, &buflen, fs.f_namemax);
5553
5554 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5555 resp->payload = ptr;
5556 resp->payload_sz = (bufsz - buflen);
5557
5558 return fxp_packet_write(resp);
5559 }
5560 #endif /* !HAVE_SYS_STATVFS_H */
5561
5562 #ifdef PR_USE_XATTR
fxp_handle_ext_getxattr(struct fxp_packet * fxp,const char * path,const char * name,uint32_t valsz)5563 static int fxp_handle_ext_getxattr(struct fxp_packet *fxp, const char *path,
5564 const char *name, uint32_t valsz) {
5565 ssize_t res;
5566 void *val;
5567 unsigned char *buf, *ptr;
5568 uint32_t buflen, bufsz, status_code;
5569 const char *reason;
5570 struct fxp_packet *resp;
5571
5572 val = pcalloc(fxp->pool, (size_t) valsz+1);
5573
5574 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ + valsz;
5575 buf = ptr = palloc(fxp->pool, bufsz);
5576
5577 res = pr_fsio_lgetxattr(fxp->pool, path, name, val, (size_t) valsz);
5578 if (res < 0) {
5579 int xerrno = errno;
5580
5581 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5582 "getxattr(2) error on '%s' for attribute '%s': %s", path, name,
5583 strerror(xerrno));
5584
5585 status_code = fxp_errno2status(xerrno, &reason);
5586
5587 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5588 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
5589 xerrno);
5590
5591 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5592 reason, NULL);
5593
5594 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5595 resp->payload = ptr;
5596 resp->payload_sz = (bufsz - buflen);
5597
5598 return fxp_packet_write(resp);
5599 }
5600
5601 pr_trace_msg(trace_channel, 8,
5602 "sending response: EXTENDED_REPLY (%lu bytes)", (unsigned long) res);
5603
5604 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
5605 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
5606 sftp_msg_write_data(&buf, &buflen, val, res, TRUE);
5607
5608 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5609 resp->payload = ptr;
5610 resp->payload_sz = (bufsz - buflen);
5611
5612 return fxp_packet_write(resp);
5613 }
5614
fxp_handle_ext_fgetxattr(struct fxp_packet * fxp,const char * handle,const char * name,uint32_t valsz)5615 static int fxp_handle_ext_fgetxattr(struct fxp_packet *fxp, const char *handle,
5616 const char *name, uint32_t valsz) {
5617 ssize_t res;
5618 void *val;
5619 unsigned char *buf, *ptr;
5620 uint32_t buflen, bufsz, status_code;
5621 const char *path, *reason;
5622 struct fxp_handle *fxh;
5623 struct fxp_packet *resp;
5624
5625 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ + valsz;
5626 buf = ptr = palloc(fxp->pool, bufsz);
5627
5628 fxh = fxp_handle_get(handle);
5629 if (fxh == NULL) {
5630 pr_trace_msg(trace_channel, 17,
5631 "fgetxattr@proftpd.org: unable to find handle for name '%s': %s", handle,
5632 strerror(errno));
5633
5634 status_code = SSH2_FX_INVALID_HANDLE;
5635
5636 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5637 (unsigned long) status_code, fxp_strerror(status_code));
5638
5639 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5640 fxp_strerror(status_code), NULL);
5641
5642 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5643 resp->payload = ptr;
5644 resp->payload_sz = (bufsz - buflen);
5645
5646 return fxp_packet_write(resp);
5647 }
5648
5649 if (fxh->dirh != NULL) {
5650 /* Request for extended attributes on a directory handle. It's not
5651 * easy to get the file descriptor on a directory, so we'll just do
5652 * by path instead.
5653 */
5654 return fxp_handle_ext_getxattr(fxp, fxh->fh->fh_path, name, valsz);
5655 }
5656
5657 if (fxh->fh == NULL) {
5658 status_code = SSH2_FX_INVALID_HANDLE;
5659
5660 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5661 (unsigned long) status_code, fxp_strerror(status_code));
5662
5663 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5664 fxp_strerror(status_code), NULL);
5665
5666 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5667 resp->payload = ptr;
5668 resp->payload_sz = (bufsz - buflen);
5669
5670 return fxp_packet_write(resp);
5671 }
5672
5673 path = fxh->fh->fh_path;
5674 val = pcalloc(fxp->pool, (size_t) valsz+1);
5675
5676 res = pr_fsio_fgetxattr(fxp->pool, fxh->fh, name, val, (size_t) valsz);
5677 if (res < 0) {
5678 int xerrno = errno;
5679
5680 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5681 "fgetxattr(2) error on '%s' for attribute '%s': %s", path, name,
5682 strerror(xerrno));
5683
5684 status_code = fxp_errno2status(xerrno, &reason);
5685
5686 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5687 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
5688 xerrno);
5689
5690 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5691 reason, NULL);
5692
5693 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5694 resp->payload = ptr;
5695 resp->payload_sz = (bufsz - buflen);
5696
5697 return fxp_packet_write(resp);
5698 }
5699
5700 pr_trace_msg(trace_channel, 8,
5701 "sending response: EXTENDED_REPLY (%lu bytes)", (unsigned long) res);
5702
5703 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
5704 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
5705 sftp_msg_write_data(&buf, &buflen, val, res, TRUE);
5706
5707 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5708 resp->payload = ptr;
5709 resp->payload_sz = (bufsz - buflen);
5710
5711 return fxp_packet_write(resp);
5712 }
5713
fxp_handle_ext_listxattr(struct fxp_packet * fxp,const char * path)5714 static int fxp_handle_ext_listxattr(struct fxp_packet *fxp, const char *path) {
5715 register unsigned int i;
5716 int res;
5717 unsigned char *buf, *ptr;
5718 uint32_t buflen, bufsz, status_code;
5719 const char *reason;
5720 struct fxp_packet *resp;
5721 array_header *names = NULL;
5722
5723 buflen = bufsz = FXP_RESPONSE_NAME_DEFAULT_SZ;
5724 buf = ptr = palloc(fxp->pool, bufsz);
5725
5726 res = pr_fsio_llistxattr(fxp->pool, path, &names);
5727 if (res < 0) {
5728 int xerrno = errno;
5729
5730 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5731 "listxattr(2) error on '%s': %s", path, strerror(xerrno));
5732
5733 status_code = fxp_errno2status(xerrno, &reason);
5734
5735 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5736 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
5737 xerrno);
5738
5739 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5740 reason, NULL);
5741
5742 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5743 resp->payload = ptr;
5744 resp->payload_sz = (bufsz - buflen);
5745
5746 return fxp_packet_write(resp);
5747 }
5748
5749 pr_trace_msg(trace_channel, 8,
5750 "sending response: EXTENDED_REPLY (%d attribute names)", names->nelts);
5751
5752 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
5753 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
5754 sftp_msg_write_int(&buf, &buflen, names->nelts);
5755 for (i = 0; i < names->nelts; i++) {
5756 const char *name;
5757
5758 name = ((const char **) names->elts)[i];
5759 sftp_msg_write_string(&buf, &buflen, name);
5760 }
5761
5762 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5763 resp->payload = ptr;
5764 resp->payload_sz = (bufsz - buflen);
5765
5766 return fxp_packet_write(resp);
5767 }
5768
fxp_handle_ext_flistxattr(struct fxp_packet * fxp,const char * handle)5769 static int fxp_handle_ext_flistxattr(struct fxp_packet *fxp,
5770 const char *handle) {
5771 register unsigned int i;
5772 int res;
5773 unsigned char *buf, *ptr;
5774 uint32_t buflen, bufsz, status_code;
5775 const char *path, *reason;
5776 struct fxp_handle *fxh;
5777 struct fxp_packet *resp;
5778 array_header *names = NULL;
5779
5780 buflen = bufsz = FXP_RESPONSE_NAME_DEFAULT_SZ;
5781 buf = ptr = palloc(fxp->pool, bufsz);
5782
5783 fxh = fxp_handle_get(handle);
5784 if (fxh == NULL) {
5785 pr_trace_msg(trace_channel, 17,
5786 "flistxattr@proftpd.org: unable to find handle for name '%s': %s", handle,
5787 strerror(errno));
5788
5789 status_code = SSH2_FX_INVALID_HANDLE;
5790
5791 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5792 (unsigned long) status_code, fxp_strerror(status_code));
5793
5794 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5795 fxp_strerror(status_code), NULL);
5796
5797 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5798 resp->payload = ptr;
5799 resp->payload_sz = (bufsz - buflen);
5800
5801 return fxp_packet_write(resp);
5802 }
5803
5804 if (fxh->dirh != NULL) {
5805 /* Request for extended attributes on a directory handle. It's not
5806 * easy to get the file descriptor on a directory, so we'll just do
5807 * by path instead.
5808 */
5809 return fxp_handle_ext_listxattr(fxp, fxh->fh->fh_path);
5810 }
5811
5812 if (fxh->fh == NULL) {
5813 status_code = SSH2_FX_INVALID_HANDLE;
5814
5815 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5816 (unsigned long) status_code, fxp_strerror(status_code));
5817
5818 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5819 fxp_strerror(status_code), NULL);
5820
5821 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5822 resp->payload = ptr;
5823 resp->payload_sz = (bufsz - buflen);
5824
5825 return fxp_packet_write(resp);
5826 }
5827
5828 path = fxh->fh->fh_path;
5829 res = pr_fsio_flistxattr(fxp->pool, fxh->fh, &names);
5830 if (res < 0) {
5831 int xerrno = errno;
5832
5833 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5834 "flistxattr(2) error on '%s': %s", path, strerror(xerrno));
5835
5836 status_code = fxp_errno2status(xerrno, &reason);
5837
5838 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5839 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
5840 xerrno);
5841
5842 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5843 reason, NULL);
5844
5845 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5846 resp->payload = ptr;
5847 resp->payload_sz = (bufsz - buflen);
5848
5849 return fxp_packet_write(resp);
5850 }
5851
5852 pr_trace_msg(trace_channel, 8,
5853 "sending response: EXTENDED_REPLY (%d attributes)", names->nelts);
5854
5855 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_EXTENDED_REPLY);
5856 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
5857 sftp_msg_write_int(&buf, &buflen, names->nelts);
5858 for (i = 0; i < names->nelts; i++) {
5859 const char *name;
5860
5861 name = ((const char **) names->elts)[i];
5862 sftp_msg_write_string(&buf, &buflen, name);
5863 }
5864
5865 sftp_msg_write_data(&buf, &buflen, (const unsigned char *) names, res, TRUE);
5866
5867 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5868 resp->payload = ptr;
5869 resp->payload_sz = (bufsz - buflen);
5870
5871 return fxp_packet_write(resp);
5872 }
5873
fxp_handle_ext_removexattr(struct fxp_packet * fxp,const char * path,const char * name)5874 static int fxp_handle_ext_removexattr(struct fxp_packet *fxp, const char *path,
5875 const char *name) {
5876 int res;
5877 unsigned char *buf, *ptr;
5878 uint32_t buflen, bufsz, status_code;
5879 const char *reason;
5880 struct fxp_packet *resp;
5881
5882 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
5883 buf = ptr = palloc(fxp->pool, bufsz);
5884
5885 res = pr_fsio_lremovexattr(fxp->pool, path, name);
5886 if (res < 0) {
5887 int xerrno = errno;
5888
5889 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5890 "removexattr(2) error on '%s' for attribute '%s': %s", path, name,
5891 strerror(xerrno));
5892
5893 status_code = fxp_errno2status(xerrno, &reason);
5894
5895 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5896 "('%s' [%d])", (unsigned long) status_code, reason,
5897 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
5898
5899 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5900 reason, NULL);
5901
5902 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5903 resp->payload = ptr;
5904 resp->payload_sz = (bufsz - buflen);
5905
5906 return fxp_packet_write(resp);
5907 }
5908
5909 status_code = SSH2_FX_OK;
5910 reason = "OK";
5911
5912 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5913 (unsigned long) status_code, reason);
5914
5915 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5916 reason, NULL);
5917
5918 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5919 resp->payload = ptr;
5920 resp->payload_sz = (bufsz - buflen);
5921
5922 return fxp_packet_write(resp);
5923 }
5924
fxp_handle_ext_fremovexattr(struct fxp_packet * fxp,const char * handle,const char * name)5925 static int fxp_handle_ext_fremovexattr(struct fxp_packet *fxp,
5926 const char *handle, const char *name) {
5927 int res;
5928 unsigned char *buf, *ptr;
5929 uint32_t buflen, bufsz, status_code;
5930 const char *path, *reason;
5931 struct fxp_handle *fxh;
5932 struct fxp_packet *resp;
5933
5934 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
5935 buf = ptr = palloc(fxp->pool, bufsz);
5936
5937 fxh = fxp_handle_get(handle);
5938 if (fxh == NULL) {
5939 pr_trace_msg(trace_channel, 17,
5940 "fremovexattr@proftpd.org: unable to find handle for name '%s': %s",
5941 handle, strerror(errno));
5942
5943 status_code = SSH2_FX_INVALID_HANDLE;
5944
5945 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5946 (unsigned long) status_code, fxp_strerror(status_code));
5947
5948 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5949 fxp_strerror(status_code), NULL);
5950
5951 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5952 resp->payload = ptr;
5953 resp->payload_sz = (bufsz - buflen);
5954
5955 return fxp_packet_write(resp);
5956 }
5957
5958 if (fxh->dirh != NULL) {
5959 /* Request for extended attributes on a directory handle. It's not
5960 * easy to get the file descriptor on a directory, so we'll just do
5961 * by path instead.
5962 */
5963 return fxp_handle_ext_removexattr(fxp, fxh->fh->fh_path, name);
5964 }
5965
5966 if (fxh->fh == NULL) {
5967 status_code = SSH2_FX_INVALID_HANDLE;
5968
5969 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
5970 (unsigned long) status_code, fxp_strerror(status_code));
5971
5972 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5973 fxp_strerror(status_code), NULL);
5974
5975 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
5976 resp->payload = ptr;
5977 resp->payload_sz = (bufsz - buflen);
5978
5979 return fxp_packet_write(resp);
5980 }
5981
5982 path = fxh->fh->fh_path;
5983
5984 res = pr_fsio_fremovexattr(fxp->pool, fxh->fh, name);
5985 if (res < 0) {
5986 int xerrno = errno;
5987
5988 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
5989 "fremovexattr(2) error on '%s' for attribute '%s': %s", path, name,
5990 strerror(xerrno));
5991
5992 status_code = fxp_errno2status(xerrno, &reason);
5993
5994 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
5995 "('%s' [%d])", (unsigned long) status_code, reason,
5996 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
5997
5998 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
5999 reason, NULL);
6000
6001 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6002 resp->payload = ptr;
6003 resp->payload_sz = (bufsz - buflen);
6004
6005 return fxp_packet_write(resp);
6006 }
6007
6008 status_code = SSH2_FX_OK;
6009 reason = "OK";
6010
6011 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6012 (unsigned long) status_code, reason);
6013
6014 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6015 reason, NULL);
6016
6017 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6018 resp->payload = ptr;
6019 resp->payload_sz = (bufsz - buflen);
6020
6021 return fxp_packet_write(resp);
6022 }
6023
fxp_handle_ext_setxattr(struct fxp_packet * fxp,const char * path,const char * name,void * val,uint32_t valsz,uint32_t pflags)6024 static int fxp_handle_ext_setxattr(struct fxp_packet *fxp, const char *path,
6025 const char *name, void *val, uint32_t valsz, uint32_t pflags) {
6026 int res, flags = 0;
6027 unsigned char *buf, *ptr;
6028 uint32_t buflen, bufsz, status_code;
6029 const char *reason;
6030 struct fxp_packet *resp;
6031
6032 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
6033 buf = ptr = palloc(fxp->pool, bufsz);
6034
6035 if (pflags & SSH2_FXE_XATTR_CREATE) {
6036 flags |= PR_FSIO_XATTR_FL_CREATE;
6037 }
6038
6039 if (pflags & SSH2_FXE_XATTR_REPLACE) {
6040 flags |= PR_FSIO_XATTR_FL_REPLACE;
6041 }
6042
6043 res = pr_fsio_lsetxattr(fxp->pool, path, name, val, (size_t) valsz, flags);
6044 if (res < 0) {
6045 int xerrno = errno;
6046
6047 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6048 "setxattr(2) error on '%s' for attribute '%s': %s", path, name,
6049 strerror(xerrno));
6050
6051 status_code = fxp_errno2status(xerrno, &reason);
6052
6053 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
6054 "('%s' [%d])", (unsigned long) status_code, reason,
6055 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
6056
6057 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6058 reason, NULL);
6059
6060 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6061 resp->payload = ptr;
6062 resp->payload_sz = (bufsz - buflen);
6063
6064 return fxp_packet_write(resp);
6065 }
6066
6067 status_code = SSH2_FX_OK;
6068 reason = "OK";
6069
6070 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6071 (unsigned long) status_code, reason);
6072
6073 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6074 reason, NULL);
6075
6076 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6077 resp->payload = ptr;
6078 resp->payload_sz = (bufsz - buflen);
6079
6080 return fxp_packet_write(resp);
6081 }
6082
fxp_handle_ext_fsetxattr(struct fxp_packet * fxp,const char * handle,const char * name,void * val,uint32_t valsz,uint32_t pflags)6083 static int fxp_handle_ext_fsetxattr(struct fxp_packet *fxp, const char *handle,
6084 const char *name, void *val, uint32_t valsz, uint32_t pflags) {
6085 int res, flags = 0;
6086 unsigned char *buf, *ptr;
6087 uint32_t buflen, bufsz, status_code;
6088 const char *path, *reason;
6089 struct fxp_handle *fxh;
6090 struct fxp_packet *resp;
6091
6092 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
6093 buf = ptr = palloc(fxp->pool, bufsz);
6094
6095 fxh = fxp_handle_get(handle);
6096 if (fxh == NULL) {
6097 pr_trace_msg(trace_channel, 17,
6098 "fsetxattr@proftpd.org: unable to find handle for name '%s': %s", handle,
6099 strerror(errno));
6100
6101 status_code = SSH2_FX_INVALID_HANDLE;
6102
6103 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6104 (unsigned long) status_code, fxp_strerror(status_code));
6105
6106 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6107 fxp_strerror(status_code), NULL);
6108
6109 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6110 resp->payload = ptr;
6111 resp->payload_sz = (bufsz - buflen);
6112
6113 return fxp_packet_write(resp);
6114 }
6115
6116 if (fxh->dirh != NULL) {
6117 /* Request for extended attributes on a directory handle. It's not
6118 * easy to get the file descriptor on a directory, so we'll just do
6119 * by path instead.
6120 */
6121 return fxp_handle_ext_setxattr(fxp, fxh->fh->fh_path, name, val, valsz,
6122 pflags);
6123 }
6124
6125 if (fxh->fh == NULL) {
6126 status_code = SSH2_FX_INVALID_HANDLE;
6127
6128 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6129 (unsigned long) status_code, fxp_strerror(status_code));
6130
6131 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6132 fxp_strerror(status_code), NULL);
6133
6134 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6135 resp->payload = ptr;
6136 resp->payload_sz = (bufsz - buflen);
6137
6138 return fxp_packet_write(resp);
6139 }
6140
6141 if (pflags & SSH2_FXE_XATTR_CREATE) {
6142 flags |= PR_FSIO_XATTR_FL_CREATE;
6143 }
6144
6145 if (pflags & SSH2_FXE_XATTR_REPLACE) {
6146 flags |= PR_FSIO_XATTR_FL_REPLACE;
6147 }
6148
6149 path = fxh->fh->fh_path;
6150
6151 res = pr_fsio_fsetxattr(fxp->pool, fxh->fh, name, val, (size_t) valsz, flags);
6152 if (res < 0) {
6153 int xerrno = errno;
6154
6155 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6156 "fsetxattr(2) error on '%s' for attribute '%s': %s", path, name,
6157 strerror(xerrno));
6158
6159 status_code = fxp_errno2status(xerrno, &reason);
6160
6161 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
6162 "('%s' [%d])", (unsigned long) status_code, reason,
6163 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
6164
6165 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6166 reason, NULL);
6167
6168 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6169 resp->payload = ptr;
6170 resp->payload_sz = (bufsz - buflen);
6171
6172 return fxp_packet_write(resp);
6173 }
6174
6175 status_code = SSH2_FX_OK;
6176 reason = "OK";
6177
6178 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6179 (unsigned long) status_code, reason);
6180
6181 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6182 reason, NULL);
6183
6184 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6185 resp->payload = ptr;
6186 resp->payload_sz = (bufsz - buflen);
6187
6188 return fxp_packet_write(resp);
6189 }
6190 #endif /* PR_USE_XATTR */
6191
fxp_handle_ext_vendor_id(struct fxp_packet * fxp)6192 static int fxp_handle_ext_vendor_id(struct fxp_packet *fxp) {
6193 unsigned char *buf, *ptr;
6194 char *vendor_name, *product_name, *product_version;
6195 uint32_t buflen, bufsz, status_code;
6196 uint64_t build_number;
6197 const char *reason;
6198 struct fxp_packet *resp;
6199
6200 vendor_name = sftp_msg_read_string(fxp->pool, &fxp->payload,
6201 &fxp->payload_sz);
6202
6203 product_name = sftp_msg_read_string(fxp->pool, &fxp->payload,
6204 &fxp->payload_sz);
6205
6206 product_version = sftp_msg_read_string(fxp->pool, &fxp->payload,
6207 &fxp->payload_sz);
6208
6209 build_number = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
6210
6211 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
6212 vendor_name = sftp_utf8_decode_str(fxp->pool, vendor_name);
6213 product_name = sftp_utf8_decode_str(fxp->pool, product_name);
6214 product_version = sftp_utf8_decode_str(fxp->pool, product_version);
6215 }
6216
6217 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6218 "client sent 'vendor-id' extension: { vendorName = '%s', "
6219 "productName = '%s', productVersion = '%s', buildNumber = %" PR_LU " }",
6220 vendor_name, product_name, product_version, (pr_off_t) build_number);
6221
6222 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
6223 buf = ptr = palloc(fxp->pool, bufsz);
6224
6225 status_code = SSH2_FX_OK;
6226 reason = "OK";
6227
6228 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6229 (unsigned long) status_code, reason);
6230
6231 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6232 reason, NULL);
6233
6234 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6235 resp->payload = ptr;
6236 resp->payload_sz = (bufsz - buflen);
6237
6238 return fxp_packet_write(resp);
6239 }
6240
fxp_handle_ext_version_select(struct fxp_packet * fxp,char * version_str)6241 static int fxp_handle_ext_version_select(struct fxp_packet *fxp,
6242 char *version_str) {
6243 unsigned char *buf, *ptr;
6244 uint32_t buflen, bufsz, status_code;
6245 const char *reason;
6246 struct fxp_packet *resp;
6247 int res = 0, val = 0;
6248 unsigned int version = 0;
6249
6250 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
6251 buf = ptr = palloc(fxp->pool, bufsz);
6252
6253 if (!allow_version_select) {
6254 int xerrno = EACCES;
6255
6256 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6257 "client sent 'version-select' request at inappropriate time, rejecting");
6258
6259 status_code = SSH2_FX_FAILURE;
6260 reason = "Failure";
6261
6262 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
6263 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
6264 xerrno);
6265
6266 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6267 reason, NULL);
6268
6269 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6270 resp->payload = ptr;
6271 resp->payload_sz = (bufsz - buflen);
6272
6273 (void) fxp_packet_write(resp);
6274
6275 errno = EINVAL;
6276 return -1;
6277 }
6278
6279 val = atoi(version_str);
6280 if (val < 0) {
6281 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6282 "client requested invalid SFTP protocol version %d via 'version-select'",
6283 val);
6284 res = -1;
6285 }
6286
6287 version = val;
6288
6289 if (res == 0 &&
6290 version > fxp_max_client_version) {
6291 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6292 "client requested SFTP protocol version %u via 'version-select', "
6293 "which exceeds SFTPClientMatch max SFTP protocol version %u, rejecting",
6294 version, fxp_max_client_version);
6295 res = -1;
6296 }
6297
6298 if (res == 0 &&
6299 version < fxp_min_client_version) {
6300 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6301 "client requested SFTP protocol version %u via 'version-select', "
6302 "which is less than SFTPClientMatch min SFTP protocol version %u, "
6303 "rejecting", version, fxp_min_client_version);
6304 res = -1;
6305 }
6306
6307 #ifndef PR_USE_NLS
6308 /* If NLS supported was enabled in the proftpd build, then we can support
6309 * UTF8, and thus every other version of SFTP. Otherwise, we can only
6310 * support up to version 3.
6311 */
6312 if (res == 0 &&
6313 version > 3) {
6314 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6315 "client requested SFTP protocol version %u via 'version-select', "
6316 "but we can only support protocol version 3 due to lack of "
6317 "UTF8 support (requires --enable-nls)", version);
6318 res = -1;
6319 }
6320 #endif
6321
6322 if (res < 0) {
6323 int xerrno = EINVAL;
6324
6325 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6326 "client sent 'version-select' request at inappropriate time, rejecting");
6327
6328 status_code = fxp_errno2status(xerrno, &reason);
6329
6330 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
6331 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
6332 xerrno);
6333
6334 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6335 reason, NULL);
6336
6337 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6338 resp->payload = ptr;
6339 resp->payload_sz = (bufsz - buflen);
6340
6341 (void) fxp_packet_write(resp);
6342
6343 errno = EINVAL;
6344 return -1;
6345 }
6346
6347 pr_trace_msg(trace_channel, 7, "client requested switch to SFTP protocol "
6348 "version %u via 'version-select'", version);
6349 fxp_session->client_version = (unsigned long) version;
6350
6351 status_code = SSH2_FX_OK;
6352 reason = "OK";
6353
6354 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6355 (unsigned long) status_code, reason);
6356
6357 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6358 reason, NULL);
6359
6360 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6361 resp->payload = ptr;
6362 resp->payload_sz = (bufsz - buflen);
6363
6364 allow_version_select = FALSE;
6365 return fxp_packet_write(resp);
6366 }
6367
6368 /* Request handlers */
6369
fxp_handle_close(struct fxp_packet * fxp)6370 static int fxp_handle_close(struct fxp_packet *fxp) {
6371 int xerrno = 0, res = 0, xfer_direction = 0;
6372 unsigned char *buf, *ptr;
6373 char *name, *xfer_filename = NULL, *xfer_path = NULL;
6374 const char *reason;
6375 uint32_t buflen, bufsz, status_code;
6376 struct fxp_handle *fxh;
6377 struct fxp_packet *resp;
6378 cmd_rec *cmd;
6379 struct timeval xfer_start_time;
6380 off_t xfer_file_size = 0, xfer_total_bytes = 0;
6381
6382 xfer_start_time.tv_sec = xfer_start_time.tv_usec = 0;
6383
6384 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6385
6386 cmd = fxp_cmd_alloc(fxp->pool, "CLOSE", name);
6387
6388 /* Set the command class to MISC for now; we'll change it later to
6389 * READ or WRITE once we know which it is.
6390 */
6391 cmd->cmd_class = CL_MISC|CL_SFTP;
6392
6393 pr_scoreboard_entry_update(session.pid,
6394 PR_SCORE_CMD, "%s", "CLOSE", NULL, NULL);
6395 pr_scoreboard_entry_update(session.pid,
6396 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
6397
6398 pr_proctitle_set("%s - %s: CLOSE %s", session.user, session.proc_prefix,
6399 name);
6400
6401 pr_trace_msg(trace_channel, 7, "received request: CLOSE %s", name);
6402
6403 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
6404 buf = ptr = palloc(fxp->pool, bufsz);
6405
6406 fxh = fxp_handle_get(name);
6407 if (fxh == NULL) {
6408 pr_trace_msg(trace_channel, 17,
6409 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
6410 name, strerror(errno));
6411
6412 status_code = SSH2_FX_INVALID_HANDLE;
6413
6414 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6415 (unsigned long) status_code, fxp_strerror(status_code));
6416
6417 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6418 fxp_strerror(status_code), NULL);
6419
6420 fxp_cmd_dispatch_err(cmd);
6421
6422 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6423 resp->payload = ptr;
6424 resp->payload_sz = (bufsz - buflen);
6425
6426 return fxp_packet_write(resp);
6427 }
6428
6429 if (fxh->dirh == NULL &&
6430 fxh->fh == NULL) {
6431 status_code = SSH2_FX_INVALID_HANDLE;
6432
6433 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6434 (unsigned long) status_code, fxp_strerror(status_code));
6435
6436 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6437 fxp_strerror(status_code), NULL);
6438
6439 fxp_handle_delete(fxh);
6440 destroy_pool(fxh->pool);
6441
6442 fxp_cmd_dispatch_err(cmd);
6443
6444 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6445 resp->payload = ptr;
6446 resp->payload_sz = (bufsz - buflen);
6447
6448 return fxp_packet_write(resp);
6449 }
6450
6451 /* Add a note containing the file handle for logging (Bug#3707). */
6452 fxp_set_filehandle_note(cmd, fxh);
6453
6454 pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
6455
6456 if (fxh->fh != NULL) {
6457 char *curr_path = NULL, *real_path = NULL;
6458 cmd_rec *cmd2 = NULL;
6459
6460 curr_path = pstrdup(fxp->pool, fxh->fh->fh_path);
6461 real_path = curr_path;
6462
6463 if (fxh->fh_real_path) {
6464 real_path = fxh->fh_real_path;
6465 }
6466
6467 /* Set session.curr_cmd appropriately here, for any FSIO callbacks. */
6468 if (fxh->fh_flags & O_APPEND) {
6469 cmd->cmd_class &= ~CL_MISC;
6470 cmd->cmd_class |= CL_WRITE;
6471 session.curr_cmd = C_APPE;
6472
6473 } else if ((fxh->fh_flags & O_WRONLY) ||
6474 (fxh->fh_flags & O_RDWR)) {
6475 cmd->cmd_class &= ~CL_MISC;
6476 cmd->cmd_class |= CL_WRITE;
6477 session.curr_cmd = C_STOR;
6478
6479 } else if (fxh->fh_flags == O_RDONLY) {
6480 cmd->cmd_class &= ~CL_MISC;
6481 cmd->cmd_class |= CL_READ;
6482 session.curr_cmd = C_RETR;
6483 }
6484
6485 res = pr_fsio_close(fxh->fh);
6486 xerrno = errno;
6487
6488 session.curr_cmd = "CLOSE";
6489
6490 pr_scoreboard_entry_update(session.pid,
6491 PR_SCORE_CMD_ARG, "%s", real_path, NULL, NULL);
6492
6493 if (fxh->fh_real_path != NULL &&
6494 res == 0) {
6495 /* This is a HiddenStores file, and needs to be renamed to the real
6496 * path.
6497 */
6498
6499 pr_trace_msg(trace_channel, 8, "renaming HiddenStores path '%s' to '%s'",
6500 curr_path, real_path);
6501
6502 res = pr_fsio_rename(curr_path, real_path);
6503 if (res < 0) {
6504 xerrno = errno;
6505
6506 pr_log_pri(PR_LOG_WARNING, "Rename of %s to %s failed: %s",
6507 curr_path, real_path, strerror(xerrno));
6508
6509 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6510 "renaming of HiddenStore path '%s' to '%s' failed: %s",
6511 curr_path, real_path, strerror(xerrno));
6512
6513 pr_fsio_unlink(curr_path);
6514 }
6515 }
6516
6517 if (fxh->fh_flags & O_APPEND) {
6518 cmd2 = fxp_cmd_alloc(fxp->pool, C_APPE, pstrdup(fxp->pool, real_path));
6519 cmd2->cmd_id = pr_cmd_get_id(C_APPE);
6520
6521 if (pr_table_add(cmd2->notes, "mod_xfer.store-path",
6522 pstrdup(fxp->pool, real_path), 0) < 0) {
6523 if (errno != EEXIST) {
6524 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6525 "error adding 'mod_xfer.store-path' note: %s", strerror(errno));
6526 }
6527 }
6528
6529 } else if ((fxh->fh_flags & O_WRONLY) ||
6530 (fxh->fh_flags & O_RDWR)) {
6531 cmd2 = fxp_cmd_alloc(fxp->pool, C_STOR, pstrdup(fxp->pool, real_path));
6532 cmd2->cmd_id = pr_cmd_get_id(C_STOR);
6533
6534 if (pr_table_add(cmd2->notes, "mod_xfer.store-path",
6535 pstrdup(fxp->pool, real_path), 0) < 0) {
6536 if (errno != EEXIST) {
6537 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6538 "error adding 'mod_xfer.store-path' note: %s", strerror(errno));
6539 }
6540 }
6541
6542 } else if (fxh->fh_flags == O_RDONLY) {
6543 cmd2 = fxp_cmd_alloc(fxp->pool, C_RETR, pstrdup(fxp->pool, real_path));
6544 cmd2->cmd_id = pr_cmd_get_id(C_RETR);
6545
6546 if (pr_table_add(cmd2->notes, "mod_xfer.retr-path",
6547 pstrdup(fxp->pool, real_path), 0) < 0) {
6548 if (errno != EEXIST) {
6549 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6550 "error adding 'mod_xfer.retr-path' note: %s", strerror(errno));
6551 }
6552 }
6553 }
6554
6555 fxh->fh = NULL;
6556
6557 /* Before we dispatch to the RETR/STOR handlers, make a copy of the
6558 * session.xfer.path variable (and others). The RETR/STOR handlers will
6559 * clear out the session.xfer.p pool, but we will want to put that path
6560 * back, after the RETR/STOR handlers, for the sake of logging e.g. a %f
6561 * LogFormat variable for the CLOSE request.
6562 */
6563
6564 xfer_direction = session.xfer.direction;
6565 xfer_filename = pstrdup(fxp->pool, session.xfer.filename);
6566 xfer_path = pstrdup(fxp->pool, session.xfer.path);
6567 memcpy(&xfer_start_time, &(session.xfer.start_time),
6568 sizeof(struct timeval));
6569 xfer_file_size = session.xfer.file_size;
6570 xfer_total_bytes = session.xfer.total_bytes;
6571
6572 if (cmd2) {
6573 if (fxh->fh_existed &&
6574 (pr_cmd_cmp(cmd2, PR_CMD_STOR_ID) == 0 ||
6575 pr_cmd_cmp(cmd2, PR_CMD_APPE_ID) == 0)) {
6576
6577 /* Clear any existing key in the notes. */
6578 (void) pr_table_remove(cmd->notes, "mod_xfer.file-modified", NULL);
6579
6580 if (pr_table_add(cmd->notes, "mod_xfer.file-modified",
6581 pstrdup(cmd->pool, "true"), 0) < 0) {
6582 if (errno != EEXIST) {
6583 pr_log_pri(PR_LOG_NOTICE,
6584 "notice: error adding 'mod_xfer.file-modified' note: %s",
6585 strerror(errno));
6586 }
6587 }
6588
6589 /* Clear any existing key in the notes. */
6590 (void) pr_table_remove(cmd2->notes, "mod_xfer.file-modified", NULL);
6591
6592 if (pr_table_add(cmd2->notes, "mod_xfer.file-modified",
6593 pstrdup(cmd2->pool, "true"), 0) < 0) {
6594 if (errno != EEXIST) {
6595 pr_log_pri(PR_LOG_NOTICE,
6596 "notice: error adding 'mod_xfer.file-modified' note: %s",
6597 strerror(errno));
6598 }
6599 }
6600 }
6601
6602 if (res < 0 &&
6603 xerrno != EOF) {
6604
6605 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
6606 fxp_cmd_dispatch_err(cmd2);
6607
6608 } else {
6609 pr_response_add(R_226, "%s", "Transfer complete");
6610 fxp_cmd_dispatch(cmd2);
6611 }
6612 }
6613
6614 } else if (fxh->dirh != NULL) {
6615 cmd_rec *cmd2;
6616
6617 cmd2 = fxp_cmd_alloc(fxp->pool, C_MLSD, (char *) fxh->dir);
6618 cmd2->cmd_class = CL_DIRS;
6619 cmd2->cmd_id = pr_cmd_get_id(C_MLSD);
6620
6621 pr_scoreboard_entry_update(session.pid,
6622 PR_SCORE_CMD_ARG, "%s", fxh->dir, NULL, NULL);
6623
6624 res = pr_fsio_closedir(fxh->dirh);
6625 if (res < 0) {
6626 xerrno = errno;
6627
6628 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
6629 "error closing directory '%s': %s", fxh->dir, strerror(xerrno));
6630 fxp_cmd_dispatch_err(cmd2);
6631
6632 } else {
6633 fxp_cmd_dispatch(cmd2);
6634 }
6635
6636 fxh->dirh = NULL;
6637 }
6638
6639 if (res < 0) {
6640 status_code = fxp_errno2status(xerrno, &reason);
6641
6642 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
6643 "('%s' [%d])", (unsigned long) status_code, reason,
6644 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
6645
6646 } else {
6647 errno = 0;
6648 status_code = fxp_errno2status(0, &reason);
6649
6650 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6651 (unsigned long) status_code, reason);
6652 }
6653
6654 fxp_handle_delete(fxh);
6655 destroy_pool(fxh->pool);
6656
6657 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6658 reason, NULL);
6659
6660 /* Now re-populate the session.xfer struct, for mod_log's handling of
6661 * the CLOSE request.
6662 */
6663 if (session.xfer.p) {
6664 destroy_pool(session.xfer.p);
6665 }
6666
6667 session.xfer.p = fxp->pool;
6668 session.xfer.direction = xfer_direction;
6669 session.xfer.filename = xfer_filename;
6670 session.xfer.path = xfer_path;
6671 memcpy(&(session.xfer.start_time), &xfer_start_time, sizeof(struct timeval));
6672 session.xfer.file_size = xfer_file_size;
6673 session.xfer.total_bytes = xfer_total_bytes;
6674
6675 if (res < 0) {
6676 fxp_cmd_dispatch_err(cmd);
6677
6678 } else {
6679 fxp_cmd_dispatch(cmd);
6680 }
6681
6682 /* Clear out session.xfer again. */
6683 memset(&session.xfer, 0, sizeof(session.xfer));
6684
6685 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6686 resp->payload = ptr;
6687 resp->payload_sz = (bufsz - buflen);
6688
6689 return fxp_packet_write(resp);
6690 }
6691
fxp_handle_extended(struct fxp_packet * fxp)6692 static int fxp_handle_extended(struct fxp_packet *fxp) {
6693 int res;
6694 unsigned char *buf, *ptr;
6695 char *ext_request_name;
6696 uint32_t buflen, bufsz, status_code;
6697 struct fxp_packet *resp;
6698 cmd_rec *cmd;
6699
6700 ext_request_name = sftp_msg_read_string(fxp->pool, &fxp->payload,
6701 &fxp->payload_sz);
6702
6703 cmd = fxp_cmd_alloc(fxp->pool, "EXTENDED", ext_request_name);
6704 cmd->cmd_class = CL_MISC|CL_SFTP;
6705
6706 pr_scoreboard_entry_update(session.pid,
6707 PR_SCORE_CMD, "%s", "EXTENDED", NULL, NULL);
6708 pr_scoreboard_entry_update(session.pid,
6709 PR_SCORE_CMD_ARG, "%s", ext_request_name, NULL, NULL);
6710
6711 pr_proctitle_set("%s - %s: EXTENDED %s", session.user, session.proc_prefix,
6712 ext_request_name);
6713
6714 pr_trace_msg(trace_channel, 7, "received request: EXTENDED %s",
6715 ext_request_name);
6716
6717 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
6718 buf = ptr = palloc(fxp->pool, bufsz);
6719
6720 /* We always handle an EXTENDED vendor-id request from the client; the
6721 * client is telling us its vendor information; it is not requesting that
6722 * we send our vendor information.
6723 */
6724 if (strncmp(ext_request_name, "vendor-id", 10) == 0) {
6725 res = fxp_handle_ext_vendor_id(fxp);
6726 if (res == 0) {
6727 fxp_cmd_dispatch(cmd);
6728
6729 } else {
6730 fxp_cmd_dispatch_err(cmd);
6731 }
6732
6733 return res;
6734 }
6735
6736 if ((fxp_ext_flags & SFTP_FXP_EXT_VERSION_SELECT) &&
6737 strncmp(ext_request_name, "version-select", 15) == 0) {
6738 char *version_str;
6739
6740 version_str = sftp_msg_read_string(fxp->pool, &fxp->payload,
6741 &fxp->payload_sz);
6742
6743 res = fxp_handle_ext_version_select(fxp, version_str);
6744 if (res == 0) {
6745 fxp_cmd_dispatch(cmd);
6746
6747 } else {
6748 fxp_cmd_dispatch_err(cmd);
6749 }
6750
6751 return res;
6752 }
6753
6754 if ((fxp_ext_flags & SFTP_FXP_EXT_CHECK_FILE) &&
6755 strncmp(ext_request_name, "check-file-name", 16) == 0) {
6756 char *path, *digest_list;
6757 off_t offset, len;
6758 uint32_t blocksz;
6759
6760 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6761 digest_list = sftp_msg_read_string(fxp->pool, &fxp->payload,
6762 &fxp->payload_sz);
6763 offset = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
6764 len = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
6765 blocksz = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
6766
6767 res = fxp_handle_ext_check_file(fxp, digest_list, path, offset, len,
6768 blocksz);
6769 if (res == 0) {
6770 fxp_cmd_dispatch(cmd);
6771
6772 } else {
6773 fxp_cmd_dispatch_err(cmd);
6774 }
6775
6776 return res;
6777 }
6778
6779 if ((fxp_ext_flags & SFTP_FXP_EXT_CHECK_FILE) &&
6780 strncmp(ext_request_name, "check-file-handle", 18) == 0) {
6781 char *handle, *path, *digest_list;
6782 off_t offset, len;
6783 uint32_t blocksz;
6784 struct fxp_handle *fxh;
6785
6786 handle = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6787
6788 fxh = fxp_handle_get(handle);
6789 if (fxh == NULL ||
6790 fxh->dirh != NULL) {
6791 status_code = SSH2_FX_INVALID_HANDLE;
6792
6793 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6794 (unsigned long) status_code, fxp_strerror(status_code));
6795
6796 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6797 fxp_strerror(status_code), NULL);
6798
6799 fxp_cmd_dispatch_err(cmd);
6800
6801 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6802 resp->payload = ptr;
6803 resp->payload_sz = (bufsz - buflen);
6804
6805 return fxp_packet_write(resp);
6806 }
6807
6808 /* Make sure the file was opened with read permissions; if it was opened
6809 * write-only, for example, we need to return EACCES.
6810 */
6811 if (fxh->fh_flags & O_WRONLY) {
6812 status_code = SSH2_FX_PERMISSION_DENIED;
6813
6814 pr_trace_msg(trace_channel, 9, "file %s opened write-only, "
6815 "unable to obtain file checksum (%s)", fxh->fh->fh_path,
6816 strerror(EACCES));
6817
6818 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6819 (unsigned long) status_code, fxp_strerror(status_code));
6820
6821 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6822 fxp_strerror(status_code), NULL);
6823
6824 fxp_cmd_dispatch_err(cmd);
6825
6826 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6827 resp->payload = ptr;
6828 resp->payload_sz = (bufsz - buflen);
6829
6830 return fxp_packet_write(resp);
6831 }
6832
6833 path = fxh->fh->fh_path;
6834
6835 digest_list = sftp_msg_read_string(fxp->pool, &fxp->payload,
6836 &fxp->payload_sz);
6837 offset = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
6838 len = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
6839 blocksz = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
6840
6841 res = fxp_handle_ext_check_file(fxp, digest_list, path, offset, len,
6842 blocksz);
6843 if (res == 0) {
6844 fxp_cmd_dispatch(cmd);
6845
6846 } else {
6847 fxp_cmd_dispatch_err(cmd);
6848 }
6849
6850 return res;
6851 }
6852
6853 if ((fxp_ext_flags & SFTP_FXP_EXT_COPY_FILE) &&
6854 strncmp(ext_request_name, "copy-file", 10) == 0) {
6855 char *src, *dst;
6856 int overwrite;
6857
6858 src = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6859 dst = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6860 overwrite = sftp_msg_read_bool(fxp->pool, &fxp->payload, &fxp->payload_sz);
6861
6862 res = fxp_handle_ext_copy_file(fxp, src, dst, overwrite);
6863 if (res == 0) {
6864 fxp_cmd_dispatch(cmd);
6865
6866 } else {
6867 fxp_cmd_dispatch_err(cmd);
6868 }
6869
6870 return res;
6871 }
6872
6873 if ((fxp_ext_flags & SFTP_FXP_EXT_FSYNC) &&
6874 strncmp(ext_request_name, "fsync@openssh.com", 18) == 0) {
6875 const char *handle;
6876 struct fxp_handle *fxh;
6877
6878 handle = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6879
6880 fxh = fxp_handle_get(handle);
6881 if (fxh == NULL) {
6882 pr_trace_msg(trace_channel, 17,
6883 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
6884 handle, strerror(errno));
6885
6886 status_code = SSH2_FX_INVALID_HANDLE;
6887
6888 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6889 (unsigned long) status_code, fxp_strerror(status_code));
6890
6891 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6892 fxp_strerror(status_code), NULL);
6893
6894 fxp_cmd_dispatch_err(cmd);
6895
6896 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6897 resp->payload = ptr;
6898 resp->payload_sz = (bufsz - buflen);
6899
6900 return fxp_packet_write(resp);
6901 }
6902
6903 if (fxh->fh == NULL) {
6904 errno = EISDIR;
6905
6906 pr_trace_msg(trace_channel, 17,
6907 "%s: handle '%s': %s", (char *) cmd->argv[0], handle, strerror(errno));
6908
6909 status_code = SSH2_FX_INVALID_HANDLE;
6910
6911 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
6912 (unsigned long) status_code, fxp_strerror(status_code));
6913
6914 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
6915 fxp_strerror(status_code), NULL);
6916
6917 fxp_cmd_dispatch_err(cmd);
6918
6919 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
6920 resp->payload = ptr;
6921 resp->payload_sz = (bufsz - buflen);
6922
6923 return fxp_packet_write(resp);
6924 }
6925
6926 res = fxp_handle_ext_fsync(fxp, fxh);
6927 if (res == 0) {
6928 fxp_cmd_dispatch(cmd);
6929
6930 } else {
6931 fxp_cmd_dispatch_err(cmd);
6932 }
6933
6934 return res;
6935 }
6936
6937 if ((fxp_ext_flags & SFTP_FXP_EXT_HARDLINK) &&
6938 strncmp(ext_request_name, "hardlink@openssh.com", 21) == 0) {
6939 char *src, *dst;
6940
6941 src = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6942 dst = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6943
6944 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
6945 src = sftp_utf8_decode_str(fxp->pool, src);
6946 dst = sftp_utf8_decode_str(fxp->pool, dst);
6947 }
6948
6949 res = fxp_handle_ext_hardlink(fxp, src, dst);
6950 if (res == 0) {
6951 fxp_cmd_dispatch(cmd);
6952
6953 } else {
6954 fxp_cmd_dispatch_err(cmd);
6955 }
6956
6957 return res;
6958 }
6959
6960 if ((fxp_ext_flags & SFTP_FXP_EXT_POSIX_RENAME) &&
6961 strncmp(ext_request_name, "posix-rename@openssh.com", 25) == 0) {
6962 char *src, *dst;
6963
6964 src = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6965 dst = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6966
6967 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
6968 src = sftp_utf8_decode_str(fxp->pool, src);
6969 dst = sftp_utf8_decode_str(fxp->pool, dst);
6970 }
6971
6972 res = fxp_handle_ext_posix_rename(fxp, src, dst);
6973 if (res == 0) {
6974 fxp_cmd_dispatch(cmd);
6975
6976 } else {
6977 fxp_cmd_dispatch_err(cmd);
6978 }
6979
6980 return res;
6981 }
6982
6983 #ifdef HAVE_SYS_STATVFS_H
6984 if ((fxp_ext_flags & SFTP_FXP_EXT_SPACE_AVAIL) &&
6985 strncmp(ext_request_name, "space-available", 16) == 0) {
6986 char *path;
6987
6988 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
6989
6990 res = fxp_handle_ext_space_avail(fxp, path);
6991 if (res == 0) {
6992 fxp_cmd_dispatch(cmd);
6993
6994 } else {
6995 fxp_cmd_dispatch_err(cmd);
6996 }
6997
6998 return res;
6999 }
7000
7001 if ((fxp_ext_flags & SFTP_FXP_EXT_STATVFS) &&
7002 strncmp(ext_request_name, "statvfs@openssh.com", 20) == 0) {
7003 const char *path;
7004
7005 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7006
7007 res = fxp_handle_ext_statvfs(fxp, path);
7008 if (res == 0) {
7009 fxp_cmd_dispatch(cmd);
7010
7011 } else {
7012 fxp_cmd_dispatch_err(cmd);
7013 }
7014
7015 return res;
7016 }
7017
7018 if ((fxp_ext_flags & SFTP_FXP_EXT_STATVFS) &&
7019 strncmp(ext_request_name, "fstatvfs@openssh.com", 21) == 0) {
7020 const char *handle, *path;
7021 struct fxp_handle *fxh;
7022
7023 handle = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7024
7025 fxh = fxp_handle_get(handle);
7026 if (fxh == NULL) {
7027 pr_trace_msg(trace_channel, 17,
7028 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
7029 handle, strerror(errno));
7030
7031 status_code = SSH2_FX_INVALID_HANDLE;
7032
7033 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7034 (unsigned long) status_code, fxp_strerror(status_code));
7035
7036 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7037 fxp_strerror(status_code), NULL);
7038
7039 fxp_cmd_dispatch_err(cmd);
7040
7041 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7042 resp->payload = ptr;
7043 resp->payload_sz = (bufsz - buflen);
7044
7045 return fxp_packet_write(resp);
7046 }
7047
7048 path = fxh->fh ? fxh->fh->fh_path : fxh->dir;
7049
7050 res = fxp_handle_ext_statvfs(fxp, path);
7051 if (res == 0) {
7052 fxp_cmd_dispatch(cmd);
7053
7054 } else {
7055 fxp_cmd_dispatch_err(cmd);
7056 }
7057
7058 return res;
7059 }
7060 #endif
7061
7062 #ifdef PR_USE_XATTR
7063 if (fxp_ext_flags & SFTP_FXP_EXT_XATTR) {
7064 if (strcmp(ext_request_name, "fgetxattr@proftpd.org") == 0) {
7065 const char *handle, *name;
7066 uint32_t valsz;
7067
7068 handle = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7069 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7070 valsz = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7071
7072 res = fxp_handle_ext_fgetxattr(fxp, handle, name, valsz);
7073 if (res == 0) {
7074 fxp_cmd_dispatch(cmd);
7075
7076 } else {
7077 fxp_cmd_dispatch_err(cmd);
7078 }
7079
7080 return res;
7081 }
7082
7083 if (strcmp(ext_request_name, "flistxattr@proftpd.org") == 0) {
7084 const char *handle;
7085
7086 handle = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7087
7088 res = fxp_handle_ext_flistxattr(fxp, handle);
7089 if (res == 0) {
7090 fxp_cmd_dispatch(cmd);
7091
7092 } else {
7093 fxp_cmd_dispatch_err(cmd);
7094 }
7095
7096 return res;
7097 }
7098
7099 if (strcmp(ext_request_name, "fremovexattr@proftpd.org") == 0) {
7100 const char *handle, *name;
7101
7102 handle = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7103 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7104
7105 res = fxp_handle_ext_fremovexattr(fxp, handle, name);
7106 if (res == 0) {
7107 fxp_cmd_dispatch(cmd);
7108
7109 } else {
7110 fxp_cmd_dispatch_err(cmd);
7111 }
7112
7113 return res;
7114 }
7115
7116 if (strcmp(ext_request_name, "fsetxattr@proftpd.org") == 0) {
7117 const char *handle, *name;
7118 void *val;
7119 uint32_t pflags, valsz;
7120
7121 handle = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7122 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7123 valsz = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7124 val = (void *) sftp_msg_read_data(fxp->pool, &fxp->payload,
7125 &fxp->payload_sz, valsz);
7126 pflags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7127
7128 res = fxp_handle_ext_fsetxattr(fxp, handle, name, val, valsz, pflags);
7129 if (res == 0) {
7130 fxp_cmd_dispatch(cmd);
7131
7132 } else {
7133 fxp_cmd_dispatch_err(cmd);
7134 }
7135
7136 return res;
7137 }
7138
7139 if (strcmp(ext_request_name, "getxattr@proftpd.org") == 0) {
7140 const char *path, *name;
7141 uint32_t valsz;
7142
7143 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7144 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7145 valsz = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7146
7147 res = fxp_handle_ext_getxattr(fxp, path, name, valsz);
7148 if (res == 0) {
7149 fxp_cmd_dispatch(cmd);
7150
7151 } else {
7152 fxp_cmd_dispatch_err(cmd);
7153 }
7154
7155 return res;
7156 }
7157
7158 if (strcmp(ext_request_name, "listxattr@proftpd.org") == 0) {
7159 const char *path;
7160
7161 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7162
7163 res = fxp_handle_ext_listxattr(fxp, path);
7164 if (res == 0) {
7165 fxp_cmd_dispatch(cmd);
7166
7167 } else {
7168 fxp_cmd_dispatch_err(cmd);
7169 }
7170
7171 return res;
7172 }
7173
7174 if (strcmp(ext_request_name, "removexattr@proftpd.org") == 0) {
7175 const char *path, *name;
7176
7177 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7178 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7179
7180 res = fxp_handle_ext_removexattr(fxp, path, name);
7181 if (res == 0) {
7182 fxp_cmd_dispatch(cmd);
7183
7184 } else {
7185 fxp_cmd_dispatch_err(cmd);
7186 }
7187
7188 return res;
7189 }
7190
7191 if (strcmp(ext_request_name, "setxattr@proftpd.org") == 0) {
7192 const char *path, *name;
7193 void *val;
7194 uint32_t pflags, valsz;
7195
7196 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7197 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7198 valsz = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7199 val = (void *) sftp_msg_read_data(fxp->pool, &fxp->payload,
7200 &fxp->payload_sz, valsz);
7201 pflags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7202
7203 res = fxp_handle_ext_setxattr(fxp, path, name, val, valsz, pflags);
7204 if (res == 0) {
7205 fxp_cmd_dispatch(cmd);
7206
7207 } else {
7208 fxp_cmd_dispatch_err(cmd);
7209 }
7210
7211 return res;
7212 }
7213 }
7214 #endif /* PR_USE_XATTR */
7215
7216 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7217 "client requested '%s' extension, rejecting", ext_request_name);
7218 status_code = SSH2_FX_OP_UNSUPPORTED;
7219
7220 fxp_cmd_dispatch_err(cmd);
7221
7222 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7223 (unsigned long) status_code, fxp_strerror(status_code));
7224
7225 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7226 fxp_strerror(status_code), NULL);
7227
7228 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7229 resp->payload = ptr;
7230 resp->payload_sz = (bufsz - buflen);
7231
7232 return fxp_packet_write(resp);
7233 }
7234
fxp_handle_fsetstat(struct fxp_packet * fxp)7235 static int fxp_handle_fsetstat(struct fxp_packet *fxp) {
7236 unsigned char *buf, *ptr;
7237 char *attrs_str, *cmd_name, *name, *path;
7238 const char *reason;
7239 uint32_t attr_flags, buflen, bufsz, status_code;
7240 int have_error = FALSE, res;
7241 struct stat *attrs;
7242 struct fxp_handle *fxh;
7243 struct fxp_packet *resp;
7244 cmd_rec *cmd;
7245 array_header *xattrs = NULL;
7246
7247 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7248
7249 cmd = fxp_cmd_alloc(fxp->pool, "FSETSTAT", name);
7250 cmd->cmd_class = CL_WRITE|CL_SFTP;
7251
7252 pr_scoreboard_entry_update(session.pid,
7253 PR_SCORE_CMD, "%s", "FSETSTAT", NULL, NULL);
7254 pr_scoreboard_entry_update(session.pid,
7255 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
7256
7257 attrs = fxp_attrs_read(fxp, &fxp->payload, &fxp->payload_sz, &attr_flags,
7258 &xattrs);
7259 if (attrs == NULL) {
7260 fxp_cmd_dispatch_err(cmd);
7261
7262 /* XXX TODO: Provide a response to the client here! */
7263 return 0;
7264 }
7265
7266 attrs_str = fxp_strattrs(fxp->pool, attrs, &attr_flags);
7267
7268 pr_proctitle_set("%s - %s: FSETSTAT %s %s", session.user, session.proc_prefix,
7269 name, attrs_str);
7270
7271 pr_trace_msg(trace_channel, 7, "received request: FSETSTAT %s %s", name,
7272 attrs_str);
7273
7274 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
7275 buf = ptr = palloc(fxp->pool, bufsz);
7276
7277 fxh = fxp_handle_get(name);
7278 if (fxh == NULL) {
7279 pr_trace_msg(trace_channel, 17,
7280 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
7281 name, strerror(errno));
7282
7283 status_code = SSH2_FX_INVALID_HANDLE;
7284
7285 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7286 (unsigned long) status_code, fxp_strerror(status_code));
7287
7288 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7289 fxp_strerror(status_code), NULL);
7290
7291 fxp_cmd_dispatch_err(cmd);
7292
7293 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7294 resp->payload = ptr;
7295 resp->payload_sz = (bufsz - buflen);
7296
7297 return fxp_packet_write(resp);
7298 }
7299
7300 /* Add a note containing the file handle for logging (Bug#3707). */
7301 fxp_set_filehandle_note(cmd, fxh);
7302
7303 cmd->arg = pstrdup(cmd->pool, (fxh->fh ? fxh->fh->fh_path : fxh->dir));
7304
7305 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
7306 status_code = SSH2_FX_PERMISSION_DENIED;
7307
7308 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7309 "FSETSTAT of '%s' blocked by '%s' handler", cmd->arg,
7310 (char *) cmd->argv[0]);
7311
7312 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7313 (unsigned long) status_code, fxp_strerror(status_code));
7314
7315 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7316 fxp_strerror(status_code), NULL);
7317
7318 fxp_cmd_dispatch_err(cmd);
7319
7320 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7321 resp->payload = ptr;
7322 resp->payload_sz = (bufsz - buflen);
7323
7324 return fxp_packet_write(resp);
7325 }
7326
7327 /* The path may have been changed by any PRE_CMD handlers. */
7328 path = dir_best_path(fxp->pool, cmd->arg);
7329 if (path == NULL) {
7330 status_code = SSH2_FX_PERMISSION_DENIED;
7331
7332 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7333 "FSETSTAT request denied: unable to access path '%s'", cmd->arg);
7334
7335 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7336 (unsigned long) status_code, fxp_strerror(status_code));
7337
7338 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7339 fxp_strerror(status_code), NULL);
7340
7341 fxp_cmd_dispatch_err(cmd);
7342
7343 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7344 resp->payload = ptr;
7345 resp->payload_sz = (bufsz - buflen);
7346
7347 return fxp_packet_write(resp);
7348 }
7349
7350 cmd_name = cmd->argv[0];
7351
7352 pr_cmd_set_name(cmd, "FSETSTAT");
7353 if (dir_check(fxp->pool, cmd, G_WRITE, path, NULL) > 0) {
7354 /* Explicitly allowed by <Limit FSETSTAT>. */
7355 have_error = FALSE;
7356
7357 } else {
7358 pr_cmd_set_name(cmd, "SETSTAT");
7359
7360 if (!dir_check(fxp->pool, cmd, G_WRITE, path, NULL)) {
7361 have_error = TRUE;
7362 }
7363 }
7364
7365 if (have_error) {
7366 status_code = SSH2_FX_PERMISSION_DENIED;
7367
7368 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7369 "FSETSTAT of '%s' blocked by <Limit %s> configuration", path,
7370 (char *) cmd->argv[0]);
7371
7372 pr_cmd_set_name(cmd, cmd_name);
7373
7374 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7375 (unsigned long) status_code, fxp_strerror(status_code));
7376
7377 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7378 fxp_strerror(status_code), NULL);
7379
7380 fxp_cmd_dispatch_err(cmd);
7381
7382 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7383 resp->payload = ptr;
7384 resp->payload_sz = (bufsz - buflen);
7385
7386 return fxp_packet_write(resp);
7387 }
7388 pr_cmd_set_name(cmd, cmd_name);
7389
7390 attr_flags = fxp_attrs_clear_unsupported(attr_flags);
7391
7392 /* If the SFTPOption for ignoring the owners for SFTP setstat requests is set,
7393 * handle it by clearing the SSH2_FX_ATTR_UIDGID and SSH2_FX_ATTR_OWNERGROUP
7394 * flags.
7395 */
7396 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_OWNERS) &&
7397 ((attr_flags & SSH2_FX_ATTR_UIDGID) ||
7398 (attr_flags & SSH2_FX_ATTR_OWNERGROUP))) {
7399 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPSetOwners' "
7400 "configured, ignoring ownership sent by client");
7401 attr_flags &= ~SSH2_FX_ATTR_UIDGID;
7402 attr_flags &= ~SSH2_FX_ATTR_OWNERGROUP;
7403 }
7404
7405 /* If the SFTPOption for ignoring the xattrs for SFTP setstat requests is set,
7406 * handle it by clearing the SSH2_FX_ATTR_EXTENDED flag.
7407 */
7408 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_XATTRS) &&
7409 (attr_flags & SSH2_FX_ATTR_EXTENDED)) {
7410 pr_trace_msg(trace_channel, 7,
7411 "SFTPOption 'IgnoreSFTPSetExtendedAttributes' configured, ignoring "
7412 "xattrs sent by client");
7413 attr_flags &= ~SSH2_FX_ATTR_EXTENDED;
7414 }
7415
7416 /* If the SFTPOption for ignoring the perms for SFTP setstat requests is set,
7417 * handle it by clearing the SSH2_FX_ATTR_PERMISSIONS flag.
7418 */
7419 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_PERMS) &&
7420 (attr_flags & SSH2_FX_ATTR_PERMISSIONS)) {
7421 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPSetPerms' "
7422 "configured, ignoring perms sent by client");
7423 attr_flags &= ~SSH2_FX_ATTR_PERMISSIONS;
7424 }
7425
7426 /* If the SFTPOption for ignoring the times for SFTP setstat requests is set,
7427 * handle it by clearing the time-related SSH2_FX_ATTR flags.
7428 */
7429 if (sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_TIMES) {
7430 if ((attr_flags & SSH2_FX_ATTR_ACCESSTIME) ||
7431 (attr_flags & SSH2_FX_ATTR_MODIFYTIME)) {
7432 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPSetTimes' "
7433 "configured, ignoring times sent by client");
7434 attr_flags &= ~SSH2_FX_ATTR_ACCESSTIME;
7435 attr_flags &= ~SSH2_FX_ATTR_MODIFYTIME;
7436 }
7437 }
7438
7439 if (fxh->fh != NULL) {
7440 res = fxp_attrs_set(fxh->fh, fxh->fh->fh_path, attrs, attr_flags, xattrs,
7441 &buf, &buflen, fxp);
7442
7443 } else {
7444 res = fxp_attrs_set(NULL, fxh->dir, attrs, attr_flags, xattrs, &buf,
7445 &buflen, fxp);
7446 }
7447
7448 if (res < 0) {
7449 int xerrno = errno;
7450
7451 status_code = fxp_errno2status(xerrno, &reason);
7452
7453 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
7454 "('%s' [%d])", (unsigned long) status_code, reason,
7455 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
7456
7457 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7458 reason, NULL);
7459
7460 fxp_cmd_dispatch_err(cmd);
7461
7462 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7463 resp->payload = ptr;
7464 resp->payload_sz = (bufsz - buflen);
7465
7466 return fxp_packet_write(resp);
7467 }
7468
7469 status_code = fxp_errno2status(0, &reason);
7470
7471 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7472 (unsigned long) status_code, reason);
7473
7474 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7475 reason, NULL);
7476
7477 fxp_cmd_dispatch(cmd);
7478
7479 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7480 resp->payload = ptr;
7481 resp->payload_sz = (bufsz - buflen);
7482
7483 return fxp_packet_write(resp);
7484 }
7485
fxp_handle_fstat(struct fxp_packet * fxp)7486 static int fxp_handle_fstat(struct fxp_packet *fxp) {
7487 unsigned char *buf;
7488 char *cmd_name, *name;
7489 uint32_t attr_flags, buflen;
7490 struct stat st;
7491 struct fxp_buffer *fxb;
7492 struct fxp_handle *fxh;
7493 struct fxp_packet *resp;
7494 cmd_rec *cmd;
7495 const char *fake_user = NULL, *fake_group = NULL;
7496
7497 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7498
7499 cmd = fxp_cmd_alloc(fxp->pool, "FSTAT", name);
7500 cmd->cmd_class = CL_READ|CL_SFTP;
7501
7502 pr_scoreboard_entry_update(session.pid,
7503 PR_SCORE_CMD, "%s", "FSTAT", NULL, NULL);
7504 pr_scoreboard_entry_update(session.pid,
7505 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
7506
7507 pr_proctitle_set("%s - %s: FSTAT %s", session.user, session.proc_prefix,
7508 name);
7509
7510 if (fxp_session->client_version > 3) {
7511 attr_flags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7512
7513 pr_trace_msg(trace_channel, 7, "received request: FSTAT %s %s", name,
7514 fxp_strattrflags(fxp->pool, attr_flags));
7515
7516 } else {
7517 pr_trace_msg(trace_channel, 7, "received request: FSTAT %s", name);
7518 attr_flags = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_UIDGID|SSH2_FX_ATTR_PERMISSIONS|
7519 SSH2_FX_ATTR_ACMODTIME;
7520 #ifdef PR_USE_XATTR
7521 if (!(fxp_fsio_opts & PR_FSIO_OPT_IGNORE_XATTR)) {
7522 attr_flags |= SSH2_FX_ATTR_EXTENDED;
7523 }
7524 #endif /* PR_USE_XATTR */
7525 }
7526
7527 fxb = pcalloc(fxp->pool, sizeof(struct fxp_buffer));
7528 fxb->bufsz = buflen = FXP_RESPONSE_NAME_DEFAULT_SZ;
7529 fxb->ptr = buf = palloc(fxp->pool, fxb->bufsz);
7530
7531 fxh = fxp_handle_get(name);
7532 if (fxh == NULL) {
7533 uint32_t status_code;
7534
7535 pr_trace_msg(trace_channel, 17,
7536 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
7537 name, strerror(errno));
7538
7539 status_code = SSH2_FX_INVALID_HANDLE;
7540
7541 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7542 (unsigned long) status_code, fxp_strerror(status_code));
7543
7544 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7545 fxp_strerror(status_code), NULL);
7546
7547 fxp_cmd_dispatch_err(cmd);
7548
7549 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7550 resp->payload = fxb->ptr;
7551 resp->payload_sz = (fxb->bufsz - buflen);
7552
7553 return fxp_packet_write(resp);
7554 }
7555
7556 if (fxh->fh == NULL) {
7557 uint32_t status_code = SSH2_FX_INVALID_HANDLE;
7558
7559 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7560 (unsigned long) status_code, fxp_strerror(status_code));
7561
7562 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7563 fxp_strerror(status_code), NULL);
7564
7565 fxp_cmd_dispatch_err(cmd);
7566
7567 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7568 resp->payload = fxb->ptr;
7569 resp->payload_sz = (fxb->bufsz - buflen);
7570
7571 return fxp_packet_write(resp);
7572 }
7573
7574 /* Add a note containing the file handle for logging (Bug#3707). */
7575 fxp_set_filehandle_note(cmd, fxh);
7576
7577 cmd_name = cmd->argv[0];
7578 pr_cmd_set_name(cmd, "FSTAT");
7579
7580 if (!dir_check(fxp->pool, cmd, G_NONE, fxh->fh->fh_path, NULL)) {
7581 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
7582
7583 pr_cmd_set_name(cmd, cmd_name);
7584
7585 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7586 "FSTAT of '%s' blocked by <Limit> configuration", fxh->fh->fh_path);
7587
7588 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7589 (unsigned long) status_code, fxp_strerror(status_code));
7590
7591 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7592 fxp_strerror(status_code), NULL);
7593
7594 fxp_cmd_dispatch_err(cmd);
7595
7596 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7597 resp->payload = fxb->ptr;
7598 resp->payload_sz = (fxb->bufsz - buflen);
7599
7600 return fxp_packet_write(resp);
7601 }
7602 pr_cmd_set_name(cmd, cmd_name);
7603
7604 if (pr_fsio_fstat(fxh->fh, &st) < 0) {
7605 uint32_t status_code;
7606 const char *reason;
7607 int xerrno = errno;
7608
7609 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7610 "error checking '%s' for FSTAT: %s", fxh->fh->fh_path, strerror(xerrno));
7611
7612 status_code = fxp_errno2status(xerrno, &reason);
7613
7614 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
7615 "('%s' [%d])", (unsigned long) status_code, reason,
7616 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
7617
7618 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7619 reason, NULL);
7620
7621 fxp_cmd_dispatch_err(cmd);
7622
7623 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7624 resp->payload = fxb->ptr;
7625 resp->payload_sz = (fxb->bufsz - buflen);
7626
7627 return fxp_packet_write(resp);
7628 }
7629
7630 pr_trace_msg(trace_channel, 8, "sending response: ATTRS %s",
7631 fxp_strattrs(fxp->pool, &st, NULL));
7632
7633 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_ATTRS);
7634 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
7635
7636 fake_user = get_param_ptr(get_dir_ctxt(fxp->pool, fxh->fh->fh_path),
7637 "DirFakeUser", FALSE);
7638 if (fake_user != NULL &&
7639 strncmp(fake_user, "~", 2) == 0) {
7640 fake_user = session.user;
7641 }
7642
7643 fake_group = get_param_ptr(get_dir_ctxt(fxp->pool, fxh->fh->fh_path),
7644 "DirFakeGroup", FALSE);
7645 if (fake_group != NULL &&
7646 strncmp(fake_group, "~", 2) == 0) {
7647 fake_group = session.group;
7648 }
7649
7650 fxb->buf = buf;
7651 fxb->buflen = buflen;
7652
7653 attr_flags = fxp_attrs_clear_unsupported(attr_flags);
7654 if (fxp_session->client_version > 3 &&
7655 sftp_opts & SFTP_OPT_INCLUDE_SFTP_TIMES) {
7656 pr_trace_msg(trace_channel, 17,
7657 "SFTPOption IncludeSFTPTimes in effect; assuring presence of "
7658 "ACCESSTIME/MODIFYTIME attributes");
7659 attr_flags |= SSH2_FX_ATTR_ACCESSTIME;
7660 attr_flags |= SSH2_FX_ATTR_MODIFYTIME;
7661 }
7662
7663 fxp_attrs_write(fxp->pool, fxb, fxh->fh->fh_path, &st, attr_flags, fake_user,
7664 fake_group);
7665
7666 /* fxp_attrs_write will have changed the buf/buflen values in the buffer. */
7667 buf = fxb->buf;
7668 buflen = fxb->buflen;
7669
7670 fxp_cmd_dispatch(cmd);
7671
7672 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7673 resp->payload = fxb->ptr;
7674 resp->payload_sz = (fxb->bufsz - buflen);
7675
7676 return fxp_packet_write(resp);
7677 }
7678
fxp_handle_init(struct fxp_packet * fxp)7679 static int fxp_handle_init(struct fxp_packet *fxp) {
7680 char version_str[16];
7681 unsigned char *buf, *ptr;
7682 uint32_t buflen, bufsz;
7683 struct fxp_packet *resp;
7684 cmd_rec *cmd;
7685 config_rec *c;
7686
7687 fxp_session->client_version = sftp_msg_read_int(fxp->pool, &fxp->payload,
7688 &fxp->payload_sz);
7689
7690 memset(version_str, '\0', sizeof(version_str));
7691 pr_snprintf(version_str, sizeof(version_str)-1, "%lu",
7692 (unsigned long) fxp_session->client_version);
7693
7694 cmd = fxp_cmd_alloc(fxp->pool, "INIT", version_str);
7695 cmd->cmd_class = CL_MISC|CL_SFTP;
7696
7697 pr_scoreboard_entry_update(session.pid,
7698 PR_SCORE_CMD, "%s", "INIT", NULL, NULL);
7699 pr_scoreboard_entry_update(session.pid,
7700 PR_SCORE_CMD_ARG, "%s", version_str, NULL, NULL);
7701
7702 pr_proctitle_set("%s - %s: INIT %s", session.user, session.proc_prefix,
7703 version_str);
7704
7705 pr_trace_msg(trace_channel, 7, "received request: INIT %lu",
7706 (unsigned long) fxp_session->client_version);
7707
7708 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
7709 buf = ptr = palloc(fxp->pool, bufsz);
7710
7711 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_VERSION);
7712
7713 if (fxp_session->client_version > fxp_max_client_version) {
7714 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7715 "client requested SFTP protocol version %lu, which exceeds "
7716 "SFTPClientMatch max SFTP protocol version %u, using protocol version %u",
7717 (unsigned long) fxp_session->client_version, fxp_max_client_version,
7718 fxp_max_client_version);
7719 fxp_session->client_version = fxp_max_client_version;
7720 }
7721
7722 if (fxp_session->client_version < fxp_min_client_version) {
7723 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7724 "client requested SFTP protocol version %lu, which is less than "
7725 "SFTPClientMatch min SFTP protocol version %u, using protocol version %u",
7726 (unsigned long) fxp_session->client_version, fxp_min_client_version,
7727 fxp_min_client_version);
7728 fxp_session->client_version = fxp_min_client_version;
7729 }
7730
7731 #ifndef PR_USE_NLS
7732 /* If NLS supported was enabled in the proftpd build, then we can support
7733 * UTF8, and thus every other version of SFTP. Otherwise, we can only
7734 * support up to version 3.
7735 */
7736 if (fxp_session->client_version > 3) {
7737 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7738 "client requested SFTP protocol version %lu, but we can only support "
7739 "protocol version 3 due to lack of UTF8 support (requires --enable-nls)",
7740 (unsigned long) fxp_session->client_version);
7741 fxp_session->client_version = 3;
7742 }
7743 #endif
7744
7745 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7746 "using SFTP protocol version %lu for this session (channel ID %lu)",
7747 (unsigned long) fxp_session->client_version,
7748 (unsigned long) fxp->channel_id);
7749
7750 pr_trace_msg(trace_channel, 8, "sending response: VERSION %lu",
7751 (unsigned long) fxp_session->client_version);
7752
7753 sftp_msg_write_int(&buf, &buflen, fxp_session->client_version);
7754
7755 if (fxp_ext_flags & SFTP_FXP_EXT_VENDOR_ID) {
7756 fxp_version_add_vendor_id_ext(fxp->pool, &buf, &buflen);
7757 }
7758
7759 fxp_version_add_version_ext(fxp->pool, &buf, &buflen);
7760
7761 if (fxp_session->client_version >= 4) {
7762 fxp_version_add_newline_ext(fxp->pool, &buf, &buflen);
7763 }
7764
7765 if (fxp_session->client_version == 5) {
7766 fxp_version_add_supported_ext(fxp->pool, &buf, &buflen);
7767 }
7768
7769 if (fxp_session->client_version >= 6) {
7770 fxp_version_add_supported2_ext(fxp->pool, &buf, &buflen);
7771 }
7772
7773 fxp_version_add_openssh_exts(fxp->pool, &buf, &buflen);
7774
7775 /* Look up the FSOptions here, for use later (Issue #593). We do not need
7776 * set these for the FSIO API; that is already done by mod_core. Instead,
7777 * we look them up for ourselves, for our own consumption/use.
7778 */
7779 c = find_config(main_server->conf, CONF_PARAM, "FSOptions", FALSE);
7780 while (c != NULL) {
7781 unsigned long opts = 0;
7782
7783 pr_signals_handle();
7784
7785 opts = *((unsigned long *) c->argv[0]);
7786 fxp_fsio_opts |= opts;
7787
7788 c = find_config_next(c, c->next, CONF_PARAM, "FSOptions", FALSE);
7789 }
7790
7791 pr_event_generate("mod_sftp.sftp.protocol-version",
7792 &(fxp_session->client_version));
7793
7794 fxp_cmd_dispatch(cmd);
7795
7796 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7797 resp->payload = ptr;
7798 resp->payload_sz = (bufsz - buflen);
7799
7800 return fxp_packet_write(resp);
7801 }
7802
fxp_handle_link(struct fxp_packet * fxp)7803 static int fxp_handle_link(struct fxp_packet *fxp) {
7804 unsigned char *buf, *ptr;
7805 char *args, *cmd_name, *link_path, *target_path;
7806 const char *reason;
7807 char is_symlink;
7808 int have_error = FALSE, res;
7809 uint32_t buflen, bufsz, status_code;
7810 struct fxp_packet *resp;
7811 cmd_rec *cmd;
7812
7813 link_path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7814 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
7815 link_path = sftp_utf8_decode_str(fxp->pool, link_path);
7816 }
7817
7818 target_path = sftp_msg_read_string(fxp->pool, &fxp->payload,
7819 &fxp->payload_sz);
7820 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
7821 target_path = sftp_utf8_decode_str(fxp->pool, target_path);
7822 }
7823
7824 args = pstrcat(fxp->pool, link_path, " ", target_path, NULL);
7825
7826 cmd = fxp_cmd_alloc(fxp->pool, "LINK", args);
7827 cmd->cmd_class = CL_WRITE|CL_SFTP;
7828
7829 pr_scoreboard_entry_update(session.pid,
7830 PR_SCORE_CMD, "%s", "LINK", NULL, NULL);
7831 pr_scoreboard_entry_update(session.pid,
7832 PR_SCORE_CMD_ARG, "%s", args, NULL, NULL);
7833
7834 is_symlink = sftp_msg_read_byte(fxp->pool, &fxp->payload, &fxp->payload_sz);
7835
7836 pr_proctitle_set("%s - %s: LINK %s %s %s", session.user, session.proc_prefix,
7837 link_path, target_path, is_symlink ? "true" : "false");
7838
7839 pr_trace_msg(trace_channel, 7, "received request: LINK %s %s %s", link_path,
7840 target_path, is_symlink ? "true" : "false");
7841
7842 if (strlen(link_path) == 0) {
7843 /* Use the default directory if the path is empty. */
7844 link_path = sftp_auth_get_default_dir();
7845
7846 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7847 "empty link path given in LINK request, using '%s'", link_path);
7848 }
7849
7850 if (strlen(target_path) == 0) {
7851 /* Use the default directory if the path is empty. */
7852 target_path = sftp_auth_get_default_dir();
7853
7854 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7855 "empty target path given in LINK request, using '%s'", target_path);
7856 }
7857
7858 /* Make sure we use the full paths. */
7859 link_path = dir_canonical_vpath(fxp->pool, link_path);
7860 target_path = dir_canonical_vpath(fxp->pool, target_path);
7861
7862 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
7863 buf = ptr = palloc(fxp->pool, bufsz);
7864
7865 cmd_name = cmd->argv[0];
7866 pr_cmd_set_name(cmd, "LINK");
7867
7868 if (!dir_check(fxp->pool, cmd, G_READ, target_path, NULL)) {
7869 have_error = TRUE;
7870 }
7871
7872 if (!have_error) {
7873 if (!dir_check(fxp->pool, cmd, G_WRITE, link_path, NULL)) {
7874 have_error = TRUE;
7875 }
7876 }
7877
7878 if (is_symlink) {
7879 if (!have_error) {
7880 pr_cmd_set_name(cmd, "SYMLINK");
7881
7882 if (!dir_check(fxp->pool, cmd, G_READ, target_path, NULL)) {
7883 have_error = TRUE;
7884 }
7885
7886 if (!have_error) {
7887 if (!dir_check(fxp->pool, cmd, G_WRITE, link_path, NULL)) {
7888 have_error = TRUE;
7889 }
7890 }
7891 }
7892 }
7893
7894 if (have_error) {
7895 status_code = SSH2_FX_PERMISSION_DENIED;
7896
7897 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7898 "LINK of '%s' to '%s' blocked by <Limit %s> configuration",
7899 target_path, link_path, (char *) cmd->argv[0]);
7900
7901 pr_cmd_set_name(cmd, cmd_name);
7902
7903 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7904 (unsigned long) status_code, fxp_strerror(status_code));
7905
7906 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7907 fxp_strerror(status_code), NULL);
7908
7909 fxp_cmd_dispatch_err(cmd);
7910
7911 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7912 resp->payload = ptr;
7913 resp->payload_sz = (bufsz - buflen);
7914
7915 return fxp_packet_write(resp);
7916 }
7917
7918 pr_cmd_set_name(cmd, cmd_name);
7919
7920 if (is_symlink) {
7921 res = pr_fsio_symlink(target_path, link_path);
7922
7923 } else {
7924 res = pr_fsio_link(target_path, link_path);
7925 }
7926
7927 if (res < 0) {
7928 int xerrno = errno;
7929
7930 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
7931 "error %s '%s' to '%s': %s", is_symlink ? "symlinking" : "linking",
7932 target_path, link_path, strerror(xerrno));
7933
7934 status_code = fxp_errno2status(xerrno, &reason);
7935
7936 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
7937 "('%s' [%d])", (unsigned long) status_code, reason,
7938 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
7939
7940 fxp_cmd_dispatch_err(cmd);
7941
7942 } else {
7943 errno = 0;
7944 status_code = fxp_errno2status(0, &reason);
7945
7946 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
7947 (unsigned long) status_code, reason);
7948
7949 fxp_cmd_dispatch(cmd);
7950 }
7951
7952 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
7953 reason, NULL);
7954
7955 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
7956 resp->payload = ptr;
7957 resp->payload_sz = (bufsz - buflen);
7958
7959 return fxp_packet_write(resp);
7960 }
7961
fxp_handle_lock(struct fxp_packet * fxp)7962 static int fxp_handle_lock(struct fxp_packet *fxp) {
7963 unsigned char *buf, *ptr;
7964 char *name;
7965 const char *lock_type_str = NULL;
7966 uint32_t buflen, bufsz, lock_flags, status_code;
7967 uint64_t offset, lock_len;
7968 struct flock lock;
7969 struct fxp_handle *fxh;
7970 struct fxp_packet *resp;
7971 cmd_rec *cmd;
7972
7973 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
7974 offset = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
7975 lock_len = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
7976 lock_flags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
7977
7978 cmd = fxp_cmd_alloc(fxp->pool, "LOCK", name);
7979 cmd->cmd_class = CL_WRITE|CL_SFTP;
7980
7981 pr_scoreboard_entry_update(session.pid,
7982 PR_SCORE_CMD, "%s", "LOCK", NULL, NULL);
7983 pr_scoreboard_entry_update(session.pid,
7984 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
7985
7986 pr_proctitle_set("%s - %s: LOCK %s", session.user, session.proc_prefix, name);
7987
7988 pr_trace_msg(trace_channel, 7,
7989 "received request: LOCK %s %" PR_LU " %" PR_LU " %lu",
7990 name, (pr_off_t) offset, (pr_off_t) lock_len, (unsigned long) lock_flags);
7991
7992 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
7993 buf = ptr = palloc(fxp->pool, bufsz);
7994
7995 fxh = fxp_handle_get(name);
7996 if (fxh == NULL) {
7997 pr_trace_msg(trace_channel, 17,
7998 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
7999 name, strerror(errno));
8000
8001 status_code = SSH2_FX_INVALID_HANDLE;
8002
8003 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8004 (unsigned long) status_code, fxp_strerror(status_code));
8005
8006 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8007 fxp_strerror(status_code), NULL);
8008
8009 fxp_cmd_dispatch_err(cmd);
8010
8011 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8012 resp->payload = ptr;
8013 resp->payload_sz = (bufsz - buflen);
8014
8015 return fxp_packet_write(resp);
8016 }
8017
8018 if (fxh->fh == NULL) {
8019 /* We do not support locking of directory handles, only files. */
8020 status_code = SSH2_FX_OP_UNSUPPORTED;
8021
8022 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8023 "client requested unsupported LOCK of a directory, rejecting");
8024
8025 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8026 (unsigned long) status_code, fxp_strerror(status_code));
8027
8028 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8029 fxp_strerror(status_code), NULL);
8030
8031 fxp_cmd_dispatch_err(cmd);
8032
8033 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8034 resp->payload = ptr;
8035 resp->payload_sz = (bufsz - buflen);
8036
8037 return fxp_packet_write(resp);
8038 }
8039
8040 if (!dir_check(fxp->pool, cmd, G_WRITE, fxh->fh->fh_path, NULL)) {
8041 status_code = SSH2_FX_PERMISSION_DENIED;
8042
8043 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8044 "LOCK of '%s' blocked by <Limit> configuration", fxh->fh->fh_path);
8045
8046 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8047 (unsigned long) status_code, fxp_strerror(status_code));
8048
8049 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8050 fxp_strerror(status_code), NULL);
8051
8052 fxp_cmd_dispatch_err(cmd);
8053
8054 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8055 resp->payload = ptr;
8056 resp->payload_sz = (bufsz - buflen);
8057
8058 return fxp_packet_write(resp);
8059 }
8060
8061 pr_scoreboard_entry_update(session.pid,
8062 PR_SCORE_CMD_ARG, "%s", fxh->fh->fh_path, NULL, NULL);
8063
8064 if (lock_flags & SSH2_FXL_DELETE) {
8065 /* The UNLOCK command is used for removing locks, not LOCK. */
8066 status_code = SSH2_FX_OP_UNSUPPORTED;
8067
8068 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8069 "client requested lock removal using LOCK, rejecting");
8070
8071 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8072 (unsigned long) status_code, fxp_strerror(status_code));
8073
8074 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8075 fxp_strerror(status_code), NULL);
8076
8077 fxp_cmd_dispatch_err(cmd);
8078
8079 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8080 resp->payload = ptr;
8081 resp->payload_sz = (bufsz - buflen);
8082
8083 return fxp_packet_write(resp);
8084
8085 } else {
8086 if ((lock_flags & SSH2_FXL_WRITE) &&
8087 (lock_flags & SSH2_FXL_READ)) {
8088 /* We do not support simultaneous read and write locking. */
8089 status_code = SSH2_FX_OP_UNSUPPORTED;
8090
8091 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8092 "client requested unsupported simultaneous read/write LOCK, "
8093 "rejecting");
8094
8095 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8096 (unsigned long) status_code, fxp_strerror(status_code));
8097
8098 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8099 fxp_strerror(status_code), NULL);
8100
8101 fxp_cmd_dispatch_err(cmd);
8102
8103 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8104 resp->payload = ptr;
8105 resp->payload_sz = (bufsz - buflen);
8106
8107 return fxp_packet_write(resp);
8108 }
8109
8110 if (lock_flags & SSH2_FXL_READ) {
8111 lock.l_type = F_RDLCK;
8112 lock_type_str = "read";
8113 }
8114
8115 if (lock_flags & SSH2_FXL_WRITE) {
8116 lock.l_type = F_WRLCK;
8117 lock_type_str = "write";
8118 }
8119 }
8120
8121 lock.l_whence = SEEK_SET;
8122 lock.l_start = offset;
8123 lock.l_len = lock_len;
8124
8125 if (lock_len > 0) {
8126 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8127 "client requested %s locking of '%s' from %" PR_LU " for %" PR_LU
8128 " bytes", lock_type_str, fxh->fh->fh_path, (pr_off_t) offset,
8129 (pr_off_t) lock_len);
8130
8131 } else {
8132 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8133 "client requested %s locking of '%s' from %" PR_LU " to end-of-file",
8134 lock_type_str, fxh->fh->fh_path, (pr_off_t) offset);
8135 }
8136
8137 pr_trace_msg("lock", 9, "attempting to %s lock file '%s'", lock_type_str,
8138 fxh->fh->fh_path);
8139
8140 while (fcntl(fxh->fh->fh_fd, F_SETLKW, &lock) < 0) {
8141 int xerrno;
8142 const char *reason;
8143
8144 if (errno == EINTR) {
8145 pr_signals_handle();
8146 continue;
8147 }
8148
8149 xerrno = errno;
8150 pr_trace_msg("lock", 3, "%s-lock of '%s' failed: %s", lock_type_str,
8151 fxh->fh->fh_path, strerror(errno));
8152
8153 if (errno == EACCES) {
8154 /* Get the PID of the process blocking this lock. */
8155 if (fcntl(fxh->fh->fh_fd, F_GETLK, &lock) == 0) {
8156 pr_trace_msg("lock", 3, "process ID %lu has blocking %s lock on '%s'",
8157 (unsigned long) lock.l_pid, lock.l_type == F_RDLCK ? "read" : "write",
8158 fxh->fh->fh_path);
8159 }
8160
8161 status_code = SSH2_FX_LOCK_CONFLICT;
8162 reason = fxp_strerror(status_code);
8163
8164 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8165 (unsigned long) status_code, reason);
8166
8167 } else {
8168 status_code = fxp_errno2status(xerrno, &reason);
8169
8170 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
8171 "('%s' [%d])", (unsigned long) status_code, reason,
8172 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
8173 }
8174
8175 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8176 reason, NULL);
8177
8178 fxp_cmd_dispatch_err(cmd);
8179
8180 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8181 resp->payload = ptr;
8182 resp->payload_sz = (bufsz - buflen);
8183
8184 return fxp_packet_write(resp);
8185 }
8186
8187 pr_trace_msg("lock", 9, "%s lock of file '%s' successful", lock_type_str,
8188 fxh->fh->fh_path);
8189
8190 status_code = SSH2_FX_OK;
8191
8192 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8193 (unsigned long) status_code, fxp_strerror(status_code));
8194
8195 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8196 fxp_strerror(status_code), NULL);
8197
8198 fxp_cmd_dispatch(cmd);
8199
8200 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8201 resp->payload = ptr;
8202 resp->payload_sz = (bufsz - buflen);
8203
8204 return fxp_packet_write(resp);
8205 }
8206
fxp_handle_lstat(struct fxp_packet * fxp)8207 static int fxp_handle_lstat(struct fxp_packet *fxp) {
8208 unsigned char *buf;
8209 char *cmd_name, *path;
8210 uint32_t attr_flags, buflen;
8211 struct stat st;
8212 struct fxp_buffer *fxb;
8213 struct fxp_packet *resp;
8214 cmd_rec *cmd;
8215 const char *fake_user = NULL, *fake_group = NULL;
8216
8217 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
8218 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
8219 path = sftp_utf8_decode_str(fxp->pool, path);
8220 }
8221
8222 pr_scoreboard_entry_update(session.pid,
8223 PR_SCORE_CMD, "%s", "LSTAT", NULL, NULL);
8224 pr_scoreboard_entry_update(session.pid,
8225 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
8226
8227 pr_proctitle_set("%s - %s: LSTAT %s", session.user, session.proc_prefix,
8228 path);
8229
8230 if (fxp_session->client_version > 3) {
8231 attr_flags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
8232
8233 pr_trace_msg(trace_channel, 7, "received request: LSTAT %s %s", path,
8234 fxp_strattrflags(fxp->pool, attr_flags));
8235
8236 } else {
8237 pr_trace_msg(trace_channel, 7, "received request: LSTAT %s", path);
8238 attr_flags = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_UIDGID|SSH2_FX_ATTR_PERMISSIONS|
8239 SSH2_FX_ATTR_ACMODTIME;
8240 #ifdef PR_USE_XATTR
8241 if (!(fxp_fsio_opts & PR_FSIO_OPT_IGNORE_XATTR)) {
8242 attr_flags |= SSH2_FX_ATTR_EXTENDED;
8243 }
8244 #endif /* PR_USE_XATTR */
8245 }
8246
8247 if (strlen(path) == 0) {
8248 /* Use the default directory if the path is empty. */
8249 path = sftp_auth_get_default_dir();
8250
8251 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8252 "empty path given in LSTAT request, using '%s'", path);
8253 }
8254
8255 cmd = fxp_cmd_alloc(fxp->pool, "LSTAT", path);
8256 cmd->cmd_class = CL_READ|CL_SFTP;
8257
8258 fxb = pcalloc(fxp->pool, sizeof(struct fxp_buffer));
8259 fxb->bufsz = buflen = FXP_RESPONSE_NAME_DEFAULT_SZ;
8260 fxb->ptr = buf = palloc(fxp->pool, fxb->bufsz);
8261
8262 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
8263 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
8264
8265 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8266 "LSTAT of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
8267
8268 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8269 (unsigned long) status_code, fxp_strerror(status_code));
8270
8271 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8272 fxp_strerror(status_code), NULL);
8273
8274 fxp_cmd_dispatch_err(cmd);
8275
8276 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8277 resp->payload = fxb->ptr;
8278 resp->payload_sz = (fxb->bufsz - buflen);
8279
8280 return fxp_packet_write(resp);
8281 }
8282
8283 /* The path may have been changed by any PRE_CMD handlers. */
8284 path = dir_best_path(fxp->pool, cmd->arg);
8285 if (path == NULL) {
8286 int xerrno = EACCES;
8287 const char *reason;
8288 uint32_t status_code;
8289
8290 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8291 "LSTAT request denied: unable to access path '%s'", cmd->arg);
8292
8293 status_code = fxp_errno2status(xerrno, &reason);
8294
8295 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
8296 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
8297 xerrno);
8298
8299 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8300 reason, NULL);
8301
8302 fxp_cmd_dispatch_err(cmd);
8303
8304 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8305 resp->payload = fxb->ptr;
8306 resp->payload_sz = (fxb->bufsz - buflen);
8307
8308 return fxp_packet_write(resp);
8309 }
8310
8311 cmd_name = cmd->argv[0];
8312 pr_cmd_set_name(cmd, "LSTAT");
8313
8314 if (!dir_check(fxp->pool, cmd, G_NONE, path, NULL)) {
8315 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
8316
8317 pr_cmd_set_name(cmd, cmd_name);
8318
8319 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8320 "LSTAT of '%s' blocked by <Limit> configuration", path);
8321
8322 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8323 (unsigned long) status_code, fxp_strerror(status_code));
8324
8325 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8326 fxp_strerror(status_code), NULL);
8327
8328 fxp_cmd_dispatch_err(cmd);
8329
8330 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8331 resp->payload = fxb->ptr;
8332 resp->payload_sz = (fxb->bufsz - buflen);
8333
8334 return fxp_packet_write(resp);
8335 }
8336 pr_cmd_set_name(cmd, cmd_name);
8337
8338 pr_fs_clear_cache2(path);
8339 if (pr_fsio_lstat(path, &st) < 0) {
8340 uint32_t status_code;
8341 const char *reason;
8342 int xerrno = errno;
8343
8344 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8345 "error checking '%s' for LSTAT: %s", path, strerror(xerrno));
8346
8347 status_code = fxp_errno2status(xerrno, &reason);
8348
8349 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
8350 "('%s' [%d])", (unsigned long) status_code, reason,
8351 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
8352
8353 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8354 reason, NULL);
8355
8356 fxp_cmd_dispatch_err(cmd);
8357
8358 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8359 resp->payload = fxb->ptr;
8360 resp->payload_sz = (fxb->bufsz - buflen);
8361
8362 return fxp_packet_write(resp);
8363 }
8364
8365 pr_trace_msg(trace_channel, 8, "sending response: ATTRS %s",
8366 fxp_strattrs(fxp->pool, &st, NULL));
8367
8368 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_ATTRS);
8369 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
8370
8371 fake_user = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeUser",
8372 FALSE);
8373 if (fake_user != NULL &&
8374 strncmp(fake_user, "~", 2) == 0) {
8375 fake_user = session.user;
8376 }
8377
8378 fake_group = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeGroup",
8379 FALSE);
8380 if (fake_group != NULL &&
8381 strncmp(fake_group, "~", 2) == 0) {
8382 fake_group = session.group;
8383 }
8384
8385 fxb->buf = buf;
8386 fxb->buflen = buflen;
8387
8388 attr_flags = fxp_attrs_clear_unsupported(attr_flags);
8389 if (fxp_session->client_version > 3 &&
8390 sftp_opts & SFTP_OPT_INCLUDE_SFTP_TIMES) {
8391 pr_trace_msg(trace_channel, 17,
8392 "SFTPOption IncludeSFTPTimes in effect; assuring presence of "
8393 "ACCESSTIME/MODIFYTIME attributes");
8394 attr_flags |= SSH2_FX_ATTR_ACCESSTIME;
8395 attr_flags |= SSH2_FX_ATTR_MODIFYTIME;
8396 }
8397
8398 fxp_attrs_write(fxp->pool, fxb, path, &st, attr_flags, fake_user, fake_group);
8399
8400 /* fxp_attrs_write will have changed the buf/buflen fields in the buffer. */
8401 buf = fxb->buf;
8402 buflen = fxb->buflen;
8403
8404 fxp_cmd_dispatch(cmd);
8405
8406 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8407 resp->payload = fxb->ptr;
8408 resp->payload_sz = (fxb->bufsz - buflen);
8409
8410 return fxp_packet_write(resp);
8411 }
8412
fxp_handle_mkdir(struct fxp_packet * fxp)8413 static int fxp_handle_mkdir(struct fxp_packet *fxp) {
8414 unsigned char *buf, *ptr;
8415 char *attrs_str, *cmd_name, *path;
8416 struct stat *attrs, st;
8417 int have_error = FALSE, res = 0;
8418 mode_t dir_mode;
8419 uint32_t attr_flags, buflen, bufsz, status_code;
8420 struct fxp_packet *resp;
8421 cmd_rec *cmd, *cmd2;
8422 array_header *xattrs = NULL;
8423
8424 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
8425 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
8426 path = sftp_utf8_decode_str(fxp->pool, path);
8427 }
8428
8429 pr_scoreboard_entry_update(session.pid,
8430 PR_SCORE_CMD, "%s", "MKDIR", NULL, NULL);
8431 pr_scoreboard_entry_update(session.pid,
8432 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
8433
8434 attrs = fxp_attrs_read(fxp, &fxp->payload, &fxp->payload_sz, &attr_flags,
8435 &xattrs);
8436 if (attrs == NULL) {
8437 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8438 "MKDIR request missing required attributes, ignoring");
8439 return 0;
8440 }
8441
8442 /* If the SFTPOption for ignoring perms for SFTP uploads is set, handle
8443 * it by clearing the SSH2_FX_ATTR_PERMISSIONS flag.
8444 */
8445 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_UPLOAD_PERMS) &&
8446 (attr_flags & SSH2_FX_ATTR_PERMISSIONS)) {
8447 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPUploadPerms' "
8448 "configured, ignoring perms sent by client");
8449 attr_flags &= ~SSH2_FX_ATTR_PERMISSIONS;
8450 }
8451
8452 /* If the SFTPOption for ignoring xattrs for SFTP uploads is set, handle it
8453 * by clearing the SSH2_FX_ATTR_EXTENDED flag.
8454 */
8455 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_UPLOAD_XATTRS) &&
8456 (attr_flags & SSH2_FX_ATTR_EXTENDED)) {
8457 pr_trace_msg(trace_channel, 7,
8458 "SFTPOption 'IgnoreSFTPUploadExtendedAttributes' configured, "
8459 "ignoring xattrs sent by client");
8460 attr_flags &= ~SSH2_FX_ATTR_EXTENDED;
8461 }
8462
8463 attrs_str = fxp_strattrs(fxp->pool, attrs, &attr_flags);
8464
8465 pr_proctitle_set("%s - %s: MKDIR %s %s", session.user, session.proc_prefix,
8466 path, attrs_str);
8467
8468 pr_trace_msg(trace_channel, 7, "received request: MKDIR %s %s", path,
8469 attrs_str);
8470
8471 if (strlen(path) == 0) {
8472 /* Use the default directory if the path is empty. */
8473 path = sftp_auth_get_default_dir();
8474
8475 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8476 "empty path given in MKDIR request, using '%s'", path);
8477 }
8478
8479 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
8480 buf = ptr = palloc(fxp->pool, bufsz);
8481
8482 cmd = fxp_cmd_alloc(fxp->pool, "MKDIR", path);
8483 cmd->cmd_class = CL_WRITE|CL_SFTP;
8484
8485 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
8486 status_code = SSH2_FX_PERMISSION_DENIED;
8487
8488 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8489 "MKDIR of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
8490
8491 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8492 (unsigned long) status_code, fxp_strerror(status_code));
8493
8494 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8495 fxp_strerror(status_code), NULL);
8496
8497 fxp_cmd_dispatch_err(cmd);
8498
8499 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8500 resp->payload = ptr;
8501 resp->payload_sz = (bufsz - buflen);
8502
8503 return fxp_packet_write(resp);
8504 }
8505
8506 path = cmd->arg;
8507
8508 cmd2 = fxp_cmd_alloc(fxp->pool, C_MKD, path);
8509 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) == -1) {
8510 status_code = SSH2_FX_PERMISSION_DENIED;
8511
8512 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8513 "MKDIR of '%s' blocked by '%s' handler", path, (char *) cmd2->argv[0]);
8514
8515 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8516 (unsigned long) status_code, fxp_strerror(status_code));
8517
8518 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
8519 fxp_cmd_dispatch_err(cmd2);
8520
8521 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8522 fxp_strerror(status_code), NULL);
8523
8524 fxp_cmd_dispatch_err(cmd);
8525
8526 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8527 resp->payload = ptr;
8528 resp->payload_sz = (bufsz - buflen);
8529
8530 return fxp_packet_write(resp);
8531 }
8532
8533 /* The path may have been changed by any PRE_CMD handlers. */
8534 path = cmd2->arg;
8535
8536 path = dir_canonical_path(fxp->pool, path);
8537 if (path == NULL) {
8538 status_code = fxp_errno2status(EINVAL, NULL);
8539
8540 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8541 (unsigned long) status_code, fxp_strerror(status_code));
8542
8543 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
8544 fxp_cmd_dispatch_err(cmd2);
8545
8546 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8547 fxp_strerror(status_code), NULL);
8548
8549 fxp_cmd_dispatch_err(cmd);
8550
8551 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8552 resp->payload = ptr;
8553 resp->payload_sz = (bufsz - buflen);
8554
8555 return fxp_packet_write(resp);
8556 }
8557
8558 cmd_name = cmd->argv[0];
8559 pr_cmd_set_name(cmd, C_XMKD);
8560
8561 if (!dir_check_canon(fxp->pool, cmd, G_WRITE, path, NULL)) {
8562 have_error = TRUE;
8563 }
8564
8565 if (have_error) {
8566 status_code = SSH2_FX_PERMISSION_DENIED;
8567
8568 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8569 "MKDIR of '%s' blocked by <Limit %s> configuration", path,
8570 (char *) cmd->argv[0]);
8571
8572 pr_cmd_set_name(cmd, cmd_name);
8573
8574 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8575 (unsigned long) status_code, fxp_strerror(status_code));
8576
8577 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
8578 fxp_cmd_dispatch_err(cmd2);
8579
8580 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8581 fxp_strerror(status_code), NULL);
8582
8583 fxp_cmd_dispatch_err(cmd);
8584
8585 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8586 resp->payload = ptr;
8587 resp->payload_sz = (bufsz - buflen);
8588
8589 return fxp_packet_write(resp);
8590 }
8591
8592 pr_cmd_set_name(cmd, cmd_name);
8593
8594 if (fxp_path_pass_regex_filters(fxp->pool, "MKDIR", path) < 0) {
8595 int xerrno = errno;
8596
8597 status_code = fxp_errno2status(xerrno, NULL);
8598
8599 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8600 (unsigned long) status_code, fxp_strerror(status_code));
8601
8602 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
8603 fxp_cmd_dispatch_err(cmd2);
8604
8605 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8606 fxp_strerror(status_code), NULL);
8607
8608 fxp_cmd_dispatch_err(cmd);
8609
8610 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8611 resp->payload = ptr;
8612 resp->payload_sz = (bufsz - buflen);
8613
8614 return fxp_packet_write(resp);
8615 }
8616
8617 dir_mode = (attr_flags & SSH2_FX_ATTR_PERMISSIONS) ? attrs->st_mode : 0777;
8618
8619 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8620 "creating directory '%s' with mode 0%o", path, (unsigned int) dir_mode);
8621
8622 /* Check if the path already exists, to avoid unnecessary work. */
8623 pr_fs_clear_cache2(path);
8624 if (pr_fsio_lstat(path, &st) == 0) {
8625 const char *reason;
8626 int xerrno = EEXIST;
8627
8628 (void) pr_trace_msg("fileperms", 1, "MKDIR, user '%s' (UID %s, GID %s): "
8629 "error making directory '%s': %s", session.user,
8630 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
8631 path, strerror(xerrno));
8632
8633 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8634 "MKDIR of '%s' failed: %s", path, strerror(xerrno));
8635
8636 status_code = fxp_errno2status(xerrno, &reason);
8637
8638 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
8639 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
8640 xerrno);
8641
8642 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
8643 fxp_cmd_dispatch_err(cmd2);
8644
8645 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8646 reason, NULL);
8647
8648 fxp_cmd_dispatch_err(cmd);
8649
8650 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8651 resp->payload = ptr;
8652 resp->payload_sz = (bufsz - buflen);
8653
8654 return fxp_packet_write(resp);
8655 }
8656
8657 res = pr_fsio_smkdir(fxp->pool, path, dir_mode, (uid_t) -1, (gid_t) -1);
8658 if (res < 0) {
8659 const char *reason;
8660 int xerrno = errno;
8661
8662 (void) pr_trace_msg("fileperms", 1, "MKDIR, user '%s' (UID %s, GID %s): "
8663 "error making directory '%s': %s", session.user,
8664 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
8665 path, strerror(xerrno));
8666
8667 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8668 "MKDIR of '%s' failed: %s", path, strerror(xerrno));
8669
8670 status_code = fxp_errno2status(xerrno, &reason);
8671
8672 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
8673 "('%s' [%d])", (unsigned long) status_code, reason,
8674 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
8675
8676 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
8677 fxp_cmd_dispatch_err(cmd2);
8678
8679 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8680 reason, NULL);
8681
8682 fxp_cmd_dispatch_err(cmd);
8683
8684 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8685 resp->payload = ptr;
8686 resp->payload_sz = (bufsz - buflen);
8687
8688 return fxp_packet_write(resp);
8689 }
8690
8691 /* Handle any possible UserOwner/GroupOwner directives for created
8692 * directories.
8693 */
8694 if (sftp_misc_chown_path(fxp->pool, path) < 0) {
8695 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8696 "error changing ownership on path '%s': %s", path, strerror(errno));
8697 }
8698
8699 status_code = SSH2_FX_OK;
8700
8701 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8702 (unsigned long) status_code, fxp_strerror(status_code));
8703
8704 fxp_cmd_dispatch(cmd2);
8705
8706 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8707 fxp_strerror(status_code), NULL);
8708
8709 pr_response_add(R_257, "\"%s\" - Directory successfully created",
8710 quote_dir(cmd->tmp_pool, path));
8711 fxp_cmd_dispatch(cmd);
8712
8713 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8714 resp->payload = ptr;
8715 resp->payload_sz = (bufsz - buflen);
8716
8717 return fxp_packet_write(resp);
8718 }
8719
fxp_handle_open(struct fxp_packet * fxp)8720 static int fxp_handle_open(struct fxp_packet *fxp) {
8721 unsigned char *buf, *ptr;
8722 const char *hiddenstore_path = NULL;
8723 char *path, *orig_path;
8724 uint32_t attr_flags, buflen, bufsz, desired_access = 0, flags;
8725 int file_existed = FALSE, open_flags, res, timeout_stalled;
8726 pr_fh_t *fh;
8727 struct stat *attrs, st;
8728 struct fxp_handle *fxh;
8729 struct fxp_packet *resp;
8730 cmd_rec *cmd, *cmd2 = NULL;
8731 array_header *xattrs = NULL;
8732
8733 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
8734 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
8735 path = sftp_utf8_decode_str(fxp->pool, path);
8736 }
8737
8738 orig_path = path;
8739 cmd = fxp_cmd_alloc(fxp->pool, "OPEN", path);
8740
8741 /* Set the command class to MISC for now; we'll change it later to
8742 * READ or WRITE once we know which it is.
8743 */
8744 cmd->cmd_class = CL_MISC|CL_SFTP;
8745
8746 pr_scoreboard_entry_update(session.pid,
8747 PR_SCORE_CMD, "%s", "OPEN", NULL, NULL);
8748 pr_scoreboard_entry_update(session.pid,
8749 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
8750
8751 pr_proctitle_set("%s - %s: OPEN %s", session.user, session.proc_prefix, path);
8752
8753 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
8754 buf = ptr = palloc(fxp->pool, bufsz);
8755
8756 if (fxp_session->client_version > 4) {
8757 desired_access = sftp_msg_read_int(fxp->pool, &fxp->payload,
8758 &fxp->payload_sz);
8759
8760 /* Check for unsupported flags. */
8761 if ((desired_access & SSH2_FXF_WANT_READ_NAMED_ATTRS) ||
8762 (desired_access & SSH2_FXF_WANT_READ_ACL) ||
8763 (desired_access & SSH2_FXF_WANT_WRITE_NAMED_ATTRS) ||
8764 (desired_access & SSH2_FXF_WANT_WRITE_ACL) ||
8765 (desired_access & SSH2_FXF_WANT_WRITE_OWNER)) {
8766 uint32_t status_code;
8767 const char *unsupported_str = "";
8768
8769 if (desired_access & SSH2_FXF_WANT_READ_NAMED_ATTRS) {
8770 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8771 *unsupported_str ? "|" : "", "WANT_READ_NAMED_ATTRS", NULL);
8772 }
8773
8774 if (desired_access & SSH2_FXF_WANT_READ_ACL) {
8775 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8776 *unsupported_str ? "|" : "", "WANT_READ_ACL", NULL);
8777 }
8778
8779 if (desired_access & SSH2_FXF_WANT_WRITE_NAMED_ATTRS) {
8780 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8781 *unsupported_str ? "|" : "", "WANT_WRITE_NAMED_ATTRS", NULL);
8782 }
8783
8784 if (desired_access & SSH2_FXF_WANT_WRITE_ACL) {
8785 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8786 *unsupported_str ? "|" : "", "WANT_WRITE_ACL", NULL);
8787 }
8788
8789 if (desired_access & SSH2_FXF_WANT_WRITE_OWNER) {
8790 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8791 *unsupported_str ? "|" : "", "WANT_WRITE_OWNER", NULL);
8792 }
8793
8794 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8795 "client requested unsupported access '%s' in OPEN command, rejecting",
8796 unsupported_str);
8797
8798 status_code = SSH2_FX_OP_UNSUPPORTED;
8799
8800 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8801 (unsigned long) status_code, fxp_strerror(status_code));
8802
8803 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8804 fxp_strerror(status_code), NULL);
8805
8806 fxp_cmd_note_file_status(cmd, "failed");
8807 fxp_cmd_dispatch_err(cmd);
8808
8809 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8810 resp->payload = ptr;
8811 resp->payload_sz = (bufsz - buflen);
8812
8813 return fxp_packet_write(resp);
8814 }
8815 }
8816
8817 flags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
8818
8819 /* Check for any unsupported flags. */
8820 if (fxp_session->client_version > 4) {
8821 /* XXX If O_SHLOCK and O_EXLOCK are defined, as they are on OSX, the
8822 * ACCESS_READ_LOCK and ACCESS_WRITE_LOCK flags should be supported.
8823 *
8824 * Note that IF we support these LOCK flags, we will need to report
8825 * this support in the VERSION response as well.
8826 */
8827
8828 if ((flags & SSH2_FXF_ACCESS_READ_LOCK) ||
8829 (flags & SSH2_FXF_ACCESS_WRITE_LOCK) ||
8830 (flags & SSH2_FXF_ACCESS_DELETE_LOCK)) {
8831 uint32_t status_code;
8832 const char *unsupported_str = "";
8833
8834 if (flags & SSH2_FXF_ACCESS_READ_LOCK) {
8835 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8836 *unsupported_str ? "|" : "", "ACCESS_READ_LOCK", NULL);
8837 }
8838
8839 if (flags & SSH2_FXF_ACCESS_WRITE_LOCK) {
8840 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8841 *unsupported_str ? "|" : "", "ACCESS_WRITE_LOCK", NULL);
8842 }
8843
8844 if (flags & SSH2_FXF_ACCESS_DELETE_LOCK) {
8845 unsupported_str = pstrcat(fxp->pool, unsupported_str,
8846 *unsupported_str ? "|" : "", "ACCESS_DELETE_LOCK", NULL);
8847 }
8848
8849 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8850 "client requested unsupported flag '%s' in OPEN command, rejecting",
8851 unsupported_str);
8852
8853 status_code = SSH2_FX_OP_UNSUPPORTED;
8854
8855 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8856 (unsigned long) status_code, fxp_strerror(status_code));
8857
8858 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8859 fxp_strerror(status_code), NULL);
8860
8861 fxp_cmd_note_file_status(cmd, "failed");
8862 fxp_cmd_dispatch_err(cmd);
8863
8864 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8865 resp->payload = ptr;
8866 resp->payload_sz = (bufsz - buflen);
8867
8868 return fxp_packet_write(resp);
8869 }
8870
8871 /* Make sure the requested path exists. */
8872 pr_fs_clear_cache2(path);
8873 if (((flags & SSH2_FXF_OPEN_EXISTING) &&
8874 !(flags & SSH2_FXF_CREATE_TRUNCATE)) &&
8875 !exists2(fxp->pool, path)) {
8876 uint32_t status_code;
8877
8878 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8879 "client requested OPEN_EXISTING flag in OPEN command and '%s' does "
8880 "not exist", path);
8881
8882 status_code = SSH2_FX_NO_SUCH_FILE;
8883
8884 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
8885 (unsigned long) status_code, fxp_strerror(status_code));
8886
8887 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
8888 fxp_strerror(status_code), NULL);
8889
8890 fxp_cmd_note_file_status(cmd, "failed");
8891 fxp_cmd_dispatch_err(cmd);
8892
8893 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
8894 resp->payload = ptr;
8895 resp->payload_sz = (bufsz - buflen);
8896
8897 return fxp_packet_write(resp);
8898 }
8899 }
8900
8901 if (fxp_session->client_version < 5) {
8902 fxp_trace_v3_open_flags(fxp->pool, flags);
8903 open_flags = fxp_get_v3_open_flags(flags);
8904
8905 } else {
8906 fxp_trace_v5_open_flags(fxp->pool, desired_access, flags);
8907 open_flags = fxp_get_v5_open_flags(desired_access, flags);
8908 }
8909
8910 attrs = fxp_attrs_read(fxp, &fxp->payload, &fxp->payload_sz, &attr_flags,
8911 &xattrs);
8912 if (attrs == NULL) {
8913 fxp_cmd_note_file_status(cmd, "failed");
8914 fxp_cmd_dispatch_err(cmd);
8915
8916 /* XXX TODO: Provide a response to the client here */
8917 return 0;
8918 }
8919
8920 pr_trace_msg(trace_channel, 7, "received request: OPEN %s %s (%s)",
8921 path, fxp_strattrs(fxp->pool, attrs, &attr_flags),
8922 fxp_stroflags(fxp->pool, open_flags));
8923
8924 if (open_flags & O_APPEND) {
8925 cmd->cmd_class &= ~CL_MISC;
8926 cmd->cmd_class |= CL_WRITE;
8927 cmd2 = fxp_cmd_alloc(fxp->pool, C_APPE, path);
8928 cmd2->cmd_id = pr_cmd_get_id(C_APPE);
8929 session.curr_cmd = C_APPE;
8930
8931 if (pr_table_add(cmd2->notes, "mod_xfer.store-path",
8932 pstrdup(fxp->pool, path), 0) < 0) {
8933 if (errno != EEXIST) {
8934 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8935 "error adding 'mod_xfer.store-path' note: %s", strerror(errno));
8936 }
8937 }
8938
8939 } else if ((open_flags & O_WRONLY) ||
8940 (open_flags & O_RDWR)) {
8941 cmd2 = fxp_cmd_alloc(fxp->pool, C_STOR, path);
8942 cmd2->cmd_id = pr_cmd_get_id(C_STOR);
8943
8944 if (open_flags & O_WRONLY) {
8945 cmd->cmd_class &= ~CL_MISC;
8946 cmd->cmd_class |= CL_WRITE;
8947
8948 } else if (open_flags & O_RDWR) {
8949 cmd->cmd_class &= ~CL_MISC;
8950 cmd->cmd_class |= (CL_READ|CL_WRITE);
8951 }
8952
8953 session.curr_cmd = C_STOR;
8954
8955 if (pr_table_add(cmd2->notes, "mod_xfer.store-path",
8956 pstrdup(fxp->pool, path), 0) < 0) {
8957 if (errno != EEXIST) {
8958 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8959 "error adding 'mod_xfer.store-path' note: %s", strerror(errno));
8960 }
8961 }
8962
8963 } else if (open_flags == O_RDONLY) {
8964 cmd->cmd_class &= ~CL_MISC;
8965 cmd->cmd_class |= CL_READ;
8966 cmd2 = fxp_cmd_alloc(fxp->pool, C_RETR, path);
8967 cmd2->cmd_id = pr_cmd_get_id(C_RETR);
8968 session.curr_cmd = C_RETR;
8969
8970 /* We ignore any perms sent by the client for read-only requests.
8971 *
8972 * This happens because we explicitly call chown(2)/chmod(2) after
8973 * open(2) in order to handle UserOwner/GroupOwner directive. But this
8974 * breaks the semantics of open(2), which does not change the mode of
8975 * an existing file if the flags are O_RDONLY.
8976 */
8977 if (attr_flags & SSH2_FX_ATTR_PERMISSIONS) {
8978 pr_trace_msg(trace_channel, 15,
8979 "read-only OPEN request, ignoring perms sent by client");
8980 attr_flags &= ~SSH2_FX_ATTR_PERMISSIONS;
8981 }
8982
8983 if (pr_table_add(cmd2->notes, "mod_xfer.retr-path",
8984 pstrdup(fxp->pool, path), 0) < 0) {
8985 if (errno != EEXIST) {
8986 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
8987 "error adding 'mod_xfer.retr-path' note: %s", strerror(errno));
8988 }
8989 }
8990 }
8991
8992 if (cmd2) {
8993 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) < 0) {
8994 int xerrno = errno;
8995 const char *reason;
8996 uint32_t status_code;
8997
8998 /* One of the PRE_CMD phase handlers rejected the command. */
8999
9000 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9001 "OPEN command for '%s' blocked by '%s' handler", path,
9002 (char *) cmd2->argv[0]);
9003
9004 /* Hopefully the command handlers set an appropriate errno value. If
9005 * they didn't, however, we need to be prepared with a fallback.
9006 */
9007 if (xerrno != ENOENT &&
9008 xerrno != EPERM &&
9009 #if defined(EDQUOT)
9010 xerrno != EDQUOT &&
9011 #endif /* EDQUOT */
9012 #if defined(EFBIG)
9013 xerrno != EFBIG &&
9014 #endif /* EFBIG */
9015 #if defined(ENOSPC)
9016 xerrno != ENOSPC &&
9017 #endif /* ENOSPC */
9018 xerrno != EINVAL) {
9019 xerrno = EACCES;
9020 }
9021
9022 status_code = fxp_errno2status(xerrno, &reason);
9023
9024 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9025 "('%s' [%d])", (unsigned long) status_code, reason, strerror(errno),
9026 xerrno);
9027
9028 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9029 fxp_cmd_note_file_status(cmd2, "failed");
9030 fxp_cmd_dispatch_err(cmd2);
9031
9032 fxp_cmd_note_file_status(cmd, "failed");
9033 fxp_cmd_dispatch_err(cmd);
9034
9035 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9036 reason, NULL);
9037
9038 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9039 resp->payload = ptr;
9040 resp->payload_sz = (bufsz - buflen);
9041
9042 return fxp_packet_write(resp);
9043 }
9044
9045 path = cmd2->arg;
9046
9047 if (session.xfer.xfer_type == STOR_HIDDEN) {
9048 const void *nfs;
9049
9050 hiddenstore_path = pr_table_get(cmd2->notes,
9051 "mod_xfer.store-hidden-path", NULL);
9052
9053 nfs = pr_table_get(cmd2->notes, "mod_xfer.store-hidden-nfs", NULL);
9054 if (nfs == NULL) {
9055 open_flags |= O_EXCL;
9056 }
9057
9058 } else {
9059 pr_fs_clear_cache2(path);
9060 if (pr_fsio_lstat(path, &st) == 0) {
9061 if (S_ISLNK(st.st_mode)) {
9062 char link_path[PR_TUNABLE_PATH_MAX];
9063 int len;
9064
9065 memset(link_path, '\0', sizeof(link_path));
9066 len = dir_readlink(fxp->pool, path, link_path, sizeof(link_path)-1,
9067 PR_DIR_READLINK_FL_HANDLE_REL_PATH);
9068 if (len > 0) {
9069 link_path[len] = '\0';
9070 path = pstrdup(fxp->pool, link_path);
9071 } else {
9072 path = dir_best_path(fxp->pool, path);
9073 }
9074
9075 } else {
9076 path = dir_best_path(fxp->pool, path);
9077 }
9078
9079 } else {
9080 path = dir_best_path(fxp->pool, path);
9081 }
9082 }
9083
9084 if (hiddenstore_path != NULL) {
9085 pr_fs_clear_cache2(hiddenstore_path);
9086 }
9087
9088 file_existed = exists2(fxp->pool,
9089 hiddenstore_path ? hiddenstore_path : path);
9090
9091 if (file_existed &&
9092 (pr_cmd_cmp(cmd2, PR_CMD_STOR_ID) == 0 ||
9093 pr_cmd_cmp(cmd2, PR_CMD_APPE_ID) == 0)) {
9094
9095 /* Clear any existing key in the notes. */
9096 (void) pr_table_remove(cmd->notes, "mod_xfer.file-modified", NULL);
9097
9098 if (pr_table_add(cmd->notes, "mod_xfer.file-modified",
9099 pstrdup(cmd->pool, "true"), 0) < 0) {
9100 if (errno != EEXIST) {
9101 pr_log_pri(PR_LOG_NOTICE,
9102 "notice: error adding 'mod_xfer.file-modified' note: %s",
9103 strerror(errno));
9104 }
9105 }
9106
9107 /* Clear any existing key in the notes. */
9108 (void) pr_table_remove(cmd2->notes, "mod_xfer.file-modified", NULL);
9109
9110 if (pr_table_add(cmd2->notes, "mod_xfer.file-modified",
9111 pstrdup(cmd2->pool, "true"), 0) < 0) {
9112 if (errno != EEXIST) {
9113 pr_log_pri(PR_LOG_NOTICE,
9114 "notice: error adding 'mod_xfer.file-modified' note: %s",
9115 strerror(errno));
9116 }
9117 }
9118 }
9119 }
9120
9121 pr_fs_clear_cache2(path);
9122 if (exists2(fxp->pool, path)) {
9123 /* draft-ietf-secsh-filexfer-06.txt, section 7.1.1 specifically
9124 * states that any attributes in a OPEN request are ignored if the
9125 * file already exists.
9126 */
9127 if (attr_flags & SSH2_FX_ATTR_PERMISSIONS) {
9128 pr_trace_msg(trace_channel, 15,
9129 "OPEN request for existing path, ignoring perms sent by client");
9130 attr_flags &= ~SSH2_FX_ATTR_PERMISSIONS;
9131 }
9132
9133 if ((attr_flags & SSH2_FX_ATTR_UIDGID) ||
9134 (attr_flags & SSH2_FX_ATTR_OWNERGROUP)) {
9135 pr_trace_msg(trace_channel, 15,
9136 "OPEN request for existing path, ignoring ownership sent by client");
9137 attr_flags &= ~SSH2_FX_ATTR_UIDGID;
9138 attr_flags &= ~SSH2_FX_ATTR_OWNERGROUP;
9139 }
9140 }
9141
9142 /* We automatically add the O_NONBLOCK flag to the set of open() flags
9143 * in order to deal with writing to a FIFO whose other end may not be
9144 * open. Then, after a successful open, we return the file to blocking
9145 * mode.
9146 */
9147 fh = pr_fsio_open(hiddenstore_path ? hiddenstore_path : path,
9148 open_flags|O_NONBLOCK);
9149 if (fh == NULL) {
9150 uint32_t status_code;
9151 const char *reason;
9152 int xerrno = errno;
9153
9154 (void) pr_trace_msg("fileperms", 1, "OPEN, user '%s' (UID %s, GID %s): "
9155 "error opening '%s': %s", session.user,
9156 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
9157 hiddenstore_path ? hiddenstore_path : path, strerror(xerrno));
9158
9159 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9160 "error opening '%s': %s", hiddenstore_path ? hiddenstore_path : path,
9161 strerror(xerrno));
9162
9163 status_code = fxp_errno2status(xerrno, &reason);
9164
9165 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9166 "('%s' [%d])", (unsigned long) status_code, reason,
9167 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
9168
9169 if (cmd2 != NULL) {
9170 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9171 fxp_cmd_note_file_status(cmd2, "failed");
9172 fxp_cmd_dispatch_err(cmd2);
9173 }
9174
9175 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9176 reason, NULL);
9177
9178 fxp_cmd_note_file_status(cmd, "failed");
9179 fxp_cmd_dispatch_err(cmd);
9180
9181 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9182 resp->payload = ptr;
9183 resp->payload_sz = (bufsz - buflen);
9184
9185 return fxp_packet_write(resp);
9186 }
9187
9188 memset(&st, 0, sizeof(st));
9189 if (pr_fsio_fstat(fh, &st) < 0) {
9190 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9191 "fstat error on '%s' (fd %d): %s", path, fh->fh_fd, strerror(errno));
9192 }
9193
9194 #ifdef S_ISFIFO
9195 /* The path in question might be a FIFO. The FIFO case requires some special
9196 * handling, modulo any IgnoreFIFOs SFTPOption that might be in effect.
9197 */
9198 if (S_ISFIFO(st.st_mode) &&
9199 (sftp_opts & SFTP_OPT_IGNORE_FIFOS)) {
9200 uint32_t status_code;
9201 const char *reason;
9202 int xerrno = EPERM;
9203
9204 (void) pr_fsio_close(fh);
9205
9206 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9207 "error opening FIFO '%s': %s (IgnoreFIFOs SFTPOption in effect)",
9208 hiddenstore_path ? hiddenstore_path : path, strerror(xerrno));
9209
9210 status_code = fxp_errno2status(xerrno, &reason);
9211
9212 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9213 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
9214 xerrno);
9215
9216 if (cmd2 != NULL) {
9217 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9218 fxp_cmd_note_file_status(cmd2, "failed");
9219 fxp_cmd_dispatch_err(cmd2);
9220 }
9221
9222 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9223 reason, NULL);
9224
9225 fxp_cmd_note_file_status(cmd, "failed");
9226 fxp_cmd_dispatch_err(cmd);
9227
9228 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9229 resp->payload = ptr;
9230 resp->payload_sz = (bufsz - buflen);
9231
9232 return fxp_packet_write(resp);
9233 }
9234 #endif /* S_ISFIFO */
9235
9236 if (pr_fsio_set_block(fh) < 0) {
9237 pr_trace_msg(trace_channel, 3,
9238 "error setting fd %d (file '%s') as blocking: %s", fh->fh_fd,
9239 fh->fh_path, strerror(errno));
9240 }
9241
9242 attr_flags = fxp_attrs_clear_unsupported(attr_flags);
9243
9244 /* If the SFTPOption for ignoring perms for SFTP uploads is set, handle
9245 * it by clearing the SSH2_FX_ATTR_PERMISSIONS flag.
9246 */
9247 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_UPLOAD_PERMS) &&
9248 (attr_flags & SSH2_FX_ATTR_PERMISSIONS)) {
9249 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPUploadPerms' "
9250 "configured, ignoring perms sent by client");
9251 attr_flags &= ~SSH2_FX_ATTR_PERMISSIONS;
9252 }
9253
9254 /* If the SFTPOption for ignoring xattrs for SFTP uploads is set, handle it
9255 * by clearing the SSH2_FX_ATTR_EXTENDED flag.
9256 */
9257 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_UPLOAD_XATTRS) &&
9258 (attr_flags & SSH2_FX_ATTR_EXTENDED)) {
9259 pr_trace_msg(trace_channel, 7,
9260 "SFTPOption 'IgnoreSFTPUploadExtendedAttributes' configured, "
9261 "ignoring xattrs sent by client");
9262 attr_flags &= ~SSH2_FX_ATTR_EXTENDED;
9263 }
9264
9265 /* If the client provided a suggested size in the OPEN, ignore it.
9266 * Trying to honor the suggested size by truncating the file here can
9267 * cause problems, as when the client is resuming a transfer and the
9268 * resumption fails; the file would then be worse off than before due to the
9269 * truncation. See:
9270 *
9271 * http://winscp.net/tracker/show_bug.cgi?id=351
9272 *
9273 * The truncation isn't really needed anyway, since the ensuing READ/WRITE
9274 * requests will contain the offsets into the file at which to begin
9275 * reading/write the file contents.
9276 *
9277 * However, if the size is provided, we should at least record it in the
9278 * handle structure. In the case of an upload, we can compare the size of
9279 * file, at CLOSE time, with the size that was provided here. If the size
9280 * of the file at CLOSE is less than the size sent here, we could log it
9281 * as an incomplete upload. Not all clients will provide the size attribute,
9282 * for those that do, it can be useful.
9283 */
9284
9285 attr_flags &= ~SSH2_FX_ATTR_SIZE;
9286
9287 res = fxp_attrs_set(fh, fh->fh_path, attrs, attr_flags, xattrs, &buf,
9288 &buflen, fxp);
9289 if (res < 0) {
9290 int xerrno = errno;
9291
9292 pr_fsio_close(fh);
9293
9294 if (cmd2 != NULL) {
9295 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9296 fxp_cmd_note_file_status(cmd2, "failed");
9297 fxp_cmd_dispatch_err(cmd2);
9298 }
9299
9300 fxp_cmd_note_file_status(cmd, "failed");
9301 fxp_cmd_dispatch_err(cmd);
9302
9303 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9304 resp->payload = ptr;
9305 resp->payload_sz = (bufsz - buflen);
9306
9307 return fxp_packet_write(resp);
9308 }
9309
9310 if ((open_flags & O_WRONLY) ||
9311 (open_flags & O_RDWR)) {
9312 /* Handle any possible UserOwner/GroupOwner directives for uploaded
9313 * files.
9314 */
9315 if (sftp_misc_chown_file(fxp->pool, fh) < 0) {
9316 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9317 "error changing ownership on file '%s': %s", fh->fh_path,
9318 strerror(errno));
9319 }
9320 }
9321
9322 fxh = fxp_handle_create(fxp_pool);
9323 if (fxh == NULL) {
9324 uint32_t status_code;
9325 const char *reason;
9326 int xerrno = errno;
9327
9328 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9329 "error creating SFTP handle for '%s': %s", fh->fh_path, strerror(xerrno));
9330
9331 status_code = fxp_errno2status(xerrno, &reason);
9332
9333 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9334 "('%s' [%d])", (unsigned long) status_code, reason,
9335 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
9336
9337 if (cmd2 != NULL) {
9338 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9339 fxp_cmd_note_file_status(cmd2, "failed");
9340 fxp_cmd_dispatch_err(cmd2);
9341 }
9342
9343 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9344 reason, NULL);
9345
9346 fxp_cmd_note_file_status(cmd, "failed");
9347 fxp_cmd_dispatch_err(cmd);
9348
9349 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9350 resp->payload = ptr;
9351 resp->payload_sz = (bufsz - buflen);
9352
9353 return fxp_packet_write(resp);
9354 }
9355
9356 fxh->fh = fh;
9357 fxh->fh_flags = open_flags;
9358 fxh->fh_existed = file_existed;
9359 memcpy(fxh->fh_st, &st, sizeof(struct stat));
9360
9361 if (hiddenstore_path) {
9362 fxh->fh_real_path = pstrdup(fxh->pool, path);
9363 }
9364
9365 if (fxp_handle_add(fxp->channel_id, fxh) < 0) {
9366 uint32_t status_code;
9367 const char *reason;
9368 int xerrno = errno;
9369
9370 buf = ptr;
9371 buflen = bufsz;
9372
9373 status_code = fxp_errno2status(xerrno, &reason);
9374
9375 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9376 "('%s' [%d])", (unsigned long) status_code, reason,
9377 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
9378
9379 pr_fsio_close(fh);
9380 destroy_pool(fxh->pool);
9381
9382 if (cmd2 != NULL) {
9383 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9384 fxp_cmd_note_file_status(cmd2, "failed");
9385 fxp_cmd_dispatch_err(cmd2);
9386 }
9387
9388 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9389 reason, NULL);
9390
9391 fxp_cmd_note_file_status(cmd, "failed");
9392 fxp_cmd_dispatch_err(cmd);
9393
9394 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9395 resp->payload = ptr;
9396 resp->payload_sz = (bufsz - buflen);
9397
9398 return fxp_packet_write(resp);
9399 }
9400
9401 pr_trace_msg(trace_channel, 8, "sending response: HANDLE %s", fxh->name);
9402
9403 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_HANDLE);
9404 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
9405 sftp_msg_write_string(&buf, &buflen, fxh->name);
9406
9407 /* Clear out any transfer-specific data. */
9408 if (session.xfer.p) {
9409 destroy_pool(session.xfer.p);
9410 }
9411 memset(&session.xfer, 0, sizeof(session.xfer));
9412
9413 session.xfer.p = make_sub_pool(fxp_pool);
9414 pr_pool_tag(session.xfer.p, "SFTP session transfer pool");
9415 session.xfer.path = pstrdup(session.xfer.p, orig_path);
9416 memset(&session.xfer.start_time, 0, sizeof(session.xfer.start_time));
9417 gettimeofday(&session.xfer.start_time, NULL);
9418
9419 if ((open_flags & O_APPEND) ||
9420 (open_flags & O_WRONLY) ||
9421 (open_flags & O_RDWR)) {
9422
9423 /* Advise the platform that we will be only writing this file. */
9424 pr_fs_fadvise(PR_FH_FD(fxh->fh), 0, 0, PR_FS_FADVISE_DONTNEED);
9425
9426 session.xfer.direction = PR_NETIO_IO_RD;
9427
9428 } else if (open_flags == O_RDONLY) {
9429 /* Advise the platform that we will be only reading this file, and that
9430 * we will be accessing the data soon.
9431 */
9432 pr_fs_fadvise(PR_FH_FD(fxh->fh), 0, 0, PR_FS_FADVISE_SEQUENTIAL);
9433 pr_fs_fadvise(PR_FH_FD(fxh->fh), 0, 0, PR_FS_FADVISE_WILLNEED);
9434
9435 session.xfer.direction = PR_NETIO_IO_WR;
9436 }
9437
9438 pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
9439
9440 timeout_stalled = pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED);
9441 if (timeout_stalled > 0) {
9442 pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL,
9443 fxp_timeout_stalled_cb, "TimeoutStalled");
9444 }
9445
9446 /* Add a note containing the file handle for logging (Bug#3707). */
9447 fxp_set_filehandle_note(cmd, fxh);
9448
9449 fxp_cmd_dispatch(cmd);
9450
9451 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9452 resp->payload = ptr;
9453 resp->payload_sz = (bufsz - buflen);
9454
9455 return fxp_packet_write(resp);
9456 }
9457
fxp_handle_opendir(struct fxp_packet * fxp)9458 static int fxp_handle_opendir(struct fxp_packet *fxp) {
9459 unsigned char *buf, *ptr;
9460 char *path, *vpath;
9461 uint32_t buflen, bufsz;
9462 int timeout_stalled;
9463 void *dirh;
9464 struct fxp_handle *fxh;
9465 struct fxp_packet *resp;
9466 cmd_rec *cmd, *cmd2;
9467 struct stat st;
9468
9469 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
9470 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
9471 path = sftp_utf8_decode_str(fxp->pool, path);
9472 }
9473
9474 pr_scoreboard_entry_update(session.pid,
9475 PR_SCORE_CMD, "%s", "OPENDIR", NULL, NULL);
9476 pr_scoreboard_entry_update(session.pid,
9477 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
9478
9479 pr_proctitle_set("%s - %s: OPENDIR %s", session.user, session.proc_prefix,
9480 path);
9481
9482 pr_trace_msg(trace_channel, 7, "received request: OPENDIR %s", path);
9483
9484 if (strlen(path) == 0) {
9485 /* Use the default directory if the path is empty. */
9486 path = sftp_auth_get_default_dir();
9487
9488 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9489 "empty path given in OPENDIR request, using '%s'", path);
9490 }
9491
9492 cmd = fxp_cmd_alloc(fxp->pool, "OPENDIR", path);
9493 cmd->cmd_class = CL_DIRS|CL_SFTP;
9494
9495 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
9496 buf = ptr = palloc(fxp->pool, bufsz);
9497
9498 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
9499 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
9500
9501 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9502 "OPENDIR of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
9503
9504 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
9505 (unsigned long) status_code, fxp_strerror(status_code));
9506
9507 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9508 fxp_strerror(status_code), NULL);
9509
9510 fxp_cmd_dispatch_err(cmd);
9511
9512 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9513 resp->payload = ptr;
9514 resp->payload_sz = (bufsz - buflen);
9515
9516 return fxp_packet_write(resp);
9517 }
9518
9519 /* The path may have been changed by any PRE_CMD handlers. */
9520 path = cmd->arg;
9521
9522 pr_fs_clear_cache2(path);
9523 if (pr_fsio_lstat(path, &st) == 0) {
9524 if (S_ISLNK(st.st_mode)) {
9525 char link_path[PR_TUNABLE_PATH_MAX];
9526 int len;
9527
9528 memset(link_path, '\0', sizeof(link_path));
9529 len = dir_readlink(fxp->pool, path, link_path, sizeof(link_path)-1,
9530 PR_DIR_READLINK_FL_HANDLE_REL_PATH);
9531 if (len > 0) {
9532 link_path[len] = '\0';
9533 path = pstrdup(fxp->pool, link_path);
9534 }
9535 }
9536 }
9537
9538 path = dir_best_path(fxp->pool, path);
9539 if (path == NULL) {
9540 int xerrno = EACCES;
9541 const char *reason;
9542 uint32_t status_code;
9543
9544 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9545 "OPENDIR request denied: unable to access path '%s'", cmd->arg);
9546
9547 status_code = fxp_errno2status(xerrno, &reason);
9548
9549 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9550 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
9551 xerrno);
9552
9553 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9554 reason, NULL);
9555
9556 fxp_cmd_dispatch_err(cmd);
9557
9558 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9559 resp->payload = ptr;
9560 resp->payload_sz = (bufsz - buflen);
9561
9562 return fxp_packet_write(resp);
9563 }
9564
9565 if (!dir_check(fxp->pool, cmd, G_DIRS, path, NULL)) {
9566 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
9567
9568 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9569 "OPENDIR of '%s' blocked by <Limit> configuration", path);
9570
9571 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
9572 (unsigned long) status_code, fxp_strerror(status_code));
9573
9574 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9575 fxp_strerror(status_code), NULL);
9576
9577 fxp_cmd_dispatch_err(cmd);
9578
9579 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9580 resp->payload = ptr;
9581 resp->payload_sz = (bufsz - buflen);
9582
9583 return fxp_packet_write(resp);
9584 }
9585
9586 cmd2 = fxp_cmd_alloc(fxp->pool, C_MLSD, path);
9587 cmd2->cmd_class = CL_DIRS;
9588 cmd2->cmd_id = pr_cmd_get_id(C_MLSD);
9589
9590 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) < 0) {
9591 int xerrno = errno;
9592 const char *reason;
9593 uint32_t status_code;
9594
9595 /* One of the PRE_CMD phase handlers rejected the command. */
9596 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9597 "OPENDIR command for '%s' blocked by '%s' handler", path,
9598 (char *) cmd2->argv[0]);
9599
9600 /* Hopefully the command handlers set an appropriate errno value. If
9601 * they didn't, however, we need to be prepared with a fallback.
9602 */
9603 if (xerrno != ENOENT &&
9604 xerrno != EACCES &&
9605 xerrno != EPERM &&
9606 xerrno != EINVAL) {
9607 xerrno = EACCES;
9608 }
9609
9610 status_code = fxp_errno2status(xerrno, &reason);
9611
9612 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9613 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
9614 xerrno);
9615
9616 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9617 fxp_cmd_dispatch_err(cmd2);
9618
9619 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9620 reason, NULL);
9621
9622 fxp_cmd_dispatch_err(cmd);
9623
9624 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9625 resp->payload = ptr;
9626 resp->payload_sz = (bufsz - buflen);
9627
9628 return fxp_packet_write(resp);
9629 }
9630
9631 /* The path may have been changed by any PRE_CMD handlers. */
9632 path = cmd2->arg;
9633
9634 vpath = dir_canonical_vpath(fxp->pool, path);
9635 if (vpath == NULL) {
9636 uint32_t status_code;
9637 const char *reason;
9638 int xerrno = errno;
9639
9640 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9641 "error resolving '%s': %s", path, strerror(xerrno));
9642
9643 status_code = fxp_errno2status(xerrno, &reason);
9644
9645 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9646 "('%s' [%d])", (unsigned long) status_code, reason,
9647 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
9648
9649 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9650 fxp_cmd_dispatch_err(cmd2);
9651
9652 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9653 reason, NULL);
9654
9655 fxp_cmd_dispatch_err(cmd);
9656
9657 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9658 resp->payload = ptr;
9659 resp->payload_sz = (bufsz - buflen);
9660
9661 return fxp_packet_write(resp);
9662 }
9663
9664 path = vpath;
9665
9666 dirh = pr_fsio_opendir(path);
9667 if (dirh == NULL) {
9668 uint32_t status_code;
9669 const char *reason;
9670 int xerrno = errno;
9671
9672 (void) pr_trace_msg("fileperms", 1, "OPENDIR, user '%s' (UID %s, "
9673 "GID %s): error opening '%s': %s", session.user,
9674 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
9675 path, strerror(xerrno));
9676
9677 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9678 "error opening '%s': %s", path, strerror(xerrno));
9679
9680 status_code = fxp_errno2status(xerrno, &reason);
9681
9682 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9683 "('%s' [%d])", (unsigned long) status_code, reason,
9684 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
9685
9686 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9687 fxp_cmd_dispatch_err(cmd2);
9688
9689 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9690 reason, NULL);
9691
9692 fxp_cmd_dispatch_err(cmd);
9693
9694 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9695 resp->payload = ptr;
9696 resp->payload_sz = (bufsz - buflen);
9697
9698 return fxp_packet_write(resp);
9699 }
9700
9701 fxh = fxp_handle_create(fxp_pool);
9702 if (fxh == NULL) {
9703 uint32_t status_code;
9704 const char *reason;
9705 int xerrno = errno;
9706
9707 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9708 "error creating SFTP handle for '%s': %s", path, strerror(xerrno));
9709
9710 status_code = fxp_errno2status(xerrno, &reason);
9711
9712 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9713 "('%s' [%d])", (unsigned long) status_code, reason,
9714 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
9715
9716 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9717 fxp_cmd_dispatch_err(cmd2);
9718
9719 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9720 reason, NULL);
9721
9722 fxp_cmd_dispatch_err(cmd);
9723
9724 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9725 resp->payload = ptr;
9726 resp->payload_sz = (bufsz - buflen);
9727
9728 return fxp_packet_write(resp);
9729 }
9730
9731 fxh->dirh = dirh;
9732 fxh->dir = pstrdup(fxh->pool, path);
9733
9734 if (fxp_handle_add(fxp->channel_id, fxh) < 0) {
9735 uint32_t status_code;
9736 const char *reason;
9737 int xerrno = errno;
9738
9739 buf = ptr;
9740 buflen = bufsz;
9741
9742 status_code = fxp_errno2status(xerrno, &reason);
9743
9744 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9745 "('%s' [%d])", (unsigned long) status_code, reason,
9746 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
9747
9748 if (pr_fsio_closedir(dirh) < 0) {
9749 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9750 "error closing directory '%s': %s", fxh->dir, strerror(xerrno));
9751 }
9752
9753 destroy_pool(fxh->pool);
9754
9755 pr_response_add_err(R_451, "%s: %s", cmd2->arg, strerror(xerrno));
9756 fxp_cmd_dispatch_err(cmd2);
9757
9758 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9759 reason, NULL);
9760
9761 fxp_cmd_dispatch_err(cmd);
9762
9763 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9764 resp->payload = ptr;
9765 resp->payload_sz = (bufsz - buflen);
9766
9767 return fxp_packet_write(resp);
9768 }
9769
9770 pr_trace_msg(trace_channel, 8, "sending response: HANDLE %s",
9771 fxh->name);
9772
9773 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_HANDLE);
9774 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
9775 sftp_msg_write_string(&buf, &buflen, fxh->name);
9776
9777 /* If there is any existing transfer-specific data, leave it alone.
9778 *
9779 * Unlike FTP, SFTP allows for file downloads whilst in the middle of
9780 * a directory listing. Thus this OPENDIR could arrive while a file
9781 * is being read/written. Assume that the per-file stats are more
9782 * important.
9783 */
9784 if (session.xfer.p == NULL) {
9785 memset(&session.xfer, 0, sizeof(session.xfer));
9786
9787 session.xfer.p = make_sub_pool(fxp_pool);
9788 pr_pool_tag(session.xfer.p, "SFTP session transfer pool");
9789 memset(&session.xfer.start_time, 0, sizeof(session.xfer.start_time));
9790 gettimeofday(&session.xfer.start_time, NULL);
9791 session.xfer.direction = PR_NETIO_IO_WR;
9792 }
9793
9794 pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
9795
9796 timeout_stalled = pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED);
9797 if (timeout_stalled > 0) {
9798 pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL,
9799 fxp_timeout_stalled_cb, "TimeoutStalled");
9800 }
9801
9802 fxp_cmd_dispatch(cmd);
9803
9804 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9805 resp->payload = ptr;
9806 resp->payload_sz = (bufsz - buflen);
9807
9808 return fxp_packet_write(resp);
9809 }
9810
fxp_handle_read(struct fxp_packet * fxp)9811 static int fxp_handle_read(struct fxp_packet *fxp) {
9812 unsigned char *buf, *data = NULL, *ptr;
9813 char *file, *name, *ptr2;
9814 ssize_t res;
9815 uint32_t buflen, bufsz, datalen;
9816 uint64_t offset;
9817 struct fxp_handle *fxh;
9818 struct fxp_packet *resp;
9819 cmd_rec *cmd, *cmd2;
9820 pr_buffer_t *pbuf;
9821
9822 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
9823 offset = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
9824 datalen = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
9825
9826 #if 0
9827 /* XXX This doesn't appear to be needed now. But I'll keep it around,
9828 * just in case some buggy client needs this treatment.
9829 */
9830 if (datalen > max_readsz) {
9831 pr_trace_msg(trace_channel, 8,
9832 "READ requested len %lu exceeds max (%lu), truncating",
9833 (unsigned long) datalen, (unsigned long) max_readsz);
9834 datalen = max_readsz;
9835 }
9836 #endif
9837
9838 cmd = fxp_cmd_alloc(fxp->pool, "READ", name);
9839 cmd->cmd_class = CL_READ|CL_SFTP;
9840
9841 pr_scoreboard_entry_update(session.pid,
9842 PR_SCORE_CMD, "%s", "READ", NULL, NULL);
9843 pr_scoreboard_entry_update(session.pid,
9844 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
9845
9846 pr_proctitle_set("%s - %s: READ %s %" PR_LU " %lu", session.user,
9847 session.proc_prefix, name, (pr_off_t) offset, (unsigned long) datalen);
9848
9849 pr_trace_msg(trace_channel, 7, "received request: READ %s %" PR_LU " %lu",
9850 name, (pr_off_t) offset, (unsigned long) datalen);
9851
9852 buflen = bufsz = datalen + 64;
9853 buf = ptr = palloc(fxp->pool, bufsz);
9854
9855 fxh = fxp_handle_get(name);
9856 if (fxh == NULL) {
9857 uint32_t status_code;
9858
9859 pr_trace_msg(trace_channel, 17,
9860 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
9861 name, strerror(errno));
9862
9863 status_code = SSH2_FX_INVALID_HANDLE;
9864
9865 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
9866 (unsigned long) status_code, fxp_strerror(status_code));
9867
9868 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9869 fxp_strerror(status_code), NULL);
9870
9871 fxp_cmd_dispatch_err(cmd);
9872
9873 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9874 resp->payload = ptr;
9875 resp->payload_sz = (bufsz - buflen);
9876
9877 return fxp_packet_write(resp);
9878 }
9879
9880 if (fxh->fh == NULL) {
9881 uint32_t status_code = SSH2_FX_INVALID_HANDLE;
9882
9883 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
9884 (unsigned long) status_code, fxp_strerror(status_code));
9885
9886 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9887 fxp_strerror(status_code), NULL);
9888
9889 fxp_cmd_dispatch_err(cmd);
9890
9891 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9892 resp->payload = ptr;
9893 resp->payload_sz = (bufsz - buflen);
9894
9895 return fxp_packet_write(resp);
9896 }
9897
9898 /* Add a note containing the file handle for logging (Bug#3707). */
9899 fxp_set_filehandle_note(cmd, fxh);
9900
9901 pr_scoreboard_entry_update(session.pid,
9902 PR_SCORE_CMD_ARG, "%s", fxh->fh->fh_path, NULL, NULL);
9903
9904 if ((off_t) offset > fxh->fh_st->st_size) {
9905 uint32_t status_code;
9906 const char *reason;
9907 int xerrno = EOF;
9908
9909 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9910 "requested read offset (%" PR_LU " bytes) greater than size of "
9911 "'%s' (%" PR_LU " bytes)", (pr_off_t) offset, fxh->fh->fh_path,
9912 (pr_off_t) fxh->fh_st->st_size);
9913
9914 status_code = fxp_errno2status(xerrno, &reason);
9915
9916 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
9917 "('%s' [%d])", (unsigned long) status_code, reason, "End of file",
9918 xerrno);
9919
9920 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9921 reason, NULL);
9922
9923 fxp_cmd_dispatch_err(cmd);
9924
9925 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9926 resp->payload = ptr;
9927 resp->payload_sz = (bufsz - buflen);
9928
9929 return fxp_packet_write(resp);
9930 }
9931
9932 pr_scoreboard_entry_update(session.pid,
9933 PR_SCORE_XFER_SIZE, fxh->fh_st->st_size,
9934 PR_SCORE_XFER_DONE, (off_t) offset,
9935 NULL);
9936
9937 /* Trim the full path to just the filename, for our RETR command. */
9938 ptr2 = strrchr(fxh->fh->fh_path, '/');
9939 if (ptr2 != NULL &&
9940 ptr2 != fxh->fh->fh_path) {
9941 file = pstrdup(fxp->pool, ptr2 + 1);
9942
9943 } else {
9944 file = fxh->fh->fh_path;
9945 }
9946
9947 cmd2 = fxp_cmd_alloc(fxp->pool, C_RETR, file);
9948 cmd2->cmd_class = CL_READ|CL_SFTP;
9949
9950 if (!dir_check(fxp->pool, cmd, G_READ, fxh->fh->fh_path, NULL)) {
9951 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
9952
9953 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
9954 "READ of '%s' blocked by <Limit> configuration", fxh->fh->fh_path);
9955
9956 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
9957 (unsigned long) status_code, fxp_strerror(status_code));
9958
9959 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9960 fxp_strerror(status_code), NULL);
9961
9962 fxp_cmd_dispatch_err(cmd);
9963
9964 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9965 resp->payload = ptr;
9966 resp->payload_sz = (bufsz - buflen);
9967
9968 return fxp_packet_write(resp);
9969 }
9970
9971 /* XXX Check MaxRetrieveFileSize */
9972
9973 if (fxp_path_pass_regex_filters(fxp->pool, "READ", fxh->fh->fh_path) < 0) {
9974 uint32_t status_code;
9975 const char *reason;
9976
9977 status_code = fxp_errno2status(errno, &reason);
9978
9979 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
9980 (unsigned long) status_code, reason);
9981
9982 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
9983 reason, NULL);
9984
9985 fxp_cmd_dispatch_err(cmd);
9986
9987 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
9988 resp->payload = ptr;
9989 resp->payload_sz = (bufsz - buflen);
9990
9991 return fxp_packet_write(resp);
9992 }
9993
9994 if (S_ISREG(fxh->fh_st->st_mode)) {
9995 off_t *file_offset;
9996
9997 /* Stash the offset at which we're reading from this file. */
9998 file_offset = palloc(cmd->pool, sizeof(off_t));
9999 *file_offset = (off_t) offset;
10000 (void) pr_table_add(cmd->notes, "mod_xfer.file-offset", file_offset,
10001 sizeof(off_t));
10002 }
10003
10004 cmd2 = fxp_cmd_alloc(fxp->pool, C_RETR, NULL);
10005 pr_throttle_init(cmd2);
10006
10007 if (datalen > 0) {
10008 data = palloc(fxp->pool, datalen);
10009 res = pr_fsio_pread(fxh->fh, data, datalen, offset);
10010
10011 } else {
10012 res = 0;
10013 }
10014
10015 if (pr_data_get_timeout(PR_DATA_TIMEOUT_NO_TRANSFER) > 0) {
10016 pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
10017 }
10018
10019 if (pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED) > 0) {
10020 pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
10021 }
10022
10023 if (res <= 0) {
10024 uint32_t status_code;
10025 const char *reason;
10026 int xerrno;
10027
10028 if (res < 0) {
10029 xerrno = errno;
10030
10031 (void) pr_trace_msg("fileperms", 1, "READ, user '%s' (UID %s, GID %s): "
10032 "error reading from '%s': %s", session.user,
10033 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
10034 fxh->fh->fh_path, strerror(xerrno));
10035
10036 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10037 "error reading from '%s': %s", fxh->fh->fh_path, strerror(xerrno));
10038
10039 errno = xerrno;
10040
10041 } else {
10042 /* Assume EOF */
10043 pr_throttle_pause(offset, TRUE);
10044 xerrno = EOF;
10045 }
10046
10047 status_code = fxp_errno2status(xerrno, &reason);
10048
10049 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
10050 "('%s' [%d])", (unsigned long) status_code, reason,
10051 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
10052
10053 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10054 reason, NULL);
10055
10056 if (xerrno != EOF) {
10057 fxp_cmd_dispatch_err(cmd);
10058
10059 } else {
10060 fxp_cmd_dispatch(cmd);
10061 }
10062
10063 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10064 resp->payload = ptr;
10065 resp->payload_sz = (bufsz - buflen);
10066
10067 return fxp_packet_write(resp);
10068 }
10069
10070 pr_throttle_pause(offset, FALSE);
10071
10072 pr_trace_msg(trace_channel, 8, "sending response: DATA (%lu bytes)",
10073 (unsigned long) res);
10074
10075 pbuf = pcalloc(fxp->pool, sizeof(pr_buffer_t));
10076 pbuf->buf = (char *) data;
10077 pbuf->buflen = res;
10078 pbuf->current = pbuf->buf;
10079 pbuf->remaining = 0;
10080 pr_event_generate("mod_sftp.sftp.data-write", pbuf);
10081
10082 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_DATA);
10083 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
10084 sftp_msg_write_data(&buf, &buflen, data, res, TRUE);
10085
10086 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10087 resp->payload = ptr;
10088 resp->payload_sz = (bufsz - buflen);
10089
10090 fxh->fh_bytes_xferred += res;
10091 session.xfer.total_bytes += res;
10092 session.total_bytes += res;
10093
10094 fxp_cmd_dispatch(cmd);
10095
10096 res = fxp_packet_write(resp);
10097 return res;
10098 }
10099
fxp_handle_readdir(struct fxp_packet * fxp)10100 static int fxp_handle_readdir(struct fxp_packet *fxp) {
10101 register unsigned int i;
10102 unsigned char *buf;
10103 char *cmd_name, *name;
10104 uint32_t attr_flags, buflen, curr_packet_pathsz = 0, max_packetsz;
10105 struct dirent *dent;
10106 struct fxp_buffer *fxb;
10107 struct fxp_dirent **paths;
10108 struct fxp_handle *fxh;
10109 struct fxp_packet *resp;
10110 array_header *path_list;
10111 cmd_rec *cmd;
10112 int have_error = FALSE, have_eod = TRUE, res;
10113 mode_t *fake_mode = NULL;
10114 const char *fake_user = NULL, *fake_group = NULL, *vwd = NULL;
10115
10116 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
10117
10118 cmd = fxp_cmd_alloc(fxp->pool, "READDIR", name);
10119 cmd->cmd_class = CL_DIRS|CL_SFTP;
10120 cmd->group = G_DIRS;
10121
10122 pr_scoreboard_entry_update(session.pid,
10123 PR_SCORE_CMD, "%s", "READDIR", NULL, NULL);
10124 pr_scoreboard_entry_update(session.pid,
10125 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
10126
10127 pr_proctitle_set("%s - %s: READDIR %s", session.user, session.proc_prefix,
10128 name);
10129
10130 pr_trace_msg(trace_channel, 7, "received request: READDIR %s", name);
10131
10132 /* XXX What's a good size here? */
10133
10134 fxb = pcalloc(fxp->pool, sizeof(struct fxp_buffer));
10135
10136 max_packetsz = sftp_channel_get_max_packetsz();
10137 fxb->bufsz = buflen = max_packetsz;
10138 fxb->ptr = buf = palloc(fxp->pool, fxb->bufsz);
10139
10140 fxh = fxp_handle_get(name);
10141 if (fxh == NULL) {
10142 uint32_t status_code;
10143
10144 pr_trace_msg(trace_channel, 17,
10145 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
10146 name, strerror(errno));
10147
10148 status_code = SSH2_FX_INVALID_HANDLE;
10149
10150 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10151 (unsigned long) status_code, fxp_strerror(status_code));
10152
10153 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10154 fxp_strerror(status_code), NULL);
10155
10156 fxp_cmd_dispatch_err(cmd);
10157
10158 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10159 resp->payload = fxb->ptr;
10160 resp->payload_sz = (fxb->bufsz - buflen);
10161
10162 return fxp_packet_write(resp);
10163 }
10164
10165 if (fxh->dirh == NULL) {
10166 uint32_t status_code = SSH2_FX_INVALID_HANDLE;
10167
10168 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10169 (unsigned long) status_code, fxp_strerror(status_code));
10170
10171 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10172 fxp_strerror(status_code), NULL);
10173
10174 fxp_cmd_dispatch_err(cmd);
10175
10176 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10177 resp->payload = fxb->ptr;
10178 resp->payload_sz = (fxb->bufsz - buflen);
10179
10180 return fxp_packet_write(resp);
10181 }
10182
10183 pr_scoreboard_entry_update(session.pid,
10184 PR_SCORE_CMD_ARG, "%s", fxh->dir, NULL, NULL);
10185
10186 path_list = make_array(fxp->pool, 5, sizeof(struct fxp_dirent *));
10187
10188 cmd_name = cmd->argv[0];
10189
10190 /* If blocked by <Limit LIST>/<Limit NLST>, return EOF immediately. */
10191 pr_cmd_set_name(cmd, C_LIST);
10192 res = dir_check(fxp->pool, cmd, cmd->group, (char *) fxh->dir, NULL);
10193 if (res == 0) {
10194 have_error = TRUE;
10195 }
10196
10197 if (!have_error) {
10198 pr_cmd_set_name(cmd, C_NLST);
10199 res = dir_check(fxp->pool, cmd, cmd->group, (char *) fxh->dir, NULL);
10200 if (res == 0) {
10201 have_error = TRUE;
10202 }
10203 }
10204
10205 pr_cmd_set_name(cmd, "READDIR");
10206 res = dir_check(fxp->pool, cmd, cmd->group, (char *) fxh->dir, NULL);
10207 if (res == 2) {
10208 /* Explicitly allowed by <Limit READDIR> configuration. */
10209 have_error = FALSE;
10210
10211 } else if (res == 0) {
10212 have_error = TRUE;
10213 }
10214
10215 if (have_error) {
10216 uint32_t status_code = SSH2_FX_EOF;
10217
10218 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10219 "READDIR of '%s' blocked by <Limit %s> configuration", fxh->dir,
10220 (char *) cmd->argv[0]);
10221
10222 pr_cmd_set_name(cmd, cmd_name);
10223
10224 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10225 (unsigned long) status_code, fxp_strerror(status_code));
10226
10227 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10228 fxp_strerror(status_code), NULL);
10229
10230 fxp_cmd_dispatch_err(cmd);
10231
10232 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10233 resp->payload = fxb->ptr;
10234 resp->payload_sz = (fxb->bufsz - buflen);
10235
10236 return fxp_packet_write(resp);
10237 }
10238
10239 pr_cmd_set_name(cmd, cmd_name);
10240
10241 /* Change into the directory being read, so that ".", "..", and relative
10242 * paths (e.g. for symlinks) get resolved properly.
10243 *
10244 * We need to dup the string returned by pr_fs_getvwd(), since it returns
10245 * a pointer to a static string which is changed by the call we make
10246 * to pr_fsio_chdir().
10247 */
10248 vwd = pstrdup(fxp->pool, pr_fs_getvwd());
10249
10250 res = pr_fsio_chdir(fxh->dir, FALSE);
10251 if (res < 0) {
10252 uint32_t status_code;
10253 const char *reason;
10254 int xerrno = errno;
10255
10256 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10257 "unable to chdir to '%s': %s", (char *) fxh->dir, strerror(xerrno));
10258
10259 status_code = fxp_errno2status(xerrno, &reason);
10260
10261 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10262 (unsigned long) status_code, reason);
10263
10264 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10265 fxp_strerror(status_code), NULL);
10266
10267 fxp_cmd_dispatch_err(cmd);
10268
10269 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10270 resp->payload = fxb->ptr;
10271 resp->payload_sz = (fxb->bufsz - buflen);
10272
10273 return fxp_packet_write(resp);
10274 }
10275
10276 fake_mode = get_param_ptr(get_dir_ctxt(fxp->pool, (char *) fxh->dir),
10277 "DirFakeMode", FALSE);
10278
10279 fake_user = get_param_ptr(get_dir_ctxt(fxp->pool, (char *) fxh->dir),
10280 "DirFakeUser", FALSE);
10281 if (fake_user != NULL &&
10282 strncmp(fake_user, "~", 2) == 0) {
10283 fake_user = session.user;
10284 }
10285
10286 fake_group = get_param_ptr(get_dir_ctxt(fxp->pool, (char *) fxh->dir),
10287 "DirFakeGroup", FALSE);
10288 if (fake_group != NULL &&
10289 strncmp(fake_group, "~", 2) == 0) {
10290 fake_group = session.group;
10291 }
10292
10293 while ((dent = pr_fsio_readdir(fxh->dirh)) != NULL) {
10294 char *real_path;
10295 struct fxp_dirent *fxd;
10296 uint32_t curr_packetsz, max_entry_metadata, max_entrysz;
10297 size_t dent_len;
10298
10299 pr_signals_handle();
10300
10301 /* How much non-path data do we expect to be associated with this entry? */
10302 #ifdef PR_USE_XATTR
10303 /* Note that the "extra space" to allocate for extended attributes is
10304 * currently a bit of a guess. Initially, this was 4K; that was causing
10305 * slower directory listings due to the need for more READDIR requests,
10306 * since we were sending fewer entries back (limited by the max packet
10307 * size) per READDIR request.
10308 *
10309 * Now, we are trying 1K, and will see how that does.
10310 */
10311 max_entry_metadata = 1024;
10312 #else
10313 max_entry_metadata = 256;
10314 #endif /* PR_USE_XATTR */
10315
10316 max_entrysz = (PR_TUNABLE_PATH_MAX + 1 + max_entry_metadata);
10317
10318 /* Do not expand/resolve dot directories; it will be handled automatically
10319 * lower down in the ACL-checking code. Plus, this allows regex filters
10320 * that rely on the dot directory name to work properly.
10321 */
10322 if (!is_dotdir(dent->d_name)) {
10323 real_path = pdircat(fxp->pool, fxh->dir, dent->d_name, NULL);
10324
10325 } else {
10326 real_path = pstrdup(fxp->pool, dent->d_name);
10327 }
10328
10329 fxd = fxp_get_dirent(fxp->pool, cmd, real_path, fake_mode);
10330 if (fxd == NULL) {
10331 int xerrno = errno;
10332
10333 pr_trace_msg(trace_channel, 3,
10334 "unable to obtain directory listing for '%s': %s", real_path,
10335 strerror(xerrno));
10336
10337 continue;
10338 }
10339
10340 dent_len = strlen(dent->d_name);
10341 fxd->client_path = pstrndup(fxp->pool, dent->d_name, dent_len);
10342 curr_packet_pathsz += (dent_len + 1);
10343
10344 *((struct fxp_dirent **) push_array(path_list)) = fxd;
10345
10346 /* We determine the number of entries to send in this packet based on
10347 * the maximum packet size and the max entry size.
10348 *
10349 * We assume that each entry will need up to PR_TUNABLE_PATH_MAX+1 bytes for
10350 * the filename, and max_entry_metadata bytes of associated data.
10351 *
10352 * We have the total number of entries for this message when there is less
10353 * than enough space for one more maximum-sized entry.
10354 */
10355
10356 curr_packetsz = curr_packet_pathsz +
10357 (path_list->nelts * max_entry_metadata);
10358 if ((max_packetsz - curr_packetsz) <= max_entrysz) {
10359 have_eod = FALSE;
10360 break;
10361 }
10362 }
10363
10364 if (pr_data_get_timeout(PR_DATA_TIMEOUT_NO_TRANSFER) > 0) {
10365 pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
10366 }
10367
10368 if (pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED) > 0) {
10369 pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
10370 }
10371
10372 /* Now make sure we switch back to the directory where we were. */
10373 res = pr_fsio_chdir(vwd, FALSE);
10374 if (res < 0) {
10375 uint32_t status_code;
10376 const char *reason;
10377 int xerrno = errno;
10378
10379 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10380 "unable to chdir to '%s': %s", vwd, strerror(xerrno));
10381
10382 status_code = fxp_errno2status(xerrno, &reason);
10383
10384 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10385 (unsigned long) status_code, reason);
10386
10387 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10388 fxp_strerror(status_code), NULL);
10389
10390 fxp_cmd_dispatch_err(cmd);
10391
10392 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10393 resp->payload = fxb->ptr;
10394 resp->payload_sz = (fxb->bufsz - buflen);
10395
10396 return fxp_packet_write(resp);
10397 }
10398
10399 if (path_list->nelts == 0) {
10400 /* We have reached the end of the directory entries; send an EOF. */
10401 uint32_t status_code = SSH2_FX_EOF;
10402
10403 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10404 (unsigned long) status_code, fxp_strerror(status_code));
10405
10406 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10407 fxp_strerror(status_code), NULL);
10408
10409 fxp_cmd_dispatch(cmd);
10410
10411 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10412 resp->payload = fxb->ptr;
10413 resp->payload_sz = (fxb->bufsz - buflen);
10414
10415 return fxp_packet_write(resp);
10416 }
10417
10418 pr_trace_msg(trace_channel, 8, "sending response: NAME (%lu count)",
10419 (unsigned long) path_list->nelts);
10420
10421 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_NAME);
10422 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
10423 sftp_msg_write_int(&buf, &buflen, path_list->nelts);
10424
10425 fxb->buf = buf;
10426 fxb->buflen = buflen;
10427 paths = path_list->elts;
10428
10429 /* For READDIR requests, since they do NOT contain a flags field for clients
10430 * to express which attributes they want, we ASSUME some standard fields.
10431 */
10432
10433 if (fxp_session->client_version <= 3) {
10434 attr_flags = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_UIDGID|SSH2_FX_ATTR_PERMISSIONS|
10435 SSH2_FX_ATTR_ACMODTIME;
10436
10437 } else {
10438 attr_flags = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_PERMISSIONS|
10439 SSH2_FX_ATTR_ACCESSTIME|SSH2_FX_ATTR_MODIFYTIME|SSH2_FX_ATTR_OWNERGROUP;
10440 }
10441
10442 /* The FX_ATTR_LINK_COUNT attribute was defined in
10443 * draft-ietf-secsh-filexfer-06, which is SFTP protocol version 6.
10444 */
10445 if (fxp_session->client_version >= 6) {
10446 attr_flags |= SSH2_FX_ATTR_LINK_COUNT;
10447
10448 /* The FX_ATTR_EXTENDED attribute was defined in
10449 * draft-ietf-secsh-filexfer-02, which is SFTP protocol version 3.
10450 * However, many SFTP clients may not be prepared for handling these.
10451 * Thus we CHOOSE to only provide these extended attributes, if supported,
10452 * to protocol version 6 clients.
10453 */
10454 #ifdef PR_USE_XATTR
10455 if (!(fxp_fsio_opts & PR_FSIO_OPT_IGNORE_XATTR)) {
10456 attr_flags |= SSH2_FX_ATTR_EXTENDED;
10457 }
10458 #endif /* PR_USE_XATTR */
10459 }
10460
10461 for (i = 0; i < path_list->nelts; i++) {
10462 uint32_t name_len = 0;
10463
10464 name_len = fxp_name_write(fxp->pool, fxb, paths[i]->client_path,
10465 paths[i]->st, attr_flags, fake_user, fake_group);
10466
10467 pr_trace_msg(trace_channel, 19, "READDIR: FXP_NAME entry size: %lu bytes",
10468 (unsigned long) name_len);
10469 }
10470
10471 /* fxp_name_write will have changed the values stashed in the buffer. */
10472 buf = fxb->buf;
10473 buflen = fxb->buflen;
10474
10475 if (fxp_session->client_version > 5) {
10476 sftp_msg_write_bool(&buf, &buflen, have_eod ? TRUE : FALSE);
10477 }
10478
10479 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10480 resp->payload = fxb->ptr;
10481 resp->payload_sz = (fxb->bufsz - buflen);
10482
10483 session.xfer.total_bytes += resp->payload_sz;
10484 session.total_bytes += resp->payload_sz;
10485
10486 fxp_cmd_dispatch(cmd);
10487
10488 return fxp_packet_write(resp);
10489 }
10490
fxp_handle_readlink(struct fxp_packet * fxp)10491 static int fxp_handle_readlink(struct fxp_packet *fxp) {
10492 char data[PR_TUNABLE_PATH_MAX + 1];
10493 unsigned char *buf;
10494 char *path, *resolved_path;
10495 int res;
10496 uint32_t buflen;
10497 struct fxp_buffer *fxb;
10498 struct fxp_packet *resp;
10499 cmd_rec *cmd;
10500
10501 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
10502 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
10503 path = sftp_utf8_decode_str(fxp->pool, path);
10504 }
10505
10506 pr_scoreboard_entry_update(session.pid,
10507 PR_SCORE_CMD, "%s", "READLINK", NULL, NULL);
10508 pr_scoreboard_entry_update(session.pid,
10509 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
10510
10511 pr_proctitle_set("%s - %s: READLINK %s", session.user, session.proc_prefix,
10512 path);
10513
10514 pr_trace_msg(trace_channel, 7, "received request: READLINK %s", path);
10515
10516 if (strlen(path) == 0) {
10517 /* Use the default directory if the path is empty. */
10518 path = sftp_auth_get_default_dir();
10519
10520 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10521 "empty path given in READLINK request, using '%s'", path);
10522 }
10523
10524 cmd = fxp_cmd_alloc(fxp->pool, "READLINK", path);
10525 cmd->cmd_class = CL_READ|CL_SFTP;
10526
10527 fxb = pcalloc(fxp->pool, sizeof(struct fxp_buffer));
10528 fxb->bufsz = buflen = FXP_RESPONSE_NAME_DEFAULT_SZ;
10529 fxb->ptr = buf = palloc(fxp->pool, fxb->bufsz);
10530
10531 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
10532 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
10533
10534 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10535 "READLINK of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
10536
10537 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10538 (unsigned long) status_code, fxp_strerror(status_code));
10539
10540 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10541 fxp_strerror(status_code), NULL);
10542
10543 fxp_cmd_dispatch_err(cmd);
10544
10545 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10546 resp->payload = fxb->ptr;
10547 resp->payload_sz = (fxb->bufsz - buflen);
10548
10549 return fxp_packet_write(resp);
10550 }
10551
10552 /* The path may have been changed by any PRE_CMD handlers. */
10553 path = cmd->arg;
10554 pr_fs_clear_cache2(path);
10555
10556 resolved_path = dir_best_path(fxp->pool, path);
10557 if (resolved_path == NULL) {
10558 int xerrno = EACCES;
10559 const char *reason;
10560 uint32_t status_code;
10561
10562 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10563 "READLINK request denied: unable to access path '%s'", cmd->arg);
10564
10565 status_code = fxp_errno2status(xerrno, &reason);
10566
10567 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
10568 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
10569 xerrno);
10570
10571 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10572 reason, NULL);
10573
10574 fxp_cmd_dispatch_err(cmd);
10575
10576 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10577 resp->payload = fxb->ptr;
10578 resp->payload_sz = (fxb->bufsz - buflen);
10579
10580 return fxp_packet_write(resp);
10581 }
10582
10583 if (!dir_check(fxp->pool, cmd, G_READ, resolved_path, NULL)) {
10584 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
10585
10586 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10587 "READLINK of '%s' (resolved to '%s') blocked by <Limit %s> configuration",
10588 path, resolved_path, (char *) cmd->argv[0]);
10589
10590 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10591 (unsigned long) status_code, fxp_strerror(status_code));
10592
10593 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10594 fxp_strerror(status_code), NULL);
10595
10596 fxp_cmd_dispatch_err(cmd);
10597
10598 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10599 resp->payload = fxb->ptr;
10600 resp->payload_sz = (fxb->bufsz - buflen);
10601
10602 return fxp_packet_write(resp);
10603 }
10604
10605 memset(data, '\0', sizeof(data));
10606
10607 /* Note: do NOT use the resolved_path variable here, as it will have
10608 * resolved by following any symlinks; readlink(2) would then return EINVAL
10609 * for reading a non-symlink path.
10610 */
10611 res = dir_readlink(fxp->pool, path, data, sizeof(data) - 1,
10612 PR_DIR_READLINK_FL_HANDLE_REL_PATH);
10613 if (res < 0) {
10614 uint32_t status_code;
10615 const char *reason;
10616 int xerrno = errno;
10617
10618 buf = fxb->ptr;
10619 buflen = fxb->bufsz;
10620
10621 status_code = fxp_errno2status(xerrno, &reason);
10622
10623 (void) pr_trace_msg("fileperms", 1, "READLINK, user '%s' (UID %s, "
10624 "GID %s): error using readlink() on '%s': %s", session.user,
10625 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
10626 path, strerror(xerrno));
10627
10628 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
10629 "('%s' [%d])", (unsigned long) status_code, reason,
10630 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
10631
10632 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10633 reason, NULL);
10634
10635 fxp_cmd_dispatch_err(cmd);
10636
10637 } else {
10638 struct stat st;
10639 const char *fake_user = NULL, *fake_group = NULL;
10640
10641 memset(&st, 0, sizeof(struct stat));
10642
10643 data[res] = '\0';
10644
10645 pr_trace_msg(trace_channel, 8, "sending response: NAME 1 %s %s",
10646 data, fxp_strattrs(fxp->pool, &st, NULL));
10647
10648 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_NAME);
10649 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
10650 sftp_msg_write_int(&buf, &buflen, 1);
10651
10652 fake_user = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeUser",
10653 FALSE);
10654 if (fake_user != NULL &&
10655 strncmp(fake_user, "~", 2) == 0) {
10656 fake_user = session.user;
10657 }
10658
10659 fake_group = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeGroup",
10660 FALSE);
10661 if (fake_group != NULL &&
10662 strncmp(fake_group, "~", 2) == 0) {
10663 fake_group = session.group;
10664 }
10665
10666 fxb->buf = buf;
10667 fxb->buflen = buflen;
10668
10669 fxp_name_write(fxp->pool, fxb, data, &st, 0, fake_user, fake_group);
10670
10671 buf = fxb->buf;
10672 buflen = fxb->buflen;
10673
10674 fxp_cmd_dispatch(cmd);
10675 }
10676
10677 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10678 resp->payload = fxb->ptr;
10679 resp->payload_sz = (fxb->bufsz - buflen);
10680
10681 return fxp_packet_write(resp);
10682 }
10683
fxp_trace_v6_realpath_flags(pool * p,unsigned char flags,int client_sent)10684 static void fxp_trace_v6_realpath_flags(pool *p, unsigned char flags,
10685 int client_sent) {
10686 char *flags_str = "";
10687 int trace_level = 15;
10688
10689 if (pr_trace_get_level(trace_channel) < trace_level) {
10690 return;
10691 }
10692
10693 switch (flags) {
10694 case SSH2_FXRP_NO_CHECK:
10695 flags_str = "FX_REALPATH_NO_CHECK";
10696 break;
10697
10698 case SSH2_FXRP_STAT_IF:
10699 flags_str = "FX_REALPATH_STAT_IF";
10700 break;
10701
10702 case SSH2_FXRP_STAT_ALWAYS:
10703 flags_str = "FX_REALPATH_STAT_ALWAYS";
10704 break;
10705 }
10706
10707 pr_trace_msg(trace_channel, trace_level, "REALPATH flags = %s (%s)",
10708 flags_str, client_sent == TRUE ? "explicit" : "default");
10709 }
10710
fxp_handle_realpath(struct fxp_packet * fxp)10711 static int fxp_handle_realpath(struct fxp_packet *fxp) {
10712 int res, xerrno;
10713 unsigned char *buf, realpath_flags = SSH2_FXRP_NO_CHECK;
10714 char *path;
10715 uint32_t buflen;
10716 struct stat st;
10717 struct fxp_buffer *fxb;
10718 struct fxp_packet *resp;
10719 cmd_rec *cmd;
10720
10721 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
10722 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
10723 path = sftp_utf8_decode_str(fxp->pool, path);
10724 }
10725
10726 pr_scoreboard_entry_update(session.pid,
10727 PR_SCORE_CMD, "%s", "REALPATH", NULL, NULL);
10728 pr_scoreboard_entry_update(session.pid,
10729 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
10730
10731 pr_proctitle_set("%s - %s: REALPATH %s", session.user, session.proc_prefix,
10732 path);
10733
10734 pr_trace_msg(trace_channel, 7, "received request: REALPATH %s", path);
10735
10736 if (strlen(path) == 0) {
10737 /* Use the default directory if the path is empty. */
10738 path = sftp_auth_get_default_dir();
10739
10740 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10741 "empty path given in REALPATH request, using '%s'", path);
10742 }
10743
10744 cmd = fxp_cmd_alloc(fxp->pool, "REALPATH", path);
10745 cmd->cmd_class = CL_INFO|CL_SFTP;
10746
10747 if (fxp_session->client_version >= 6) {
10748 /* See Section 8.9 of:
10749 *
10750 * http://tools.ietf.org/id/draft-ietf-secsh-filexfer-13.txt
10751 *
10752 * for the semantics and defaults of these crazy flags.
10753 */
10754
10755 if (fxp->payload_sz >= sizeof(char)) {
10756 char *composite_path = NULL;
10757
10758 realpath_flags = sftp_msg_read_byte(fxp->pool, &fxp->payload,
10759 &fxp->payload_sz);
10760 fxp_trace_v6_realpath_flags(fxp->pool, realpath_flags, TRUE);
10761
10762 if (fxp->payload_sz > 0) {
10763 composite_path = sftp_msg_read_string(fxp->pool, &fxp->payload,
10764 &fxp->payload_sz);
10765
10766 /* XXX One problem with the most recent SFTP Draft is that it does NOT
10767 * include a count of the number of composite-paths that the client
10768 * may send. The format of the REALPATH request, currently, only allows
10769 * for one composite-path element; the description of this feature
10770 * implies that multiple such composite-path elements could be supplied.
10771 * Sigh. Maybe it's meant to a blob of strings? Or we keep reading
10772 * a string until the remaining payload size is zero?
10773 */
10774 pr_trace_msg(trace_channel, 13,
10775 "REALPATH request set composite-path: '%s'", composite_path);
10776 }
10777
10778 } else {
10779 fxp_trace_v6_realpath_flags(fxp->pool, realpath_flags, FALSE);
10780 }
10781 }
10782
10783 fxb = pcalloc(fxp->pool, sizeof(struct fxp_buffer));
10784 fxb->bufsz = buflen = FXP_RESPONSE_NAME_DEFAULT_SZ;
10785 fxb->ptr = buf = palloc(fxp->pool, fxb->bufsz);
10786
10787 res = pr_cmd_dispatch_phase(cmd, PRE_CMD, 0);
10788 if (res < 0) {
10789 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
10790
10791 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10792 "REALPATH of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
10793
10794 if (fxp_session->client_version <= 5 ||
10795 (fxp_session->client_version >= 6 &&
10796 realpath_flags != SSH2_FXRP_NO_CHECK)) {
10797 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
10798 (unsigned long) status_code, fxp_strerror(status_code));
10799
10800 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10801 fxp_strerror(status_code), NULL);
10802
10803 } else {
10804 uint32_t attr_flags = 0;
10805
10806 memset(&st, 0, sizeof(st));
10807 st.st_uid = (uid_t) -1;
10808 st.st_gid = (gid_t) -1;
10809
10810 pr_trace_msg(trace_channel, 8, "sending response: NAME 1 %s %s",
10811 path, fxp_strattrs(fxp->pool, &st, &attr_flags));
10812
10813 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_NAME);
10814 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
10815 sftp_msg_write_int(&buf, &buflen, 1);
10816
10817 fxb->buf = buf;
10818 fxb->buflen = buflen;
10819
10820 fxp_name_write(fxp->pool, fxb, path, &st, 0, "nobody", "nobody");
10821
10822 buf = fxb->buf;
10823 buflen = fxb->buflen;
10824 }
10825
10826 fxp_cmd_dispatch_err(cmd);
10827
10828 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10829 resp->payload = fxb->ptr;
10830 resp->payload_sz = (fxb->bufsz - buflen);
10831
10832 return fxp_packet_write(resp);
10833 }
10834
10835 /* The path may have been changed by any PRE_CMD handlers. */
10836 path = cmd->arg;
10837
10838 if (strncmp(path, ".", 2) == 0) {
10839 /* The client is asking about the current working directory. Easy. */
10840 path = (char *) pr_fs_getvwd();
10841
10842 } else {
10843 char *vpath;
10844
10845 vpath = dir_realpath(fxp->pool, path);
10846 if (vpath == NULL) {
10847 uint32_t status_code;
10848 const char *reason;
10849
10850 xerrno = errno;
10851
10852 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10853 "error resolving '%s': %s", path, strerror(xerrno));
10854
10855 status_code = fxp_errno2status(xerrno, &reason);
10856
10857 if (fxp_session->client_version <= 5 ||
10858 (fxp_session->client_version >= 6 &&
10859 realpath_flags != SSH2_FXRP_NO_CHECK)) {
10860 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
10861 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
10862 xerrno);
10863
10864 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10865 reason, NULL);
10866
10867 } else {
10868 uint32_t attr_flags = 0;
10869
10870 memset(&st, 0, sizeof(st));
10871 st.st_uid = (uid_t) -1;
10872 st.st_gid = (gid_t) -1;
10873
10874 pr_trace_msg(trace_channel, 8, "sending response: NAME 1 %s %s",
10875 path, fxp_strattrs(fxp->pool, &st, &attr_flags));
10876
10877 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_NAME);
10878 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
10879 sftp_msg_write_int(&buf, &buflen, 1);
10880
10881 fxb->buf = buf;
10882 fxb->buflen = buflen;
10883
10884 fxp_name_write(fxp->pool, fxb, path, &st, 0, "nobody", "nobody");
10885
10886 buf = fxb->buf;
10887 buflen = fxb->buflen;
10888 }
10889
10890 fxp_cmd_dispatch_err(cmd);
10891
10892 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
10893 resp->payload = fxb->ptr;
10894 resp->payload_sz = (fxb->bufsz - buflen);
10895
10896 return fxp_packet_write(resp);
10897 }
10898
10899 pr_trace_msg(trace_channel, 15,
10900 "resolved client-sent path '%s' to local path '%s'", path, vpath);
10901 path = vpath;
10902 }
10903
10904 /* Force a full lookup. */
10905 pr_fs_clear_cache2(path);
10906 if (!dir_check_full(fxp->pool, cmd, G_DIRS, path, NULL)) {
10907 uint32_t status_code;
10908 const char *reason;
10909
10910 xerrno = errno;
10911
10912 status_code = SSH2_FX_PERMISSION_DENIED;
10913
10914 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10915 "REALPATH of '%s' blocked by <Limit> configuration", path);
10916
10917 buf = fxb->ptr;
10918 buflen = fxb->bufsz;
10919
10920 status_code = fxp_errno2status(xerrno, &reason);
10921
10922 if (fxp_session->client_version <= 5 ||
10923 (fxp_session->client_version >= 6 &&
10924 realpath_flags != SSH2_FXRP_NO_CHECK)) {
10925
10926 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
10927 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
10928 xerrno);
10929
10930 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
10931 reason, NULL);
10932
10933 } else {
10934 uint32_t attr_flags = 0;
10935
10936 memset(&st, 0, sizeof(st));
10937 st.st_uid = (uid_t) -1;
10938 st.st_gid = (gid_t) -1;
10939
10940 pr_trace_msg(trace_channel, 8, "sending response: NAME 1 %s %s",
10941 path, fxp_strattrs(fxp->pool, &st, &attr_flags));
10942
10943 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_NAME);
10944 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
10945 sftp_msg_write_int(&buf, &buflen, 1);
10946
10947 fxb->buf = buf;
10948 fxb->buflen = buflen;
10949
10950 fxp_name_write(fxp->pool, fxb, path, &st, 0, "nobody", "nobody");
10951
10952 buf = fxb->buf;
10953 buflen = fxb->buflen;
10954 }
10955
10956 fxp_cmd_dispatch_err(cmd);
10957
10958 } else {
10959 /* draft-ietf-secsh-filexfer-13 says:
10960 *
10961 * SSH_FXP_REALPATH_NO_CHECK:
10962 * NOT resolve symbolic links (thus use lstat(2))
10963 *
10964 * SSH_FXP_REALPATH_STAT_IF:
10965 * stat(2) the file, but if the stat(2) fails, do NOT fail the request,
10966 * but send a NAME with type UNKNOWN.
10967 *
10968 * SSH_FXP_REALPATH_STAT_ALWAYS:
10969 * stat(2) the file, and return any error.
10970 */
10971
10972 pr_fs_clear_cache2(path);
10973 switch (realpath_flags) {
10974 case SSH2_FXRP_NO_CHECK:
10975 res = pr_fsio_lstat(path, &st);
10976 xerrno = errno;
10977 break;
10978
10979 case SSH2_FXRP_STAT_IF:
10980 case SSH2_FXRP_STAT_ALWAYS:
10981 res = pr_fsio_stat(path, &st);
10982 xerrno = errno;
10983 break;
10984 }
10985
10986 if (res < 0) {
10987 uint32_t status_code;
10988 const char *reason;
10989
10990 xerrno = errno;
10991
10992 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
10993 "error checking '%s' for REALPATH: %s", path, strerror(xerrno));
10994
10995 buf = fxb->ptr;
10996 buflen = fxb->bufsz;
10997
10998 status_code = fxp_errno2status(xerrno, &reason);
10999
11000 if (fxp_session->client_version <= 5 ||
11001 (fxp_session->client_version >= 6 &&
11002 realpath_flags == SSH2_FXRP_STAT_ALWAYS)) {
11003
11004 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
11005 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
11006 xerrno);
11007
11008 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11009 reason, NULL);
11010
11011 } else {
11012 uint32_t attr_flags = 0;
11013
11014 memset(&st, 0, sizeof(st));
11015 st.st_uid = (uid_t) -1;
11016 st.st_gid = (gid_t) -1;
11017
11018 pr_trace_msg(trace_channel, 8, "sending response: NAME 1 %s %s",
11019 path, fxp_strattrs(fxp->pool, &st, &attr_flags));
11020
11021 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_NAME);
11022 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
11023 sftp_msg_write_int(&buf, &buflen, 1);
11024
11025 fxb->buf = buf;
11026 fxb->buflen = buflen;
11027
11028 fxp_name_write(fxp->pool, fxb, path, &st, 0, "nobody", "nobody");
11029
11030 buf = fxb->buf;
11031 buflen = fxb->buflen;
11032 }
11033
11034 fxp_cmd_dispatch_err(cmd);
11035
11036 } else {
11037 const char *fake_user = NULL, *fake_group = NULL;
11038
11039 pr_trace_msg(trace_channel, 8, "sending response: NAME 1 %s %s",
11040 path, fxp_strattrs(fxp->pool, &st, NULL));
11041
11042 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_NAME);
11043 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
11044 sftp_msg_write_int(&buf, &buflen, 1);
11045
11046 fake_user = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeUser",
11047 FALSE);
11048 if (fake_user != NULL &&
11049 strncmp(fake_user, "~", 2) == 0) {
11050 fake_user = session.user;
11051 }
11052
11053 fake_group = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeGroup",
11054 FALSE);
11055 if (fake_group != NULL &&
11056 strncmp(fake_group, "~", 2) == 0) {
11057 fake_group = session.group;
11058 }
11059
11060 fxb->buf = buf;
11061 fxb->buflen = buflen;
11062
11063 fxp_name_write(fxp->pool, fxb, path, &st, 0, fake_user, fake_group);
11064
11065 buf = fxb->buf;
11066 buflen = fxb->buflen;
11067
11068 fxp_cmd_dispatch(cmd);
11069 }
11070 }
11071
11072 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11073 resp->payload = fxb->ptr;
11074 resp->payload_sz = (fxb->bufsz - buflen);
11075
11076 return fxp_packet_write(resp);
11077 }
11078
fxp_handle_remove(struct fxp_packet * fxp)11079 static int fxp_handle_remove(struct fxp_packet *fxp) {
11080 unsigned char *buf, *ptr;
11081 char *cmd_name, *path, *real_path;
11082 const char *reason;
11083 uint32_t buflen, bufsz, status_code;
11084 struct stat st;
11085 struct fxp_packet *resp;
11086 cmd_rec *cmd, *cmd2;
11087 int res;
11088
11089 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
11090 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
11091 path = sftp_utf8_decode_str(fxp->pool, path);
11092 }
11093
11094 pr_scoreboard_entry_update(session.pid,
11095 PR_SCORE_CMD, "%s", "REMOVE", NULL, NULL);
11096 pr_scoreboard_entry_update(session.pid,
11097 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
11098
11099 pr_proctitle_set("%s - %s: REMOVE %s", session.user, session.proc_prefix,
11100 path);
11101
11102 pr_trace_msg(trace_channel, 7, "received request: REMOVE %s", path);
11103
11104 if (strlen(path) == 0) {
11105 /* Use the default directory if the path is empty. */
11106 path = sftp_auth_get_default_dir();
11107
11108 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11109 "empty path given in REMOVE request, using '%s'", path);
11110 }
11111
11112 cmd = fxp_cmd_alloc(fxp->pool, "REMOVE", path);
11113 cmd->cmd_class = CL_WRITE|CL_SFTP;
11114
11115 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
11116 buf = ptr = palloc(fxp->pool, bufsz);
11117
11118 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
11119 status_code = SSH2_FX_PERMISSION_DENIED;
11120
11121 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11122 "REMOVE of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
11123
11124 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11125 (unsigned long) status_code, fxp_strerror(status_code));
11126
11127 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11128 fxp_strerror(status_code), NULL);
11129
11130 fxp_cmd_dispatch_err(cmd);
11131
11132 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11133 resp->payload = ptr;
11134 resp->payload_sz = (bufsz - buflen);
11135
11136 return fxp_packet_write(resp);
11137 }
11138
11139 path = cmd->arg;
11140
11141 cmd2 = fxp_cmd_alloc(fxp->pool, C_DELE, path);
11142 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) < 0) {
11143 status_code = SSH2_FX_PERMISSION_DENIED;
11144
11145 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11146 "DELE of '%s' blocked by '%s' handler", path, (char *) cmd2->argv[0]);
11147
11148 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11149 (unsigned long) status_code, fxp_strerror(status_code));
11150
11151 pr_response_add_err(R_550, "%s: %s", path, strerror(EPERM));
11152 fxp_cmd_dispatch_err(cmd2);
11153
11154 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11155 fxp_strerror(status_code), NULL);
11156
11157 fxp_cmd_dispatch_err(cmd);
11158
11159 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11160 resp->payload = ptr;
11161 resp->payload_sz = (bufsz - buflen);
11162
11163 return fxp_packet_write(resp);
11164 }
11165
11166 /* The path may have been changed by any PRE_CMD handlers. */
11167 path = cmd2->arg;
11168
11169 cmd_name = cmd->argv[0];
11170 pr_cmd_set_name(cmd, C_DELE);
11171
11172 if (!dir_check_canon(fxp->pool, cmd, G_WRITE, path, NULL)) {
11173 status_code = SSH2_FX_PERMISSION_DENIED;
11174
11175 pr_cmd_set_name(cmd, cmd_name);
11176
11177 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11178 "REMOVE of '%s' blocked by <Limit> configuration", path);
11179
11180 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11181 (unsigned long) status_code, fxp_strerror(status_code));
11182
11183 pr_response_add_err(R_550, "%s: %s", path, strerror(EPERM));
11184 fxp_cmd_dispatch_err(cmd2);
11185
11186 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11187 fxp_strerror(status_code), NULL);
11188
11189 fxp_cmd_dispatch_err(cmd);
11190
11191 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11192 resp->payload = ptr;
11193 resp->payload_sz = (bufsz - buflen);
11194
11195 return fxp_packet_write(resp);
11196 }
11197
11198 pr_cmd_set_name(cmd, cmd_name);
11199
11200 if (fxp_path_pass_regex_filters(fxp->pool, "REMOVE", path) < 0) {
11201 int xerrno = errno;
11202
11203 status_code = fxp_errno2status(errno, NULL);
11204
11205 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11206 (unsigned long) status_code, fxp_strerror(status_code));
11207
11208 pr_response_add_err(R_550, "%s: %s", path, strerror(xerrno));
11209 fxp_cmd_dispatch_err(cmd2);
11210
11211 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11212 fxp_strerror(status_code), NULL);
11213
11214 fxp_cmd_dispatch_err(cmd);
11215
11216 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11217 resp->payload = ptr;
11218 resp->payload_sz = (bufsz - buflen);
11219
11220 return fxp_packet_write(resp);
11221 }
11222
11223 real_path = dir_canonical_path(fxp->pool, path);
11224 if (real_path == NULL) {
11225 int xerrno = errno;
11226
11227 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11228 "error resolving '%s': %s", path, strerror(xerrno));
11229
11230 status_code = fxp_errno2status(xerrno, &reason);
11231
11232 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
11233 "('%s' [%d])", (unsigned long) status_code, reason,
11234 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
11235
11236 pr_response_add_err(R_550, "%s: %s", path, strerror(xerrno));
11237 fxp_cmd_dispatch_err(cmd2);
11238
11239 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11240 reason, NULL);
11241
11242 fxp_cmd_dispatch_err(cmd);
11243
11244 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11245 resp->payload = ptr;
11246 resp->payload_sz = (bufsz - buflen);
11247
11248 return fxp_packet_write(resp);
11249 }
11250
11251 pr_fs_clear_cache2(real_path);
11252 res = pr_fsio_lstat(real_path, &st);
11253 if (res < 0) {
11254 int xerrno = errno;
11255
11256 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11257 "unable to check '%s': %s", real_path, strerror(xerrno));
11258
11259 status_code = fxp_errno2status(xerrno, &reason);
11260
11261 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
11262 "('%s' [%d])", (unsigned long) status_code, reason,
11263 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
11264
11265 pr_response_add_err(R_550, "%s: %s", path, strerror(xerrno));
11266 fxp_cmd_dispatch_err(cmd2);
11267
11268 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11269 reason, NULL);
11270
11271 fxp_cmd_dispatch_err(cmd);
11272
11273 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11274 resp->payload = ptr;
11275 resp->payload_sz = (bufsz - buflen);
11276
11277 return fxp_packet_write(resp);
11278 }
11279
11280 if (S_ISDIR(st.st_mode)) {
11281 int xerrno = EISDIR;
11282
11283 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11284 "unable to remove '%s': %s", real_path, strerror(xerrno));
11285
11286 status_code = fxp_errno2status(xerrno, &reason);
11287
11288 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
11289 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
11290 xerrno);
11291
11292 pr_response_add_err(R_550, "%s: %s", path, strerror(xerrno));
11293 fxp_cmd_dispatch_err(cmd2);
11294
11295 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11296 reason, NULL);
11297
11298 fxp_cmd_dispatch_err(cmd);
11299
11300 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11301 resp->payload = ptr;
11302 resp->payload_sz = (bufsz - buflen);
11303
11304 return fxp_packet_write(resp);
11305 }
11306
11307 res = pr_fsio_unlink(real_path);
11308 if (res < 0) {
11309 int xerrno = errno;
11310
11311 (void) pr_trace_msg("fileperms", 1, "REMOVE, user '%s' (UID %s, GID %s): "
11312 "error deleting '%s': %s", session.user,
11313 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
11314 real_path, strerror(xerrno));
11315
11316 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11317 "error unlinking '%s': %s", real_path, strerror(xerrno));
11318
11319 pr_response_add_err(R_550, "%s: %s", path, strerror(xerrno));
11320 fxp_cmd_dispatch_err(cmd2);
11321
11322 errno = xerrno;
11323
11324 } else {
11325 char *abs_path;
11326
11327 /* The TransferLog format wants the full path to the deleted file,
11328 * regardless of a chroot.
11329 */
11330 abs_path = sftp_misc_vroot_abs_path(fxp->pool, path, TRUE);
11331
11332 xferlog_write(0, session.c->remote_name, st.st_size, abs_path,
11333 'b', 'd', 'r', session.user, 'c', "_");
11334
11335 pr_response_add(R_250, "%s command successful", (char *) cmd2->argv[0]);
11336 fxp_cmd_dispatch(cmd2);
11337
11338 errno = 0;
11339 }
11340
11341 status_code = fxp_errno2status(errno, &reason);
11342
11343 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
11344 "('%s' [%d])", (unsigned long) status_code, reason,
11345 errno != EOF ? strerror(errno) : "End of file", errno);
11346
11347 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11348 reason, NULL);
11349
11350 if (res == 0) {
11351 fxp_cmd_dispatch(cmd);
11352
11353 } else {
11354 fxp_cmd_dispatch_err(cmd);
11355 }
11356
11357 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11358 resp->payload = ptr;
11359 resp->payload_sz = (bufsz - buflen);
11360
11361 return fxp_packet_write(resp);
11362 }
11363
fxp_handle_rename(struct fxp_packet * fxp)11364 static int fxp_handle_rename(struct fxp_packet *fxp) {
11365 unsigned char *buf, *ptr;
11366 char *args, *old_path, *new_path;
11367 const char *reason;
11368 uint32_t buflen, bufsz, flags, status_code;
11369 struct fxp_packet *resp;
11370 cmd_rec *cmd = NULL, *cmd2 = NULL, *cmd3 = NULL;
11371 int xerrno = 0;
11372
11373 old_path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
11374 new_path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
11375
11376 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
11377 old_path = sftp_utf8_decode_str(fxp->pool, old_path);
11378 new_path = sftp_utf8_decode_str(fxp->pool, new_path);
11379 }
11380
11381 /* In protocol version 5 and later, there is a flags int which follows.
11382 * However, this flags argument is usually used to indicate to servers
11383 * that they can use the POSIX rename(2) semantics, i.e. that overwriting
11384 * a file at the new/destination path is OK.
11385 *
11386 * At the moment, since we use rename(2) anyway, even for the older protocol
11387 * versions, we don't read in the flags value. This does mean, however,
11388 * that mod_sftp will not properly return an "file already exists" error
11389 * if the specified new/destination path already exists.
11390 */
11391
11392 args = pstrcat(fxp->pool, old_path, " ", new_path, NULL);
11393
11394 pr_trace_msg(trace_channel, 7, "received request: RENAME %s %s", old_path,
11395 new_path);
11396
11397 pr_scoreboard_entry_update(session.pid,
11398 PR_SCORE_CMD, "%s", "RENAME", NULL, NULL);
11399 pr_scoreboard_entry_update(session.pid,
11400 PR_SCORE_CMD_ARG, "%s", args, NULL, NULL);
11401
11402 pr_proctitle_set("%s - %s: RENAME %s %s", session.user, session.proc_prefix,
11403 old_path, new_path);
11404
11405 if (strlen(old_path) == 0) {
11406 /* Use the default directory if the path is empty. */
11407 old_path = sftp_auth_get_default_dir();
11408
11409 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11410 "empty old path given in RENAME request, using '%s'", old_path);
11411 }
11412
11413 if (strlen(new_path) == 0) {
11414 /* Use the default directory if the path is empty. */
11415 new_path = sftp_auth_get_default_dir();
11416
11417 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11418 "empty new path given in RENAME request, using '%s'", new_path);
11419 }
11420
11421 if (fxp_session->client_version > 4) {
11422 flags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
11423
11424 if (flags & SSH2_FXR_ATOMIC) {
11425 /* The ATOMIC flag implies OVERWRITE. */
11426 flags |= SSH2_FXR_OVERWRITE;
11427 }
11428
11429 } else {
11430 flags = 0;
11431 }
11432
11433 cmd = fxp_cmd_alloc(fxp->pool, "RENAME", args);
11434 cmd->cmd_class = CL_MISC|CL_SFTP;
11435
11436 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
11437 buf = ptr = palloc(fxp->pool, bufsz);
11438
11439 cmd2 = fxp_cmd_alloc(fxp->pool, C_RNFR, old_path);
11440 cmd2->cmd_class = CL_MISC|CL_WRITE;
11441 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) < 0) {
11442 status_code = SSH2_FX_PERMISSION_DENIED;
11443
11444 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11445 "RENAME from '%s' blocked by '%s' handler", old_path,
11446 (char *) cmd2->argv[0]);
11447
11448 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11449 (unsigned long) status_code, fxp_strerror(status_code));
11450
11451 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11452 fxp_cmd_dispatch_err(cmd2);
11453
11454 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11455 fxp_strerror(status_code), NULL);
11456
11457 fxp_cmd_dispatch_err(cmd);
11458
11459 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11460 resp->payload = ptr;
11461 resp->payload_sz = (bufsz - buflen);
11462
11463 return fxp_packet_write(resp);
11464 }
11465
11466 old_path = dir_best_path(fxp->pool, cmd2->arg);
11467 if (old_path == NULL) {
11468 status_code = SSH2_FX_PERMISSION_DENIED;
11469
11470 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11471 "RENAME request denied: unable to access path '%s'", cmd2->arg);
11472
11473 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11474 (unsigned long) status_code, fxp_strerror(status_code));
11475
11476 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11477 fxp_cmd_dispatch_err(cmd2);
11478
11479 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11480 fxp_strerror(status_code), NULL);
11481
11482 fxp_cmd_dispatch_err(cmd);
11483
11484 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11485 resp->payload = ptr;
11486 resp->payload_sz = (bufsz - buflen);
11487
11488 return fxp_packet_write(resp);
11489 }
11490
11491 if (pr_table_add(session.notes, "mod_core.rnfr-path",
11492 pstrdup(session.pool, old_path), 0) < 0) {
11493 if (errno != EEXIST) {
11494 pr_trace_msg(trace_channel, 8,
11495 "error setting 'mod_core.rnfr-path' note: %s", strerror(errno));
11496 }
11497 }
11498
11499 cmd3 = fxp_cmd_alloc(fxp->pool, C_RNTO, new_path);
11500 cmd3->cmd_class = CL_MISC|CL_WRITE;
11501 if (pr_cmd_dispatch_phase(cmd3, PRE_CMD, 0) < 0) {
11502 status_code = SSH2_FX_PERMISSION_DENIED;
11503
11504 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11505 "RENAME to '%s' blocked by '%s' handler", new_path,
11506 (char *) cmd3->argv[0]);
11507
11508 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11509 (unsigned long) status_code, fxp_strerror(status_code));
11510
11511 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11512 fxp_cmd_dispatch_err(cmd2);
11513
11514 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(EACCES));
11515 fxp_cmd_dispatch_err(cmd3);
11516
11517 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11518 fxp_strerror(status_code), NULL);
11519
11520 fxp_cmd_dispatch_err(cmd);
11521
11522 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11523 resp->payload = ptr;
11524 resp->payload_sz = (bufsz - buflen);
11525
11526 return fxp_packet_write(resp);
11527 }
11528
11529 new_path = dir_best_path(fxp->pool, cmd3->arg);
11530 if (new_path == NULL) {
11531 status_code = SSH2_FX_PERMISSION_DENIED;
11532
11533 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11534 "RENAME request denied: unable to access path '%s'", cmd3->arg);
11535
11536 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11537 (unsigned long) status_code, fxp_strerror(status_code));
11538
11539 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(EACCES));
11540 fxp_cmd_dispatch_err(cmd3);
11541
11542 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11543 fxp_cmd_dispatch_err(cmd2);
11544
11545 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11546 fxp_strerror(status_code), NULL);
11547
11548 fxp_cmd_dispatch_err(cmd);
11549
11550 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11551 resp->payload = ptr;
11552 resp->payload_sz = (bufsz - buflen);
11553
11554 return fxp_packet_write(resp);
11555 }
11556
11557 if (!dir_check(fxp->pool, cmd2, G_DIRS, old_path, NULL) ||
11558 !dir_check(fxp->pool, cmd3, G_WRITE, new_path, NULL)) {
11559 status_code = SSH2_FX_PERMISSION_DENIED;
11560
11561 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11562 "RENAME of '%s' to '%s' blocked by <Limit> configuration",
11563 old_path, new_path);
11564
11565 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11566 (unsigned long) status_code, fxp_strerror(status_code));
11567
11568 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11569 fxp_cmd_dispatch_err(cmd2);
11570
11571 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11572 fxp_cmd_dispatch_err(cmd3);
11573
11574 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11575 fxp_strerror(status_code), NULL);
11576
11577 fxp_cmd_dispatch_err(cmd);
11578
11579 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11580 resp->payload = ptr;
11581 resp->payload_sz = (bufsz - buflen);
11582
11583 return fxp_packet_write(resp);
11584 }
11585
11586 if (strcmp(old_path, new_path) == 0) {
11587 xerrno = EEXIST;
11588
11589 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11590 "RENAME of '%s' to same path '%s', rejecting", old_path, new_path);
11591
11592 status_code = fxp_errno2status(xerrno, &reason);
11593
11594 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
11595 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
11596 xerrno);
11597
11598 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
11599 fxp_cmd_dispatch_err(cmd2);
11600
11601 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(xerrno));
11602 fxp_cmd_dispatch_err(cmd3);
11603
11604 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11605 reason, NULL);
11606
11607 fxp_cmd_dispatch_err(cmd);
11608
11609 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11610 resp->payload = ptr;
11611 resp->payload_sz = (bufsz - buflen);
11612
11613 return fxp_packet_write(resp);
11614 }
11615
11616 if (!(flags & SSH2_FXR_OVERWRITE) &&
11617 exists2(fxp->pool, new_path)) {
11618 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11619 "denying RENAME of '%s' to '%s': '%s' already exists and client did not "
11620 "specify OVERWRITE flag", old_path, new_path, new_path);
11621
11622 status_code = SSH2_FX_FILE_ALREADY_EXISTS;
11623
11624 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11625 (unsigned long) status_code, fxp_strerror(status_code));
11626
11627 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
11628 fxp_cmd_dispatch_err(cmd2);
11629
11630 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(xerrno));
11631 fxp_cmd_dispatch_err(cmd3);
11632
11633 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11634 fxp_strerror(status_code), NULL);
11635
11636 fxp_cmd_dispatch_err(cmd);
11637
11638 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11639 resp->payload = ptr;
11640 resp->payload_sz = (bufsz - buflen);
11641
11642 return fxp_packet_write(resp);
11643 }
11644
11645 if (fxp_path_pass_regex_filters(fxp->pool, "RENAME", old_path) < 0 ||
11646 fxp_path_pass_regex_filters(fxp->pool, "RENAME", new_path) < 0) {
11647 xerrno = errno;
11648
11649 status_code = fxp_errno2status(xerrno, NULL);
11650
11651 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11652 (unsigned long) status_code, fxp_strerror(status_code));
11653
11654 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
11655 fxp_cmd_dispatch_err(cmd2);
11656
11657 pr_response_add_err(R_550, "%s: %s", cmd3->arg, strerror(xerrno));
11658 fxp_cmd_dispatch_err(cmd3);
11659
11660 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11661 fxp_strerror(status_code), NULL);
11662
11663 fxp_cmd_dispatch_err(cmd);
11664
11665 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11666 resp->payload = ptr;
11667 resp->payload_sz = (bufsz - buflen);
11668
11669 return fxp_packet_write(resp);
11670 }
11671
11672 if (pr_fsio_rename(old_path, new_path) < 0) {
11673 if (errno != EXDEV) {
11674 xerrno = errno;
11675
11676 (void) pr_trace_msg("fileperms", 1, "RENAME, user '%s' (UID %s, "
11677 "GID %s): error renaming '%s' to '%s': %s", session.user,
11678 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
11679 old_path, new_path, strerror(xerrno));
11680
11681 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11682 "error renaming '%s' to '%s': %s", old_path, new_path,
11683 strerror(xerrno));
11684
11685 errno = xerrno;
11686
11687 } else {
11688 /* In this case, we should manually copy the file from the source
11689 * path to the destination path.
11690 */
11691 errno = 0;
11692 if (pr_fs_copy_file2(old_path, new_path, 0, NULL) < 0) {
11693 xerrno = errno;
11694
11695 (void) pr_trace_msg("fileperms", 1, "RENAME, user '%s' (UID %s, "
11696 "GID %s): error copying '%s' to '%s': %s", session.user,
11697 pr_uid2str(fxp->pool, session.uid),
11698 pr_gid2str(fxp->pool, session.gid), old_path, new_path,
11699 strerror(xerrno));
11700
11701 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11702 "error copying '%s' to '%s': %s", old_path, new_path,
11703 strerror(xerrno));
11704
11705 errno = xerrno;
11706
11707 } else {
11708 /* Once copied, remove the original path. */
11709 if (pr_fsio_unlink(old_path) < 0) {
11710 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11711 "error deleting '%s': %s", old_path, strerror(errno));
11712 }
11713
11714 xerrno = errno = 0;
11715 }
11716 }
11717
11718 } else {
11719 /* No errors. */
11720 xerrno = errno = 0;
11721 }
11722
11723 status_code = fxp_errno2status(xerrno, &reason);
11724
11725 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
11726 "('%s' [%d])", (unsigned long) status_code, reason,
11727 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
11728
11729 /* Clear out any transfer-specific data. */
11730 if (session.xfer.p) {
11731 destroy_pool(session.xfer.p);
11732 }
11733 memset(&session.xfer, 0, sizeof(session.xfer));
11734
11735 /* The timing of these steps may look peculiar, but it's deliberate,
11736 * in order to get the expected log messages in an ExtendedLog.
11737 */
11738
11739 session.xfer.p = make_sub_pool(fxp_pool);
11740 pr_pool_tag(session.xfer.p, "SFTP session transfer pool");
11741 memset(&session.xfer.start_time, 0, sizeof(session.xfer.start_time));
11742 gettimeofday(&session.xfer.start_time, NULL);
11743
11744 session.xfer.path = pstrdup(session.xfer.p, old_path);
11745
11746 if (xerrno == 0) {
11747 pr_response_add(R_350,
11748 "File or directory exists, ready for destination name");
11749 fxp_cmd_dispatch(cmd2);
11750
11751 } else {
11752 pr_response_add_err(R_550, "%s: %s", (char *) cmd2->argv[0],
11753 strerror(xerrno));
11754 fxp_cmd_dispatch_err(cmd2);
11755 }
11756
11757 session.xfer.path = pstrdup(session.xfer.p, new_path);
11758
11759 if (xerrno == 0) {
11760 pr_response_add(R_250, "Rename successful");
11761 fxp_cmd_dispatch(cmd3);
11762
11763 } else {
11764 pr_response_add_err(R_550, "%s: %s", (char *) cmd3->argv[0],
11765 strerror(xerrno));
11766 fxp_cmd_dispatch_err(cmd3);
11767 }
11768
11769 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11770 reason, NULL);
11771 if (xerrno == 0) {
11772 fxp_cmd_dispatch(cmd);
11773
11774 } else {
11775 fxp_cmd_dispatch_err(cmd);
11776 }
11777
11778 /* Clear out any transfer-specific data. */
11779 if (session.xfer.p) {
11780 destroy_pool(session.xfer.p);
11781 }
11782 memset(&session.xfer, 0, sizeof(session.xfer));
11783
11784 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11785 resp->payload = ptr;
11786 resp->payload_sz = (bufsz - buflen);
11787
11788 return fxp_packet_write(resp);
11789 }
11790
fxp_handle_rmdir(struct fxp_packet * fxp)11791 static int fxp_handle_rmdir(struct fxp_packet *fxp) {
11792 unsigned char *buf, *ptr;
11793 char *cmd_name, *path;
11794 const char *reason;
11795 uint32_t buflen, bufsz, status_code;
11796 struct fxp_packet *resp;
11797 cmd_rec *cmd, *cmd2;
11798 int have_error = FALSE, res = 0;
11799 struct stat st;
11800
11801 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
11802 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
11803 path = sftp_utf8_decode_str(fxp->pool, path);
11804 }
11805
11806 pr_scoreboard_entry_update(session.pid,
11807 PR_SCORE_CMD, "%s", "RMDIR", NULL, NULL);
11808 pr_scoreboard_entry_update(session.pid,
11809 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
11810
11811 pr_proctitle_set("%s - %s: RMDIR %s", session.user, session.proc_prefix,
11812 path);
11813
11814 pr_trace_msg(trace_channel, 7, "received request: RMDIR %s", path);
11815
11816 if (strlen(path) == 0) {
11817 /* Use the default directory if the path is empty. */
11818 path = sftp_auth_get_default_dir();
11819
11820 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11821 "empty path given in RMDIR request, using '%s'", path);
11822 }
11823
11824 cmd = fxp_cmd_alloc(fxp->pool, "RMDIR", path);
11825 cmd->cmd_class = CL_WRITE|CL_SFTP;
11826
11827 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
11828 buf = ptr = palloc(fxp->pool, bufsz);
11829
11830 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
11831 status_code = SSH2_FX_PERMISSION_DENIED;
11832
11833 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11834 "RMDIR of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
11835
11836 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11837 (unsigned long) status_code, fxp_strerror(status_code));
11838
11839 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11840 fxp_strerror(status_code), NULL);
11841
11842 fxp_cmd_dispatch_err(cmd);
11843
11844 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11845 resp->payload = ptr;
11846 resp->payload_sz = (bufsz - buflen);
11847
11848 return fxp_packet_write(resp);
11849 }
11850
11851 /* The path may have been changed by any PRE_CMD handlers. */
11852 path = cmd->arg;
11853
11854 pr_fs_clear_cache2(path);
11855 if (pr_fsio_lstat(path, &st) == 0) {
11856 if (S_ISLNK(st.st_mode)) {
11857 char link_path[PR_TUNABLE_PATH_MAX];
11858 int len;
11859
11860 memset(link_path, '\0', sizeof(link_path));
11861 len = dir_readlink(fxp->pool, path, link_path, sizeof(link_path)-1,
11862 PR_DIR_READLINK_FL_HANDLE_REL_PATH);
11863 if (len > 0) {
11864 link_path[len] = '\0';
11865 path = pstrdup(fxp->pool, link_path);
11866 }
11867 }
11868 }
11869
11870 path = dir_best_path(fxp->pool, path);
11871 if (path == NULL) {
11872 status_code = SSH2_FX_PERMISSION_DENIED;
11873
11874 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11875 "RMDIR request denied: unable to access path '%s'", cmd->arg);
11876
11877 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11878 (unsigned long) status_code, fxp_strerror(status_code));
11879
11880 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11881 fxp_strerror(status_code), NULL);
11882
11883 fxp_cmd_dispatch_err(cmd);
11884
11885 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11886 resp->payload = ptr;
11887 resp->payload_sz = (bufsz - buflen);
11888
11889 return fxp_packet_write(resp);
11890 }
11891
11892 cmd2 = fxp_cmd_alloc(fxp->pool, C_RMD, path);
11893 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) == -1) {
11894 status_code = SSH2_FX_PERMISSION_DENIED;
11895
11896 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11897 "RMDIR of '%s' blocked by '%s' handler", path, (char *) cmd2->argv[0]);
11898
11899 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11900 (unsigned long) status_code, fxp_strerror(status_code));
11901
11902 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11903 fxp_cmd_dispatch_err(cmd2);
11904
11905 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11906 fxp_strerror(status_code), NULL);
11907
11908 fxp_cmd_dispatch_err(cmd);
11909
11910 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11911 resp->payload = ptr;
11912 resp->payload_sz = (bufsz - buflen);
11913
11914 return fxp_packet_write(resp);
11915 }
11916
11917 /* The path may have been changed by any PRE_CMD handlers. */
11918 path = cmd2->arg;
11919
11920 cmd_name = cmd->argv[0];
11921 pr_cmd_set_name(cmd, C_RMD);
11922
11923 if (!dir_check(fxp->pool, cmd, G_WRITE, path, NULL)) {
11924 have_error = TRUE;
11925 }
11926
11927 pr_cmd_set_name(cmd, C_XRMD);
11928
11929 if (!have_error &&
11930 !dir_check(fxp->pool, cmd, G_WRITE, path, NULL)) {
11931 have_error = TRUE;
11932 }
11933
11934 pr_cmd_set_name(cmd, cmd_name);
11935
11936 if (have_error) {
11937 status_code = SSH2_FX_PERMISSION_DENIED;
11938
11939 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11940 "RMDIR of '%s' blocked by <Limit> configuration", path);
11941
11942 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11943 (unsigned long) status_code, fxp_strerror(status_code));
11944
11945 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
11946 fxp_cmd_dispatch_err(cmd2);
11947
11948 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11949 fxp_strerror(status_code), NULL);
11950
11951 fxp_cmd_dispatch_err(cmd);
11952
11953 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11954 resp->payload = ptr;
11955 resp->payload_sz = (bufsz - buflen);
11956
11957 return fxp_packet_write(resp);
11958 }
11959
11960 if (fxp_path_pass_regex_filters(fxp->pool, "RMDIR", path) < 0) {
11961 int xerrno = errno;
11962
11963 status_code = fxp_errno2status(xerrno, NULL);
11964
11965 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
11966 (unsigned long) status_code, fxp_strerror(status_code));
11967
11968 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(xerrno));
11969 fxp_cmd_dispatch_err(cmd2);
11970
11971 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
11972 fxp_strerror(status_code), NULL);
11973
11974 fxp_cmd_dispatch_err(cmd);
11975
11976 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
11977 resp->payload = ptr;
11978 resp->payload_sz = (bufsz - buflen);
11979
11980 return fxp_packet_write(resp);
11981 }
11982
11983 res = pr_fsio_rmdir(path);
11984 if (res < 0) {
11985 int xerrno = errno;
11986
11987 (void) pr_trace_msg("fileperms", 1, "RMDIR, user '%s' (UID %s, GID %s): "
11988 "error removing directory '%s': %s", session.user,
11989 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
11990 path, strerror(xerrno));
11991
11992 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
11993 "error removing directory '%s': %s", path, strerror(xerrno));
11994
11995 #if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST
11996 status_code = fxp_errno2status(xerrno, &reason);
11997
11998 #else
11999 /* On AIX5, ENOTEMPTY and EEXIST are defined to the same value. See:
12000 *
12001 * http://forums.proftpd.org/smf/index.php/topic,3971.0.html
12002 *
12003 * We still want to send the proper SFTP error code/string if we see
12004 * these values, though. The fix for handling this case in
12005 * fxp_errno2status() means that we need to do the errno lookup a little
12006 * more manually here.
12007 */
12008
12009 if (xerrno != ENOTEMPTY) {
12010 status_code = fxp_errno2status(xerrno, &reason);
12011
12012 } else {
12013 /* Generic failure code, works for all protocol versions. */
12014 status_code = SSH2_FX_FAILURE;
12015
12016 if (fxp_session->client_version > 3) {
12017 status_code = SSH2_FX_FILE_ALREADY_EXISTS;
12018 }
12019
12020 if (fxp_session->client_version > 5) {
12021 status_code = SSH2_FX_DIR_NOT_EMPTY;
12022 }
12023
12024 reason = fxp_strerror(status_code);
12025 }
12026 #endif
12027
12028 errno = xerrno;
12029
12030 } else {
12031 /* No error. */
12032 errno = 0;
12033 status_code = SSH2_FX_OK;
12034 reason = fxp_strerror(status_code);
12035 }
12036
12037 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
12038 "('%s' [%d])", (unsigned long) status_code, reason,
12039 errno != EOF ? strerror(errno) : "End of file", errno);
12040
12041 if (res == 0) {
12042 fxp_cmd_dispatch(cmd2);
12043
12044 } else {
12045 fxp_cmd_dispatch_err(cmd2);
12046 }
12047
12048 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12049 reason, NULL);
12050
12051 if (res == 0) {
12052 fxp_cmd_dispatch(cmd);
12053
12054 } else {
12055 fxp_cmd_dispatch_err(cmd);
12056 }
12057
12058 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12059 resp->payload = ptr;
12060 resp->payload_sz = (bufsz - buflen);
12061
12062 return fxp_packet_write(resp);
12063 }
12064
fxp_handle_setstat(struct fxp_packet * fxp)12065 static int fxp_handle_setstat(struct fxp_packet *fxp) {
12066 unsigned char *buf, *ptr;
12067 char *attrs_str, *cmd_name, *path;
12068 const char *reason;
12069 uint32_t attr_flags, buflen, bufsz, status_code;
12070 int res;
12071 struct stat *attrs;
12072 struct fxp_packet *resp;
12073 cmd_rec *cmd;
12074 struct stat st;
12075 array_header *xattrs = NULL;
12076
12077 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
12078 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
12079 path = sftp_utf8_decode_str(fxp->pool, path);
12080 }
12081
12082 pr_scoreboard_entry_update(session.pid,
12083 PR_SCORE_CMD, "%s", "SETSTAT", NULL, NULL);
12084 pr_scoreboard_entry_update(session.pid,
12085 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
12086
12087 attrs = fxp_attrs_read(fxp, &fxp->payload, &fxp->payload_sz, &attr_flags,
12088 &xattrs);
12089 if (attrs == NULL) {
12090 return 0;
12091 }
12092
12093 attrs_str = fxp_strattrs(fxp->pool, attrs, &attr_flags);
12094
12095 pr_proctitle_set("%s - %s: SETSTAT %s %s", session.user, session.proc_prefix,
12096 path, attrs_str);
12097
12098 pr_trace_msg(trace_channel, 7, "received request: SETSTAT %s %s", path,
12099 attrs_str);
12100
12101 if (strlen(path) == 0) {
12102 /* Use the default directory if the path is empty. */
12103 path = sftp_auth_get_default_dir();
12104
12105 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12106 "empty path given in SETSTAT request, using '%s'", path);
12107 }
12108
12109 cmd = fxp_cmd_alloc(fxp->pool, "SETSTAT", path);
12110 cmd->cmd_class = CL_WRITE|CL_SFTP;
12111
12112 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
12113 buf = ptr = palloc(fxp->pool, bufsz);
12114
12115 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
12116 status_code = SSH2_FX_PERMISSION_DENIED;
12117
12118 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12119 "SETSTAT of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
12120
12121 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12122 (unsigned long) status_code, fxp_strerror(status_code));
12123
12124 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12125 fxp_strerror(status_code), NULL);
12126
12127 fxp_cmd_dispatch_err(cmd);
12128
12129 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12130 resp->payload = ptr;
12131 resp->payload_sz = (bufsz - buflen);
12132
12133 return fxp_packet_write(resp);
12134 }
12135
12136 /* The path may have been changed by any PRE_CMD handlers. */
12137 path = cmd->arg;
12138
12139 pr_fs_clear_cache2(path);
12140 if (pr_fsio_lstat(path, &st) == 0) {
12141 if (S_ISLNK(st.st_mode)) {
12142 char link_path[PR_TUNABLE_PATH_MAX];
12143 int len;
12144
12145 memset(link_path, '\0', sizeof(link_path));
12146 len = dir_readlink(fxp->pool, path, link_path, sizeof(link_path)-1,
12147 PR_DIR_READLINK_FL_HANDLE_REL_PATH);
12148 if (len > 0) {
12149 link_path[len] = '\0';
12150 path = pstrdup(fxp->pool, link_path);
12151 }
12152 }
12153 }
12154
12155 path = dir_best_path(fxp->pool, path);
12156 if (path == NULL) {
12157 status_code = SSH2_FX_PERMISSION_DENIED;
12158
12159 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12160 "SETSTAT request denied: unable to access path '%s'", cmd->arg);
12161
12162 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12163 (unsigned long) status_code, fxp_strerror(status_code));
12164
12165 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12166 fxp_strerror(status_code), NULL);
12167
12168 fxp_cmd_dispatch_err(cmd);
12169
12170 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12171 resp->payload = ptr;
12172 resp->payload_sz = (bufsz - buflen);
12173
12174 return fxp_packet_write(resp);
12175 }
12176
12177 cmd_name = cmd->argv[0];
12178 pr_cmd_set_name(cmd, "SETSTAT");
12179
12180 if (!dir_check(fxp->pool, cmd, G_WRITE, path, NULL)) {
12181 status_code = SSH2_FX_PERMISSION_DENIED;
12182
12183 pr_cmd_set_name(cmd, cmd_name);
12184
12185 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12186 "SETSTAT of '%s' blocked by <Limit> configuration", path);
12187
12188 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12189 (unsigned long) status_code, fxp_strerror(status_code));
12190
12191 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12192 fxp_strerror(status_code), NULL);
12193
12194 fxp_cmd_dispatch_err(cmd);
12195
12196 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12197 resp->payload = ptr;
12198 resp->payload_sz = (bufsz - buflen);
12199
12200 return fxp_packet_write(resp);
12201 }
12202 pr_cmd_set_name(cmd, cmd_name);
12203
12204 attr_flags = fxp_attrs_clear_unsupported(attr_flags);
12205
12206 /* If the SFTPOption for ignoring the owners for SFTP setstat requests is set,
12207 * handle it by clearing the SSH2_FX_ATTR_UIDGID and SSH2_FX_ATTR_OWNERGROUP
12208 * flags.
12209 */
12210 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_OWNERS) &&
12211 ((attr_flags & SSH2_FX_ATTR_UIDGID) ||
12212 (attr_flags & SSH2_FX_ATTR_OWNERGROUP))) {
12213 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPSetOwners' "
12214 "configured, ignoring ownership sent by client");
12215 attr_flags &= ~SSH2_FX_ATTR_UIDGID;
12216 attr_flags &= ~SSH2_FX_ATTR_OWNERGROUP;
12217 }
12218
12219 /* If the SFTPOption for ignoring the xattrs for SFTP setstat requests is set,
12220 * handle it by clearing the SSH2_FX_ATTR_EXTENDED flag.
12221 */
12222 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_XATTRS) &&
12223 (attr_flags & SSH2_FX_ATTR_EXTENDED)) {
12224 pr_trace_msg(trace_channel, 7,
12225 "SFTPOption 'IgnoreSFTPSetExtendedAttributes' configured, ignoring "
12226 "xattrs sent by client");
12227 attr_flags &= ~SSH2_FX_ATTR_EXTENDED;
12228 }
12229
12230 /* If the SFTPOption for ignoring the perms for SFTP setstat requests is set,
12231 * handle it by clearing the SSH2_FX_ATTR_PERMISSIONS flag.
12232 */
12233 if ((sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_PERMS) &&
12234 (attr_flags & SSH2_FX_ATTR_PERMISSIONS)) {
12235 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPSetPerms' "
12236 "configured, ignoring perms sent by client");
12237 attr_flags &= ~SSH2_FX_ATTR_PERMISSIONS;
12238 }
12239
12240 /* If the SFTPOption for ignoring the times for SFTP setstat requests is set,
12241 * handle it by clearing the time-related SSH2_FX_ATTR flags.
12242 */
12243 if (sftp_opts & SFTP_OPT_IGNORE_SFTP_SET_TIMES) {
12244 if ((attr_flags & SSH2_FX_ATTR_ACCESSTIME) ||
12245 (attr_flags & SSH2_FX_ATTR_MODIFYTIME)) {
12246 pr_trace_msg(trace_channel, 7, "SFTPOption 'IgnoreSFTPSetTimes' "
12247 "configured, ignoring times sent by client");
12248 attr_flags &= ~SSH2_FX_ATTR_ACCESSTIME;
12249 attr_flags &= ~SSH2_FX_ATTR_MODIFYTIME;
12250 }
12251 }
12252
12253 res = fxp_attrs_set(NULL, path, attrs, attr_flags, xattrs, &buf, &buflen,
12254 fxp);
12255 if (res < 0) {
12256 fxp_cmd_dispatch_err(cmd);
12257
12258 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12259 resp->payload = ptr;
12260 resp->payload_sz = (bufsz - buflen);
12261
12262 return fxp_packet_write(resp);
12263 }
12264
12265 status_code = fxp_errno2status(0, &reason);
12266
12267 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12268 (unsigned long) status_code, reason);
12269
12270 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12271 reason, NULL);
12272
12273 fxp_cmd_dispatch(cmd);
12274
12275 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12276 resp->payload = ptr;
12277 resp->payload_sz = (bufsz - buflen);
12278
12279 return fxp_packet_write(resp);
12280 }
12281
fxp_handle_stat(struct fxp_packet * fxp)12282 static int fxp_handle_stat(struct fxp_packet *fxp) {
12283 unsigned char *buf;
12284 char *cmd_name, *path;
12285 uint32_t attr_flags, buflen;
12286 struct stat st;
12287 struct fxp_buffer *fxb;
12288 struct fxp_packet *resp;
12289 cmd_rec *cmd;
12290 const char *fake_user = NULL, *fake_group = NULL;
12291
12292 path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
12293 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
12294 path = sftp_utf8_decode_str(fxp->pool, path);
12295 }
12296
12297 pr_scoreboard_entry_update(session.pid,
12298 PR_SCORE_CMD, "%s", "STAT", NULL, NULL);
12299 pr_scoreboard_entry_update(session.pid,
12300 PR_SCORE_CMD_ARG, "%s", path, NULL, NULL);
12301
12302 pr_proctitle_set("%s - %s: STAT %s", session.user, session.proc_prefix, path);
12303
12304 if (fxp_session->client_version > 3) {
12305 attr_flags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
12306
12307 pr_trace_msg(trace_channel, 7, "received request: STAT %s %s", path,
12308 fxp_strattrflags(fxp->pool, attr_flags));
12309
12310 } else {
12311 pr_trace_msg(trace_channel, 7, "received request: STAT %s", path);
12312 attr_flags = SSH2_FX_ATTR_SIZE|SSH2_FX_ATTR_UIDGID|SSH2_FX_ATTR_PERMISSIONS|
12313 SSH2_FX_ATTR_ACMODTIME;
12314 #ifdef PR_USE_XATTR
12315 if (!(fxp_fsio_opts & PR_FSIO_OPT_IGNORE_XATTR)) {
12316 attr_flags |= SSH2_FX_ATTR_EXTENDED;
12317 }
12318 #endif /* PR_USE_XATTR */
12319 }
12320
12321 if (strlen(path) == 0) {
12322 /* Use the default directory if the path is empty. */
12323 path = sftp_auth_get_default_dir();
12324
12325 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12326 "empty path given in STAT request, using '%s'", path);
12327 }
12328
12329 cmd = fxp_cmd_alloc(fxp->pool, "STAT", path);
12330 cmd->cmd_class = CL_READ|CL_SFTP;
12331
12332 fxb = pcalloc(fxp->pool, sizeof(struct fxp_buffer));
12333 fxb->bufsz = buflen = FXP_RESPONSE_NAME_DEFAULT_SZ;
12334 fxb->ptr = buf = palloc(fxp->pool, fxb->bufsz);
12335
12336 if (pr_cmd_dispatch_phase(cmd, PRE_CMD, 0) < 0) {
12337 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
12338
12339 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12340 "STAT of '%s' blocked by '%s' handler", path, (char *) cmd->argv[0]);
12341
12342 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12343 (unsigned long) status_code, fxp_strerror(status_code));
12344
12345 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12346 fxp_strerror(status_code), NULL);
12347
12348 fxp_cmd_dispatch_err(cmd);
12349
12350 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12351 resp->payload = fxb->ptr;
12352 resp->payload_sz = (fxb->bufsz - buflen);
12353
12354 return fxp_packet_write(resp);
12355 }
12356
12357 /* The path may have been changed by any PRE_CMD handlers. */
12358 path = cmd->arg;
12359
12360 pr_fs_clear_cache2(path);
12361 if (pr_fsio_lstat(path, &st) == 0) {
12362 if (S_ISLNK(st.st_mode)) {
12363 char link_path[PR_TUNABLE_PATH_MAX];
12364 int len;
12365
12366 memset(link_path, '\0', sizeof(link_path));
12367 len = dir_readlink(fxp->pool, path, link_path, sizeof(link_path)-1,
12368 PR_DIR_READLINK_FL_HANDLE_REL_PATH);
12369 if (len > 0) {
12370 link_path[len] = '\0';
12371 path = pstrdup(fxp->pool, link_path);
12372 }
12373 }
12374 }
12375
12376 path = dir_best_path(fxp->pool, path);
12377 if (path == NULL) {
12378 int xerrno = EACCES;
12379 const char *reason;
12380 uint32_t status_code;
12381
12382 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12383 "STAT request denied: unable to access path '%s'", cmd->arg);
12384
12385 status_code = fxp_errno2status(xerrno, &reason);
12386
12387 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
12388 "('%s' [%d])", (unsigned long) status_code, reason, strerror(xerrno),
12389 xerrno);
12390
12391 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12392 reason, NULL);
12393
12394 fxp_cmd_dispatch_err(cmd);
12395
12396 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12397 resp->payload = fxb->ptr;
12398 resp->payload_sz = (fxb->bufsz - buflen);
12399
12400 return fxp_packet_write(resp);
12401 }
12402
12403 cmd_name = cmd->argv[0];
12404 pr_cmd_set_name(cmd, "STAT");
12405
12406 if (!dir_check(fxp->pool, cmd, G_READ, path, NULL)) {
12407 uint32_t status_code = SSH2_FX_PERMISSION_DENIED;
12408
12409 pr_cmd_set_name(cmd, cmd_name);
12410
12411 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12412 "STAT of '%s' blocked by <Limit> configuration", path);
12413
12414 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12415 (unsigned long) status_code, fxp_strerror(status_code));
12416
12417 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12418 fxp_strerror(status_code), NULL);
12419
12420 fxp_cmd_dispatch_err(cmd);
12421
12422 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12423 resp->payload = fxb->ptr;
12424 resp->payload_sz = (fxb->bufsz - buflen);
12425
12426 return fxp_packet_write(resp);
12427 }
12428 pr_cmd_set_name(cmd, cmd_name);
12429
12430 pr_fs_clear_cache2(path);
12431 if (pr_fsio_stat(path, &st) < 0) {
12432 uint32_t status_code;
12433 const char *reason;
12434 int xerrno = errno;
12435
12436 if (xerrno != ENOENT) {
12437 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12438 "error checking '%s' for STAT: %s", path, strerror(xerrno));
12439 }
12440
12441 status_code = fxp_errno2status(xerrno, &reason);
12442
12443 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
12444 "('%s' [%d])", (unsigned long) status_code, reason,
12445 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
12446
12447 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12448 reason, NULL);
12449
12450 fxp_cmd_dispatch_err(cmd);
12451
12452 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12453 resp->payload = fxb->ptr;
12454 resp->payload_sz = (fxb->bufsz - buflen);
12455
12456 return fxp_packet_write(resp);
12457 }
12458
12459 pr_trace_msg(trace_channel, 8, "sending response: ATTRS %s",
12460 fxp_strattrs(fxp->pool, &st, &attr_flags));
12461
12462 sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_FXP_ATTRS);
12463 sftp_msg_write_int(&buf, &buflen, fxp->request_id);
12464
12465 fake_user = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeUser",
12466 FALSE);
12467 if (fake_user != NULL &&
12468 strncmp(fake_user, "~", 2) == 0) {
12469 fake_user = session.user;
12470 }
12471
12472 fake_group = get_param_ptr(get_dir_ctxt(fxp->pool, path), "DirFakeGroup",
12473 FALSE);
12474 if (fake_group != NULL &&
12475 strncmp(fake_group, "~", 2) == 0) {
12476 fake_group = session.group;
12477 }
12478
12479 fxb->buf = buf;
12480 fxb->buflen = buflen;
12481
12482 attr_flags = fxp_attrs_clear_unsupported(attr_flags);
12483 if (fxp_session->client_version > 3 &&
12484 sftp_opts & SFTP_OPT_INCLUDE_SFTP_TIMES) {
12485 pr_trace_msg(trace_channel, 17,
12486 "SFTPOption IncludeSFTPTimes in effect; assuring presence of "
12487 "ACCESSTIME/MODIFYTIME attributes");
12488 attr_flags |= SSH2_FX_ATTR_ACCESSTIME;
12489 attr_flags |= SSH2_FX_ATTR_MODIFYTIME;
12490 }
12491
12492 fxp_attrs_write(fxp->pool, fxb, path, &st, attr_flags, fake_user, fake_group);
12493
12494 buf = fxb->buf;
12495 buflen = fxb->buflen;
12496
12497 fxp_cmd_dispatch(cmd);
12498
12499 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12500 resp->payload = fxb->ptr;
12501 resp->payload_sz = (fxb->bufsz - buflen);
12502
12503 return fxp_packet_write(resp);
12504 }
12505
fxp_handle_symlink(struct fxp_packet * fxp)12506 static int fxp_handle_symlink(struct fxp_packet *fxp) {
12507 unsigned char *buf, *ptr;
12508 char *args, *args2, *cmd_name, *link_path, *link_vpath, *target_path,
12509 *target_vpath, *vpath;
12510 const char *reason;
12511 int have_error = FALSE, res;
12512 uint32_t buflen, bufsz, status_code;
12513 struct fxp_packet *resp;
12514 cmd_rec *cmd, *cmd2;
12515
12516 /* Note: The ietf-secsh-filexfer drafts define the arguments for SYMLINK
12517 * as "linkpath" (the file being created), followed by "targetpath" (the
12518 * target of the link). The following code reads the arguments in the
12519 * opposite (thus wrong) order. This is done deliberately, to match
12520 * the behavior that OpenSSH uses; see:
12521 *
12522 * https://bugzilla.mindrot.org/show_bug.cgi?id=861
12523 */
12524
12525 target_path = sftp_msg_read_string(fxp->pool, &fxp->payload,
12526 &fxp->payload_sz);
12527 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
12528 target_path = sftp_utf8_decode_str(fxp->pool, target_path);
12529 }
12530
12531 link_path = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
12532 if (fxp_session->client_version >= fxp_utf8_protocol_version) {
12533 link_path = sftp_utf8_decode_str(fxp->pool, link_path);
12534 }
12535
12536 args = pstrcat(fxp->pool, target_path, " ", link_path, NULL);
12537
12538 cmd = fxp_cmd_alloc(fxp->pool, "SYMLINK", args);
12539 cmd->cmd_class = CL_WRITE|CL_SFTP;
12540
12541 pr_scoreboard_entry_update(session.pid,
12542 PR_SCORE_CMD, "%s", "SYMLINK", NULL, NULL);
12543 pr_scoreboard_entry_update(session.pid,
12544 PR_SCORE_CMD_ARG, "%s", args, NULL, NULL);
12545
12546 pr_proctitle_set("%s - %s: SYMLINK %s %s", session.user, session.proc_prefix,
12547 link_path, target_path);
12548
12549 pr_trace_msg(trace_channel, 7, "received request: SYMLINK %s %s", target_path,
12550 link_path);
12551
12552 if (strlen(target_path) == 0) {
12553 /* Use the default directory if the path is empty. */
12554 target_path = sftp_auth_get_default_dir();
12555
12556 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12557 "empty target path given in SYMLINK request, using '%s'", target_path);
12558 }
12559
12560 if (strlen(link_path) == 0) {
12561 /* Use the default directory if the path is empty. */
12562 link_path = sftp_auth_get_default_dir();
12563
12564 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12565 "empty link path given in SYMLINK request, using '%s'", link_path);
12566 }
12567
12568 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
12569 buf = ptr = palloc(fxp->pool, bufsz);
12570
12571 /* Make sure we use the full paths. */
12572 vpath = dir_canonical_vpath(fxp->pool, target_path);
12573 if (vpath == NULL) {
12574 int xerrno = errno;
12575
12576 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12577 "error resolving '%s': %s", target_path, strerror(xerrno));
12578
12579 status_code = fxp_errno2status(xerrno, &reason);
12580
12581 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
12582 "('%s' [%d])", (unsigned long) status_code, reason,
12583 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
12584
12585 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12586 reason, NULL);
12587
12588 fxp_cmd_dispatch_err(cmd);
12589
12590 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12591 resp->payload = ptr;
12592 resp->payload_sz = (bufsz - buflen);
12593
12594 return fxp_packet_write(resp);
12595 }
12596 target_vpath = vpath;
12597
12598 vpath = dir_canonical_vpath(fxp->pool, link_path);
12599 if (vpath == NULL) {
12600 int xerrno = errno;
12601
12602 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12603 "error resolving '%s': %s", link_path, strerror(xerrno));
12604
12605 status_code = fxp_errno2status(xerrno, &reason);
12606
12607 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
12608 "('%s' [%d])", (unsigned long) status_code, reason,
12609 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
12610
12611 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12612 reason, NULL);
12613
12614 fxp_cmd_dispatch_err(cmd);
12615
12616 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12617 resp->payload = ptr;
12618 resp->payload_sz = (bufsz - buflen);
12619
12620 return fxp_packet_write(resp);
12621 }
12622 link_vpath = vpath;
12623
12624 /* We use a slightly different cmd_rec here, for the benefit of PRE_CMD
12625 * handlers such as mod_rewrite. It is impossible for a client to
12626 * send a tab ('\t') in SFTP, so we use that as our delimiter in the
12627 * single-string args argument in the cmd_rec.
12628 *
12629 * If the PRE_CMD dispatch is successful, we can then check to see
12630 * if the args string changed, and if so, parse back out the individual
12631 * paths.
12632 */
12633
12634 args2 = pstrcat(fxp->pool, target_vpath, "\t", link_vpath, NULL);
12635 cmd2 = fxp_cmd_alloc(fxp->pool, "SYMLINK", args2);
12636 cmd2->cmd_class = CL_WRITE;
12637
12638 if (pr_cmd_dispatch_phase(cmd2, PRE_CMD, 0) < 0) {
12639 status_code = SSH2_FX_PERMISSION_DENIED;
12640
12641 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12642 "SYMLINK of '%s' to '%s' blocked by '%s' handler", target_path, link_path,
12643 (char *) cmd2->argv[0]);
12644
12645 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12646 (unsigned long) status_code, fxp_strerror(status_code));
12647
12648 pr_response_add_err(R_550, "%s: %s", cmd2->arg, strerror(EACCES));
12649 fxp_cmd_dispatch_err(cmd2);
12650
12651 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12652 fxp_strerror(status_code), NULL);
12653
12654 fxp_cmd_dispatch_err(cmd);
12655
12656 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12657 resp->payload = ptr;
12658 resp->payload_sz = (bufsz - buflen);
12659
12660 return fxp_packet_write(resp);
12661 }
12662
12663 /* The paths may have been changed by any PRE_CMD handlers. */
12664 if (strcmp(args2, cmd2->arg) != 0) {
12665 char *ptr2;
12666
12667 ptr2 = strchr(cmd2->arg, '\t');
12668 if (ptr2) {
12669 *ptr2 = '\0';
12670 target_path = cmd2->arg;
12671 link_path = ptr2 + 1;
12672 }
12673 }
12674
12675 cmd_name = cmd->argv[0];
12676 pr_cmd_set_name(cmd, "SYMLINK");
12677
12678 if (!dir_check(fxp->pool, cmd, G_READ, target_vpath, NULL)) {
12679 pr_cmd_set_name(cmd, cmd_name);
12680 have_error = TRUE;
12681 }
12682
12683 if (!have_error &&
12684 !dir_check(fxp->pool, cmd, G_WRITE, link_vpath, NULL)) {
12685 pr_cmd_set_name(cmd, cmd_name);
12686 have_error = TRUE;
12687 }
12688
12689 pr_cmd_set_name(cmd, cmd_name);
12690
12691 if (have_error) {
12692 status_code = SSH2_FX_PERMISSION_DENIED;
12693
12694 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12695 "SYMLINK of '%s' to '%s' blocked by <Limit> configuration",
12696 target_path, link_path);
12697
12698 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12699 (unsigned long) status_code, fxp_strerror(status_code));
12700
12701 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12702 fxp_strerror(status_code), NULL);
12703
12704 fxp_cmd_dispatch_err(cmd);
12705
12706 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12707 resp->payload = ptr;
12708 resp->payload_sz = (bufsz - buflen);
12709
12710 return fxp_packet_write(resp);
12711 }
12712
12713 res = pr_fsio_symlink(target_path, link_path);
12714
12715 if (res < 0) {
12716 int xerrno = errno;
12717
12718 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12719 "error symlinking '%s' to '%s': %s", target_path, link_path,
12720 strerror(xerrno));
12721
12722 status_code = fxp_errno2status(xerrno, &reason);
12723
12724 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
12725 "('%s' [%d])", (unsigned long) status_code, reason,
12726 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
12727
12728 fxp_cmd_dispatch_err(cmd);
12729
12730 } else {
12731 errno = 0;
12732 status_code = fxp_errno2status(0, &reason);
12733
12734 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12735 (unsigned long) status_code, reason);
12736
12737 fxp_cmd_dispatch(cmd);
12738 }
12739
12740 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12741 reason, NULL);
12742
12743 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12744 resp->payload = ptr;
12745 resp->payload_sz = (bufsz - buflen);
12746
12747 return fxp_packet_write(resp);
12748 }
12749
fxp_handle_write(struct fxp_packet * fxp)12750 static int fxp_handle_write(struct fxp_packet *fxp) {
12751 unsigned char *buf, *data, *ptr;
12752 char cmd_arg[256], *file, *name, *ptr2;
12753 ssize_t res;
12754 int xerrno = 0;
12755 uint32_t buflen, bufsz, datalen, status_code;
12756 uint64_t offset;
12757 struct fxp_handle *fxh;
12758 struct fxp_packet *resp;
12759 cmd_rec *cmd, *cmd2;
12760 pr_buffer_t *pbuf;
12761
12762 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
12763 offset = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
12764 datalen = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
12765 data = sftp_msg_read_data(fxp->pool, &fxp->payload, &fxp->payload_sz,
12766 datalen);
12767
12768 memset(cmd_arg, '\0', sizeof(cmd_arg));
12769 pr_snprintf(cmd_arg, sizeof(cmd_arg)-1, "%s %" PR_LU " %lu", name,
12770 (pr_off_t) offset, (unsigned long) datalen);
12771 cmd = fxp_cmd_alloc(fxp->pool, "WRITE", cmd_arg);
12772 cmd->cmd_class = CL_WRITE|CL_SFTP;
12773
12774 pr_scoreboard_entry_update(session.pid,
12775 PR_SCORE_CMD, "%s", "WRITE", NULL, NULL);
12776 pr_scoreboard_entry_update(session.pid,
12777 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
12778
12779 pr_proctitle_set("%s - %s: WRITE %s %" PR_LU " %lu", session.user,
12780 session.proc_prefix, name, (pr_off_t) offset, (unsigned long) datalen);
12781
12782 pr_trace_msg(trace_channel, 7, "received request: WRITE %s %" PR_LU " %lu",
12783 name, (pr_off_t) offset, (unsigned long) datalen);
12784
12785 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
12786 buf = ptr = palloc(fxp->pool, bufsz);
12787
12788 fxh = fxp_handle_get(name);
12789 if (fxh == NULL) {
12790 pr_trace_msg(trace_channel, 17,
12791 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
12792 name, strerror(errno));
12793
12794 status_code = SSH2_FX_INVALID_HANDLE;
12795
12796 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12797 (unsigned long) status_code, fxp_strerror(status_code));
12798
12799 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12800 fxp_strerror(status_code), NULL);
12801
12802 fxp_cmd_dispatch_err(cmd);
12803
12804 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12805 resp->payload = ptr;
12806 resp->payload_sz = (bufsz - buflen);
12807
12808 return fxp_packet_write(resp);
12809 }
12810
12811 if (fxh->fh == NULL) {
12812 status_code = SSH2_FX_INVALID_HANDLE;
12813
12814 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12815 (unsigned long) status_code, fxp_strerror(status_code));
12816
12817 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12818 fxp_strerror(status_code), NULL);
12819
12820 fxp_cmd_dispatch_err(cmd);
12821
12822 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12823 resp->payload = ptr;
12824 resp->payload_sz = (bufsz - buflen);
12825
12826 return fxp_packet_write(resp);
12827 }
12828
12829 /* Add a note containing the file handle for logging (Bug#3707). */
12830 fxp_set_filehandle_note(cmd, fxh);
12831
12832 pr_scoreboard_entry_update(session.pid,
12833 PR_SCORE_CMD_ARG, "%s", fxh->fh->fh_path, NULL, NULL);
12834 fxh->fh_bytes_xferred += datalen;
12835
12836 /* It would be nice to check the requested offset against the size of
12837 * the file. However, the protocol specifically allows for sparse files,
12838 * where the requested offset is far beyond the end of the file.
12839 *
12840 * XXX Perhaps this should be configurable?
12841 */
12842 #if 0
12843 if (offset > st.st_size) {
12844 const char *reason;
12845
12846 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12847 "requested write offset (%" PR_LU " bytes) greater than size of "
12848 "'%s' (%" PR_LU " bytes)", (pr_off_t) offset, fxh->fh->fh_path,
12849 (pr_off_t) st.st_size);
12850
12851 status_code = fxp_errno2status(EINVAL, &reason);
12852
12853 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
12854 "('%s' [%d])", (unsigned long) status_code, reason, strerror(EINVAL),
12855 EINVAL);
12856
12857 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12858 reason, NULL);
12859
12860 fxp_cmd_dispatch_err(cmd);
12861
12862 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12863 resp->payload = ptr;
12864 resp->payload_sz = (bufsz - buflen);
12865
12866 return fxp_packet_write(resp);
12867 }
12868 #endif
12869
12870 /* Trim the full path to just the filename, for our STOR command. */
12871 ptr2 = strrchr(fxh->fh->fh_path, '/');
12872 if (ptr2 != NULL &&
12873 ptr2 != fxh->fh->fh_path) {
12874 file = pstrdup(fxp->pool, ptr2 + 1);
12875
12876 } else {
12877 file = fxh->fh->fh_path;
12878 }
12879
12880 cmd2 = fxp_cmd_alloc(fxp->pool, C_STOR, file);
12881 cmd2->cmd_class = CL_WRITE|CL_SFTP;
12882
12883 if (!dir_check(fxp->pool, cmd2, G_WRITE, fxh->fh->fh_path, NULL)) {
12884 status_code = SSH2_FX_PERMISSION_DENIED;
12885
12886 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
12887 "WRITE of '%s' blocked by <Limit> configuration", fxh->fh->fh_path);
12888
12889 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12890 (unsigned long) status_code, fxp_strerror(status_code));
12891
12892 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12893 fxp_strerror(status_code), NULL);
12894
12895 fxp_cmd_dispatch_err(cmd);
12896
12897 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12898 resp->payload = ptr;
12899 resp->payload_sz = (bufsz - buflen);
12900
12901 return fxp_packet_write(resp);
12902 }
12903
12904 if (fxp_path_pass_regex_filters(fxp->pool, "WRITE", fxh->fh->fh_path) < 0) {
12905 status_code = fxp_errno2status(errno, NULL);
12906
12907 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
12908 (unsigned long) status_code, fxp_strerror(status_code));
12909
12910 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
12911 fxp_strerror(status_code), NULL);
12912
12913 fxp_cmd_dispatch_err(cmd);
12914
12915 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
12916 resp->payload = ptr;
12917 resp->payload_sz = (bufsz - buflen);
12918
12919 return fxp_packet_write(resp);
12920 }
12921
12922 if (S_ISREG(fxh->fh_st->st_mode)) {
12923 off_t *file_offset;
12924
12925 /* Stash the offset at which we're writing to this file. */
12926 file_offset = palloc(cmd->pool, sizeof(off_t));
12927 *file_offset = (off_t) offset;
12928 (void) pr_table_add(cmd->notes, "mod_xfer.file-offset", file_offset,
12929 sizeof(off_t));
12930 }
12931
12932 /* If the open flags have O_APPEND, treat this as an APPE command, rather
12933 * than a STOR command.
12934 */
12935 if (!(fxh->fh_flags & O_APPEND)) {
12936 cmd2 = fxp_cmd_alloc(fxp->pool, C_STOR, NULL);
12937
12938 } else {
12939 cmd2 = fxp_cmd_alloc(fxp->pool, C_APPE, NULL);
12940 }
12941
12942 pbuf = pcalloc(fxp->pool, sizeof(pr_buffer_t));
12943 pbuf->buf = (char *) data;
12944 pbuf->buflen = datalen;
12945 pbuf->current = pbuf->buf;
12946 pbuf->remaining = 0;
12947 pr_event_generate("mod_sftp.sftp.data-read", pbuf);
12948
12949 pr_throttle_init(cmd2);
12950
12951 /* Handle zero-length writes as a special case; see Bug#4398. */
12952 if (datalen > 0) {
12953 res = pr_fsio_pwrite(fxh->fh, data, datalen, offset);
12954
12955 } else {
12956 res = 0;
12957 }
12958
12959 xerrno = errno;
12960
12961 /* Increment the "on-disk" file size with the number of bytes written.
12962 * We do this, rather than using fstat(2), to avoid performance penalties
12963 * associated with fstat(2) on network filesystems such as NFS. And we
12964 * want to track the on-disk size for enforcing limits such as
12965 * MaxStoreFileSize.
12966 *
12967 * Note that we only want to increment the file size if the chunk we
12968 * just wrote is PAST the current end of the file; we could be just
12969 * overwriting a chunk of the file.
12970 */
12971 if (res > 0) {
12972 size_t new_size;
12973
12974 new_size = offset + res;
12975 if ((off_t) new_size > fxh->fh_st->st_size) {
12976 fxh->fh_st->st_size = new_size;
12977 }
12978
12979 session.xfer.total_bytes += datalen;
12980 session.total_bytes += datalen;
12981 }
12982
12983 if (pr_data_get_timeout(PR_DATA_TIMEOUT_NO_TRANSFER) > 0) {
12984 pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
12985 }
12986
12987 if (pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED) > 0) {
12988 pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
12989 }
12990
12991 pr_throttle_pause(offset, FALSE);
12992
12993 if (res < 0) {
12994 const char *reason;
12995
12996 (void) pr_trace_msg("fileperms", 1, "WRITE, user '%s' (UID %s, GID %s): "
12997 "error writing to '%s': %s", session.user,
12998 pr_uid2str(fxp->pool, session.uid), pr_gid2str(fxp->pool, session.gid),
12999 fxh->fh->fh_path, strerror(xerrno));
13000
13001 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13002 "error writing to '%s': %s", fxh->fh->fh_path, strerror(xerrno));
13003
13004 status_code = fxp_errno2status(xerrno, &reason);
13005
13006 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
13007 "('%s' [%d])", (unsigned long) status_code, reason,
13008 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
13009
13010 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13011 reason, NULL);
13012
13013 fxp_cmd_dispatch_err(cmd);
13014
13015 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13016 resp->payload = ptr;
13017 resp->payload_sz = (bufsz - buflen);
13018
13019 return fxp_packet_write(resp);
13020 }
13021
13022 if (fxh->fh_st->st_size > 0) {
13023 config_rec *c;
13024 off_t nbytes_max_store = 0;
13025
13026 /* Check MaxStoreFileSize */
13027 c = find_config(get_dir_ctxt(fxp->pool, fxh->fh->fh_path), CONF_PARAM,
13028 "MaxStoreFileSize", FALSE);
13029 if (c != NULL) {
13030 nbytes_max_store = *((off_t *) c->argv[0]);
13031 }
13032
13033 if (nbytes_max_store > 0) {
13034 if (fxh->fh_st->st_size > nbytes_max_store) {
13035 const char *reason;
13036 #if defined(EFBIG)
13037 xerrno = EFBIG;
13038 #elif defined(ENOSPC)
13039 xerrno = ENOSPC;
13040 #else
13041 xerrno = EIO;
13042 #endif
13043
13044 pr_log_pri(PR_LOG_NOTICE, "MaxStoreFileSize (%" PR_LU " %s) reached: "
13045 "aborting transfer of '%s'", (pr_off_t) nbytes_max_store,
13046 nbytes_max_store != 1 ? "bytes" : "byte", fxh->fh->fh_path);
13047
13048 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13049 "error writing %" PR_LU " bytes to '%s': %s "
13050 "(MaxStoreFileSize %" PR_LU " exceeded)", (pr_off_t) datalen,
13051 fxh->fh->fh_path, strerror(xerrno), (pr_off_t) nbytes_max_store);
13052
13053 status_code = fxp_errno2status(xerrno, &reason);
13054
13055 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
13056 "('%s' [%d])", (unsigned long) status_code, reason,
13057 strerror(xerrno), xerrno);
13058
13059 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13060 reason, NULL);
13061
13062 fxp_cmd_dispatch_err(cmd);
13063
13064 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13065 resp->payload = ptr;
13066 resp->payload_sz = (bufsz - buflen);
13067
13068 return fxp_packet_write(resp);
13069 }
13070 }
13071 }
13072
13073 status_code = SSH2_FX_OK;
13074
13075 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
13076 (unsigned long) status_code, fxp_strerror(status_code));
13077
13078 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13079 fxp_strerror(status_code), NULL);
13080
13081 fxp_cmd_dispatch(cmd);
13082
13083 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13084 resp->payload = ptr;
13085 resp->payload_sz = (bufsz - buflen);
13086
13087 return fxp_packet_write(resp);
13088 }
13089
fxp_handle_unlock(struct fxp_packet * fxp)13090 static int fxp_handle_unlock(struct fxp_packet *fxp) {
13091 unsigned char *buf, *ptr;
13092 char *cmd_name, *name;
13093 uint32_t buflen, bufsz, lock_flags, status_code;
13094 uint64_t offset, lock_len;
13095 struct flock lock;
13096 struct fxp_handle *fxh;
13097 struct fxp_packet *resp;
13098 cmd_rec *cmd;
13099
13100 name = sftp_msg_read_string(fxp->pool, &fxp->payload, &fxp->payload_sz);
13101 offset = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
13102 lock_len = sftp_msg_read_long(fxp->pool, &fxp->payload, &fxp->payload_sz);
13103 lock_flags = sftp_msg_read_int(fxp->pool, &fxp->payload, &fxp->payload_sz);
13104
13105 cmd = fxp_cmd_alloc(fxp->pool, "UNLOCK", name);
13106 cmd->cmd_class = CL_WRITE|CL_SFTP;
13107
13108 pr_scoreboard_entry_update(session.pid,
13109 PR_SCORE_CMD, "%s", "UNLOCK", NULL, NULL);
13110 pr_scoreboard_entry_update(session.pid,
13111 PR_SCORE_CMD_ARG, "%s", name, NULL, NULL);
13112
13113 pr_proctitle_set("%s - %s: UNLOCK %s", session.user, session.proc_prefix,
13114 name);
13115
13116 pr_trace_msg(trace_channel, 7,
13117 "received request: UNLOCK %s %" PR_LU " %" PR_LU " %lu", name,
13118 (pr_off_t) offset, (pr_off_t) lock_len, (unsigned long) lock_flags);
13119
13120 buflen = bufsz = FXP_RESPONSE_DATA_DEFAULT_SZ;
13121 buf = ptr = palloc(fxp->pool, bufsz);
13122
13123 fxh = fxp_handle_get(name);
13124 if (fxh == NULL) {
13125 pr_trace_msg(trace_channel, 17,
13126 "%s: unable to find handle for name '%s': %s", (char *) cmd->argv[0],
13127 name, strerror(errno));
13128
13129 status_code = SSH2_FX_INVALID_HANDLE;
13130
13131 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
13132 (unsigned long) status_code, fxp_strerror(status_code));
13133
13134 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13135 fxp_strerror(status_code), NULL);
13136
13137 fxp_cmd_dispatch_err(cmd);
13138
13139 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13140 resp->payload = ptr;
13141 resp->payload_sz = (bufsz - buflen);
13142
13143 return fxp_packet_write(resp);
13144 }
13145
13146 if (fxh->fh == NULL) {
13147 /* We do not support locking of directory handles, only files. */
13148 status_code = SSH2_FX_OP_UNSUPPORTED;
13149
13150 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13151 "client requested unsupported UNLOCK of a directory, rejecting");
13152
13153 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
13154 (unsigned long) status_code, fxp_strerror(status_code));
13155
13156 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13157 fxp_strerror(status_code), NULL);
13158
13159 fxp_cmd_dispatch_err(cmd);
13160
13161 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13162 resp->payload = ptr;
13163 resp->payload_sz = (bufsz - buflen);
13164
13165 return fxp_packet_write(resp);
13166 }
13167
13168 cmd_name = cmd->argv[0];
13169 pr_cmd_set_name(cmd, "LOCK");
13170
13171 if (!dir_check(fxp->pool, cmd, G_WRITE, fxh->fh->fh_path, NULL)) {
13172 status_code = SSH2_FX_PERMISSION_DENIED;
13173
13174 pr_cmd_set_name(cmd, cmd_name);
13175
13176 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13177 "UNLOCK of '%s' blocked by <Limit> configuration", fxh->fh->fh_path);
13178
13179 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
13180 (unsigned long) status_code, fxp_strerror(status_code));
13181
13182 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13183 fxp_strerror(status_code), NULL);
13184
13185 fxp_cmd_dispatch_err(cmd);
13186
13187 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13188 resp->payload = ptr;
13189 resp->payload_sz = (bufsz - buflen);
13190
13191 return fxp_packet_write(resp);
13192 }
13193 pr_cmd_set_name(cmd, cmd_name);
13194
13195 pr_scoreboard_entry_update(session.pid,
13196 PR_SCORE_CMD_ARG, "%s", fxh->fh->fh_path, NULL, NULL);
13197
13198 if (lock_flags & SSH2_FXL_DELETE) {
13199 lock.l_type = F_UNLCK;
13200
13201 } else {
13202 /* The LOCK command is used for adding locks, not UNLOCK. */
13203 status_code = SSH2_FX_OP_UNSUPPORTED;
13204
13205 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13206 "client requested locking using UNLOCK, rejecting");
13207
13208 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
13209 (unsigned long) status_code, fxp_strerror(status_code));
13210
13211 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13212 fxp_strerror(status_code), NULL);
13213
13214 fxp_cmd_dispatch_err(cmd);
13215
13216 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13217 resp->payload = ptr;
13218 resp->payload_sz = (bufsz - buflen);
13219
13220 return fxp_packet_write(resp);
13221 }
13222
13223 lock.l_whence = SEEK_SET;
13224 lock.l_start = offset;
13225 lock.l_len = lock_len;
13226
13227 if (lock_len > 0) {
13228 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13229 "client requested unlocking of '%s' from %" PR_LU " for %" PR_LU
13230 " bytes", fxh->fh->fh_path, (pr_off_t) offset, (pr_off_t) lock_len);
13231
13232 } else {
13233 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13234 "client requested unlocking of '%s' from %" PR_LU " to end-of-file",
13235 fxh->fh->fh_path, (pr_off_t) offset);
13236 }
13237
13238 pr_trace_msg("lock", 9, "attempting to unlock file '%s'", fxh->fh->fh_path);
13239
13240 while (fcntl(fxh->fh->fh_fd, F_SETLK, &lock) < 0) {
13241 int xerrno;
13242 const char *reason;
13243
13244 if (errno == EINTR) {
13245 pr_signals_handle();
13246 continue;
13247 }
13248
13249 xerrno = errno;
13250 pr_trace_msg("lock", 3, "unlock of '%s' failed: %s", fxh->fh->fh_path,
13251 strerror(errno));
13252
13253 status_code = fxp_errno2status(xerrno, &reason);
13254
13255 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s' "
13256 "('%s' [%d])", (unsigned long) status_code, reason,
13257 xerrno != EOF ? strerror(xerrno) : "End of file", xerrno);
13258
13259 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13260 reason, NULL);
13261
13262 fxp_cmd_dispatch_err(cmd);
13263
13264 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13265 resp->payload = ptr;
13266 resp->payload_sz = (bufsz - buflen);
13267
13268 return fxp_packet_write(resp);
13269 }
13270
13271 pr_trace_msg("lock", 9, "unlock of file '%s' successful", fxh->fh->fh_path);
13272
13273 status_code = SSH2_FX_OK;
13274
13275 pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'",
13276 (unsigned long) status_code, fxp_strerror(status_code));
13277
13278 fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code,
13279 fxp_strerror(status_code), NULL);
13280
13281 fxp_cmd_dispatch(cmd);
13282
13283 resp = fxp_packet_create(fxp->pool, fxp->channel_id);
13284 resp->payload = ptr;
13285 resp->payload_sz = (bufsz - buflen);
13286
13287 return fxp_packet_write(resp);
13288 }
13289
fxp_send_display_login_file(uint32_t channel_id)13290 static int fxp_send_display_login_file(uint32_t channel_id) {
13291 const char *msg;
13292 int res, xerrno;
13293 pool *sub_pool;
13294
13295 if (fxp_sent_display_login_file) {
13296 /* Already sent the file; no need to do it again. */
13297 return 0;
13298 }
13299
13300 if (fxp_displaylogin_fh == NULL) {
13301 /* No DisplayLogin file found. */
13302 return 0;
13303 }
13304
13305 if (fxp_pool == NULL) {
13306 fxp_pool = make_sub_pool(sftp_pool);
13307 pr_pool_tag(fxp_pool, "SFTP Pool");
13308 }
13309
13310 sub_pool = make_sub_pool(fxp_pool);
13311 pr_pool_tag(sub_pool, "SFTP DisplayLogin pool");
13312
13313 msg = sftp_display_fh_get_msg(sub_pool, fxp_displaylogin_fh);
13314 pr_fsio_close(fxp_displaylogin_fh);
13315
13316 if (msg == NULL) {
13317 destroy_pool(sub_pool);
13318 fxp_displaylogin_fh = NULL;
13319 return -1;
13320 }
13321
13322 pr_trace_msg(trace_channel, 3,
13323 "sending data from DisplayLogin file '%s'", fxp_displaylogin_fh->fh_path);
13324 fxp_displaylogin_fh = NULL;
13325
13326 res = sftp_channel_write_ext_data_stderr(sub_pool, channel_id,
13327 (unsigned char *) msg, strlen(msg));
13328 xerrno = errno;
13329
13330 if (res == 0) {
13331 fxp_sent_display_login_file = TRUE;
13332 }
13333
13334 destroy_pool(sub_pool);
13335 errno = xerrno;
13336 return res;
13337 }
13338
13339 /* Main entry point */
sftp_fxp_handle_packet(pool * p,void * ssh2,uint32_t channel_id,unsigned char * data,uint32_t datalen)13340 int sftp_fxp_handle_packet(pool *p, void *ssh2, uint32_t channel_id,
13341 unsigned char *data, uint32_t datalen) {
13342 struct fxp_packet *fxp;
13343 int have_cache, res;
13344
13345 /* Unused parameter; we read the SFTP request out of the provided buffer. */
13346 (void) ssh2;
13347
13348 if (fxp_pool == NULL) {
13349 fxp_pool = make_sub_pool(sftp_pool);
13350 pr_pool_tag(fxp_pool, "SFTP Pool");
13351 }
13352
13353 fxp = fxp_packet_read(channel_id, &data, &datalen, &have_cache);
13354 while (fxp) {
13355 pr_signals_handle();
13356
13357 /* This is a bit of a hack, for playing along better with mod_vroot,
13358 * which pays attention to the session.curr_phase value.
13359 *
13360 * I'm not sure which is better here, PRE_CMD vs CMD. Let's go with
13361 * PRE_CMD for now.
13362 */
13363 session.curr_phase = PRE_CMD;
13364
13365 if (fxp->request_id) {
13366 pr_trace_msg(trace_channel, 6,
13367 "received %s (%d) SFTP request (request ID %lu, channel ID %lu)",
13368 fxp_get_request_type_desc(fxp->request_type), fxp->request_type,
13369 (unsigned long) fxp->request_id, (unsigned long) channel_id);
13370
13371 } else {
13372 pr_trace_msg(trace_channel, 6,
13373 "received %s (%d) SFTP request (channel ID %lu)",
13374 fxp_get_request_type_desc(fxp->request_type), fxp->request_type,
13375 (unsigned long) channel_id);
13376 }
13377
13378 if (fxp->packet_len > FXP_MAX_PACKET_LEN) {
13379 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13380 "received excessive SFTP packet (len %lu > max %lu bytes), rejecting",
13381 (unsigned long) fxp->packet_len, (unsigned long) FXP_MAX_PACKET_LEN);
13382 destroy_pool(fxp->pool);
13383 errno = EPERM;
13384 return -1;
13385 }
13386
13387 fxp_session = fxp_get_session(channel_id);
13388 if (fxp_session == NULL) {
13389 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13390 "no existing SFTP session for channel ID %lu, rejecting request",
13391 (unsigned long) channel_id);
13392 destroy_pool(fxp->pool);
13393 errno = EPERM;
13394 return -1;
13395 }
13396
13397 pr_response_set_pool(fxp->pool);
13398
13399 /* Make sure to clear the response lists of any cruft from previous
13400 * requests.
13401 */
13402 pr_response_clear(&resp_list);
13403 pr_response_clear(&resp_err_list);
13404
13405 switch (fxp->request_type) {
13406 case SFTP_SSH2_FXP_INIT:
13407 /* If we already know the version, then the client has sent
13408 * FXP_INIT before, and should NOT be sending it again.
13409 *
13410 * However, per Bug#4227, there ARE clients which do send INIT
13411 * multiple times; I don't know why. And since OpenSSH handles
13412 * these repeated INITs without disconnecting clients, that is the
13413 * de facto expected behavior. We will do the same, but at least
13414 * log about it.
13415 */
13416 if (fxp_session->client_version > 0) {
13417 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13418 "already received SFTP INIT %u request from client",
13419 (unsigned int) fxp_session->client_version);
13420 }
13421
13422 res = fxp_handle_init(fxp);
13423 break;
13424
13425 case SFTP_SSH2_FXP_CLOSE:
13426 allow_version_select = FALSE;
13427 res = fxp_handle_close(fxp);
13428 break;
13429
13430 case SFTP_SSH2_FXP_EXTENDED:
13431 res = fxp_handle_extended(fxp);
13432 break;
13433
13434 case SFTP_SSH2_FXP_FSETSTAT:
13435 allow_version_select = FALSE;
13436 res = fxp_handle_fsetstat(fxp);
13437 break;
13438
13439 case SFTP_SSH2_FXP_FSTAT:
13440 allow_version_select = FALSE;
13441 res = fxp_handle_fstat(fxp);
13442 break;
13443
13444 case SFTP_SSH2_FXP_LINK:
13445 allow_version_select = FALSE;
13446 res = fxp_handle_link(fxp);
13447 break;
13448
13449 case SFTP_SSH2_FXP_LOCK:
13450 allow_version_select = FALSE;
13451 res = fxp_handle_lock(fxp);
13452 break;
13453
13454 case SFTP_SSH2_FXP_LSTAT:
13455 allow_version_select = FALSE;
13456 res = fxp_handle_lstat(fxp);
13457 break;
13458
13459 case SFTP_SSH2_FXP_MKDIR:
13460 allow_version_select = FALSE;
13461 res = fxp_handle_mkdir(fxp);
13462 break;
13463
13464 case SFTP_SSH2_FXP_OPEN:
13465 allow_version_select = FALSE;
13466 res = fxp_handle_open(fxp);
13467 break;
13468
13469 case SFTP_SSH2_FXP_OPENDIR:
13470 allow_version_select = FALSE;
13471 res = fxp_handle_opendir(fxp);
13472 break;
13473
13474 case SFTP_SSH2_FXP_READ:
13475 allow_version_select = FALSE;
13476 res = fxp_handle_read(fxp);
13477 break;
13478
13479 case SFTP_SSH2_FXP_READDIR:
13480 allow_version_select = FALSE;
13481 res = fxp_handle_readdir(fxp);
13482 break;
13483
13484 case SFTP_SSH2_FXP_READLINK:
13485 allow_version_select = FALSE;
13486 res = fxp_handle_readlink(fxp);
13487 break;
13488
13489 case SFTP_SSH2_FXP_REALPATH:
13490 allow_version_select = FALSE;
13491 res = fxp_handle_realpath(fxp);
13492 break;
13493
13494 case SFTP_SSH2_FXP_REMOVE:
13495 allow_version_select = FALSE;
13496 res = fxp_handle_remove(fxp);
13497 break;
13498
13499 case SFTP_SSH2_FXP_RENAME:
13500 allow_version_select = FALSE;
13501 res = fxp_handle_rename(fxp);
13502 break;
13503
13504 case SFTP_SSH2_FXP_RMDIR:
13505 allow_version_select = FALSE;
13506 res = fxp_handle_rmdir(fxp);
13507 break;
13508
13509 case SFTP_SSH2_FXP_SETSTAT:
13510 allow_version_select = FALSE;
13511 res = fxp_handle_setstat(fxp);
13512 break;
13513
13514 case SFTP_SSH2_FXP_STAT:
13515 allow_version_select = FALSE;
13516 res = fxp_handle_stat(fxp);
13517 break;
13518
13519 case SFTP_SSH2_FXP_SYMLINK:
13520 allow_version_select = FALSE;
13521 res = fxp_handle_symlink(fxp);
13522 break;
13523
13524 case SFTP_SSH2_FXP_WRITE:
13525 allow_version_select = FALSE;
13526 res = fxp_handle_write(fxp);
13527 break;
13528
13529 case SFTP_SSH2_FXP_UNLOCK:
13530 allow_version_select = FALSE;
13531 res = fxp_handle_unlock(fxp);
13532 break;
13533
13534 default:
13535 pr_event_generate("sftp.invalid-request", fxp);
13536
13537 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13538 "unhandled SFTP request type %d", fxp->request_type);
13539 destroy_pool(fxp->pool);
13540 fxp_packet_set_packet(NULL);
13541 fxp_session = NULL;
13542 return -1;
13543 }
13544
13545 destroy_pool(fxp->pool);
13546 fxp_packet_set_packet(NULL);
13547
13548 if (res < 0) {
13549 fxp_session = NULL;
13550 return res;
13551 }
13552
13553 if (have_cache) {
13554 fxp = fxp_packet_read(channel_id, NULL, NULL, &have_cache);
13555 continue;
13556 }
13557
13558 fxp_session = NULL;
13559 return res;
13560 }
13561
13562 fxp_session = NULL;
13563 return 0;
13564 }
13565
sftp_fxp_set_displaylogin(const char * path)13566 int sftp_fxp_set_displaylogin(const char *path) {
13567 pr_fh_t *fh;
13568
13569 if (path == NULL) {
13570 errno = EINVAL;
13571 return -1;
13572 }
13573
13574 /* Support "DisplayLogin none", in case we need to disable support for
13575 * DisplayLogin files inherited from <Global> configurations.
13576 */
13577 if (strncasecmp(path, "none", 5) == 0) {
13578 return 0;
13579 }
13580
13581 fh = pr_fsio_open(path, O_RDONLY);
13582 if (fh == NULL)
13583 return -1;
13584
13585 fxp_displaylogin_fh = fh;
13586 return 0;
13587 }
13588
sftp_fxp_set_extensions(unsigned long ext_flags)13589 int sftp_fxp_set_extensions(unsigned long ext_flags) {
13590 fxp_ext_flags = ext_flags;
13591 return 0;
13592 }
13593
sftp_fxp_set_protocol_version(unsigned int min_version,unsigned int max_version)13594 int sftp_fxp_set_protocol_version(unsigned int min_version,
13595 unsigned int max_version) {
13596 if ((min_version < 1 || min_version > 6) ||
13597 (max_version < 1 || max_version > 6)) {
13598 errno = EINVAL;
13599 return -1;
13600 }
13601
13602 if (min_version > max_version) {
13603 errno = EINVAL;
13604 return -1;
13605 }
13606
13607 fxp_min_client_version = min_version;
13608 fxp_max_client_version = max_version;
13609 return 0;
13610 }
13611
sftp_fxp_set_utf8_protocol_version(unsigned int version)13612 int sftp_fxp_set_utf8_protocol_version(unsigned int version) {
13613 if (version < 1 || version > 6) {
13614 errno = EINVAL;
13615 return -1;
13616 }
13617
13618 fxp_utf8_protocol_version = version;
13619 return 0;
13620 }
13621
sftp_fxp_use_gmt(int use_gmt)13622 void sftp_fxp_use_gmt(int use_gmt) {
13623 fxp_use_gmt = use_gmt;
13624 }
13625
sftp_fxp_open_session(uint32_t channel_id)13626 int sftp_fxp_open_session(uint32_t channel_id) {
13627 pool *sub_pool;
13628 struct fxp_session *sess, *last;
13629
13630 /* Check to see if we already have an SFTP session opened for the given
13631 * channel ID.
13632 */
13633 sess = last = fxp_sessions;
13634 while (sess) {
13635 pr_signals_handle();
13636
13637 if (sess->channel_id == channel_id) {
13638 errno = EEXIST;
13639 return -1;
13640 }
13641
13642 if (sess->next == NULL) {
13643 /* This is the last item in the list. */
13644 last = sess;
13645 }
13646
13647 sess = sess->next;
13648 }
13649
13650 /* Looks like we get to allocate a new one. */
13651 sub_pool = make_sub_pool(fxp_pool);
13652 pr_pool_tag(sub_pool, "SFTP session pool");
13653
13654 sess = pcalloc(sub_pool, sizeof(struct fxp_session));
13655 sess->pool = sub_pool;
13656 sess->channel_id = channel_id;
13657
13658 if (last) {
13659 last->next = sess;
13660 sess->prev = last;
13661
13662 } else {
13663 fxp_sessions = sess;
13664 }
13665
13666 pr_event_generate("mod_sftp.sftp.session-opened", NULL);
13667
13668 /* XXX Ignore any return value, for now. */
13669 (void) fxp_send_display_login_file(channel_id);
13670
13671 pr_session_set_protocol("sftp");
13672
13673 /* Clear any ASCII flags (set by default for FTP sessions. */
13674 session.sf_flags &= ~SF_ASCII;
13675
13676 return 0;
13677 }
13678
sftp_fxp_close_session(uint32_t channel_id)13679 int sftp_fxp_close_session(uint32_t channel_id) {
13680 struct fxp_session *sess;
13681
13682 /* Check to see if we have an SFTP session opened for the given channel ID.
13683 */
13684 sess = fxp_sessions;
13685 while (sess) {
13686 pr_signals_handle();
13687
13688 if (sess->channel_id == channel_id) {
13689 if (sess->next)
13690 sess->next->prev = sess->prev;
13691
13692 if (sess->prev) {
13693 sess->prev->next = sess->next;
13694
13695 } else {
13696 /* This is the start of the session list. */
13697 fxp_sessions = sess->next;
13698 }
13699
13700 if (sess->handle_tab) {
13701 int count;
13702
13703 count = pr_table_count(sess->handle_tab);
13704 if (count > 0) {
13705 int res;
13706 config_rec *c;
13707 void *callback_data = NULL;
13708
13709 c = find_config(main_server->conf, CONF_PARAM, "DeleteAbortedStores",
13710 FALSE);
13711 if (c) {
13712 callback_data = c->argv[0];
13713 }
13714
13715 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13716 "aborting %d unclosed file %s", count,
13717 count != 1 ? "handles" : "handle");
13718
13719 /* Make sure that any abort processing has a valid response pool to
13720 * work with.
13721 */
13722 pr_response_set_pool(sess->pool);
13723
13724 res = pr_table_do(sess->handle_tab, fxp_handle_abort, callback_data,
13725 PR_TABLE_DO_FL_ALL);
13726 if (res < 0) {
13727 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
13728 "error doing session filehandle table: %s", strerror(errno));
13729 }
13730 }
13731
13732 (void) pr_table_empty(sess->handle_tab);
13733 (void) pr_table_free(sess->handle_tab);
13734 sess->handle_tab = NULL;
13735 }
13736
13737 destroy_pool(sess->pool);
13738 pr_session_set_protocol("ssh2");
13739
13740 pr_event_generate("mod_sftp.sftp.session-closed", NULL);
13741 return 0;
13742 }
13743
13744 sess = sess->next;
13745 }
13746
13747 errno = ENOENT;
13748 return -1;
13749 }
13750