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

Collapse All | Expand All

(-)sftp-server.8 (-1 / +7 lines)
Lines 30-36 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
.Op Fl eh
33
.Op Fl Reh
34
.Op Fl f Ar log_facility
34
.Op Fl f Ar log_facility
35
.Op Fl l Ar log_level
35
.Op Fl l Ar log_level
36
.Op Fl u Ar umask
36
.Op Fl u Ar umask
Lines 56-61 for more information. Link Here
56
.Pp
56
.Pp
57
Valid options are:
57
Valid options are:
58
.Bl -tag -width Ds
58
.Bl -tag -width Ds
59
.It Fl R
60
Places this instance of
61
.Nm
62
into a read-only mode.
63
Attempts to open files for writing, as well as other operations that change
64
the state of the filesystem will be denied.
59
.It Fl e
65
.It Fl e
60
Causes
66
Causes
61
.Nm
67
.Nm
(-)sftp-server.c (-28 / +73 lines)
Lines 61-66 Buffer oqueue; Link Here
61
/* Version of client */
61
/* Version of client */
62
int version;
62
int version;
63
63
64
/* Disable writes */
65
int readonly;
66
64
/* portable attributes, etc. */
67
/* portable attributes, etc. */
65
68
66
typedef struct Stat Stat;
69
typedef struct Stat Stat;
Lines 544-559 process_open(void) Link Here
544
	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
547
	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
545
	logit("open \"%s\" flags %s mode 0%o",
548
	logit("open \"%s\" flags %s mode 0%o",
546
	    name, string_from_portable(pflags), mode);
549
	    name, string_from_portable(pflags), mode);
547
	fd = open(name, flags, mode);
550
	if (readonly &&
548
	if (fd < 0) {
551
	    ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR))
549
		status = errno_to_portable(errno);
552
		status = SSH2_FX_PERMISSION_DENIED;
550
	} else {
553
	else {
551
		handle = handle_new(HANDLE_FILE, name, fd, NULL);
554
		fd = open(name, flags, mode);
552
		if (handle < 0) {
555
		if (fd < 0) {
553
			close(fd);
556
			status = errno_to_portable(errno);
554
		} else {
557
		} else {
555
			send_handle(id, handle);
558
			handle = handle_new(HANDLE_FILE, name, fd, NULL);
556
			status = SSH2_FX_OK;
559
			if (handle < 0) {
560
				close(fd);
561
			} else {
562
				send_handle(id, handle);
563
				status = SSH2_FX_OK;
564
			}
557
		}
565
		}
558
	}
566
	}
559
	if (status != SSH2_FX_OK)
567
	if (status != SSH2_FX_OK)
Lines 623-629 process_write(void) Link Here
623
	u_int32_t id;
631
	u_int32_t id;
624
	u_int64_t off;
632
	u_int64_t off;
625
	u_int len;
633
	u_int len;
626
	int handle, fd, ret, status = SSH2_FX_FAILURE;
634
	int handle, fd, ret, status;
627
	char *data;
635
	char *data;
628
636
629
	id = get_int();
637
	id = get_int();
Lines 634-640 process_write(void) Link Here
634
	debug("request %u: write \"%s\" (handle %d) off %llu len %d",
642
	debug("request %u: write \"%s\" (handle %d) off %llu len %d",
635
	    id, handle_to_name(handle), handle, (unsigned long long)off, len);
643
	    id, handle_to_name(handle), handle, (unsigned long long)off, len);
636
	fd = handle_to_fd(handle);
644
	fd = handle_to_fd(handle);
637
	if (fd >= 0) {
645
	
646
	if (fd < 0)
647
		status = SSH2_FX_FAILURE;
648
	else if (readonly)
649
		status = SSH2_FX_PERMISSION_DENIED;
650
	else {
638
		if (lseek(fd, off, SEEK_SET) < 0) {
651
		if (lseek(fd, off, SEEK_SET) < 0) {
639
			status = errno_to_portable(errno);
652
			status = errno_to_portable(errno);
640
			error("process_write: seek failed");
653
			error("process_write: seek failed");
Lines 649-654 process_write(void) Link Here
649
				handle_update_write(handle, ret);
662
				handle_update_write(handle, ret);
650
			} else {
663
			} else {
651
				debug2("nothing at all written");
664
				debug2("nothing at all written");
665
				status = SSH2_FX_FAILURE;
652
			}
666
			}
653
		}
667
		}
654
	}
668
	}
Lines 745-750 process_setstat(void) Link Here
745
	name = get_string(NULL);
759
	name = get_string(NULL);
746
	a = get_attrib();
760
	a = get_attrib();
747
	debug("request %u: setstat name \"%s\"", id, name);
761
	debug("request %u: setstat name \"%s\"", id, name);
762
	if (readonly) {
763
		status = SSH2_FX_PERMISSION_DENIED;
764
		a->flags = 0;
765
	}
748
	if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
766
	if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
749
		logit("set \"%s\" size %llu",
767
		logit("set \"%s\" size %llu",
750
		    name, (unsigned long long)a->size);
768
		    name, (unsigned long long)a->size);
Lines 793-801 process_fsetstat(void) Link Here
793
	a = get_attrib();
811
	a = get_attrib();
794
	debug("request %u: fsetstat handle %d", id, handle);
812
	debug("request %u: fsetstat handle %d", id, handle);
795
	fd = handle_to_fd(handle);
813
	fd = handle_to_fd(handle);
796
	if (fd < 0) {
814
	if (fd < 0)
797
		status = SSH2_FX_FAILURE;
815
		status = SSH2_FX_FAILURE;
798
	} else {
816
	else if (readonly)
817
		status = SSH2_FX_PERMISSION_DENIED;
818
	else {
799
		char *name = handle_to_name(handle);
819
		char *name = handle_to_name(handle);
800
820
801
		if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
821
		if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
Lines 931-938 process_remove(void) Link Here
931
	name = get_string(NULL);
951
	name = get_string(NULL);
932
	debug3("request %u: remove", id);
952
	debug3("request %u: remove", id);
933
	logit("remove name \"%s\"", name);
953
	logit("remove name \"%s\"", name);
934
	ret = unlink(name);
954
	if (readonly)
935
	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
955
		status = SSH2_FX_PERMISSION_DENIED;
956
	else {
957
		ret = unlink(name);
958
		status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
959
	}
936
	send_status(id, status);
960
	send_status(id, status);
937
	xfree(name);
961
	xfree(name);
938
}
962
}
Lines 952-959 process_mkdir(void) Link Here
952
	    a->perm & 07777 : 0777;
976
	    a->perm & 07777 : 0777;
953
	debug3("request %u: mkdir", id);
977
	debug3("request %u: mkdir", id);
954
	logit("mkdir name \"%s\" mode 0%o", name, mode);
978
	logit("mkdir name \"%s\" mode 0%o", name, mode);
955
	ret = mkdir(name, mode);
979
	if (readonly)
956
	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
980
		status = SSH2_FX_PERMISSION_DENIED;
981
	else {
982
		ret = mkdir(name, mode);
983
		status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
984
	}
957
	send_status(id, status);
985
	send_status(id, status);
958
	xfree(name);
986
	xfree(name);
959
}
987
}
Lines 969-976 process_rmdir(void) Link Here
969
	name = get_string(NULL);
997
	name = get_string(NULL);
970
	debug3("request %u: rmdir", id);
998
	debug3("request %u: rmdir", id);
971
	logit("rmdir name \"%s\"", name);
999
	logit("rmdir name \"%s\"", name);
972
	ret = rmdir(name);
1000
	if (readonly)
973
	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1001
		status = SSH2_FX_PERMISSION_DENIED;
1002
	else {
1003
		ret = rmdir(name);
1004
		status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1005
	}
974
	send_status(id, status);
1006
	send_status(id, status);
975
	xfree(name);
1007
	xfree(name);
976
}
1008
}
Lines 1015-1021 process_rename(void) Link Here
1015
	debug3("request %u: rename", id);
1047
	debug3("request %u: rename", id);
1016
	logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
1048
	logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
1017
	status = SSH2_FX_FAILURE;
1049
	status = SSH2_FX_FAILURE;
1018
	if (lstat(oldpath, &sb) == -1)
1050
	if (readonly)
1051
		status = SSH2_FX_PERMISSION_DENIED;
1052
	else if (lstat(oldpath, &sb) == -1)
1019
		status = errno_to_portable(errno);
1053
		status = errno_to_portable(errno);
1020
	else if (S_ISREG(sb.st_mode)) {
1054
	else if (S_ISREG(sb.st_mode)) {
1021
		/* Race-free rename of regular files */
1055
		/* Race-free rename of regular files */
Lines 1092-1099 process_symlink(void) Link Here
1092
	debug3("request %u: symlink", id);
1126
	debug3("request %u: symlink", id);
1093
	logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
1127
	logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
1094
	/* this will fail if 'newpath' exists */
1128
	/* this will fail if 'newpath' exists */
1095
	ret = symlink(oldpath, newpath);
1129
	if (readonly)
1096
	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1130
		status = SSH2_FX_PERMISSION_DENIED;
1131
	else {
1132
		ret = symlink(oldpath, newpath);
1133
		status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1134
	}
1097
	send_status(id, status);
1135
	send_status(id, status);
1098
	xfree(oldpath);
1136
	xfree(oldpath);
1099
	xfree(newpath);
1137
	xfree(newpath);
Lines 1103-1117 static void Link Here
1103
process_extended_posix_rename(u_int32_t id)
1141
process_extended_posix_rename(u_int32_t id)
1104
{
1142
{
1105
	char *oldpath, *newpath;
1143
	char *oldpath, *newpath;
1144
	int ret, status;
1106
1145
1107
	oldpath = get_string(NULL);
1146
	oldpath = get_string(NULL);
1108
	newpath = get_string(NULL);
1147
	newpath = get_string(NULL);
1109
	debug3("request %u: posix-rename", id);
1148
	debug3("request %u: posix-rename", id);
1110
	logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
1149
	logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
1111
	if (rename(oldpath, newpath) == -1)
1150
	if (readonly)
1112
		send_status(id, errno_to_portable(errno));
1151
		status = SSH2_FX_PERMISSION_DENIED;
1113
	else
1152
	else {
1114
		send_status(id, SSH2_FX_OK);
1153
		ret = rename(oldpath, newpath);
1154
		status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1155
	}
1156
	send_status(id, status);
1115
	xfree(oldpath);
1157
	xfree(oldpath);
1116
	xfree(newpath);
1158
	xfree(newpath);
1117
}
1159
}
Lines 1294-1300 sftp_server_usage(void) Link Here
1294
	extern char *__progname;
1336
	extern char *__progname;
1295
1337
1296
	fprintf(stderr,
1338
	fprintf(stderr,
1297
	    "usage: %s [-eh] [-f log_facility] [-l log_level] [-u umask]\n",
1339
	    "usage: %s [-Reh] [-f log_facility] [-l log_level] [-u umask]\n",
1298
	    __progname);
1340
	    __progname);
1299
	exit(1);
1341
	exit(1);
1300
}
1342
}
Lines 1315-1322 sftp_server_main(int argc, char **argv, Link Here
1315
1357
1316
	log_init(__progname, log_level, log_facility, log_stderr);
1358
	log_init(__progname, log_level, log_facility, log_stderr);
1317
1359
1318
	while (!skipargs && (ch = getopt(argc, argv, "f:l:u:che")) != -1) {
1360
	while (!skipargs && (ch = getopt(argc, argv, "f:l:u:Rche")) != -1) {
1319
		switch (ch) {
1361
		switch (ch) {
1362
		case 'R':
1363
			readonly = 1;
1364
			break;
1320
		case 'c':
1365
		case 'c':
1321
			/*
1366
			/*
1322
			 * Ignore all arguments if we are invoked as a
1367
			 * Ignore all arguments if we are invoked as a

Return to bug 430