Hi,

This patch allows changing file permissions via ftp.
Mode is limited to octal values (no a+rwx etc.) and just access permissions 
(0777, no suid), like in vsftpd.
Verified with following FTP clients: Midnight Commander, ncftp (in the latter 
case explicit chmod command is needed).
Without this patch the executable bit is lost and you have to recover 
permissions of uploaded files on your own.

function                                             old     new   delta
ftpd_main                                           2061    2280    +219
.rodata                                            33114   33120      +6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 225/0)             Total: 225 bytes
   text    data     bss     dec     hex filename
 300584    1331    1212  303127   4a017 busybox_old
 300809    1331    1212  303352   4a0f8 busybox_unstripped
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -92,6 +92,7 @@
 #define FTP_PORTOK              200
 #define FTP_STRUOK              200
 #define FTP_MODEOK              200
+#define FTP_SITEOK              200
 #define FTP_ALLOOK              202
 #define FTP_STATOK              211
 #define FTP_STATFILE_OK         213
@@ -118,6 +119,7 @@
 #define FTP_BADSENDNET          426
 #define FTP_BADSENDFILE         451
 #define FTP_BADCMD              500
+#define FTP_BADARG              501
 #define FTP_COMMANDNOTIMPL      502
 #define FTP_NEEDUSER            503
 #define FTP_NEEDRNFR            503
@@ -1031,6 +1033,50 @@
 	G.restart_pos = 0;
 	handle_upload_common(0, 1);
 }
+
+static void
+handle_site_chmod(const char *site_args)
+{
+	/* example site_args: 0755 /path/to/file */
+	char *path = site_args ? strchr(site_args, ' ') : NULL;
+	unsigned long mode;
+	char *e;
+
+	if (!path) {
+		WRITE_ERR(FTP_BADCMD);
+		return;
+	}
+	*path++ = '\0';
+	/* support octal mask only - like vsftpd (no stat+bb_parse_mode) */
+	mode = strtoul(site_args, &e, 8);
+	if (*e || (mode > 07777U)) {
+		WRITE_ERR(FTP_BADARG);
+		return;
+	}
+	/* mask mode to just access permissions like vsftpd (no suid) */
+	if (chmod(path, mode & 0777)) {
+		WRITE_ERR(FTP_FILEFAIL);
+		return;
+	}
+	WRITE_OK(FTP_SITEOK);
+}
+
+static void
+handle_site(void)
+{
+	if (G.ftp_arg) {
+		/* e.g. CHMOD 0755 /path/to/file */
+		char *site_cmd = G.ftp_arg;
+		char *site_arg = strchr(site_cmd, ' ');
+
+		if (site_arg)
+			*site_arg++ = '\0';
+		if (!strcasecmp(site_cmd, "chmod"))
+			return handle_site_chmod(site_arg);
+	}
+
+	WRITE_ERR(FTP_BADCMD);
+}
 #endif /* ENABLE_FEATURE_FTPD_WRITE */
 
 static uint32_t
@@ -1157,6 +1203,7 @@
 	const_SYST = mk_const4('S', 'Y', 'S', 'T'),
 	const_TYPE = mk_const4('T', 'Y', 'P', 'E'),
 	const_USER = mk_const4('U', 'S', 'E', 'R'),
+	const_SITE = mk_const4('S', 'I', 'T', 'E'),
 
 #if !BB_MMU
 	OPT_l = (1 << 0),
@@ -1451,6 +1498,8 @@
 				handle_appe();
 			else if (cmdval == const_STOU) /* "store unique" */
 				handle_stou();
+			else if (cmdval == const_SITE)
+				handle_site();
 			else
 				goto bad_cmd;
 		}
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to