Ejemplo n.º 1
0
static int
getstreamsocket(int family, char *errbuf, size_t errbufsize)
{
  int fd, optval, r;

  fd = netSocket(family, SOCK_STREAM, IPPROTO_TCP);
  if(fd < 0) {
    snprintf(errbuf, errbufsize, "Unable to create socket: %s",
	     strerror(net_errno));
    return -1;  
  }

  /**
   * Switch to nonblocking
   */
  optval = 1;
  r = netSetSockOpt(fd, SOL_SOCKET, SO_NBIO, &optval, sizeof(optval));
  if(r < 0) {
    snprintf(errbuf, errbufsize, "Unable to go nonblocking: %s",
	     strerror(net_errno));
    netClose(fd);
    return -1;
  }

  return fd;
}
Ejemplo n.º 2
0
void
tcp_close(tcpcon_t *tc)
{
#if ENABLE_POLARSSL
  if(tc->ssl != NULL) {
    ssl_close_notify(tc->ssl);
    ssl_free(tc->ssl);

    free(tc->ssl);
    free(tc->ssn);
    free(tc->hs);
  }
#endif
  htsbuf_queue_flush(&tc->spill);
  netClose(tc->fd);
  free(tc);
}
Ejemplo n.º 3
0
tcpcon_t *
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
	    int timeout, int ssl)
{
  struct net_hostent *hp;
  char *tmphstbuf;
  int fd, r, err, herr, optval;
  const char *errtxt;
  struct sockaddr_in in;
  socklen_t errlen = sizeof(int);


  if(!strcmp(hostname, "localhost")) {
    if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1)
      return NULL;

    memset(&in, 0, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    r = netConnect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
  } else {

    herr = 0;
    tmphstbuf = NULL; /* free NULL is a nop */
    hp = netGetHostByName(hostname);
    if(hp == NULL)
      herr = h_errno;

    if(herr != 0) {
      switch(herr) {
      case HOST_NOT_FOUND:
	errtxt = "Unknown host";
	break;

      case NO_ADDRESS:
	errtxt = "The requested name is valid but does not have an IP address";
	break;
      
      case NO_RECOVERY:
	errtxt = "A non-recoverable name server error occurred";
	break;
      
      case TRY_AGAIN:
	errtxt = "A temporary error occurred on an authoritative name server";
	break;
      
      default:
	errtxt = "Unknown error";
	break;
      }

      snprintf(errbuf, errbufsize, "%s", errtxt);
      free(tmphstbuf);
      return NULL;
    } else if(hp == NULL) {
      snprintf(errbuf, errbufsize, "Resolver internal error");
      free(tmphstbuf);
      return NULL;
    }

    if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) {
      free(tmphstbuf);
      return NULL;
    }

    switch(hp->h_addrtype) {
    case AF_INET:
      memset(&in, 0, sizeof(in));
      in.sin_family = AF_INET;
      in.sin_port = htons(port);
      lv2_void* netaddrlist = (lv2_void*)(u64)hp->h_addr_list;
      memcpy(&in.sin_addr, (char*)(u64)netaddrlist[0], sizeof(struct in_addr));
      r = netConnect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
      break;

    default:
      snprintf(errbuf, errbufsize, "Invalid protocol family");
      free(tmphstbuf);
      return NULL;
    }

    free(tmphstbuf);
  }

  if(r < 0) {
    if(net_errno == NET_EINPROGRESS) {

      struct pollfd pfd;
      pfd.fd = fd;
      pfd.events = POLLOUT;
      pfd.revents = 0;

      r = netPoll(&pfd, 1, timeout);
      if(r == 0) {
	/* Timeout */
	snprintf(errbuf, errbufsize, "Connection attempt timed out");
	netClose(fd);
	return NULL;
      }
      
      if(r == -1) {
	snprintf(errbuf, errbufsize, "poll() error: %s", 
		 strerror(net_errno));
	netClose(fd);
	return NULL;
      }

      netGetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
    } else {
      err = net_errno;
    }
  } else {
    err = 0;
  }

  if(err != 0) {
    snprintf(errbuf, errbufsize, "%s", strerror(err));
    netClose(fd);
    return NULL;
  }
  
  optval = 0;
  r = netSetSockOpt(fd, SOL_SOCKET, SO_NBIO, &optval, sizeof(optval));
  if(r < 0) {
    snprintf(errbuf, errbufsize, "Unable to go blocking: %s",
	     strerror(net_errno));
    netClose(fd);
    return NULL;
  }

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);


  if(ssl) {
#if ENABLE_POLARSSL
    if(1) {
      tc->ssl = malloc(sizeof(ssl_context));
      if(ssl_init(tc->ssl)) {
	snprintf(errbuf, errlen, "SSL failed to initialize");
	close(fd);
	free(tc->ssl);
	free(tc);
	return NULL;
      }

      tc->ssn = malloc(sizeof(ssl_session));
      tc->hs = malloc(sizeof(havege_state));

      havege_init(tc->hs);
      memset(tc->ssn, 0, sizeof(ssl_session));


      ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT );
      ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE );

      ssl_set_rng(tc->ssl, havege_rand, tc->hs );
      ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd);
      ssl_set_ciphers(tc->ssl, ssl_default_ciphers );
      ssl_set_session(tc->ssl, 1, 600, tc->ssn );
      
      tc->read = polarssl_read;
      tc->write = polarssl_write;
      
    } else
#endif
    {

      snprintf(errbuf, errlen, "SSL not supported");
      tcp_close(tc);
      return NULL;
    }
  } else {
    tc->read = tcp_read;
    tc->write = tcp_write;
  }

  return tc;
}
Ejemplo n.º 4
0
static void handleclient(u64 conn_s_p)
{
	// todo: clean up
	
	int conn_s = (int)conn_s_p;
	int list_s_data = -1;
	int conn_s_data = -1;
	int datareq = 0;
	
	char		cwd[256];
	char		rnfr[256];
	char		filename[256];
	char		user[32];
	u32		rest = 0;
	int		authd = 0;
	int		active = 1;
	Lv2FsFile	tempfd;
	char		buf[BUFFER_SIZE];

	char	buffer[1024];
	char	client_cmd[8][128];
	ssize_t	bytes;
	
	#if LOGIN_CHECK == 1
	// load password file
	char passwordcheck[33];
						
	// check if password file exists - if not, use default password
	if(exists(PASSWORD_FPATH) == 0)
	{
		Lv2FsFile fd;
		u64 read;
		
		lv2FsOpen(PASSWORD_FPATH, LV2_O_RDONLY, &fd, 0, NULL, 0);
		lv2FsRead(fd, passwordcheck, 32, &read);
		lv2FsClose(fd);
		
		if(strlen(passwordcheck) != 32)
		{
			strcpy(passwordcheck, LOGIN_PASSWORD);
		}
	}
	else
	{
		strcpy(passwordcheck, LOGIN_PASSWORD);
	}
	#endif
	
	// start directory
	strcpy(cwd, "/");
	
	// welcome message
	swritel(conn_s, "220-OpenPS3FTP by @jjolano\r\n");
	sprintf(buffer, "220 Version %s\r\n", VERSION);
	swritel(conn_s, buffer);
	
	while(exitapp == 0 && active && (bytes = sreadl(conn_s, buffer, 1024)) > 0)
	{
		// get rid of the newline at the end of the string
		buffer[strcspn(buffer, "\n")] = '\0';
		buffer[strcspn(buffer, "\r")] = '\0';
		
		// parse received string into array
		int parameter_count = 0;
		
		char *result = strtok(buffer, " ");
		
		strcpy(client_cmd[0], result);
		
		while(parameter_count < 7 && (result = strtok(NULL, " ")) != NULL)
		{
			parameter_count++;
			strcpy(client_cmd[parameter_count], result);
		}
		
		// identify the command
		int cmd_id;
		for(cmd_id = 0; cmd_id < client_cmds_count; cmd_id++)
		{
			if(strcasecmp(client_cmd[0], client_cmds[cmd_id]) == 0)
			{
				break;
			}
		}
		
		// execute command
		if(authd == 0)
		{
			// not logged in
			
			switch(cmd_id)
			{
				case 0: // USER
					#if LOGIN_CHECK == 1
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						strcpy(user, client_cmd[1]);
						sprintf(buffer, "331 User %s OK. Password required\r\n", user);
						swritel(conn_s, buffer);
					}
					else
					{
						swritel(conn_s, "501 Please provide a username\r\n");
					}
					#else
					sprintf(buffer, "331 User %s OK. Password (not really) required\r\n", user);
					swritel(conn_s, buffer);
					#endif
					break;
				case 1: // PASS
					#if LOGIN_CHECK == 1
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						// hash the password given
						char output[33];
						md5(output, client_cmd[1]);
					
						if(strcmp(user, LOGIN_USERNAME) == 0 && strcmp(output, passwordcheck) == 0)
						{
							swritel(conn_s, "230 Successful authentication\r\n");
							authd = 1;
						}
						else
						{
							swritel(conn_s, "430 Invalid username or password - \r\n");
						}
					}
					else
					{
						swritel(conn_s, "501 Invalid username or password\r\n");
					}
					#else
					swritel(conn_s, "230 Successful authentication\r\n");
					authd = 1;
					#endif
					break;
				case 2: // QUIT
					swritel(conn_s, "221 See you later\r\n");
					active = 0;
					break;
				default: swritel(conn_s, "530 You are not logged in\r\n");
			}
		}
		else
		{
			// logged in
			
			switch(cmd_id)
			{
				case 0: // USER
				case 1: // PASS
					swritel(conn_s, "530 You are already logged in\r\n");
					break;
				case 2: // QUIT
					swritel(conn_s, "221 See you later\r\n");
					active = 0;
					break;
				case 3: // PASV
					rest = 0;
				
					netSocketInfo snf;
				
					int ret = netGetSockInfo(conn_s, &snf, 1);
				
					if(ret >= 0 && snf.local_adr.s_addr != 0)
					{
						// assign a random port for passive mode
						srand(conn_s);
						
						int rand1 = (rand() % 251) + 4;
						int rand2 = rand() % 256;
						
						sprintf(buffer, "227 Entering Passive Mode (%u,%u,%u,%u,%i,%i)\r\n",
							(snf.local_adr.s_addr & 0xFF000000) >> 24,
							(snf.local_adr.s_addr & 0xFF0000) >> 16,
							(snf.local_adr.s_addr & 0xFF00) >> 8,
							(snf.local_adr.s_addr & 0xFF),
							rand1, rand2);
						
						short int pasvport = (rand1 * 256) + rand2;
						
						struct sockaddr_in servaddr;
						memset(&servaddr, 0, sizeof(servaddr));
						servaddr.sin_family      = AF_INET;
						servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
						servaddr.sin_port        = htons(pasvport);
						
						list_s_data = netSocket(AF_INET, SOCK_STREAM, 0);
						netBind(list_s_data, (struct sockaddr *) &servaddr, sizeof(servaddr));
						netListen(list_s_data, 1);
						
						swritel(conn_s, buffer);
						
						if((conn_s_data = netAccept(list_s_data, NULL, NULL)) == -1)
						{
							swritel(conn_s, "550 PASV command failed\r\n");
						}
						else
						{
							datareq = 1;
						}
						break;
					}
		
					swritel(conn_s, "550 PASV command failed\r\n");
					break;
				case 4: // PORT
					if(parameter_count == 1)
					{
						rest = 0;
						
						char connectinfo[32];
						strcpy(connectinfo, client_cmd[1]);
						
						char data[7][4];
						int i = 0;
						
						char *result = strtok(connectinfo, ",");
	
						strcpy(data[0], result);
	
						while(i < 6 && (result = strtok(NULL, ",")) != NULL)
						{
							i++;
							strcpy(data[i], result);
						}
					
						char conn_ipaddr[16];
						sprintf(conn_ipaddr, "%s.%s.%s.%s", data[0], data[1], data[2], data[3]);
						
						struct sockaddr_in servaddr;
						memset(&servaddr, 0, sizeof(servaddr));
						servaddr.sin_family	= AF_INET;
						servaddr.sin_port	= htons((atoi(data[4]) * 256) + atoi(data[5]));
						inet_pton(AF_INET, conn_ipaddr, &servaddr.sin_addr);
						
						conn_s_data = netSocket(AF_INET, SOCK_STREAM, 0);
					
						if(connect(conn_s_data, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0)
						{
							swritel(conn_s, "200 PORT command successful\r\n");
							datareq = 1;
						}
						else
						{
							swritel(conn_s, "550 PORT command failed\r\n");
						}
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 5: // SITE
					if(strcasecmp(client_cmd[1], "CHMOD") == 0)
					{
						int i;
						for(i = 4; i <= parameter_count; i++)
						{
							strcat(client_cmd[3], " ");
							strcat(client_cmd[3], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[3], cwd);
					
						char perms[4];
						sprintf(perms, "0%s", client_cmd[2]);
						
						if(lv2FsChmod(filename, S_IFMT | strtol(perms, NULL, 8)) == 0)
						{
							swritel(conn_s, "250 File permissions successfully set\r\n");
						}
						else
						{
							swritel(conn_s, "550 Failed to set file permissions\r\n");
						}
					}
					else
					{
						swritel(conn_s, "500 Unrecognized SITE command\r\n");
					}
					break;
				case 6: // FEAT
					swritel(conn_s, "211- Extensions supported:\r\n");
				
					int i;
					for(i = 0; i < feat_cmds_count; i++)
					{
						sprintf(buffer, " %s\r\n", feat_cmds[i]);
						swritel(conn_s, buffer);
					}
				
					swritel(conn_s, "211 End.\r\n");
					break;
				case 7: // TYPE
					swritel(conn_s, "200 TYPE command successful\r\n");
					break;
				case 8: // REST
					if(parameter_count == 1)
					{
						rest = atoi(client_cmd[1]);
						swritel(conn_s, "350 REST command successful\r\n");
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 9: // RETR
					if(parameter_count >= 1)
					{
						if(conn_s_data == -1)
						{
							swritel(conn_s, "425 No data connection\r\n");
							break;
						}
					
						swritel(conn_s, "150 Opening data connection\r\n");

						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
						
						u64 pos;
						u64 read = -1;
					
						Lv2FsFile fd;
					
						lv2FsOpen(filename, LV2_O_RDONLY, &fd, 0, NULL, 0);
						lv2FsLSeek64(fd, (s64)rest, SEEK_SET, &pos);
					
						if(fd >= 0)
						{
							while(lv2FsRead(fd, buf, BUFFER_SIZE - 1, &read) == 0 && read > 0)
							{
								netSend(conn_s_data, buf, read, 0);
							}
						
							if(read == 0)
							{
								swritel(conn_s, "226 Transfer complete\r\n");
							}
							else
							{
								swritel(conn_s, "426 Transfer failed\r\n");
							}
						}
						else
						{
							swritel(conn_s, "452 File access error\r\n");
						}
						
						lv2FsClose(fd);
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 10: // PWD
					sprintf(buffer, "257 \"%s\" is the current directory\r\n", cwd);
					swritel(conn_s, buffer);
					break;
				case 11: // CWD
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						strcpy(filename, client_cmd[1]);
						
						if(strcmp(filename, "../") == 0)
						{
							for(int i = strlen(cwd) - 2; i > 0; i--)
							{
								if(cwd[i] != '/')
								{
									cwd[i] = '\0';
								}
								else
								{
									break;
								}
							}
							
							sprintf(buffer, "250 Directory change successful: %s\r\n", cwd);
							swritel(conn_s, buffer);
							break;
						}
					
						if(filename[0] == '/')
						{
							strcpy(cwd, (strlen(filename) == 1) ? "/" : filename);
						}
						else
						{
							strcat(cwd, filename);
						}
					
						if(cwd[strlen(cwd) - 1] != '/')
						{
							strcat(cwd, "/");
						}
					
						if(isDir(cwd))
						{
							sprintf(buffer, "250 Directory change successful: %s\r\n", cwd);
						}
						else
						{
							sprintf(buffer, "550 Could not change directory: %s\r\n", cwd);
						}
					
						swritel(conn_s, buffer);
					}
					else
					{
						sprintf(buffer, "257 \"%s\" is the current directory\r\n", cwd);
						swritel(conn_s, buffer);
					}
					break;
				case 12: // CDUP
					for(int i = strlen(cwd) - 2; i > 0; i--)
					{
						if(cwd[i] != '/')
						{
							cwd[i] = '\0';
						}
						else
						{
							break;
						}
					}
				
					sprintf(buffer, "250 Directory change successful: %s\r\n", cwd);
					swritel(conn_s, buffer);
					break;
				case 13: // NLST
					if(conn_s_data == -1)
					{
						swritel(conn_s, "425 No data connection\r\n");
						break;
					}
				
					swritel(conn_s, "150 Opening data connection\r\n");
				
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					}
					else
					{
						strcpy(filename, cwd);
					}
				
					if(lv2FsOpenDir(filename, &tempfd) == 0)
					{
						u64 read;
						Lv2FsDirent ent;
					
						while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0)
						{
							sprintf(buffer, "%s\r\n", ent.d_name);
							swritel(conn_s_data, buffer);
						}
						
						swritel(conn_s, "226 Transfer complete\r\n");
					}
					else
					{
						swritel(conn_s, "451 Cannot access directory\r\n");
					}
				
					lv2FsCloseDir(tempfd);
					break;
				case 14: // LIST
					if(conn_s_data == -1)
					{
						swritel(conn_s, "425 No data connection\r\n");
						break;
					}
				
					swritel(conn_s, "150 Opening data connection\r\n");
				
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					}
					else
					{
						strcpy(filename, cwd);
					}
				
					if(lv2FsOpenDir(filename, &tempfd) == 0)
					{
						u64 read;
						Lv2FsDirent ent;
						
						while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0)
						{
							sprintf(filename, "%s%s", cwd, ent.d_name);
							
							Lv2FsStat entry;
							lv2FsStat(filename, &entry);
						
							struct tm *tm;
							char timebuf[32];
							tm = localtime(&entry.st_mtime);
							strftime(timebuf, 31, "%b %d %Y", tm);
						
							sprintf(buffer, "%s%s%s%s%s%s%s%s%s%s 1 root root %lu %s %s\r\n", 
								((entry.st_mode & S_IFDIR) != 0)?"d":"-", 
								((entry.st_mode & S_IRUSR) != 0)?"r":"-",
								((entry.st_mode & S_IWUSR) != 0)?"w":"-",
								((entry.st_mode & S_IXUSR) != 0)?"x":"-",
								((entry.st_mode & S_IRGRP) != 0)?"r":"-",
								((entry.st_mode & S_IWGRP) != 0)?"w":"-",
								((entry.st_mode & S_IXGRP) != 0)?"x":"-",
								((entry.st_mode & S_IROTH) != 0)?"r":"-",
								((entry.st_mode & S_IWOTH) != 0)?"w":"-",
								((entry.st_mode & S_IXOTH) != 0)?"x":"-",
								(long unsigned int)entry.st_size, 
								timebuf, 
								ent.d_name);

							swritel(conn_s_data, buffer);
						}
						
						swritel(conn_s, "226 Transfer complete\r\n");
					}
					else
					{
						swritel(conn_s, "451 Cannot access directory\r\n");
					}
				
					lv2FsCloseDir(tempfd);
					break;
				case 15: // STOR
					if(parameter_count >= 1)
					{
						if(conn_s_data == -1)
						{
							swritel(conn_s, "425 No data connection\r\n");
							break;
						}
						
						swritel(conn_s, "150 Opening data connection\r\n");

						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
						
						u64 pos;
						u64 read = -1;
						u64 write = -1;
						
						Lv2FsFile fd;
					
						lv2FsOpen(filename, LV2_O_WRONLY | LV2_O_CREAT, &fd, 0, NULL, 0);
						lv2FsChmod(filename, S_IFMT | 0666);
					
						lv2FsLSeek64(fd, (s32)rest, SEEK_SET, &pos);
						
						if(fd >= 0)
						{
							while((read = (u64)netRecv(conn_s_data, buf, BUFFER_SIZE - 1, MSG_WAITALL)) > 0)
							{
								lv2FsWrite(fd, buf, read, &write);
							
								if(write != read)
								{
									break;
								}
							}
							
							if(read == 0)
							{
								swritel(conn_s, "226 Transfer complete\r\n");
							}
							else
							{
								swritel(conn_s, "426 Transfer failed\r\n");
							}
						}
						else
						{
							swritel(conn_s, "452 File access error\r\n");
						}
						
						lv2FsClose(fd);
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 16: // NOOP
					swritel(conn_s, "200 Zzzz...\r\n");
					break;
				case 17: // DELE
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
						
						if(lv2FsUnlink(filename) == 0)
						{
							swritel(conn_s, "250 File successfully deleted\r\n");
						}
						else
						{
							swritel(conn_s, "550 Failed to delete file\r\n");
						}
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 18: // MKD
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					
						if(lv2FsMkdir(filename, 0775) == 0)
						{
							swritel(conn_s, "250 Directory successfully created\r\n");
						}
						else
						{
							swritel(conn_s, "550 Failed to create directory\r\n");
						}
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 19: // RMD
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					
						if(lv2FsRmdir(filename) == 0)
						{
							swritel(conn_s, "250 Directory successfully deleted\r\n");
						}
						else
						{
							swritel(conn_s, "550 Failed to remove directory\r\n");
						}
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 20: // RNFR
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(rnfr, client_cmd[1], cwd);
					
						if(exists(rnfr) == 0)
						{
							swritel(conn_s, "350 RNFR successful - ready for destination\r\n");
						}
						else
						{
							swritel(conn_s, "550 RNFR failed - file does not exist\r\n");
						}
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 21: // RNTO
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					
						if(lv2FsRename(rnfr, filename) == 0)
						{
							swritel(conn_s, "250 File successfully renamed\r\n");
						}
						else
						{
							swritel(conn_s, "550 Failed to rename file\r\n");
						}
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 22: // SIZE
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					
						Lv2FsStat entry;
						
						if(lv2FsStat(filename, &entry) == 0)
						{
							sprintf(buffer, "213 %lu\r\n", (long unsigned int)entry.st_size);
						}
						else
						{
							sprintf(buffer, "550 Requested file doesn't exist\r\n");
						}
					
						swritel(conn_s, buffer);
					}
					else
					{
						swritel(conn_s, "501 Syntax error\r\n");
					}
					break;
				case 23: // SYST
					swritel(conn_s, "215 UNIX Type: L8\r\n");
					break;
				case 24: // HELP
					swritel(conn_s, "214 No help for you.\r\n");
					break;
				case 25: // PASSWD
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						// hash the password given
						char output[33];
						md5(output, client_cmd[1]);
					
						Lv2FsFile fd;
						u64 written;
					
						lv2FsOpen(PASSWORD_FPATH, LV2_O_WRONLY | LV2_O_CREAT, &fd, 0, NULL, 0);
						lv2FsWrite(fd, output, 32, &written);
						lv2FsClose(fd);
					
						swritel(conn_s, "200 Password successfully changed\r\n");
					}
					else
					{
						swritel(conn_s, "501 Invalid password\r\n");
					}
					break;
				case 26: // MLSD
					if(conn_s_data == -1)
					{
						swritel(conn_s, "425 No data connection\r\n");
						break;
					}
				
					swritel(conn_s, "150 Opening data connection\r\n");
				
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					}
					else
					{
						strcpy(filename, cwd);
					}
				
					if(lv2FsOpenDir(filename, &tempfd) == 0)
					{
						u64 read;
						Lv2FsDirent ent;
					
						while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0)
						{
							sprintf(filename, "%s%s", cwd, ent.d_name);
							
							Lv2FsStat entry;
							lv2FsStat(filename, &entry);
						
							struct tm *tm;
							char timebuf[32];
							tm = localtime(&entry.st_mtime);
							strftime(timebuf, 31, "%Y%m%d%H%M%S", tm);
						
							int permint = 0;

							permint +=	(((entry.st_mode & S_IRUSR) != 0)?400:0) +
									(((entry.st_mode & S_IWUSR) != 0)?200:0) +
									(((entry.st_mode & S_IXUSR) != 0)?100:0);
						
							permint +=	(((entry.st_mode & S_IRGRP) != 0)?40:0) +
									(((entry.st_mode & S_IWGRP) != 0)?20:0) +
									(((entry.st_mode & S_IXGRP) != 0)?10:0);
						
							permint +=	(((entry.st_mode & S_IROTH) != 0)?4:0) +
									(((entry.st_mode & S_IWOTH) != 0)?2:0) +
									(((entry.st_mode & S_IXOTH) != 0)?1:0);
						
							sprintf(buffer, "type=%s;size=%lu;modify=%s;UNIX.mode=0%i;UNIX.uid=root;UNIX.gid=root; %s\r\n", 
								((entry.st_mode & S_IFDIR) != 0)?"dir":"file", 
								(long unsigned int)entry.st_size, 
								timebuf, 
								permint,
								ent.d_name);
						
							swritel(conn_s_data, buffer);
						}
						
						swritel(conn_s, "226 Transfer complete\r\n");
					}
					else
					{
						swritel(conn_s, "501 Directory access error\r\n");
					}

					lv2FsCloseDir(tempfd);
					break;
				case 27: // MLST
					swritel(conn_s, "250- Listing directory");
				
					if(parameter_count >= 1)
					{
						int i;
						for(i = 2; i <= parameter_count; i++)
						{
							strcat(client_cmd[1], " ");
							strcat(client_cmd[1], client_cmd[i]);
						}
						
						absPath(filename, client_cmd[1], cwd);
					}
					else
					{
						strcpy(filename, cwd);
					}
					
					if(lv2FsOpenDir(filename, &tempfd) == 0)
					{
						u64 read;
						Lv2FsDirent ent;
					
						while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0)
						{
							sprintf(filename, "%s%s", cwd, ent.d_name);
							
							Lv2FsStat entry;
							lv2FsStat(filename, &entry);
						
							struct tm *tm;
							char timebuf[32];
							tm = localtime(&entry.st_mtime);
							strftime(timebuf, 31, "%Y%m%d%H%M%S", tm);
						
							int permint = 0;

							permint +=	(((entry.st_mode & S_IRUSR) != 0)?400:0) +
									(((entry.st_mode & S_IWUSR) != 0)?200:0) +
									(((entry.st_mode & S_IXUSR) != 0)?100:0);
						
							permint +=	(((entry.st_mode & S_IRGRP) != 0)?40:0) +
									(((entry.st_mode & S_IWGRP) != 0)?20:0) +
									(((entry.st_mode & S_IXGRP) != 0)?10:0);
						
							permint +=	(((entry.st_mode & S_IROTH) != 0)?4:0) +
									(((entry.st_mode & S_IWOTH) != 0)?2:0) +
									(((entry.st_mode & S_IXOTH) != 0)?1:0);
						
							sprintf(buffer, " type=%s;size=%lu;modify=%s;UNIX.mode=0%i;UNIX.uid=root;UNIX.gid=root; %s\r\n", 
								((entry.st_mode & S_IFDIR) != 0)?"dir":"file", 
								(long unsigned int)entry.st_size, 
								timebuf, 
								permint,
								ent.d_name);
						
							swritel(conn_s, buffer);
						}
					}
				
					swritel(conn_s, "250 End\r\n");
				
					lv2FsCloseDir(tempfd);
					break;
				case 28: // EXITAPP
					swritel(conn_s, "221 Exiting OpenPS3FTP, bye\r\n");
					exitapp = 1;
					break;
				case 29: // TEST
					swritel(conn_s, "211-Listing parameters\r\n");
					sprintf(buffer, "211-Count: %i\r\n", parameter_count);
					swritel(conn_s, buffer);
					
					int tx;
					for(tx = 0; tx <= parameter_count; tx++)
					{
						sprintf(buffer, " %i:%s\r\n", tx, client_cmd[tx]);
						swritel(conn_s, buffer);
					}
					
					swritel(conn_s, "211 End\r\n");
					break;
				default: swritel(conn_s, "500 Unrecognized command\r\n");
			}
			
			if(datareq == 1)
			{
				datareq = 0;
			}
			else
			{
				// close any active data connections
				if(conn_s_data > -1)
				{
					netShutdown(conn_s_data, 2);
					netClose(conn_s_data);
					conn_s_data = -1;
				}
				
				if(list_s_data > -1)
				{
					netShutdown(list_s_data, 2);
					netClose(list_s_data);
					list_s_data = -1;
				}
			}
		}
	}
Ejemplo n.º 5
0
static void handleclient(u64 conn_s_p)
{
	int conn_s = (int)conn_s_p;
	int list_s_data = -1;
	int conn_s_data = -1;
	
	char	cwd[2048];
	char	login_user[32];
	char	login_pass[64];
	char	rename_from[2048];
	u32	rest = 0;
	int	authd = 0;
	
	char	message[4096];
	char	buffer[2048];
	
	sprintf(cwd, "/");
	
	sprintf(message, "220-OpenPS3FTP by @jjolano\r\n");
	Writeline(conn_s, message, strlen(message));
	
	sprintf(message, "220 Version %s\r\n", VERSION);
	Writeline(conn_s, message, strlen(message));
	
	while(program_running == 1)
	{
		sys_ppu_thread_yield();
		
		if(Readline(conn_s, buffer, 2047) == 0 || strncmp(buffer, "QUIT", 4) == 0 || strncmp(buffer, "BYE", 3) == 0)
		{
			break;
		}
		
		buffer[strcspn(buffer, "\n")] = '\0';
		buffer[strcspn(buffer, "\r")] = '\0';
		
		if(strncmp(buffer, "USER", 4) == 0)
		{
			if(strlen(buffer) > 7)
			{
				strcpy(login_user, buffer+5);
				
				sprintf(message, "331 Username %s OK. Password required\r\n", login_user);
				Writeline(conn_s, message, strlen(message));
			}
			else
			{
				sprintf(message, "430 No username specified\r\n");
				Writeline(conn_s, message, strlen(message));
			}
		}
		else if(strncmp(buffer, "PASS", 4) == 0)
		{
			if(strlen(buffer) > 7)
			{
				strcpy(login_pass, buffer+5);
				
				if(strcmp(LOGIN_USERNAME, login_user) == 0 && strcmp(LOGIN_PASSWORD, login_pass) == 0)
				{
					authd = 1;
					sprintf(message, "230 Successful authentication\r\n");
				}
				else
				{
					sprintf(message, "430 Invalid username or password\r\n");
					Writeline(conn_s, message, strlen(message));
				}
			}
			else
			{
				sprintf(message, "430 Invalid username or password\r\n");
			}
			
			Writeline(conn_s, message, strlen(message));
		}
		else if(authd == 0)
		{
			sprintf(message, "530 Not logged in\r\n");
			Writeline(conn_s, message, strlen(message));
		}
		else if(strncmp(buffer, "FEAT", 4) == 0)
		{
			sprintf(message, "211-Extensions supported:\r\n");
			Writeline(conn_s, message, strlen(message));
			
			sprintf(message, " SIZE\r\n");
			Writeline(conn_s, message, strlen(message));
			sprintf(message, " PASV\r\n");
			Writeline(conn_s, message, strlen(message));
			
			
			sprintf(message, "211 End\r\n");
			Writeline(conn_s, message, strlen(message));
		}
		else if(strncmp(buffer, "TYPE", 4) == 0)
		{
			sprintf(message, "200 TYPE is now %s\r\n", buffer+5);
			Writeline(conn_s, message, strlen(message));
		}
		else if(strncmp(buffer, "PORT", 4) == 0)
		{
			rest = 0;
			
			char connectinfo[24];
			strcpy(connectinfo, buffer+5);
			
			char data[7][4];
			int len = strlen(connectinfo);
			int i, x = 0, y = 0;
			
			for(i = 0;i < len;i++)
			{
				if(connectinfo[i] == ',')
				{
					data[x][y] = '\0';
					x++;
					y = 0;
				}
				else
				{
					data[x][y] =  connectinfo[i];
					y++;
				}
			}
			
			char conn_ipaddr[16];
			sprintf(conn_ipaddr, "%s.%s.%s.%s", data[0], data[1], data[2], data[3]);

			int p1 = atoi(data[4]);
			int p2 = atoi(data[5]);
			
			short int conn_port = (p1 * 256) + p2;
			
			netClose(conn_s_data);
			netClose(list_s_data);
			
			list_s_data = -1;
			conn_s_data = netSocket(AF_INET, SOCK_STREAM, 0);
			
			struct sockaddr_in servaddr;
			memset(&servaddr, 0, sizeof(servaddr));
			servaddr.sin_family	= AF_INET;
			servaddr.sin_port	= htons(conn_port);
			inet_pton(AF_INET, conn_ipaddr, &servaddr.sin_addr);
			
			if(connect(conn_s_data, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0)
			{
				sprintf(message, "200 PORT command successful\r\n");
				Writeline(conn_s, message, strlen(message));
				continue;
			}
			
			sprintf(message, "425 Internal Error\r\n");
			Writeline(conn_s, message, strlen(message));
		}
		else if(strncmp(buffer, "PASV", 4) == 0)
		{
			rest = 0;
			netSocketInfo snf;
			
			int ret = netGetSockInfo(conn_s, &snf, 1);
			
			if(ret >= 0 && snf.local_adr.s_addr != 0)
			{
				netClose(conn_s_data);
				netClose(list_s_data);
				
				conn_s_data = -1;
				list_s_data = -1;
				
				// create the socket
				list_s_data = netSocket(AF_INET, SOCK_STREAM, 0);

				// calculate the passive mode port
				//srand((unsigned)time(NULL));
				//srand((unsigned)time(NULL) + rand());
				
				int rand1 = 4 + rand() % 255;
				int rand2 = rand() % 256;
				
				short int port = (rand1 * 256) + rand2;
				
				struct sockaddr_in servaddr;
				memset(&servaddr, 0, sizeof(servaddr));
				servaddr.sin_family      = AF_INET;
				servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
				servaddr.sin_port        = htons(port);
				
				// bind address to listener, listen, and accept
				netBind(list_s_data, (struct sockaddr *) &servaddr, sizeof(servaddr));
				netListen(list_s_data, LISTENQ);
				sprintf(message, "227 Entering Passive Mode (%u,%u,%u,%u,%i,%i)\r\n",
					(snf.local_adr.s_addr & 0xFF000000) >> 24,
					(snf.local_adr.s_addr & 0xFF0000) >> 16,
					(snf.local_adr.s_addr & 0xFF00) >> 8,
					(snf.local_adr.s_addr & 0xFF),
					rand1, rand2);
				
				Writeline(conn_s, message, strlen(message));
						
				if((conn_s_data = netAccept(list_s_data, NULL, NULL)) < 0)
				{
					printf("warning: failed to accept a connection\n");
					netClose(conn_s_data);
					netClose(list_s_data);
					
					conn_s_data = -1;
					list_s_data = -1;
				}
				else
				{
					// PASV success
					continue;
				}
			}
		
		sprintf(message, "425 Internal Error\r\n");
		Writeline(conn_s, message, strlen(message));
		}