View | Details | Raw Unified | Return to bug 474 | Differences between
and this patch

Collapse All | Expand All

(-)servconf.c (+12 lines)
Lines 411-416 process_server_config_line(ServerOptions Link Here
411
	ServerOpCodes opcode;
411
	ServerOpCodes opcode;
412
	u_short port;
412
	u_short port;
413
	u_int i;
413
	u_int i;
414
	size_t len;
414
415
415
	cp = line;
416
	cp = line;
416
	if ((arg = strdelim(&cp)) == NULL)
417
	if ((arg = strdelim(&cp)) == NULL)
Lines 860-865 parse_flag: Link Here
860
			fatal("%s line %d: Missing subsystem command.",
861
			fatal("%s line %d: Missing subsystem command.",
861
			    filename, linenum);
862
			    filename, linenum);
862
		options->subsystem_command[options->num_subsystems] = xstrdup(arg);
863
		options->subsystem_command[options->num_subsystems] = xstrdup(arg);
864
865
		/* Collect arguments (separate to executable) */
866
		p = xstrdup(arg);
867
		len = strlen(p) + 1;
868
		while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
869
			len += 1 + strlen(arg);
870
			p = xrealloc(p, 1, len);
871
			strlcat(p, " ", len);
872
			strlcat(p, arg, len);
873
		}
874
		options->subsystem_args[options->num_subsystems] = p;
863
		options->num_subsystems++;
875
		options->num_subsystems++;
864
		break;
876
		break;
865
877
(-)servconf.h (+1 lines)
Lines 111-116 typedef struct { Link Here
111
	u_int num_subsystems;
111
	u_int num_subsystems;
112
	char   *subsystem_name[MAX_SUBSYSTEMS];
112
	char   *subsystem_name[MAX_SUBSYSTEMS];
113
	char   *subsystem_command[MAX_SUBSYSTEMS];
113
	char   *subsystem_command[MAX_SUBSYSTEMS];
114
	char   *subsystem_args[MAX_SUBSYSTEMS];
114
115
115
	u_int num_accept_env;
116
	u_int num_accept_env;
116
	char   *accept_env[MAX_ACCEPT_ENV];
117
	char   *accept_env[MAX_ACCEPT_ENV];
(-)session.c (-4 / +5 lines)
Lines 1467-1473 session_subsystem_req(Session *s) Link Here
1467
	struct stat st;
1418
	struct stat st;
1468
	u_int len;
1419
	u_int len;
1469
	int success = 0;
1420
	int success = 0;
1470
	char *cmd, *subsys = packet_get_string(&len);
1421
	char *prog, *cmd, *subsys = packet_get_string(&len);
1471
	u_int i;
1422
	u_int i;
1472
1423
1473
	packet_check_eom();
1424
	packet_check_eom();
Lines 1475-1483 session_subsystem_req(Session *s) Link Here
1475
1426
1476
	for (i = 0; i < options.num_subsystems; i++) {
1427
	for (i = 0; i < options.num_subsystems; i++) {
1477
		if (strcmp(subsys, options.subsystem_name[i]) == 0) {
1428
		if (strcmp(subsys, options.subsystem_name[i]) == 0) {
1478
			cmd = options.subsystem_command[i];
1429
			prog = options.subsystem_command[i];
1479
			if (stat(cmd, &st) < 0) {
1430
			cmd = options.subsystem_args[i];
1480
				error("subsystem: cannot stat %s: %s", cmd,
1431
			if (stat(prog, &st) < 0) {
1432
				error("subsystem: cannot stat %s: %s", prog,
1481
				    strerror(errno));
1433
				    strerror(errno));
1482
				break;
1434
				break;
1483
			}
1435
			}
(-)sftp-server.8 (+31 lines)
Lines 30-35 Link Here
30
.Nd SFTP server subsystem
30
.Nd SFTP server subsystem
31
.Sh SYNOPSIS
31
.Sh SYNOPSIS
32
.Nm sftp-server
32
.Nm sftp-server
33
.Bk -words
34
.Op Fl l Ar log_level
35
.Op Fl f Ar log_facility
36
.Ek
33
.Sh DESCRIPTION
37
.Sh DESCRIPTION
34
.Nm
38
.Nm
35
is a program that speaks the server side of SFTP protocol
39
is a program that speaks the server side of SFTP protocol
Lines 40-48 is not intended to be called directly, b Link Here
40
using the
44
using the
41
.Cm Subsystem
45
.Cm Subsystem
42
option.
46
option.
47
.Pp
48
Command-line flags to
49
.Nm
50
should be specified in the
51
.Cm Subsystem
52
declarations.
43
See
53
See
44
.Xr sshd_config 5
54
.Xr sshd_config 5
45
for more information.
55
for more information.
56
.Pp
57
Valid options are:
58
.Bl -tag -width Ds
59
.It Fl l Ar log_level
60
Specifies which messages will be logged by
61
.Nm .
62
The possible values are:
63
QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
64
INFO and VERBOSE log transactions that
65
.Nm
66
performs on behalf of the client.
67
DEBUG and DEBUG1 are equivalent.
68
DEBUG2 and DEBUG3 each specify higher levels of debugging output.
69
The default is ERROR.
70
.It Fl f Ar log_facility
71
Specifies the facility code that is used when logging messages from
72
.Nm .
73
The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
74
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
75
The default is AUTH.
76
.El
46
.Sh SEE ALSO
77
.Sh SEE ALSO
47
.Xr sftp 1 ,
78
.Xr sftp 1 ,
48
.Xr ssh 1 ,
79
.Xr ssh 1 ,
(-)sftp-server.c (-46 / +223 lines)
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);
(-)sshd_config.5 (-2 / +2 lines)
Lines 636-643 The default is Link Here
636
.Dq yes .
636
.Dq yes .
637
.It Cm Subsystem
637
.It Cm Subsystem
638
Configures an external subsystem (e.g. file transfer daemon).
638
Configures an external subsystem (e.g. file transfer daemon).
639
Arguments should be a subsystem name and a command to execute upon subsystem
639
Arguments should be a subsystem name and a command (with optional arguments)
640
request.
640
to execute upon subsystem request.
641
The command
641
The command
642
.Xr sftp-server 8
642
.Xr sftp-server 8
643
implements the
643
implements the

Return to bug 474