|
Lines 34-40
Link Here
|
| 34 |
#define get_int64() buffer_get_int64(&iqueue); |
34 |
#define get_int64() buffer_get_int64(&iqueue); |
| 35 |
#define get_int() buffer_get_int(&iqueue); |
35 |
#define get_int() buffer_get_int(&iqueue); |
| 36 |
#define get_string(lenp) buffer_get_string(&iqueue, lenp); |
36 |
#define get_string(lenp) buffer_get_string(&iqueue, lenp); |
| 37 |
#define TRACE debug |
37 |
|
|
|
38 |
/* Our verbosity */ |
| 39 |
LogLevel log_level = SYSLOG_LEVEL_ERROR; |
| 40 |
|
| 41 |
/* Our client */ |
| 42 |
char *local_user; |
| 43 |
char *client_addr; |
| 38 |
|
44 |
|
| 39 |
/* input and output queue */ |
45 |
/* input and output queue */ |
| 40 |
Buffer iqueue; |
46 |
Buffer iqueue; |
|
Lines 106-111
flags_from_portable(int pflags)
Link Here
|
| 106 |
return flags; |
112 |
return flags; |
| 107 |
} |
113 |
} |
| 108 |
|
114 |
|
|
|
115 |
static const char * |
| 116 |
string_from_portable(int pflags) |
| 117 |
{ |
| 118 |
static char ret[128]; |
| 119 |
|
| 120 |
*ret = '\0'; |
| 121 |
|
| 122 |
#define PAPPEND(str) { \ |
| 123 |
if (*ret != '\0') \ |
| 124 |
strlcat(ret, ",", sizeof(ret)); \ |
| 125 |
strlcat(ret, str, sizeof(ret)); \ |
| 126 |
} |
| 127 |
|
| 128 |
if (pflags & SSH2_FXF_READ) |
| 129 |
PAPPEND("READ") |
| 130 |
if (pflags & SSH2_FXF_WRITE) |
| 131 |
PAPPEND("WRITE") |
| 132 |
if (pflags & SSH2_FXF_CREAT) |
| 133 |
PAPPEND("CREATE") |
| 134 |
if (pflags & SSH2_FXF_TRUNC) |
| 135 |
PAPPEND("TRUNCATE") |
| 136 |
if (pflags & SSH2_FXF_EXCL) |
| 137 |
PAPPEND("EXCL") |
| 138 |
|
| 139 |
return ret; |
| 140 |
} |
| 141 |
|
| 109 |
static Attrib * |
142 |
static Attrib * |
| 110 |
get_attrib(void) |
143 |
get_attrib(void) |
| 111 |
{ |
144 |
{ |
|
Lines 120-125
struct Handle {
Link Here
|
| 120 |
DIR *dirp; |
153 |
DIR *dirp; |
| 121 |
int fd; |
154 |
int fd; |
| 122 |
char *name; |
155 |
char *name; |
|
|
156 |
u_int64_t bytes_read, bytes_write; |
| 123 |
}; |
157 |
}; |
| 124 |
|
158 |
|
| 125 |
enum { |
159 |
enum { |
|
Lines 150-155
handle_new(int use, const char *name, in
Link Here
|
| 150 |
handles[i].dirp = dirp; |
184 |
handles[i].dirp = dirp; |
| 151 |
handles[i].fd = fd; |
185 |
handles[i].fd = fd; |
| 152 |
handles[i].name = xstrdup(name); |
186 |
handles[i].name = xstrdup(name); |
|
|
187 |
handles[i].bytes_read = handles[i].bytes_write = 0; |
| 153 |
return i; |
188 |
return i; |
| 154 |
} |
189 |
} |
| 155 |
} |
190 |
} |
|
Lines 213-218
handle_to_fd(int handle)
Link Here
|
| 213 |
return -1; |
248 |
return -1; |
| 214 |
} |
249 |
} |
| 215 |
|
250 |
|
|
|
251 |
static void |
| 252 |
handle_update_read(int handle, ssize_t bytes) |
| 253 |
{ |
| 254 |
if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) |
| 255 |
handles[handle].bytes_read += bytes; |
| 256 |
} |
| 257 |
|
| 258 |
static void |
| 259 |
handle_update_write(int handle, ssize_t bytes) |
| 260 |
{ |
| 261 |
if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) |
| 262 |
handles[handle].bytes_write += bytes; |
| 263 |
} |
| 264 |
|
| 265 |
static u_int64_t |
| 266 |
handle_bytes_read(int handle) |
| 267 |
{ |
| 268 |
if (handle_is_ok(handle, HANDLE_FILE)) |
| 269 |
return (handles[handle].bytes_read); |
| 270 |
return 0; |
| 271 |
} |
| 272 |
|
| 273 |
static u_int64_t |
| 274 |
handle_bytes_write(int handle) |
| 275 |
{ |
| 276 |
if (handle_is_ok(handle, HANDLE_FILE)) |
| 277 |
return (handles[handle].bytes_write); |
| 278 |
return 0; |
| 279 |
} |
| 280 |
|
| 216 |
static int |
281 |
static int |
| 217 |
handle_close(int handle) |
282 |
handle_close(int handle) |
| 218 |
{ |
283 |
{ |
|
Lines 258-267
send_msg(Buffer *m)
Link Here
|
| 258 |
buffer_consume(m, mlen); |
323 |
buffer_consume(m, mlen); |
| 259 |
} |
324 |
} |
| 260 |
|
325 |
|
| 261 |
static void |
326 |
static const char * |
| 262 |
send_status(u_int32_t id, u_int32_t status) |
327 |
status_to_message(u_int32_t status) |
| 263 |
{ |
328 |
{ |
| 264 |
Buffer msg; |
|
|
| 265 |
const char *status_messages[] = { |
329 |
const char *status_messages[] = { |
| 266 |
"Success", /* SSH_FX_OK */ |
330 |
"Success", /* SSH_FX_OK */ |
| 267 |
"End of file", /* SSH_FX_EOF */ |
331 |
"End of file", /* SSH_FX_EOF */ |
|
Lines 274-288
send_status(u_int32_t id, u_int32_t stat
Link Here
|
| 274 |
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ |
338 |
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ |
| 275 |
"Unknown error" /* Others */ |
339 |
"Unknown error" /* Others */ |
| 276 |
}; |
340 |
}; |
|
|
341 |
return (status_messages[MIN(status,SSH2_FX_MAX)]); |
| 342 |
} |
| 277 |
|
343 |
|
| 278 |
TRACE("sent status id %u error %u", id, status); |
344 |
static void |
|
|
345 |
send_status(u_int32_t id, u_int32_t status) |
| 346 |
{ |
| 347 |
Buffer msg; |
| 348 |
|
| 349 |
debug3("request %u: sent status %u", id, status); |
| 350 |
if (log_level > SYSLOG_LEVEL_VERBOSE || |
| 351 |
(status != SSH2_FX_OK && status != SSH2_FX_EOF)) |
| 352 |
logit("sent status %s", status_to_message(status)); |
| 279 |
buffer_init(&msg); |
353 |
buffer_init(&msg); |
| 280 |
buffer_put_char(&msg, SSH2_FXP_STATUS); |
354 |
buffer_put_char(&msg, SSH2_FXP_STATUS); |
| 281 |
buffer_put_int(&msg, id); |
355 |
buffer_put_int(&msg, id); |
| 282 |
buffer_put_int(&msg, status); |
356 |
buffer_put_int(&msg, status); |
| 283 |
if (version >= 3) { |
357 |
if (version >= 3) { |
| 284 |
buffer_put_cstring(&msg, |
358 |
buffer_put_cstring(&msg, status_to_message(status)); |
| 285 |
status_messages[MIN(status,SSH2_FX_MAX)]); |
|
|
| 286 |
buffer_put_cstring(&msg, ""); |
359 |
buffer_put_cstring(&msg, ""); |
| 287 |
} |
360 |
} |
| 288 |
send_msg(&msg); |
361 |
send_msg(&msg); |
|
Lines 304-310
send_data_or_handle(char type, u_int32_t
Link Here
|
| 304 |
static void |
377 |
static void |
| 305 |
send_data(u_int32_t id, const char *data, int dlen) |
378 |
send_data(u_int32_t id, const char *data, int dlen) |
| 306 |
{ |
379 |
{ |
| 307 |
TRACE("sent data id %u len %d", id, dlen); |
380 |
debug("request %u: sent data len %d", id, dlen); |
| 308 |
send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); |
381 |
send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); |
| 309 |
} |
382 |
} |
| 310 |
|
383 |
|
|
Lines 315-321
send_handle(u_int32_t id, int handle)
Link Here
|
| 315 |
int hlen; |
388 |
int hlen; |
| 316 |
|
389 |
|
| 317 |
handle_to_string(handle, &string, &hlen); |
390 |
handle_to_string(handle, &string, &hlen); |
| 318 |
TRACE("sent handle id %u handle %d", id, handle); |
391 |
debug("request %u: sent handle handle %d", id, handle); |
| 319 |
send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); |
392 |
send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); |
| 320 |
xfree(string); |
393 |
xfree(string); |
| 321 |
} |
394 |
} |
|
Lines 330-336
send_names(u_int32_t id, int count, cons
Link Here
|
| 330 |
buffer_put_char(&msg, SSH2_FXP_NAME); |
403 |
buffer_put_char(&msg, SSH2_FXP_NAME); |
| 331 |
buffer_put_int(&msg, id); |
404 |
buffer_put_int(&msg, id); |
| 332 |
buffer_put_int(&msg, count); |
405 |
buffer_put_int(&msg, count); |
| 333 |
TRACE("sent names id %u count %d", id, count); |
406 |
debug("request %u: sent names count %d", id, count); |
| 334 |
for (i = 0; i < count; i++) { |
407 |
for (i = 0; i < count; i++) { |
| 335 |
buffer_put_cstring(&msg, stats[i].name); |
408 |
buffer_put_cstring(&msg, stats[i].name); |
| 336 |
buffer_put_cstring(&msg, stats[i].long_name); |
409 |
buffer_put_cstring(&msg, stats[i].long_name); |
|
Lines 345-351
send_attrib(u_int32_t id, const Attrib *
Link Here
|
| 345 |
{ |
418 |
{ |
| 346 |
Buffer msg; |
419 |
Buffer msg; |
| 347 |
|
420 |
|
| 348 |
TRACE("sent attrib id %u have 0x%x", id, a->flags); |
421 |
debug("request %u: sent attrib have 0x%x", id, a->flags); |
| 349 |
buffer_init(&msg); |
422 |
buffer_init(&msg); |
| 350 |
buffer_put_char(&msg, SSH2_FXP_ATTRS); |
423 |
buffer_put_char(&msg, SSH2_FXP_ATTRS); |
| 351 |
buffer_put_int(&msg, id); |
424 |
buffer_put_int(&msg, id); |
|
Lines 362-368
process_init(void)
Link Here
|
| 362 |
Buffer msg; |
435 |
Buffer msg; |
| 363 |
|
436 |
|
| 364 |
version = get_int(); |
437 |
version = get_int(); |
| 365 |
TRACE("client version %d", version); |
438 |
verbose("received client version %d", version); |
| 366 |
buffer_init(&msg); |
439 |
buffer_init(&msg); |
| 367 |
buffer_put_char(&msg, SSH2_FXP_VERSION); |
440 |
buffer_put_char(&msg, SSH2_FXP_VERSION); |
| 368 |
buffer_put_int(&msg, SSH2_FILEXFER_VERSION); |
441 |
buffer_put_int(&msg, SSH2_FILEXFER_VERSION); |
|
Lines 379-390
process_open(void)
Link Here
|
| 379 |
int handle, fd, flags, mode, status = SSH2_FX_FAILURE; |
452 |
int handle, fd, flags, mode, status = SSH2_FX_FAILURE; |
| 380 |
|
453 |
|
| 381 |
id = get_int(); |
454 |
id = get_int(); |
|
|
455 |
debug3("request %u: open flags %d", id, pflags); |
| 382 |
name = get_string(NULL); |
456 |
name = get_string(NULL); |
| 383 |
pflags = get_int(); /* portable flags */ |
457 |
pflags = get_int(); /* portable flags */ |
| 384 |
a = get_attrib(); |
458 |
a = get_attrib(); |
| 385 |
flags = flags_from_portable(pflags); |
459 |
flags = flags_from_portable(pflags); |
| 386 |
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; |
460 |
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; |
| 387 |
TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode); |
461 |
logit("open \"%s\" flags %s mode 0%o", |
|
|
462 |
name, string_from_portable(pflags), mode); |
| 388 |
fd = open(name, flags, mode); |
463 |
fd = open(name, flags, mode); |
| 389 |
if (fd < 0) { |
464 |
if (fd < 0) { |
| 390 |
status = errno_to_portable(errno); |
465 |
status = errno_to_portable(errno); |
|
Lines 410-416
process_close(void)
Link Here
|
| 410 |
|
485 |
|
| 411 |
id = get_int(); |
486 |
id = get_int(); |
| 412 |
handle = get_handle(); |
487 |
handle = get_handle(); |
| 413 |
TRACE("close id %u handle %d", id, handle); |
488 |
debug3("request %u: close handle %u", id, handle); |
|
|
489 |
if (handle_is_ok(handle, HANDLE_FILE)) { |
| 490 |
logit("close \"%s\" bytes read %llu written %llu", |
| 491 |
handle_to_name(handle), |
| 492 |
handle_bytes_read(handle), handle_bytes_write(handle)); |
| 493 |
} else |
| 494 |
logit("closedir \"%s\"", handle_to_name(handle)); |
| 414 |
ret = handle_close(handle); |
495 |
ret = handle_close(handle); |
| 415 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
496 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 416 |
send_status(id, status); |
497 |
send_status(id, status); |
|
Lines 429-439
process_read(void)
Link Here
|
| 429 |
off = get_int64(); |
510 |
off = get_int64(); |
| 430 |
len = get_int(); |
511 |
len = get_int(); |
| 431 |
|
512 |
|
| 432 |
TRACE("read id %u handle %d off %llu len %d", id, handle, |
513 |
debug("request %u: read \"%s\" (handle %d) off %llu len %d", |
| 433 |
(unsigned long long)off, len); |
514 |
id, handle_to_name(handle), handle, (unsigned long long)off, len); |
| 434 |
if (len > sizeof buf) { |
515 |
if (len > sizeof buf) { |
| 435 |
len = sizeof buf; |
516 |
len = sizeof buf; |
| 436 |
logit("read change len %d", len); |
517 |
debug2("read change len %d", len); |
| 437 |
} |
518 |
} |
| 438 |
fd = handle_to_fd(handle); |
519 |
fd = handle_to_fd(handle); |
| 439 |
if (fd >= 0) { |
520 |
if (fd >= 0) { |
|
Lines 449-454
process_read(void)
Link Here
|
| 449 |
} else { |
530 |
} else { |
| 450 |
send_data(id, buf, ret); |
531 |
send_data(id, buf, ret); |
| 451 |
status = SSH2_FX_OK; |
532 |
status = SSH2_FX_OK; |
|
|
533 |
handle_update_read(handle, ret); |
| 452 |
} |
534 |
} |
| 453 |
} |
535 |
} |
| 454 |
} |
536 |
} |
|
Lines 470-477
process_write(void)
Link Here
|
| 470 |
off = get_int64(); |
552 |
off = get_int64(); |
| 471 |
data = get_string(&len); |
553 |
data = get_string(&len); |
| 472 |
|
554 |
|
| 473 |
TRACE("write id %u handle %d off %llu len %d", id, handle, |
555 |
debug("request %u: write \"%s\" (handle %d) off %llu len %d", |
| 474 |
(unsigned long long)off, len); |
556 |
id, handle_to_name(handle), handle, (unsigned long long)off, len); |
| 475 |
fd = handle_to_fd(handle); |
557 |
fd = handle_to_fd(handle); |
| 476 |
if (fd >= 0) { |
558 |
if (fd >= 0) { |
| 477 |
if (lseek(fd, off, SEEK_SET) < 0) { |
559 |
if (lseek(fd, off, SEEK_SET) < 0) { |
|
Lines 485-492
process_write(void)
Link Here
|
| 485 |
status = errno_to_portable(errno); |
567 |
status = errno_to_portable(errno); |
| 486 |
} else if ((size_t)ret == len) { |
568 |
} else if ((size_t)ret == len) { |
| 487 |
status = SSH2_FX_OK; |
569 |
status = SSH2_FX_OK; |
|
|
570 |
handle_update_write(handle, ret); |
| 488 |
} else { |
571 |
} else { |
| 489 |
logit("nothing at all written"); |
572 |
debug2("nothing at all written"); |
| 490 |
} |
573 |
} |
| 491 |
} |
574 |
} |
| 492 |
} |
575 |
} |
|
Lines 505-511
process_do_stat(int do_lstat)
Link Here
|
| 505 |
|
588 |
|
| 506 |
id = get_int(); |
589 |
id = get_int(); |
| 507 |
name = get_string(NULL); |
590 |
name = get_string(NULL); |
| 508 |
TRACE("%sstat id %u name %s", do_lstat ? "l" : "", id, name); |
591 |
debug3("request %u: %sstat", id, do_lstat ? "l" : ""); |
|
|
592 |
verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); |
| 509 |
ret = do_lstat ? lstat(name, &st) : stat(name, &st); |
593 |
ret = do_lstat ? lstat(name, &st) : stat(name, &st); |
| 510 |
if (ret < 0) { |
594 |
if (ret < 0) { |
| 511 |
status = errno_to_portable(errno); |
595 |
status = errno_to_portable(errno); |
|
Lines 541-547
process_fstat(void)
Link Here
|
| 541 |
|
625 |
|
| 542 |
id = get_int(); |
626 |
id = get_int(); |
| 543 |
handle = get_handle(); |
627 |
handle = get_handle(); |
| 544 |
TRACE("fstat id %u handle %d", id, handle); |
628 |
debug("request %u: fstat \"%s\" (handle %u)", |
|
|
629 |
id, handle_to_name(handle), handle); |
| 545 |
fd = handle_to_fd(handle); |
630 |
fd = handle_to_fd(handle); |
| 546 |
if (fd >= 0) { |
631 |
if (fd >= 0) { |
| 547 |
ret = fstat(fd, &st); |
632 |
ret = fstat(fd, &st); |
|
Lines 580-602
process_setstat(void)
Link Here
|
| 580 |
id = get_int(); |
665 |
id = get_int(); |
| 581 |
name = get_string(NULL); |
666 |
name = get_string(NULL); |
| 582 |
a = get_attrib(); |
667 |
a = get_attrib(); |
| 583 |
TRACE("setstat id %u name %s", id, name); |
668 |
debug("request %u: setstat name \"%s\"", id, name); |
| 584 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
669 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
|
|
670 |
logit("set \"%s\" size %llu", name, a->size); |
| 585 |
ret = truncate(name, a->size); |
671 |
ret = truncate(name, a->size); |
| 586 |
if (ret == -1) |
672 |
if (ret == -1) |
| 587 |
status = errno_to_portable(errno); |
673 |
status = errno_to_portable(errno); |
| 588 |
} |
674 |
} |
| 589 |
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
675 |
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
|
|
676 |
logit("set \"%s\" mode %04o", name, a->perm); |
| 590 |
ret = chmod(name, a->perm & 0777); |
677 |
ret = chmod(name, a->perm & 0777); |
| 591 |
if (ret == -1) |
678 |
if (ret == -1) |
| 592 |
status = errno_to_portable(errno); |
679 |
status = errno_to_portable(errno); |
| 593 |
} |
680 |
} |
| 594 |
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
681 |
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
|
|
682 |
char buf[64]; |
| 683 |
time_t t = a->mtime; |
| 684 |
|
| 685 |
strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", |
| 686 |
localtime(&t)); |
| 687 |
logit("set \"%s\" modtime %s", name, buf); |
| 595 |
ret = utimes(name, attrib_to_tv(a)); |
688 |
ret = utimes(name, attrib_to_tv(a)); |
| 596 |
if (ret == -1) |
689 |
if (ret == -1) |
| 597 |
status = errno_to_portable(errno); |
690 |
status = errno_to_portable(errno); |
| 598 |
} |
691 |
} |
| 599 |
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
692 |
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
|
|
693 |
logit("set \"%s\" owner %lu group %lu", name, |
| 694 |
(u_long)a->uid, (u_long)a->gid); |
| 600 |
ret = chown(name, a->uid, a->gid); |
695 |
ret = chown(name, a->uid, a->gid); |
| 601 |
if (ret == -1) |
696 |
if (ret == -1) |
| 602 |
status = errno_to_portable(errno); |
697 |
status = errno_to_portable(errno); |
|
Lines 616-642
process_fsetstat(void)
Link Here
|
| 616 |
id = get_int(); |
711 |
id = get_int(); |
| 617 |
handle = get_handle(); |
712 |
handle = get_handle(); |
| 618 |
a = get_attrib(); |
713 |
a = get_attrib(); |
| 619 |
TRACE("fsetstat id %u handle %d", id, handle); |
714 |
debug("request %u: fsetstat handle %d", id, handle); |
| 620 |
fd = handle_to_fd(handle); |
715 |
fd = handle_to_fd(handle); |
| 621 |
if (fd < 0) { |
716 |
if (fd < 0) { |
| 622 |
status = SSH2_FX_FAILURE; |
717 |
status = SSH2_FX_FAILURE; |
| 623 |
} else { |
718 |
} else { |
|
|
719 |
char *name = handle_to_name(handle); |
| 720 |
|
| 624 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
721 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
|
|
722 |
logit("set \"%s\" size %llu", name, a->size); |
| 625 |
ret = ftruncate(fd, a->size); |
723 |
ret = ftruncate(fd, a->size); |
| 626 |
if (ret == -1) |
724 |
if (ret == -1) |
| 627 |
status = errno_to_portable(errno); |
725 |
status = errno_to_portable(errno); |
| 628 |
} |
726 |
} |
| 629 |
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
727 |
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
|
|
728 |
logit("set \"%s\" mode %04o", name, a->perm); |
| 630 |
ret = fchmod(fd, a->perm & 0777); |
729 |
ret = fchmod(fd, a->perm & 0777); |
| 631 |
if (ret == -1) |
730 |
if (ret == -1) |
| 632 |
status = errno_to_portable(errno); |
731 |
status = errno_to_portable(errno); |
| 633 |
} |
732 |
} |
| 634 |
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
733 |
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
|
|
734 |
char buf[64]; |
| 735 |
time_t t = a->mtime; |
| 736 |
|
| 737 |
strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", |
| 738 |
localtime(&t)); |
| 739 |
logit("set \"%s\" modtime %s", name, buf); |
| 635 |
ret = futimes(fd, attrib_to_tv(a)); |
740 |
ret = futimes(fd, attrib_to_tv(a)); |
| 636 |
if (ret == -1) |
741 |
if (ret == -1) |
| 637 |
status = errno_to_portable(errno); |
742 |
status = errno_to_portable(errno); |
| 638 |
} |
743 |
} |
| 639 |
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
744 |
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
|
|
745 |
logit("set \"%s\" owner %lu group %lu", name, |
| 746 |
(u_long)a->uid, (u_long)a->gid); |
| 640 |
ret = fchown(fd, a->uid, a->gid); |
747 |
ret = fchown(fd, a->uid, a->gid); |
| 641 |
if (ret == -1) |
748 |
if (ret == -1) |
| 642 |
status = errno_to_portable(errno); |
749 |
status = errno_to_portable(errno); |
|
Lines 655-661
process_opendir(void)
Link Here
|
| 655 |
|
762 |
|
| 656 |
id = get_int(); |
763 |
id = get_int(); |
| 657 |
path = get_string(NULL); |
764 |
path = get_string(NULL); |
| 658 |
TRACE("opendir id %u path %s", id, path); |
765 |
debug3("request %u: opendir", id); |
|
|
766 |
logit("opendir \"%s\"", path); |
| 659 |
dirp = opendir(path); |
767 |
dirp = opendir(path); |
| 660 |
if (dirp == NULL) { |
768 |
if (dirp == NULL) { |
| 661 |
status = errno_to_portable(errno); |
769 |
status = errno_to_portable(errno); |
|
Lines 685-698
process_readdir(void)
Link Here
|
| 685 |
|
793 |
|
| 686 |
id = get_int(); |
794 |
id = get_int(); |
| 687 |
handle = get_handle(); |
795 |
handle = get_handle(); |
| 688 |
TRACE("readdir id %u handle %d", id, handle); |
796 |
debug("request %u: readdir \"%s\" (handle %d)", id, |
|
|
797 |
handle_to_name(handle), handle); |
| 689 |
dirp = handle_to_dir(handle); |
798 |
dirp = handle_to_dir(handle); |
| 690 |
path = handle_to_name(handle); |
799 |
path = handle_to_name(handle); |
| 691 |
if (dirp == NULL || path == NULL) { |
800 |
if (dirp == NULL || path == NULL) { |
| 692 |
send_status(id, SSH2_FX_FAILURE); |
801 |
send_status(id, SSH2_FX_FAILURE); |
| 693 |
} else { |
802 |
} else { |
| 694 |
struct stat st; |
803 |
struct stat st; |
| 695 |
char pathname[1024]; |
804 |
char pathname[MAXPATHLEN]; |
| 696 |
Stat *stats; |
805 |
Stat *stats; |
| 697 |
int nstats = 10, count = 0, i; |
806 |
int nstats = 10, count = 0, i; |
| 698 |
|
807 |
|
|
Lines 739-745
process_remove(void)
Link Here
|
| 739 |
|
848 |
|
| 740 |
id = get_int(); |
849 |
id = get_int(); |
| 741 |
name = get_string(NULL); |
850 |
name = get_string(NULL); |
| 742 |
TRACE("remove id %u name %s", id, name); |
851 |
debug3("request %u: remove", id); |
|
|
852 |
logit("remove name \"%s\"", name); |
| 743 |
ret = unlink(name); |
853 |
ret = unlink(name); |
| 744 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
854 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 745 |
send_status(id, status); |
855 |
send_status(id, status); |
|
Lines 759-765
process_mkdir(void)
Link Here
|
| 759 |
a = get_attrib(); |
869 |
a = get_attrib(); |
| 760 |
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? |
870 |
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? |
| 761 |
a->perm & 0777 : 0777; |
871 |
a->perm & 0777 : 0777; |
| 762 |
TRACE("mkdir id %u name %s mode 0%o", id, name, mode); |
872 |
debug3("request %u: mkdir", id); |
|
|
873 |
logit("mkdir name \"%s\" mode 0%o", name, mode); |
| 763 |
ret = mkdir(name, mode); |
874 |
ret = mkdir(name, mode); |
| 764 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
875 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 765 |
send_status(id, status); |
876 |
send_status(id, status); |
|
Lines 775-781
process_rmdir(void)
Link Here
|
| 775 |
|
886 |
|
| 776 |
id = get_int(); |
887 |
id = get_int(); |
| 777 |
name = get_string(NULL); |
888 |
name = get_string(NULL); |
| 778 |
TRACE("rmdir id %u name %s", id, name); |
889 |
debug3("request %u: rmdir", id); |
|
|
890 |
logit("rmdir name \"%s\"", name); |
| 779 |
ret = rmdir(name); |
891 |
ret = rmdir(name); |
| 780 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
892 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 781 |
send_status(id, status); |
893 |
send_status(id, status); |
|
Lines 795-801
process_realpath(void)
Link Here
|
| 795 |
xfree(path); |
907 |
xfree(path); |
| 796 |
path = xstrdup("."); |
908 |
path = xstrdup("."); |
| 797 |
} |
909 |
} |
| 798 |
TRACE("realpath id %u path %s", id, path); |
910 |
debug3("request %u: realpath", id); |
|
|
911 |
verbose("realpath \"%s\"", path); |
| 799 |
if (realpath(path, resolvedname) == NULL) { |
912 |
if (realpath(path, resolvedname) == NULL) { |
| 800 |
send_status(id, errno_to_portable(errno)); |
913 |
send_status(id, errno_to_portable(errno)); |
| 801 |
} else { |
914 |
} else { |
|
Lines 818-824
process_rename(void)
Link Here
|
| 818 |
id = get_int(); |
931 |
id = get_int(); |
| 819 |
oldpath = get_string(NULL); |
932 |
oldpath = get_string(NULL); |
| 820 |
newpath = get_string(NULL); |
933 |
newpath = get_string(NULL); |
| 821 |
TRACE("rename id %u old %s new %s", id, oldpath, newpath); |
934 |
debug3("request %u: rename", id); |
|
|
935 |
logit("rename old \"%s\" new \"%s\"", oldpath, newpath); |
| 822 |
status = SSH2_FX_FAILURE; |
936 |
status = SSH2_FX_FAILURE; |
| 823 |
if (lstat(oldpath, &sb) == -1) |
937 |
if (lstat(oldpath, &sb) == -1) |
| 824 |
status = errno_to_portable(errno); |
938 |
status = errno_to_portable(errno); |
|
Lines 869-875
process_readlink(void)
Link Here
|
| 869 |
|
983 |
|
| 870 |
id = get_int(); |
984 |
id = get_int(); |
| 871 |
path = get_string(NULL); |
985 |
path = get_string(NULL); |
| 872 |
TRACE("readlink id %u path %s", id, path); |
986 |
debug3("request %u: readlink", id); |
|
|
987 |
verbose("readlink \"%s\"", path); |
| 873 |
if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) |
988 |
if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) |
| 874 |
send_status(id, errno_to_portable(errno)); |
989 |
send_status(id, errno_to_portable(errno)); |
| 875 |
else { |
990 |
else { |
|
Lines 893-899
process_symlink(void)
Link Here
|
| 893 |
id = get_int(); |
1008 |
id = get_int(); |
| 894 |
oldpath = get_string(NULL); |
1009 |
oldpath = get_string(NULL); |
| 895 |
newpath = get_string(NULL); |
1010 |
newpath = get_string(NULL); |
| 896 |
TRACE("symlink id %u old %s new %s", id, oldpath, newpath); |
1011 |
debug3("request %u: symlink", id); |
|
|
1012 |
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); |
| 897 |
/* this will fail if 'newpath' exists */ |
1013 |
/* this will fail if 'newpath' exists */ |
| 898 |
ret = symlink(oldpath, newpath); |
1014 |
ret = symlink(oldpath, newpath); |
| 899 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1015 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
|
Lines 931-937
process(void)
Link Here
|
| 931 |
cp = buffer_ptr(&iqueue); |
1047 |
cp = buffer_ptr(&iqueue); |
| 932 |
msg_len = get_u32(cp); |
1048 |
msg_len = get_u32(cp); |
| 933 |
if (msg_len > SFTP_MAX_MSG_LENGTH) { |
1049 |
if (msg_len > SFTP_MAX_MSG_LENGTH) { |
| 934 |
error("bad message "); |
1050 |
error("bad message from %s local user %s", |
|
|
1051 |
client_addr, local_user); |
| 935 |
exit(11); |
1052 |
exit(11); |
| 936 |
} |
1053 |
} |
| 937 |
if (buf_len < msg_len + 4) |
1054 |
if (buf_len < msg_len + 4) |
|
Lines 1006-1036
process(void)
Link Here
|
| 1006 |
} |
1123 |
} |
| 1007 |
/* discard the remaining bytes from the current packet */ |
1124 |
/* discard the remaining bytes from the current packet */ |
| 1008 |
if (buf_len < buffer_len(&iqueue)) |
1125 |
if (buf_len < buffer_len(&iqueue)) |
| 1009 |
fatal("iqueue grows"); |
1126 |
fatal("iqueue grew unexpectedly (client %s local user %s)", |
|
|
1127 |
client_addr, local_user); |
| 1010 |
consumed = buf_len - buffer_len(&iqueue); |
1128 |
consumed = buf_len - buffer_len(&iqueue); |
| 1011 |
if (msg_len < consumed) |
1129 |
if (msg_len < consumed) |
| 1012 |
fatal("msg_len %d < consumed %d", msg_len, consumed); |
1130 |
fatal("msg_len %d < consumed %d (client %s local user %s)", |
|
|
1131 |
msg_len, consumed, client_addr, local_user); |
| 1013 |
if (msg_len > consumed) |
1132 |
if (msg_len > consumed) |
| 1014 |
buffer_consume(&iqueue, msg_len - consumed); |
1133 |
buffer_consume(&iqueue, msg_len - consumed); |
| 1015 |
} |
1134 |
} |
| 1016 |
|
1135 |
|
|
|
1136 |
static void |
| 1137 |
usage(void) |
| 1138 |
{ |
| 1139 |
extern char *__progname; |
| 1140 |
|
| 1141 |
fprintf(stderr, |
| 1142 |
"usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname); |
| 1143 |
exit(1); |
| 1144 |
} |
| 1145 |
|
| 1017 |
int |
1146 |
int |
| 1018 |
main(int ac, char **av) |
1147 |
main(int argc, char **argv) |
| 1019 |
{ |
1148 |
{ |
| 1020 |
fd_set *rset, *wset; |
1149 |
fd_set *rset, *wset; |
| 1021 |
int in, out, max; |
1150 |
int in, out, max, ch, log_stderr = 0; |
| 1022 |
ssize_t len, olen, set_size; |
1151 |
ssize_t len, olen, set_size; |
|
|
1152 |
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; |
| 1153 |
char *cp; |
| 1154 |
struct passwd *pw; |
| 1155 |
|
| 1156 |
extern int optind; |
| 1157 |
extern char *optarg; |
| 1158 |
extern char *__progname; |
| 1023 |
|
1159 |
|
| 1024 |
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
1160 |
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
| 1025 |
sanitise_stdfd(); |
1161 |
sanitise_stdfd(); |
| 1026 |
|
1162 |
|
| 1027 |
/* XXX should use getopt */ |
1163 |
log_init(__progname, log_level, log_facility, log_stderr); |
| 1028 |
|
1164 |
|
| 1029 |
handle_init(); |
1165 |
while ((ch = getopt(argc, argv, "hef:l:")) != -1) { |
|
|
1166 |
switch (ch) { |
| 1167 |
case 'e': |
| 1168 |
log_stderr = 1; |
| 1169 |
break; |
| 1170 |
case 'l': |
| 1171 |
log_level = log_level_number(optarg); |
| 1172 |
if (log_level == SYSLOG_LEVEL_NOT_SET) |
| 1173 |
error("Invalid log level \"%s\"", optarg); |
| 1174 |
break; |
| 1175 |
case 'f': |
| 1176 |
log_facility = log_facility_number(optarg); |
| 1177 |
if (log_level == SYSLOG_FACILITY_NOT_SET) |
| 1178 |
error("Invalid log facility \"%s\"", optarg); |
| 1179 |
break; |
| 1180 |
case 'h': |
| 1181 |
default: |
| 1182 |
usage(); |
| 1183 |
} |
| 1184 |
} |
| 1185 |
|
| 1186 |
log_init(__progname, log_level, log_facility, 1); |
| 1030 |
|
1187 |
|
| 1031 |
#ifdef DEBUG_SFTP_SERVER |
1188 |
if ((cp = getenv("SSH_CONNECTION")) != NULL) { |
| 1032 |
log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0); |
1189 |
client_addr = xstrdup(cp); |
| 1033 |
#endif |
1190 |
if ((cp = strchr(client_addr, ' ')) == NULL) |
|
|
1191 |
fatal("Malformed SSH_CONNECTION variable: \"%s\"", |
| 1192 |
getenv("SSH_CONNECTION")); |
| 1193 |
*cp = '\0'; |
| 1194 |
} else |
| 1195 |
client_addr = xstrdup("UNKNOWN"); |
| 1196 |
|
| 1197 |
if ((pw = getpwuid(getuid())) == NULL) |
| 1198 |
fatal("No user found for uid %lu", (u_long)getuid()); |
| 1199 |
local_user = xstrdup(pw->pw_name); |
| 1200 |
|
| 1201 |
logit("session opened for client %s local user %s", |
| 1202 |
client_addr, local_user); |
| 1203 |
|
| 1204 |
handle_init(); |
| 1034 |
|
1205 |
|
| 1035 |
in = dup(STDIN_FILENO); |
1206 |
in = dup(STDIN_FILENO); |
| 1036 |
out = dup(STDOUT_FILENO); |
1207 |
out = dup(STDOUT_FILENO); |
|
Lines 1060-1065
main(int ac, char **av)
Link Here
|
| 1060 |
if (select(max+1, rset, wset, NULL, NULL) < 0) { |
1231 |
if (select(max+1, rset, wset, NULL, NULL) < 0) { |
| 1061 |
if (errno == EINTR) |
1232 |
if (errno == EINTR) |
| 1062 |
continue; |
1233 |
continue; |
|
|
1234 |
error("select %s (client %s local user %s)", |
| 1235 |
strerror(errno), client_addr, local_user); |
| 1063 |
exit(2); |
1236 |
exit(2); |
| 1064 |
} |
1237 |
} |
| 1065 |
|
1238 |
|
|
Lines 1069-1077
main(int ac, char **av)
Link Here
|
| 1069 |
len = read(in, buf, sizeof buf); |
1242 |
len = read(in, buf, sizeof buf); |
| 1070 |
if (len == 0) { |
1243 |
if (len == 0) { |
| 1071 |
debug("read eof"); |
1244 |
debug("read eof"); |
|
|
1245 |
logit("session closed for client %s " |
| 1246 |
"local user %s", client_addr, local_user); |
| 1072 |
exit(0); |
1247 |
exit(0); |
| 1073 |
} else if (len < 0) { |
1248 |
} else if (len < 0) { |
| 1074 |
error("read error"); |
1249 |
error("read error %s (client %s local user %s)", |
|
|
1250 |
strerror(errno), client_addr, local_user); |
| 1075 |
exit(1); |
1251 |
exit(1); |
| 1076 |
} else { |
1252 |
} else { |
| 1077 |
buffer_append(&iqueue, buf, len); |
1253 |
buffer_append(&iqueue, buf, len); |
|
Lines 1081-1087
main(int ac, char **av)
Link Here
|
| 1081 |
if (FD_ISSET(out, wset)) { |
1257 |
if (FD_ISSET(out, wset)) { |
| 1082 |
len = write(out, buffer_ptr(&oqueue), olen); |
1258 |
len = write(out, buffer_ptr(&oqueue), olen); |
| 1083 |
if (len < 0) { |
1259 |
if (len < 0) { |
| 1084 |
error("write error"); |
1260 |
error("write error %s (client %s local user %s)", |
|
|
1261 |
strerror(errno), client_addr, local_user); |
| 1085 |
exit(1); |
1262 |
exit(1); |
| 1086 |
} else { |
1263 |
} else { |
| 1087 |
buffer_consume(&oqueue, len); |
1264 |
buffer_consume(&oqueue, len); |