⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	(void) initgroups(pw->pw_name, pw->pw_gid);	/* open wtmp before chroot */	(void)sprintf(ttyline, "ftp%d", getpid());	logwtmp(ttyline, pw->pw_name, remotehost);	logged_in = 1;	if (guest) {		/*		 * We MUST do a chdir() after the chroot. Otherwise		 * the old current directory will be accessible as "."		 * outside the new root!		 */		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {			reply(550, "Can't set guest privileges.");			goto bad;		}	} else if (chdir(pw->pw_dir) < 0) {		if (chdir("/") < 0) {			reply(530, "User %s: can't change directory to %s.",			    pw->pw_name, pw->pw_dir);			goto bad;		} else			lreply(230, "No directory! Logging in with home=/");	}	if (seteuid((uid_t)pw->pw_uid) < 0) {		reply(550, "Can't set uid.");		goto bad;	}	/*	 * Display a login message, if it exists.	 * N.B. reply(230,) must follow the message.	 */	if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {		char *cp, line[LINE_MAX];		while (fgets(line, sizeof(line), fd) != NULL) {			if ((cp = strchr(line, '\n')) != NULL)				*cp = '\0';			lreply(230, "%s", line);		}		(void) fflush(stdout);		(void) fclose(fd);	}	if (guest) {		reply(230, "Guest login ok, access restrictions apply.");#ifdef SETPROCTITLE		snprintf(proctitle, sizeof(proctitle),		    "%s: anonymous/%.*s", remotehost,		    sizeof(proctitle) - sizeof(remotehost) -		    sizeof(": anonymous/"), passwd);		setproctitle(proctitle);#endif /* SETPROCTITLE */		if (logging)			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",			    remotehost, passwd);	} else {		reply(230, "User %s logged in.", pw->pw_name);#ifdef SETPROCTITLE		snprintf(proctitle, sizeof(proctitle),		    "%s: %s", remotehost, pw->pw_name);		setproctitle(proctitle);#endif /* SETPROCTITLE */		if (logging)			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",			    remotehost, pw->pw_name);	}	(void) umask(defumask);	return;bad:	/* Forget all about it... */	end_login();}voidretrieve(cmd, name)	char *cmd, *name;{	FILE *fin, *dout;	struct stat st;	int (*closefunc) __P((FILE *));	if (cmd == 0) {		fin = fopen(name, "r"), closefunc = fclose;		st.st_size = 0;	} else {		char line[BUFSIZ];		(void) sprintf(line, cmd, name), name = line;		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;		st.st_size = -1;		st.st_blksize = BUFSIZ;	}	if (fin == NULL) {		if (errno != 0) {			perror_reply(550, name);			if (cmd == 0) {				LOGCMD("get", name);			}		}		return;	}	byte_count = -1;	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {		reply(550, "%s: not a plain file.", name);		goto done;	}	if (restart_point) {		if (type == TYPE_A) {			off_t i, n;			int c;			n = restart_point;			i = 0;			while (i++ < n) {				if ((c=getc(fin)) == EOF) {					perror_reply(550, name);					goto done;				}				if (c == '\n')					i++;			}		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {			perror_reply(550, name);			goto done;		}	}	dout = dataconn(name, st.st_size, "w");	if (dout == NULL)		goto done;	send_data(fin, dout, st.st_blksize);	(void) fclose(dout);	data = -1;	pdata = -1;done:	if (cmd == 0)		LOGBYTES("get", name, byte_count);	(*closefunc)(fin);}voidstore(name, mode, unique)	char *name, *mode;	int unique;{	FILE *fout, *din;	struct stat st;	int (*closefunc) __P((FILE *));	if (unique && stat(name, &st) == 0 &&	    (name = gunique(name)) == NULL) {		LOGCMD(*mode == 'w' ? "put" : "append", name);		return;	}	if (restart_point)		mode = "r+";	fout = fopen(name, mode);	closefunc = fclose;	if (fout == NULL) {		perror_reply(553, name);		LOGCMD(*mode == 'w' ? "put" : "append", name);		return;	}	byte_count = -1;	if (restart_point) {		if (type == TYPE_A) {			off_t i, n;			int c;			n = restart_point;			i = 0;			while (i++ < n) {				if ((c=getc(fout)) == EOF) {					perror_reply(550, name);					goto done;				}				if (c == '\n')					i++;			}			/*			 * We must do this seek to "current" position			 * because we are changing from reading to			 * writing.			 */			if (fseek(fout, 0L, L_INCR) < 0) {				perror_reply(550, name);				goto done;			}		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {			perror_reply(550, name);			goto done;		}	}	din = dataconn(name, (off_t)-1, "r");	if (din == NULL)		goto done;	if (receive_data(din, fout) == 0) {		if (unique)			reply(226, "Transfer complete (unique file name:%s).",			    name);		else			reply(226, "Transfer complete.");	}	(void) fclose(din);	data = -1;	pdata = -1;done:	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);	(*closefunc)(fout);}static FILE *getdatasock(mode)	char *mode;{	int on = 1, s, t, tries;	if (data >= 0)		return (fdopen(data, mode));	(void) seteuid((uid_t)0);	s = socket(AF_INET, SOCK_STREAM, 0);	if (s < 0)		goto bad;	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,	    (char *) &on, sizeof(on)) < 0)		goto bad;	/* anchor socket to avoid multi-homing problems */	data_source.sin_family = AF_INET;	data_source.sin_addr = ctrl_addr.sin_addr;	for (tries = 1; ; tries++) {		if (bind(s, (struct sockaddr *)&data_source,		    sizeof(data_source)) >= 0)			break;		if (errno != EADDRINUSE || tries > 10)			goto bad;		sleep(tries);	}	(void) seteuid((uid_t)pw->pw_uid);#ifdef IP_TOS	on = IPTOS_THROUGHPUT;	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");#endif	return (fdopen(s, mode));bad:	/* Return the real value of errno (close may change it) */	t = errno;	(void) seteuid((uid_t)pw->pw_uid);	(void) close(s);	errno = t;	return (NULL);}static FILE *dataconn(name, size, mode)	char *name;	off_t size;	char *mode;{	char sizebuf[32];	FILE *file;	int retry = 0, tos;	file_size = size;	byte_count = 0;	if (size != (off_t) -1)		(void) sprintf(sizebuf, " (%qd bytes)", size);	else		(void) strcpy(sizebuf, "");	if (pdata >= 0) {		struct sockaddr_in from;		int s, fromlen = sizeof(from);		s = accept(pdata, (struct sockaddr *)&from, &fromlen);		if (s < 0) {			reply(425, "Can't open data connection.");			(void) close(pdata);			pdata = -1;			return (NULL);		}		(void) close(pdata);		pdata = s;#ifdef IP_TOS		tos = IPTOS_LOWDELAY;		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,		    sizeof(int));#endif		reply(150, "Opening %s mode data connection for '%s'%s.",		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);		return (fdopen(pdata, mode));	}	if (data >= 0) {		reply(125, "Using existing data connection for '%s'%s.",		    name, sizebuf);		usedefault = 1;		return (fdopen(data, mode));	}	if (usedefault)		data_dest = his_addr;	usedefault = 1;	file = getdatasock(mode);	if (file == NULL) {		reply(425, "Can't create data socket (%s,%d): %s.",		    inet_ntoa(data_source.sin_addr),		    ntohs(data_source.sin_port), strerror(errno));		return (NULL);	}	data = fileno(file);	while (connect(data, (struct sockaddr *)&data_dest,	    sizeof(data_dest)) < 0) {		if (errno == EADDRINUSE && retry < swaitmax) {			sleep((unsigned) swaitint);			retry += swaitint;			continue;		}		perror_reply(425, "Can't build data connection");		(void) fclose(file);		data = -1;		return (NULL);	}	reply(150, "Opening %s mode data connection for '%s'%s.",	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);	return (file);}/* * Tranfer the contents of "instr" to "outstr" peer using the appropriate * encapsulation of the data subject * to Mode, Structure, and Type. * * NB: Form isn't handled. */static voidsend_data(instr, outstr, blksize)	FILE *instr, *outstr;	off_t blksize;{	int c, cnt, filefd, netfd;	char *buf;	transflag++;	if (setjmp(urgcatch)) {		transflag = 0;		return;	}	switch (type) {	case TYPE_A:		while ((c = getc(instr)) != EOF) {			byte_count++;			if (c == '\n') {				if (ferror(outstr))					goto data_err;				(void) putc('\r', outstr);			}			(void) putc(c, outstr);		}		fflush(outstr);		transflag = 0;		if (ferror(instr))			goto file_err;		if (ferror(outstr))			goto data_err;		reply(226, "Transfer complete.");		return;	case TYPE_I:	case TYPE_L:		if ((buf = malloc((u_int)blksize)) == NULL) {			transflag = 0;			perror_reply(451, "Local resource failure: malloc");			return;		}		netfd = fileno(outstr);		filefd = fileno(instr);		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&		    write(netfd, buf, cnt) == cnt)			byte_count += cnt;		transflag = 0;		(void)free(buf);		if (cnt != 0) {			if (cnt < 0)				goto file_err;			goto data_err;		}		reply(226, "Transfer complete.");		return;	default:		transflag = 0;		reply(550, "Unimplemented TYPE %d in send_data", type);		return;	}data_err:	transflag = 0;	perror_reply(426, "Data connection");	return;file_err:	transflag = 0;	perror_reply(551, "Error on input file");}/* * Transfer data from peer to "outstr" using the appropriate encapulation of * the data subject to Mode, Structure, and Type. * * N.B.: Form isn't handled. */static intreceive_data(instr, outstr)	FILE *instr, *outstr;{	int c;	int cnt, bare_lfs = 0;	char buf[BUFSIZ];	transflag++;	if (setjmp(urgcatch)) {		transflag = 0;		return (-1);	}	switch (type) {	case TYPE_I:	case TYPE_L:		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {			if (write(fileno(outstr), buf, cnt) != cnt)				goto file_err;			byte_count += cnt;		}		if (cnt < 0)			goto data_err;		transflag = 0;		return (0);	case TYPE_E:		reply(553, "TYPE E not implemented.");		transflag = 0;		return (-1);	case TYPE_A:		while ((c = getc(instr)) != EOF) {			byte_count++;			if (c == '\n')				bare_lfs++;			while (c == '\r') {				if (ferror(outstr))					goto data_err;				if ((c = getc(instr)) != '\n') {					(void) putc ('\r', outstr);					if (c == '\0' || c == EOF)						goto contin2;				}			}			(void) putc(c, outstr);	contin2:	;		}		fflush(outstr);		if (ferror(instr))			goto data_err;		if (ferror(outstr))			goto file_err;		transflag = 0;		if (bare_lfs) {			lreply(226,		"WARNING! %d bare linefeeds received in ASCII mode",			    bare_lfs);		(void)printf("   File may not have transferred correctly.\r\n");		}		return (0);	default:		reply(550, "Unimplemented TYPE %d in receive_data", type);		transflag = 0;		return (-1);	}data_err:	transflag = 0;	perror_reply(426, "Data Connection");	return (-1);file_err:	transflag = 0;	perror_reply(452, "Error writing file");	return (-1);}voidstatfilecmd(filename)	char *filename;{	FILE *fin;	int c;	char line[LINE_MAX];	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);	fin = ftpd_popen(line, "r");	lreply(211, "status of %s:", filename);	while ((c = getc(fin)) != EOF) {		if (c == '\n') {			if (ferror(stdout)){				perror_reply(421, "control connection");				(void) ftpd_pclose(fin);				dologout(1);				/* NOTREACHED */			}			if (ferror(fin)) {				perror_reply(551, filename);				(void) ftpd_pclose(fin);				return;			}			(void) putc('\r', stdout);		}		(void) putc(c, stdout);	}	(void) ftpd_pclose(fin);	reply(211, "End of Status");}voidstatcmd(){	struct sockaddr_in *sin;	u_char *a, *p;	lreply(211, "%s FTP server status:", hostname, version);	printf("     %s\r\n", version);	printf("     Connected to %s", remotehost);	if (!isdigit(remotehost[0]))		printf(" (%s)", inet_ntoa(his_addr.sin_addr));	printf("\r\n");	if (logged_in) {		if (guest)			printf("     Logged in anonymously\r\n");		else			printf("     Logged in as %s\r\n", pw->pw_name);	} else if (askpasswd)		printf("     Waiting for password\r\n");	else		printf("     Waiting for user name\r\n");	printf("     TYPE: %s", typenames[type]);	if (type == TYPE_A || type == TYPE_E)		printf(", FORM: %s", formnames[form]);	if (type == TYPE_L)#if NBBY == 8		printf(" %d", NBBY);#else		printf(" %d", bytesize);	/* need definition! */#endif	printf("; STRUcture: %s; transfer MODE: %s\r\n",	    strunames[stru], modenames[mode]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -