/* Nessuslib -- the Nessus Library
 * Copyright (C) 1998 Renaud Deraison
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * handy FTP functions
 */

#define EXPORTING
#include <includes.h>

ExtFunc int ftp_log_in(int soc, char * username, char * passwd)
{
 char * buf;
 fd_set read_set;
 struct timeval tv = {10,0};
 
 FD_ZERO(&read_set);
 FD_SET(soc, &read_set);
 select(soc+1, &read_set, NULL,NULL, &tv);
 if(!FD_ISSET(soc, &read_set))return(1);
 
 buf = emalloc(512);
 recv_line(soc, buf, 512);
 if(strncmp(buf, "220", 3))
 { 
  efree(&buf);
  return(1);
 }
 
 while(buf[3]=='-')recv_line(soc, buf, 512);
 bzero(buf, 512);
 sprintf(buf, "USER %s\n", username);
 send(soc, buf, strlen(buf), 0);
 recv_line(soc, buf, 512);
 if(strncmp(buf, "331", 3))
 {
  efree(&buf);
  return(1);
 }
 bzero(buf, 512);
 sprintf(buf, "PASS %s\n", passwd);
 send(soc, buf, strlen(buf),0);
 recv_line(soc, buf, 512);
 if(strncmp(buf, "230", 3)){
  efree(&buf);
  return(1);
 }
 while(buf[3]=='-')recv_line(soc, buf, 512);
 efree(&buf);
 return(0);
}


ExtFunc int ftp_get_pasv_address(int soc, struct sockaddr_in * addr)
{
 char * buf = emalloc(255);
 char * t,*s;
 unsigned char * l;
 unsigned long  * a;
 unsigned short * p;
 sprintf(buf, "PASV\n");
 send(soc, buf, strlen(buf), 0);
 bzero(buf, 255);
 bzero(addr, sizeof(struct sockaddr_in));
 recv_line(soc, buf, 255);
 if(strncmp(buf, "227", 3)){
   efree(&buf);
   return(1);
   }
 t = strchr(buf, '(');
 if(!t)return(1);
 t++;
 s = strchr(t, ',');
 if(!s)return(1);
 s[0] = 0;
 
 l = emalloc(6);
 l[0] = (unsigned char)atoi(t);
 s++;
 t = strchr(s, ',');if(!t)return(1);
 t[0]=0;
 l[1] = (unsigned char)atoi(s);
 t++;
 s = strchr(t, ',');if(!s)return(1);
 s[0]=0;
 l[2] = (unsigned char)atoi(t);
 s++;
 t = strchr(s, ',');if(!t)return(1);
 t[0]=0;
 l[3] = (unsigned char)atoi(s);
 t++;
 s = strchr(t, ',');if(!s)return(1);
 s[0]=0;
 l[4] = (unsigned char)atoi(t);
 s++;
 t = strchr(s, ')');if(!t)return(1);
 t[0]=0;
 l[5] = (unsigned char)atoi(s);
 a = (unsigned long*)l;
 p = (unsigned short*)(l+4);
 addr->sin_addr.s_addr = *a;
 addr->sin_port=*p;
 addr->sin_family = AF_INET;
 return(0);
} 


ExtFunc
short is_cgi_installed(data, cgi_name)
 struct arglist * data;
 const char * cgi_name;
{
  char * command;
  short soc=-1;
  short i=0;
  fd_set rd;
  struct timeval tv =  {5,0};
  int port = (int)plug_get_key(data, "Services/www");
  struct arglist * preferences = arg_get_value(data, "preferences");
  char * cgi_path = preferences ? arg_get_value(preferences, "cgi_path"):"/cgi-bin";
  char * buff;
  char * cur_path;
  int finished = 0;

  cgi_path = strdup(cgi_path);
  cur_path = cgi_path;
  FD_ZERO(&rd);
  if(!port)port = 80;
  else port = atoi((char*)port);
  if(!cgi_name)return(0);
  if(!host_get_port_state(data, port))return(0);
  buff = emalloc(256);
  command = emalloc(256);
  /*
   * Open a connection to the remote host
   */
  while(!finished)
  {
  soc = open_sock_tcp(data, port);
  if(soc <0){
  	efree(&buff);efree(&command);
	efree(&cgi_path);
	return(0); /* couldn't open a connection */
	}
  if(cgi_name[0]!='/')
    	{
	  char * t = strchr(cur_path, ':');

	  if(t)t[0]=0;
	  sprintf(command, "GET %s/%s HTTP/1.0\r\n\r\n",
	  cur_path, cgi_name);
	  if(t)cur_path = t+sizeof(char);
	  else finished++;
	    
	}
  else {
    	sprintf(command, "GET %s HTTP/1.0\r\n\r\n", cgi_name);
  	finished++;
  }

  send(soc, command, strlen(command), 0);
  FD_SET(soc, &rd);
  if(select(soc+1, &rd, NULL, NULL, &tv))
   recv(soc, buff, 30,0);
  shutdown(soc, 2);
  closesocket(soc);

  if(strstr(buff, " 200 ")){i=1;break;}	       /* No error */
  else if(strstr(buff, " 301 ")){i = 1; break;}/* Page moved - the script is likely to exist */
  else i=0; /* Error */
  }
  efree(&command);
  efree(&cgi_path);
  efree(&buff);
  return(i);
}
