Ejemplo n.º 1
0
/* Handle --exec if appropriate, otherwise start the initial read events and set
   the idle timeout. */
static void post_connect(nsock_pool nsp, nsock_iod iod)
{
    /* Command to execute. */
    if (o.cmdexec) {
        struct fdinfo info;

        info.fd = nsi_getsd(iod);
#ifdef HAVE_OPENSSL
        info.ssl = (SSL *) nsi_getssl(iod);
#endif
        /* Convert Nsock's non-blocking socket to an ordinary blocking one. It's
           possible for a program to write fast enough that it will get an
           EAGAIN on write on a non-blocking socket. */
        block_socket(info.fd);
        netexec(&info, o.cmdexec);
    }

    /* Start the initial reads. */

    if (!o.sendonly)
        nsock_read(nsp, cs.sock_nsi, read_socket_handler, -1, NULL);

    if (!o.recvonly)
        nsock_readbytes(nsp, cs.stdin_nsi, read_stdin_handler, -1, NULL, 0);

    /* The --idle-timeout option says to exit after a certain period of
       inactivity. We start a timer here and reset it on every read event; see
       refresh_idle_timer. */
    if (o.idletimeout > 0) {
        cs.idle_timer_event_id =
            nsock_timer_create(nsp, idle_timer_handler, o.idletimeout, NULL);
    }
}
Ejemplo n.º 2
0
/* If we are sending a large amount of data, we might momentarily run out of send
   space and get an EAGAIN when we send. Temporarily convert a socket to
   blocking more, do the send, and unblock it again. Assumes that the socket was
   in nonblocking mode to begin with; it has the side effect of leaving the
   socket nonblocking on return. */
static int blocking_fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size)
{
    int ret;

    block_socket(fdn->fd);
    ret = fdinfo_send(fdn, buf, size);
    unblock_socket(fdn->fd);

    return ret;
}
Ejemplo n.º 3
0
/* Relay data between a socket and a process until the process dies or stops
   sending or receiving data. The socket descriptor and process pipe handles
   are in the data argument, which must be a pointer to struct subprocess_info.

   This function is a workaround for the fact that we can't just run a process
   after redirecting its input handles to a socket. If the process, for
   example, redirects its own stdin, it somehow confuses the socket and stdout
   stops working. This is exactly what ncat does (as part of the Windows stdin
   workaround), so it can't be ignored.

   This function can be invoked through CreateThread to simulate fork+exec, or
   called directly to simulate exec. It frees the subprocess_info struct and
   closes the socket and pipe handles before returning. Returns the exit code
   of the subprocess. */
static DWORD WINAPI subprocess_thread_func(void *data)
{
    struct subprocess_info *info;
    char pipe_buffer[BUFSIZ];
    OVERLAPPED overlap = { 0 };
    HANDLE events[3];
    DWORD ret, rc;
    int crlf_state = 0;

    info = (struct subprocess_info *) data;

    /* Three events we watch for: socket read, pipe read, and process end. */
    events[0] = (HANDLE) WSACreateEvent();
    WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE);
    events[1] = info->child_out_r;
    events[2] = info->proc;

    /* To avoid blocking or polling, we use asynchronous I/O, or what Microsoft
       calls "overlapped" I/O, on the process pipe. WaitForMultipleObjects
       reports when the read operation is complete. */
    ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap);

    /* Loop until EOF or error. */
    for (;;) {
        DWORD n, nwritten;
        int i;

        i = WaitForMultipleObjects(3, events, FALSE, INFINITE);
        if (i == WAIT_OBJECT_0) {
            /* Read from socket, write to process. */
            char buffer[BUFSIZ];
            int pending;

            ResetEvent(events[0]);
            do {
                n = ncat_recv(&info->fdn, buffer, sizeof(buffer), &pending);
                if (n <= 0)
                    goto loop_end;
                if (WriteFile(info->child_in_w, buffer, n, &nwritten, NULL) == 0)
                    break;
                if (nwritten != n)
                    goto loop_end;
            } while (pending);
        } else if (i == WAIT_OBJECT_0 + 1) {
            char *crlf = NULL, *wbuf;
            /* Read from process, write to socket. */
            if (GetOverlappedResult(info->child_out_r, &overlap, &n, FALSE)) {
                int n_r;

                wbuf = pipe_buffer;
                n_r = n;
                if (o.crlf) {
                    if (fix_line_endings((char *) pipe_buffer, &n_r, &crlf, &crlf_state))
                        wbuf = crlf;
                }
                /* The above call to WSAEventSelect puts the socket in
                   non-blocking mode, but we want this send to block, not
                   potentially return WSAEWOULDBLOCK. We call block_socket, but
                   first we must clear out the select event. */
                WSAEventSelect(info->fdn.fd, events[0], 0);
                block_socket(info->fdn.fd);
                nwritten = ncat_send(&info->fdn, wbuf, n_r);
                if (crlf != NULL)
                    free(crlf);
                if (nwritten != n_r)
                    break;
                /* Restore the select event (and non-block the socket again.) */
                WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE);
                /* Queue another ansychronous read. */
                ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap);
            } else {
                if (GetLastError() != ERROR_IO_PENDING)
                    /* Error or end of file. */
                    break;
            }
        } else if (i == WAIT_OBJECT_0 + 2) {
            /* The child died. There are no more writes left in the pipe
               because WaitForMultipleObjects guarantees events with lower
               indexes are handled first. */
            break;
        } else {
            break;
        }
    }

loop_end:

    WSACloseEvent(events[0]);

    rc = unregister_subprocess(info->proc);
    ncat_assert(rc != -1);

    GetExitCodeProcess(info->proc, &ret);
    if (ret == STILL_ACTIVE) {
        if (o.debug > 1)
            logdebug("Subprocess still running, terminating it.\n");
        rc = TerminateProcess(info->proc, 0);
        if (rc == 0) {
            if (o.debug > 1)
                logdebug("TerminateProcess failed with code %d.\n", rc);
        }
    }
    GetExitCodeProcess(info->proc, &ret);
    if (o.debug > 1)
        logdebug("Subprocess ended with exit code %d.\n", ret);

    shutdown(info->fdn.fd, 2);
    subprocess_info_close(info);
    free(info);

    rc = WaitForSingleObject(pseudo_sigchld_mutex, INFINITE);
    ncat_assert(rc == WAIT_OBJECT_0);
    if (pseudo_sigchld_handler != NULL)
        pseudo_sigchld_handler();
    rc = ReleaseMutex(pseudo_sigchld_mutex);
    ncat_assert(rc != 0);

    return ret;
}
Ejemplo n.º 4
0
static tree_cell * nasl_open_privileged_socket(lex_ctxt * lexic, int proto)
{
 struct arglist * script_infos = lexic->script_infos;
 int sport, current_sport = -1;
 int dport;
 int sock;
 int e, err;
 struct sockaddr_in addr, daddr;
 struct in_addr * p;
 int to = get_int_local_var_by_name(lexic, "timeout", lexic->recv_timeout);
 tree_cell * retc;
 struct timeval tv;
 fd_set rd;
 int opt, opt_sz;
 
 
 
 sport = get_int_local_var_by_name(lexic, "sport", -1);
 dport = get_int_local_var_by_name(lexic, "dport", -1);
 if(dport <= 0)
   {
     nasl_perror(lexic, "open_private_socket: missing or undefined parameter dport!\n");
     return NULL;
   }
 
 if(sport < 0) current_sport = 1023;


restart: 
 bzero(&addr, sizeof(addr));
 if(proto == IPPROTO_TCP)
  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 else
  sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  
  
 /*
  * We will bind to a privileged port. Let's declare
  * our socket ready for reuse
  */
 
 if(sock < 0)
	 return NULL;
 add_socket(script_infos, sock);

tryagain :
 if ( current_sport < 128 ) return NULL;
 e =  set_socket_source_addr(sock, sport > 0 ? sport : current_sport--);
 
 /*
  * bind() failed - try again on a lower port
  */
 if(e < 0)
 {
  closesocket ( sock );
  if(sport > 0) 
    return NULL;
   else 
     goto tryagain;
 }
 
 /*
  * Connect to the other end
  */
 p = plug_get_host_ip(script_infos);
 bzero(&daddr, sizeof(daddr));
 daddr.sin_addr = *p;
 daddr.sin_port = htons(dport);
 daddr.sin_family = AF_INET;
 
 unblock_socket(sock);
 e = connect(sock, (struct sockaddr*)&daddr, sizeof(daddr));
 if ( e < 0 )
 {
   err = WSAGetLastError();
   if ( err == WSAEADDRINUSE || err == WSAEADDRNOTAVAIL )
   {
     closesocket(sock);
     if ( sport < 0 ) 
          goto restart;
     else  
          return NULL;
   }
 }

  do {
  tv.tv_sec = to;
  tv.tv_usec = 0;
  FD_ZERO(&rd);
  FD_SET(sock, &rd);
  e = select(sock + 1, NULL, &rd, NULL, to > 0 ? &tv:NULL);
  err = WSAGetLastError();
  } while ( e < 0 && err == WSAEINTR );

 block_socket(sock);
 opt_sz = sizeof(opt);

 if ( getsockopt(sock, SOL_SOCKET, SO_ERROR, &opt, &opt_sz) < 0 )
 {
  fprintf(stderr, "[%d] open_priv_sock()->getsockopt() failed : %s\n", getpid(), strerror(errno));
  closesocket(sock);
  return NULL;
 }
 

 switch ( opt )
 {
   case WSAEADDRINUSE:
   case WSAEADDRNOTAVAIL:
     closesocket ( sock );
     if ( sport < 0 )
 	 goto restart;
      else 
         return FAKE_CELL;

   case 0:
	break;
   default:
       closesocket ( sock );
       return FAKE_CELL;
       break;
 }
 
 if(proto == IPPROTO_TCP)
   sock = nessus_register_connection(sock, NULL);

  retc = alloc_tree_cell(0, NULL);
  retc->type = CONST_INT;
  retc->x.i_val = sock < 0 ? 0 : sock;
  return retc;
}
Ejemplo n.º 5
0
static tree_cell *
nasl_open_privileged_socket (lex_ctxt * lexic, int proto)
{
  struct arglist *script_infos = lexic->script_infos;
  int sport, current_sport = -1;
  int dport;
  int sock;
  int e;
  struct sockaddr_in addr, daddr;
  struct sockaddr_in6 addr6, daddr6;
  struct in6_addr *p;
  int to = get_int_local_var_by_name (lexic, "timeout", lexic->recv_timeout);
  tree_cell *retc;
  struct timeval tv;
  fd_set rd;
  int opt;
  unsigned int opt_sz;
  int family;



  sport = get_int_local_var_by_name (lexic, "sport", -1);
  dport = get_int_local_var_by_name (lexic, "dport", -1);
  if (dport <= 0)
    {
      nasl_perror (lexic,
                   "open_private_socket: missing or undefined parameter dport!\n");
      return NULL;
    }

  if (sport < 0)
    current_sport = 1023;


restart:
  p = plug_get_host_ip (script_infos);
  if (IN6_IS_ADDR_V4MAPPED (p))
    {
      family = AF_INET;
      bzero (&addr, sizeof (addr));
      if (proto == IPPROTO_TCP)
        sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
      else
        sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    }
  else
    {
      family = AF_INET6;
      bzero (&addr6, sizeof (addr6));
      if (proto == IPPROTO_TCP)
        sock = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
      else
        sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
    }


  /*
   * We will bind to a privileged port. Let's declare
   * our socket ready for reuse
   */

  if (sock < 0)
    return NULL;

tryagain:
  if (current_sport < 128 && sport < 0)
    return NULL;
  e =
    openvas_source_set_socket (sock, sport > 0 ? sport : current_sport--, family);

  /*
   * bind() failed - try again on a lower port
   */
  if (e < 0)
    {
      close (sock);
      if (sport > 0)
        return NULL;
      else
        goto tryagain;
    }


  /*
   * Connect to the other end
   */
  p = plug_get_host_ip (script_infos);

  if (IN6_IS_ADDR_V4MAPPED (p))
    {
      bzero (&daddr, sizeof (daddr));
      daddr.sin_addr.s_addr = p->s6_addr32[3];
      daddr.sin_family = AF_INET;
      daddr.sin_port = htons (dport);
      unblock_socket (sock);
      e = connect (sock, (struct sockaddr *) &daddr, sizeof (daddr));
    }
  else
    {
      bzero (&daddr6, sizeof (daddr6));
      memcpy (&daddr6.sin6_addr, p, sizeof (struct in6_addr));
      daddr6.sin6_family = AF_INET6;
      daddr6.sin6_port = htons (dport);
      unblock_socket (sock);
      e = connect (sock, (struct sockaddr *) &daddr6, sizeof (daddr6));
    }


  if (e < 0)
    {
      if (errno == EADDRINUSE || errno == EADDRNOTAVAIL)
        {
          close (sock);
          if (sport < 0)
            goto restart;
          else
            return NULL;
        }
      else if (errno != EINPROGRESS)
        {
          close (sock);
          return NULL;
        }
    }

  do
    {
      tv.tv_sec = to;
      tv.tv_usec = 0;
      FD_ZERO (&rd);
      FD_SET (sock, &rd);
      e = select (sock + 1, NULL, &rd, NULL, to > 0 ? &tv : NULL);
    }
  while (e < 0 && errno == EINTR);

  if (e <= 0)
    {
      close (sock);
      return FAKE_CELL;
    }

  block_socket (sock);
  opt_sz = sizeof (opt);

  if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &opt, &opt_sz) < 0)
    {
      log_legacy_write ("[%d] open_priv_sock()->getsockopt() failed : %s\n",
                        getpid (), strerror (errno));
      close (sock);
      return NULL;
    }


  switch (opt)
    {
    case EADDRINUSE:
    case EADDRNOTAVAIL:
      close (sock);
      if (sport < 0)
        goto restart;
      else
        return FAKE_CELL;

    case 0:
      break;
    default:
      close (sock);
      return FAKE_CELL;
      break;
    }

  if (proto == IPPROTO_TCP)
    sock = openvas_register_connection (sock, NULL, NULL,
                                        OPENVAS_ENCAPS_TLScustom);

  retc = alloc_tree_cell (0, NULL);
  retc->type = CONST_INT;
  retc->x.i_val = sock < 0 ? 0 : sock;
  return retc;
}
Ejemplo n.º 6
0
int connect_socket(char *url, char *port)
{
	struct addrinfo servinfobase, *servinfo, hints, *p;
	int sockd = -1;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	memset(&servinfobase, 0, sizeof(struct addrinfo));
	servinfo = &servinfobase;

	if (getaddrinfo(url, port, &hints, &servinfo) != 0) {
		LOGWARNING("Failed to resolve (?wrong URL) %s:%s", url, port);
		goto out;
	}

	for (p = servinfo; p != NULL; p = p->ai_next) {
		sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
		if (sockd == -1) {
			LOGDEBUG("Failed socket");
			continue;
		}

		/* Iterate non blocking over entries returned by getaddrinfo
		 * to cope with round robin DNS entries, finding the first one
		 * we can connect to quickly. */
		noblock_socket(sockd);
		if (connect(sockd, p->ai_addr, p->ai_addrlen) == -1) {
			int selret;

			if (!sock_connecting()) {
				Close(sockd);
				LOGDEBUG("Failed sock connect");
				continue;
			}
			selret = wait_write_select(sockd, 5);
			if  (selret > 0) {
				socklen_t len;
				int err, n;

				len = sizeof(err);
				n = getsockopt(sockd, SOL_SOCKET, SO_ERROR, (void *)&err, &len);
				if (!n && !err) {
					LOGDEBUG("Succeeded delayed connect");
					block_socket(sockd);
					break;
				}
			}
			Close(sockd);
			LOGDEBUG("Select timeout/failed connect");
			continue;
		}
		LOGDEBUG("Succeeded immediate connect");
		if (sockd >= 0)
			block_socket(sockd);

		break;
	}
	if (p == NULL) {
		LOGNOTICE("Failed to connect to %s:%s", url, port);
		sockd = -1;
	}
	freeaddrinfo(servinfo);
out:
	return sockd;
}