Ejemplo n.º 1
0
/*
 * Receive a file.
 */
static void recvtftp(struct testcase *test, struct formats *pf)
{
  ssize_t n, size;
  /* These are volatile to live through a siglongjmp */
  volatile unsigned short recvblock; /* block count */
  struct tftphdr * volatile rdp;     /* data buffer */
  struct tftphdr *rap;      /* ack buffer */

  recvblock = 0;
  rdp = w_init();
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  rap = &ackbuf.hdr;
  do {
    timeout = 0;
    rap->th_opcode = htons((unsigned short)opcode_ACK);
    rap->th_block = htons(recvblock);
    recvblock++;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
send_ack:
    if (swrite(peer, &ackbuf.storage[0], 4) != 4) {
      logmsg("write: fail\n");
      goto abort;
    }
    write_behind(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);
#endif
      n = sread(peer, rdp, PKTSIZE);
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if(got_exit_signal)
        goto abort;
      if (n < 0) {                       /* really? */
        logmsg("read: fail\n");
        goto abort;
      }
      rdp->th_opcode = ntohs((unsigned short)rdp->th_opcode);
      rdp->th_block = ntohs(rdp->th_block);
      if (rdp->th_opcode == opcode_ERROR)
        goto abort;
      if (rdp->th_opcode == opcode_DATA) {
        if (rdp->th_block == recvblock) {
          break;                         /* normal */
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (rdp->th_block == (recvblock-1))
          goto send_ack;                 /* rexmit */
      }
    }

    size = writeit(test, &rdp, (int)(n - 4), pf->f_convert);
    if (size != (n-4)) {                 /* ahem */
      if (size < 0)
        nak(errno + 100);
      else
        nak(ENOSPACE);
      goto abort;
    }
  } while (size == SEGSIZE);
  write_behind(test, pf->f_convert);

  rap->th_opcode = htons((unsigned short)opcode_ACK);  /* send the "final" ack */
  rap->th_block = htons(recvblock);
  (void) swrite(peer, &ackbuf.storage[0], 4);
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, justtimeout);        /* just abort read on timeout */
  alarm(rexmtval);
#endif
  /* normally times out and quits */
  n = sread(peer, &buf.storage[0], sizeof(buf.storage));
#ifdef HAVE_ALARM
  alarm(0);
#endif
  if(got_exit_signal)
    goto abort;
  if (n >= 4 &&                               /* if read some data */
      rdp->th_opcode == opcode_DATA &&        /* and got a data block */
      recvblock == rdp->th_block) {           /* then my last ack was lost */
    (void) swrite(peer, &ackbuf.storage[0], 4);  /* resend final ack */
  }
abort:
  return;
}
Ejemplo n.º 2
0
static void suboption(struct connectdata *conn)
{
  struct curl_slist *v;
  unsigned char temp[2048];
  ssize_t bytes_written;
  size_t len;
  size_t tmplen;
  int err;
  char varname[128];
  char varval[128];
  struct SessionHandle *data = conn->data;
  struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;

  printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
  switch (CURL_SB_GET(tn)) {
    case CURL_TELOPT_TTYPE:
      len = strlen(tn->subopt_ttype) + 4 + 2;
      snprintf((char *)temp, sizeof(temp),
               "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
               CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
      bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
      if(bytes_written < 0) {
        err = SOCKERRNO;
        failf(data,"Sending data failed (%d)",err);
      }
      printsub(data, '>', &temp[2], len-2);
      break;
    case CURL_TELOPT_XDISPLOC:
      len = strlen(tn->subopt_xdisploc) + 4 + 2;
      snprintf((char *)temp, sizeof(temp),
               "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
               CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
      bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
      if(bytes_written < 0) {
        err = SOCKERRNO;
        failf(data,"Sending data failed (%d)",err);
      }
      printsub(data, '>', &temp[2], len-2);
      break;
    case CURL_TELOPT_NEW_ENVIRON:
      snprintf((char *)temp, sizeof(temp),
               "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
               CURL_TELQUAL_IS);
      len = 4;

      for(v = tn->telnet_vars;v;v = v->next) {
        tmplen = (strlen(v->data) + 1);
        /* Add the variable only if it fits */
        if(len + tmplen < (int)sizeof(temp)-6) {
          sscanf(v->data, "%127[^,],%127s", varname, varval);
          snprintf((char *)&temp[len], sizeof(temp) - len,
                   "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
                   CURL_NEW_ENV_VALUE, varval);
          len += tmplen;
        }
      }
      snprintf((char *)&temp[len], sizeof(temp) - len,
               "%c%c", CURL_IAC, CURL_SE);
      len += 2;
      bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
      if(bytes_written < 0) {
        err = SOCKERRNO;
        failf(data,"Sending data failed (%d)",err);
      }
      printsub(data, '>', &temp[2], len-2);
      break;
  }
  return;
}
Ejemplo n.º 3
0
int writeDN( INOUT STREAM *stream, 
			 IN_OPT const DN_PTR *dnComponentList,
			 IN_TAG const int tag )
	{
	DN_COMPONENT *dnComponentPtr;
	int size, iterationCount, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( dnComponentList == NULL || \
			isReadPtr( dnComponentList, sizeof( DN_COMPONENT ) ) );

	REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );

	/* Special case for empty DNs */
	if( dnComponentList == NULL )
		return( writeConstructed( stream, 0, tag ) );

	status = preEncodeDN( ( DN_COMPONENT * ) dnComponentList, &size );
	if( cryptStatusError( status ) )
		return( status );

	/* Write the DN */
	writeConstructed( stream, size, tag );
	for( dnComponentPtr = ( DN_COMPONENT * ) dnComponentList, \
			iterationCount = 0;
		 dnComponentPtr != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 dnComponentPtr = dnComponentPtr->next, iterationCount++ )
		{
		const DN_COMPONENT_INFO *dnComponentInfo = dnComponentPtr->typeInfo;
		BYTE dnString[ MAX_ATTRIBUTE_SIZE + 8 ];
		int dnStringLength;

		/* Write the RDN wrapper */
		if( dnComponentPtr->encodedRDNdataSize > 0 )
			{
			/* If it's the start of an RDN, write the RDN header */
			writeSet( stream, dnComponentPtr->encodedRDNdataSize );
			}
		writeSequence( stream, dnComponentPtr->encodedAVAdataSize );
		status = swrite( stream, dnComponentInfo->oid, 
						 sizeofOID( dnComponentInfo->oid ) );
		if( cryptStatusError( status ) )
			return( status );

		/* Convert the string to an ASN.1-compatible format and write it
		   out */
		status = copyToAsn1String( dnString, MAX_ATTRIBUTE_SIZE, 
								   &dnStringLength, dnComponentPtr->value,
								   dnComponentPtr->valueLength,
								   dnComponentPtr->valueStringType );
		if( cryptStatusError( status ) )
			return( status );
		if( dnComponentPtr->asn1EncodedStringType == BER_STRING_IA5 && \
			!dnComponentInfo->ia5OK )
			{
			/* If an IA5String isn't allowed in this instance, use a
			   T61String instead */
			dnComponentPtr->asn1EncodedStringType = BER_STRING_T61;
			}
		status = writeCharacterString( stream, dnString, dnStringLength,
									   dnComponentPtr->asn1EncodedStringType );
		if( cryptStatusError( status ) )
			return( status );
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( CRYPT_OK );
	}
Ejemplo n.º 4
0
/*
 * Send the requested file.
 */
static void sendtftp(struct testcase *test, struct formats *pf)
{
  int size;
  ssize_t n;
  /* This is volatile to live through a siglongjmp */
  volatile unsigned short sendblock; /* block count */
  struct tftphdr *sdp;      /* data buffer */
  struct tftphdr *sap;      /* ack buffer */

  sendblock = 1;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  sdp = r_init();
  sap = &ackbuf.hdr;
  do {
    size = readit(test, &sdp, pf->f_convert);
    if (size < 0) {
      nak(errno + 100);
      return;
    }
    sdp->th_opcode = htons((unsigned short)opcode_DATA);
    sdp->th_block = htons(sendblock);
    timeout = 0;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
    if(test->writedelay) {
      logmsg("Pausing %d seconds before %d bytes", test->writedelay,
             size);
      wait_ms(1000*test->writedelay);
    }

    send_data:
    if (swrite(peer, sdp, size + 4) != size + 4) {
      logmsg("write");
      return;
    }
    read_ahead(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);        /* read the ack */
#endif
      n = sread(peer, &ackbuf.storage[0], sizeof(ackbuf.storage));
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if(got_exit_signal)
        return;
      if (n < 0) {
        logmsg("read: fail");
        return;
      }
      sap->th_opcode = ntohs((unsigned short)sap->th_opcode);
      sap->th_block = ntohs(sap->th_block);

      if (sap->th_opcode == opcode_ERROR) {
        logmsg("got ERROR");
        return;
      }

      if (sap->th_opcode == opcode_ACK) {
        if (sap->th_block == sendblock) {
          break;
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (sap->th_block == (sendblock-1)) {
          goto send_data;
        }
      }

    }
    sendblock++;
  } while (size == SEGSIZE);
}
Ejemplo n.º 5
0
/*
  sockfdp is a pointer to an established stream or CURL_SOCKET_BAD

  if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must
  accept()
*/
static bool juggle(curl_socket_t *sockfdp,
                   curl_socket_t listenfd,
                   enum sockmode *mode)
{
  struct timeval timeout;
  fd_set fds_read;
  fd_set fds_write;
  fd_set fds_err;
  curl_socket_t sockfd = CURL_SOCKET_BAD;
  int maxfd = -99;
  ssize_t rc;
  int error = 0;

 /* 'buffer' is this excessively large only to be able to support things like
    test 1003 which tests exceedingly large server response lines */
  unsigned char buffer[17010];
  char data[16];

  if(got_exit_signal) {
    logmsg("signalled to die, exiting...");
    return FALSE;
  }

#ifdef HAVE_GETPPID
  /* As a last resort, quit if sockfilt process becomes orphan. Just in case
     parent ftpserver process has died without killing its sockfilt children */
  if(getppid() <= 1) {
    logmsg("process becomes orphan, exiting");
    return FALSE;
  }
#endif

  timeout.tv_sec = 120;
  timeout.tv_usec = 0;

  FD_ZERO(&fds_read);
  FD_ZERO(&fds_write);
  FD_ZERO(&fds_err);

  FD_SET((curl_socket_t)fileno(stdin), &fds_read);

  switch(*mode) {

  case PASSIVE_LISTEN:

    /* server mode */
    sockfd = listenfd;
    /* there's always a socket to wait for */
    FD_SET(sockfd, &fds_read);
    maxfd = (int)sockfd;
    break;

  case PASSIVE_CONNECT:

    sockfd = *sockfdp;
    if(CURL_SOCKET_BAD == sockfd) {
      /* eeek, we are supposedly connected and then this cannot be -1 ! */
      logmsg("socket is -1! on %s:%d", __FILE__, __LINE__);
      maxfd = 0; /* stdin */
    }
    else {
      /* there's always a socket to wait for */
      FD_SET(sockfd, &fds_read);
#ifdef USE_WINSOCK
      FD_SET(sockfd, &fds_err);
#endif
      maxfd = (int)sockfd;
    }
    break;

  case ACTIVE:

    sockfd = *sockfdp;
    /* sockfd turns CURL_SOCKET_BAD when our connection has been closed */
    if(CURL_SOCKET_BAD != sockfd) {
      FD_SET(sockfd, &fds_read);
#ifdef USE_WINSOCK
      FD_SET(sockfd, &fds_err);
#endif
      maxfd = (int)sockfd;
    }
    else {
      logmsg("No socket to read on");
      maxfd = 0;
    }
    break;

  case ACTIVE_DISCONNECT:

    logmsg("disconnected, no socket to read on");
    maxfd = 0;
    sockfd = CURL_SOCKET_BAD;
    break;

  } /* switch(*mode) */


  do {

    /* select() blocking behavior call on blocking descriptors please */

    rc = select(maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);

    if(got_exit_signal) {
      logmsg("signalled to die, exiting...");
      return FALSE;
    }

  } while((rc == -1) && ((error = errno) == EINTR));

  if(rc < 0) {
    logmsg("select() failed with error: (%d) %s",
           error, strerror(error));
    return FALSE;
  }

  if(rc == 0)
    /* timeout */
    return TRUE;


  if(FD_ISSET(fileno(stdin), &fds_read)) {
    ssize_t buffer_len;
    /* read from stdin, commands/data to be dealt with and possibly passed on
       to the socket

       protocol:

       4 letter command + LF [mandatory]

       4-digit hexadecimal data length + LF [if the command takes data]
       data                       [the data being as long as set above]

       Commands:

       DATA - plain pass-through data
    */

    if(!read_stdin(buffer, 5))
      return FALSE;

    logmsg("Received %c%c%c%c (on stdin)",
           buffer[0], buffer[1], buffer[2], buffer[3]);

    if(!memcmp("PING", buffer, 4)) {
      /* send reply on stdout, just proving we are alive */
      if(!write_stdout("PONG\n", 5))
        return FALSE;
    }

    else if(!memcmp("PORT", buffer, 4)) {
      /* Question asking us what PORT number we are listening to.
         Replies to PORT with "IPv[num]/[port]" */
      snprintf((char *)buffer, sizeof(buffer), "%s/%hu\n", ipv_inuse, port);
      buffer_len = (ssize_t)strlen((char *)buffer);
      snprintf(data, sizeof(data), "PORT\n%04zx\n", buffer_len);
      if(!write_stdout(data, 10))
        return FALSE;
      if(!write_stdout(buffer, buffer_len))
        return FALSE;
    }
    else if(!memcmp("QUIT", buffer, 4)) {
      /* just die */
      logmsg("quits");
      return FALSE;
    }
    else if(!memcmp("DATA", buffer, 4)) {
      /* data IN => data OUT */

      if(!read_stdin(buffer, 5))
        return FALSE;

      buffer[5] = '\0';

      buffer_len = (ssize_t)strtol((char *)buffer, NULL, 16);
      if(buffer_len > (ssize_t)sizeof(buffer)) {
        logmsg("ERROR: Buffer size (%zu bytes) too small for data size "
               "(%zd bytes)", sizeof(buffer), buffer_len);
        return FALSE;
      }
      logmsg("> %zd bytes data, server => client", buffer_len);

      if(!read_stdin(buffer, buffer_len))
        return FALSE;

      lograw(buffer, buffer_len);

      if(*mode == PASSIVE_LISTEN) {
        logmsg("*** We are disconnected!");
        if(!write_stdout("DISC\n", 5))
          return FALSE;
      }
      else {
        /* send away on the socket */
        ssize_t bytes_written = swrite(sockfd, buffer, buffer_len);
        if(bytes_written != buffer_len) {
          logmsg("Not all data was sent. Bytes to send: %zd sent: %zd",
                 buffer_len, bytes_written);
        }
      }
    }
    else if(!memcmp("DISC", buffer, 4)) {
      /* disconnect! */
      if(!write_stdout("DISC\n", 5))
        return FALSE;
      if(sockfd != CURL_SOCKET_BAD) {
        logmsg("====> Client forcibly disconnected");
        sclose(sockfd);
        *sockfdp = CURL_SOCKET_BAD;
        if(*mode == PASSIVE_CONNECT)
          *mode = PASSIVE_LISTEN;
        else
          *mode = ACTIVE_DISCONNECT;
      }
      else
        logmsg("attempt to close already dead connection");
      return TRUE;
    }
  }


  if((sockfd != CURL_SOCKET_BAD) && (FD_ISSET(sockfd, &fds_read)) ) {
    ssize_t nread_socket;
    if(*mode == PASSIVE_LISTEN) {
      /* there's no stream set up yet, this is an indication that there's a
         client connecting. */
      curl_socket_t newfd = accept(sockfd, NULL, NULL);
      if(CURL_SOCKET_BAD == newfd) {
        error = SOCKERRNO;
        logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
               sockfd, error, strerror(error));
      }
      else {
        logmsg("====> Client connect");
        if(!write_stdout("CNCT\n", 5))
          return FALSE;
        *sockfdp = newfd; /* store the new socket */
        *mode = PASSIVE_CONNECT; /* we have connected */
      }
      return TRUE;
    }

    /* read from socket, pass on data to stdout */
    nread_socket = sread(sockfd, buffer, sizeof(buffer));

    if(nread_socket > 0) {
      snprintf(data, sizeof(data), "DATA\n%04zx\n", nread_socket);
      if(!write_stdout(data, 10))
        return FALSE;
      if(!write_stdout(buffer, nread_socket))
        return FALSE;

      logmsg("< %zd bytes data, client => server", nread_socket);
      lograw(buffer, nread_socket);
    }

    if(nread_socket <= 0
#ifdef USE_WINSOCK
       || FD_ISSET(sockfd, &fds_err)
#endif
       ) {
      logmsg("====> Client disconnect");
      if(!write_stdout("DISC\n", 5))
        return FALSE;
      sclose(sockfd);
      *sockfdp = CURL_SOCKET_BAD;
      if(*mode == PASSIVE_CONNECT)
        *mode = PASSIVE_LISTEN;
      else
        *mode = ACTIVE_DISCONNECT;
      return TRUE;
    }
  }

  return TRUE;
}
Ejemplo n.º 6
0
static KWNetStatus
SendSMTPData(
   IMFILE *imf                   /* IN Contents of message            */
)
{


   char InputBuf[MAXPACK];
   char OutputBuf[MAXPACK];
   char c;
   int nBytesSeen = 0;
   int nBytesQueued = 0;
   int nBytesRead;

   int nTotalSeen = 0;
   int nTotalRead = 0;
   int nTotalQueued = 0;

   KWBoolean bAllPeriods = KWTrue;
   KWBoolean bWriteNow   = KWFalse;
   KWBoolean bDirtyLine  = KWFalse;

   imrewind(imf);

/*--------------------------------------------------------------------*/
/*                      Outer loop handles input                      */
/*--------------------------------------------------------------------*/

   while((nBytesRead = (int) imread(InputBuf,
                                    1,
                                    sizeof InputBuf,
                                    imf)) != 0)
   {

     nTotalRead += nBytesRead;

     nBytesSeen = 0;

/*--------------------------------------------------------------------*/
/*          Inner loop handles output from buffer to network          */
/*--------------------------------------------------------------------*/

     while (nBytesRead > nBytesSeen)
     {
        c = InputBuf[nBytesSeen++];

        switch(c)
        {
            default:                    /* non-period, non end of line */
                bAllPeriods = KWFalse;
                /* FALL THROUGH */

            case '.':                   /* Period, may need quoting */
                bDirtyLine = KWTrue;
                OutputBuf[nBytesQueued++] = c;
                break;

            case '\n':                  /* End of data line */

                /* Quote output if only all periods in non-empty line */
                if (bDirtyLine && bAllPeriods)
                {
                    OutputBuf[nBytesQueued++] = '.';
                }

                /* Print previous line if desired */
                if (debuglevel >= 5)
                {
                    OutputBuf[nBytesQueued] = '\0';
                    printmsg(5, "--> %.75s", OutputBuf);
                    bWriteNow      = KWTrue;
                }

                memcpy(OutputBuf + nBytesQueued, CRLF, CRLF_LEN);
                nBytesQueued += CRLF_LEN;

                /* Reset line specific conditions for following line */
                bAllPeriods = KWTrue;
                bDirtyLine  = KWFalse;
                break;

        } /* END switch(c) */

/*--------------------------------------------------------------------*/
/*       Write the output buffer if explicitly requested or or it     */
/*       is nearly full.                                              */
/*--------------------------------------------------------------------*/

        if (bWriteNow ||
            (nBytesQueued >= (sizeof OutputBuf - (CRLF_LEN + 2))))
        {

            bWriteNow = KWFalse;

            if (swrite(OutputBuf, (size_t) nBytesQueued) < nBytesQueued)
            {
                printmsg(0, "SendSMTPData of %d bytes failed: %.80s",
                           OutputBuf,
                           nBytesQueued);
                return KWNSNoNet;
            }

            nTotalQueued += nBytesQueued;
            nBytesQueued = 0;

        } /* if (bWriteNow || ...))) */

     } /* END while(nBytesRead < nBytesSeen) */

     nTotalSeen += nBytesSeen;

   } /* END while((nBytesRead = imread()) */

/*--------------------------------------------------------------------*/
/*                    Write final data out, if any                    */
/*--------------------------------------------------------------------*/

   if (nBytesQueued > 0)
   {
       if (swrite(OutputBuf, (size_t) nBytesQueued) < nBytesQueued)
       {
           printmsg(0, "SendSMTPData of %d bytes failed: %.80s",
                      OutputBuf,
                      nBytesQueued);
           return KWNSNoNet;
       }

       nTotalQueued += nBytesQueued;

   } /* if (nBytesQueued > 0) */

   printmsg(2,"SendSMTPData: Read %d bytes, examined %d bytes, wrote %d bytes",
               nTotalRead,
               nTotalSeen,
               nTotalQueued);

/*--------------------------------------------------------------------*/
/*     Verify that RMAIL previously terminated final line for us      */
/*--------------------------------------------------------------------*/

   if (bDirtyLine)
   {
      printmsg(0,"SendSMTPData: Unterminated final line not trapped: %.80s",
               OutputBuf);
      panic();
   }

   return KWNSSuccess;

} /* SendSMTPData */
Ejemplo n.º 7
0
static int memcached_query_daemon (char *buffer, size_t buffer_size, memcached_t *st)
{
  int fd, status;
  size_t buffer_fill;

  fd = memcached_connect (st);
  if (fd < 0) {
    ERROR ("memcached plugin: Instance \"%s\" could not connect to daemon.",
        st->name);
    return -1;
  }

  status = (int) swrite (fd, "stats\r\n", strlen ("stats\r\n"));
  if (status != 0)
  {
    char errbuf[1024];
    ERROR ("memcached plugin: write(2) failed: %s",
        sstrerror (errno, errbuf, sizeof (errbuf)));
    shutdown(fd, SHUT_RDWR);
    close (fd);
    return (-1);
  }

  /* receive data from the memcached daemon */
  memset (buffer, 0, buffer_size);

  buffer_fill = 0;
  while ((status = (int) recv (fd, buffer + buffer_fill,
          buffer_size - buffer_fill, /* flags = */ 0)) != 0)
  {
    char const end_token[5] = {'E', 'N', 'D', '\r', '\n'};
    if (status < 0)
    {
      char errbuf[1024];

      if ((errno == EAGAIN) || (errno == EINTR))
          continue;

      ERROR ("memcached: Error reading from socket: %s",
          sstrerror (errno, errbuf, sizeof (errbuf)));
      shutdown(fd, SHUT_RDWR);
      close (fd);
      return (-1);
    }

    buffer_fill += (size_t) status;
    if (buffer_fill > buffer_size)
    {
      buffer_fill = buffer_size;
      WARNING ("memcached plugin: Message was truncated.");
      break;
    }

    /* If buffer ends in end_token, we have all the data. */
    if (memcmp (buffer + buffer_fill - sizeof (end_token),
          end_token, sizeof (end_token)) == 0)
      break;
  } /* while (recv) */

  status = 0;
  if (buffer_fill == 0)
  {
    WARNING ("memcached plugin: No data returned by memcached.");
    status = -1;
  }

  shutdown(fd, SHUT_RDWR);
  close(fd);
  return (status);
} /* int memcached_query_daemon */
Ejemplo n.º 8
0
/*
 * Custom push and pull callback functions used by GNU TLS to read and write
 * to the socket.  These functions are simple wrappers to send() and recv()
 * (although here using the sread/swrite macros as defined by setup_once.h).
 * We use custom functions rather than the GNU TLS defaults because it allows
 * us to get specific about the fourth "flags" argument, and to use arbitrary
 * private data with gnutls_transport_set_ptr if we wish.
 */
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
  return swrite(s, buf, len);
}
Ejemplo n.º 9
0
static int multimeter_read_value(double *value)
{
	int retry = 3; /* sometimes we receive garbadge */

	do
	{
		struct timeval time_end;

		tcflush(fd, TCIFLUSH);

		if (gettimeofday (&time_end, NULL) < 0)
	        {
			char errbuf[1024];
	                ERROR ("multimeter plugin: gettimeofday failed: %s",
					sstrerror (errno, errbuf,
						sizeof (errbuf)));
	                return (-1);
	        }
	        time_end.tv_sec++;	

		while (1)
		{
		        char buf[LINE_LENGTH];
			char *range;
			int status;
			fd_set rfds;
    			struct timeval timeout;
    			struct timeval time_now;

			status = swrite (fd, "D", 1);
			if (status < 0)
			{
				ERROR ("multimeter plugin: swrite failed.");
				return (-1);
			}

			FD_ZERO(&rfds);
			FD_SET(fd, &rfds);

			if (gettimeofday (&time_now, NULL) < 0)
	                {
				char errbuf[1024];
		                ERROR ("multimeter plugin: "
						"gettimeofday failed: %s",
						sstrerror (errno, errbuf,
							sizeof (errbuf)));
	                        return (-1);
	                }
			if (timeval_cmp (time_end, time_now, &timeout) < 0)
	                        break;

			status = select(fd+1, &rfds, NULL, NULL, &timeout);

			if (status > 0) /* usually we succeed */
			{
				status = read(fd, buf, LINE_LENGTH);

				if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
				        continue;

				/* Format: "DC 00.000mV  \r" */
				if (status > 0 && status == LINE_LENGTH)
				{
					*value = strtod(buf + 2, &range);

					if ( range > (buf + 6) )
					{
			    			range = buf + 9;

						switch ( *range )
						{
			    				case 'p': *value *= 1.0E-12; break;
					    		case 'n': *value *= 1.0E-9; break;
							case 'u': *value *= 1.0E-6; break;
			    				case 'm': *value *= 1.0E-3; break;
							case 'k': *value *= 1.0E3; break;
							case 'M': *value *= 1.0E6; break;
							case 'G': *value *= 1.0E9; break;
						}
					}
					else
						return (-1); /* Overflow */

					return (0); /* value received */
				}
				else break;
			}
			else if (!status) /* Timeout */
            		{
	                        break;
			}
			else if ((status == -1) && ((errno == EAGAIN) || (errno == EINTR)))
			{
			        continue;
			}
			else /* status == -1 */
            		{
				char errbuf[1024];
		                ERROR ("multimeter plugin: "
						"select failed: %s",
						sstrerror (errno, errbuf, sizeof (errbuf)));
	                        break;
			}
		}
	} while (--retry);

	return (-2);  /* no value received */
} /* int multimeter_read_value */
Ejemplo n.º 10
0
/*
 * Send the requested file.
 */
static void sendtftp(struct testcase *test, struct formats *pf)
{
  int size;
  ssize_t n;
  sendblock = 1;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  sdp = r_init();
  sap = (struct tftphdr *)ackbuf;
  do {
    size = readit(test, &sdp, pf->f_convert);
    if (size < 0) {
      nak(ERRNO + 100);
      return;
    }
    sdp->th_opcode = htons((u_short)opcode_DATA);
    sdp->th_block = htons((u_short)sendblock);
    timeout = 0;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
    send_data:
    if (swrite(peer, sdp, size + 4) != size + 4) {
      logmsg("write\n");
      return;
    }
    read_ahead(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);        /* read the ack */
#endif
      n = sread(peer, ackbuf, sizeof (ackbuf));
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if (n < 0) {
        logmsg("read: fail\n");
        return;
      }
      sap->th_opcode = ntohs((u_short)sap->th_opcode);
      sap->th_block = ntohs((u_short)sap->th_block);

      if (sap->th_opcode == opcode_ERROR) {
        logmsg("got ERROR");
        return;
      }

      if (sap->th_opcode == opcode_ACK) {
        if (sap->th_block == sendblock) {
          break;
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (sap->th_block == (sendblock-1)) {
          goto send_data;
        }
      }

    }
    sendblock++;
  } while (size == SEGSIZE);
}
Ejemplo n.º 11
0
int beginServerHandshake( INOUT SESSION_INFO *sessionInfoPtr, 
						  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	STREAM *stream = &handshakeInfo->stream;
	SCOREBOARD_LOOKUP_RESULT lookupResult = DUMMY_INIT_STRUCT;
	MESSAGE_DATA msgData;
	int length, resumedSessionID = CRYPT_ERROR;
	int packetOffset, status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );

	/* Read and process the client hello */
	status = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,
							  SSL_MSG_FIRST_HANDSHAKE );
	if( cryptStatusError( status ) )
		return( status );
	sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );
	status = processHelloSSL( sessionInfoPtr, handshakeInfo, stream, TRUE );
	sMemDisconnect( stream );
	if( cryptStatusError( status ) )
		{
		if( status != OK_SPECIAL )
			return( status );

		/* The client has sent us a sessionID in an attempt to resume a 
		   previous session, see if it's in the session cache */
		resumedSessionID = \
			lookupScoreboardEntry( sessionInfoPtr->sessionSSL->scoreboardInfoPtr,
					SCOREBOARD_KEY_SESSIONID_SVR, handshakeInfo->sessionID, 
					handshakeInfo->sessionIDlength,
					&lookupResult );
#ifdef CONFIG_SUITEB_TESTS 
		resumedSessionID = CRYPT_ERROR;	/* Disable for Suite B tests */
#endif /* CONFIG_SUITEB_TESTS */
		}

	/* Handle session resumption.  If it's a new session or the session data 
	   has expired from the cache, generate a new session ID */
	if( cryptStatusError( resumedSessionID ) )
		{
		setMessageData( &msgData, handshakeInfo->sessionID, SESSIONID_SIZE );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_GETATTRIBUTE_S, &msgData, 
								  CRYPT_IATTRIBUTE_RANDOM_NONCE );
		if( cryptStatusError( status ) )
			return( status );
		handshakeInfo->sessionIDlength = SESSIONID_SIZE;
		}
	else
		{
		/* We're resuming a previous session, remember the premaster secret */
		status = attributeCopyParams( handshakeInfo->premasterSecret, 
									  SSL_SECRET_SIZE,
									  &handshakeInfo->premasterSecretSize,
									  lookupResult.data, 
									  lookupResult.dataSize );
		ENSURES( cryptStatusOK( status ) );
		}

	/* Get the nonce that's used to randomise all crypto operations and set 
	   up the server DH/ECDH context if necessary */
	setMessageData( &msgData, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
							  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
	if( cryptStatusOK( status ) && isKeyxAlgo( handshakeInfo->keyexAlgo ) )
		{
		status = initDHcontextSSL( &handshakeInfo->dhContext, NULL, 0,
							( handshakeInfo->authAlgo != CRYPT_ALGO_NONE ) ? \
							sessionInfoPtr->privateKey : CRYPT_UNUSED,
							isEccAlgo( handshakeInfo->keyexAlgo ) ? \
								handshakeInfo->eccCurveID : CRYPT_ECCCURVE_NONE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Build the server hello, certificate, optional certificate request, 
	   and done packets:

		byte		ID = SSL_HAND_SERVER_HELLO
		uint24		len
		byte[2]		version = { 0x03, 0x0n }
		byte[32]	nonce
		byte		sessIDlen
		byte[]		sessID
		uint16		suite
		byte		copr = 0
	  [	uint16	extListLen		-- RFC 3546/RFC 4366
			byte	extType
			uint16	extLen
			byte[]	extData ] 
		...

	   We have to be careful how we handle extensions because the RFC makes 
	   the rather optimistic assumption that implementations can handle the 
	   presence of unexpected data at the end of the hello packet, to avoid 
	   problems with this we avoid sending extensions unless they're in 
	   response to extensions already sent by the client */
	status = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT, 
								  SSL_MSG_HANDSHAKE );
	if( cryptStatusError( status ) )
		return( status );
	status = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLO, 
									 &packetOffset );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( stream );
		return( status );
		}
	sputc( stream, SSL_MAJOR_VERSION );
	sputc( stream, sessionInfoPtr->version );
	swrite( stream, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
	sputc( stream, handshakeInfo->sessionIDlength );
	swrite( stream, handshakeInfo->sessionID, 
			handshakeInfo->sessionIDlength );
	writeUint16( stream, handshakeInfo->cipherSuite ); 
	status = sputc( stream, 0 );	/* No compression */
	if( handshakeInfo->hasExtensions )
		status = writeServerExtensions( stream, handshakeInfo );
	if( cryptStatusOK( status ) )
		status = completeHSPacketStream( stream, packetOffset );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( stream );
		return( status );
		}

	/* If it's a resumed session then the server hello is followed 
	   immediately by the change cipherspec, which is sent by the shared 
	   handshake completion code */
	if( !cryptStatusError( resumedSessionID ) )
		{
		status = completePacketStreamSSL( stream, 0 );
		if( cryptStatusOK( status ) )
			status = hashHSPacketWrite( handshakeInfo, stream, 0 );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}

		/* Tell the caller that it's a resumed session, leaving the stream
		   open in order to write the change cipherspec message that follows 
		   the server hello in a resumed session */
		DEBUG_PRINT(( "Resuming session with client based on "
					  "sessionID = \n" ));
		DEBUG_DUMP_DATA( handshakeInfo->sessionID, 
						 handshakeInfo->sessionIDlength );
		return( OK_SPECIAL );
		}

	/*	...	(optional server supplemental data)
		byte		ID = SSL_HAND_SUPPLEMENTAL_DATA
		uint24		len
		uint16		type
		uint16		len
		byte[]		value
		... */

	/*	...
		(optional server certificate chain)
		... */
	if( handshakeInfo->authAlgo != CRYPT_ALGO_NONE )
		{
		status = writeSSLCertChain( sessionInfoPtr, stream );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		}

	/*	...			(optional server keyex)
		byte		ID = SSL_HAND_SERVER_KEYEXCHANGE
		uint24		len
	   DH:
		uint16		dh_pLen
		byte[]		dh_p
		uint16		dh_gLen
		byte[]		dh_g
		uint16		dh_YsLen
		byte[]		dh_Ys
	  [	byte		hashAlgoID		-- TLS 1.2 ]
	  [	byte		sigAlgoID		-- TLS 1.2 ]
		uint16		signatureLen
		byte[]		signature
	   ECDH:
		byte		curveType
		uint16		namedCurve
		uint8		ecPointLen		-- NB uint8 not uint16
		byte[]		ecPoint
	  [	byte		hashAlgoID		-- TLS 1.2 ]
	  [	byte		sigAlgoID		-- TLS 1.2 ]
		uint16		signatureLen
		byte[]		signature */
	if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
		{
		KEYAGREE_PARAMS keyAgreeParams;
		void *keyData = DUMMY_INIT_PTR;
		int keyDataOffset, keyDataLength = DUMMY_INIT;

		/* Perform phase 1 of the DH/ECDH key agreement process */
		memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
		status = krnlSendMessage( handshakeInfo->dhContext,
								  IMESSAGE_CTX_ENCRYPT, &keyAgreeParams,
								  sizeof( KEYAGREE_PARAMS ) );
		if( cryptStatusError( status ) )
			{
			zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
			sMemDisconnect( stream );
			return( status );
			}

		/* Write the DH/ECDH key parameters and public value and sign them */
		status = continueHSPacketStream( stream, SSL_HAND_SERVER_KEYEXCHANGE, 
										 &packetOffset );
		if( cryptStatusError( status ) )
			{
			zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
			sMemDisconnect( stream );
			return( status );
			}
		keyDataOffset = stell( stream );
		status = exportAttributeToStream( stream, handshakeInfo->dhContext,
										  CRYPT_IATTRIBUTE_KEY_SSL );
		if( cryptStatusOK( status ) )
			{
			if( isEccAlgo( handshakeInfo->keyexAlgo ) )
				{
				sputc( stream, keyAgreeParams.publicValueLen );
				swrite( stream, keyAgreeParams.publicValue,
						keyAgreeParams.publicValueLen );
				}
			else
				{
				status = writeInteger16U( stream, keyAgreeParams.publicValue, 
										  keyAgreeParams.publicValueLen );
				}
			}
		if( cryptStatusOK( status ) )
			{
			keyDataLength = stell( stream ) - keyDataOffset;
			status = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData, 
										  keyDataLength );
			}
		if( cryptStatusOK( status ) )
			{
			status = createKeyexSignature( sessionInfoPtr, handshakeInfo,
										   stream, keyData, keyDataLength );
			}
		zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
		if( cryptStatusOK( status ) )
			status = completeHSPacketStream( stream, packetOffset );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		}

	/*	...			(optional request for client certificate authentication)
		byte		ID = SSL_HAND_SERVER_CERTREQUEST
		uint24		len
		byte		certTypeLen
		byte[]		certType = { RSA, DSA, ECDSA }
	  [	uint16	sigHashListLen		-- TLS 1.2 ]
	  [		byte	hashAlgoID		-- TLS 1.2 ]
	  [		byte	sigAlgoID		-- TLS 1.2 ]
		uint16		caNameListLen = 4
			uint16	caNameLen = 2
			byte[]	caName = { 0x30, 0x00 }
		... */
	if( clientCertAuthRequired( sessionInfoPtr ) )
		{
		status = continueHSPacketStream( stream, SSL_HAND_SERVER_CERTREQUEST, 
										 &packetOffset );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		status = writeCertRequest( sessionInfoPtr, handshakeInfo, stream );
		if( cryptStatusOK( status ) )
			status = completeHSPacketStream( stream, packetOffset );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( stream );
			return( status );
			}
		}

	/*	...
		byte		ID = SSL_HAND_SERVER_HELLODONE
		uint24		len = 0 */
	status = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLODONE, 
									 &packetOffset );
	if( cryptStatusOK( status ) )
		status = completeHSPacketStream( stream, packetOffset );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( stream );
		return( status );
		}

	/* Send the combined server packets to the client.  We perform the 
	   assorted hashing of the packets in between the network ops where 
	   it's effectively free */
	status = sendPacketSSL( sessionInfoPtr, stream, FALSE );
	if( cryptStatusOK( status ) )
		status = hashHSPacketWrite( handshakeInfo, stream, 0 );
	sMemDisconnect( stream );
	return( status );
	}
Ejemplo n.º 12
0
static int writeCertRequest( INOUT SESSION_INFO *sessionInfoPtr, 
							 INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
							 INOUT STREAM *stream )
	{
	const BOOLEAN rsaAvailable = algoAvailable( CRYPT_ALGO_RSA );
	const BOOLEAN dsaAvailable = algoAvailable( CRYPT_ALGO_DSA );
	const BOOLEAN ecdsaAvailable = algoAvailable( CRYPT_ALGO_ECDSA );

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );

	REQUIRES( rsaAvailable || ecdsaAvailable );

	/* Write the certificate type */
	sputc( stream, ( rsaAvailable ? 1 : 0 ) + \
				   ( dsaAvailable ? 1 : 0 ) + \
				   ( ecdsaAvailable ? 1 : 0 ) );
	if( rsaAvailable )
		sputc( stream, TLS_CERTTYPE_RSA );
	if( dsaAvailable )
		sputc( stream, TLS_CERTTYPE_DSA );
	if( ecdsaAvailable )
		sputc( stream, TLS_CERTTYPE_ECDSA );

	/* Write the list of accepted signature and hash algorithms if required.  
	   In theory we could write the full list of algorithms, but thanks to 
	   SSL/TLS' braindamaged way of handling certificate-based 
	   authentication (see the comment above) this would make the 
	   certificate-authentication process unmanageable.  To get around this 
	   we only allow one single algorithm, the SHA-2 default for TLS 1.2+.  
	   In addition we can't allow DSA because it's only defined for use with 
	   SHA-1 (unless we go for "DSA-2" / FIPS 186-3 key sizes like 2048 
	   bits, which nothing seems to support).

	   For Suite B things get a bit more complicated because this allows 
	   both SHA-256 and SHA-384, dropping us straight back into the mess 
	   that we've just escaped from.  To get around this we specify the
	   use of the hash algorithm that we've negotiated for the handshake,
	   on the assumption that a client using SHA384 for the handshake isn't 
	   going to then try and use SHA256 for the authentication */
	if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
		{
#ifdef CONFIG_SUITEB
		writeUint16( stream, 2 );
		if( handshakeInfo->keyexSigHashAlgoParam == bitsToBytes( 384 ) )
			sputc( stream, TLS_HASHALGO_SHA384 );
		else
			sputc( stream, TLS_HASHALGO_SHA2 );
		sputc( stream, TLS_SIGALGO_ECDSA );
#else
		writeUint16( stream, ( rsaAvailable ? 2 : 0 ) + \
							 ( ecdsaAvailable ? 2 : 0 ) );
		if( rsaAvailable )
			{
			sputc( stream, TLS_HASHALGO_SHA2 );
			sputc( stream, TLS_SIGALGO_RSA );
			}
		if( ecdsaAvailable )
			{
			sputc( stream, TLS_HASHALGO_SHA2 );
			sputc( stream, TLS_SIGALGO_ECDSA );
			}
#endif /* CONFIG_SUITEB */
		}

	/* Write the CA name list */ 
	writeUint16( stream, UINT16_SIZE + 2 );
	writeUint16( stream, 2 );
	return( swrite( stream, "\x30\x00", 2 ) );
	}
Ejemplo n.º 13
0
void
dofile(const char *name)
{
  int		fd;
  struct stat	st;
  char		*s;

  if ((fd=open(name, O_RDWR))<0)
    swrite("?");
  else if (fstat(fd, &st) ||
	   !S_ISREG(st.st_mode))
    ex("open");
  else
    swrite_free(md5sum(fd, st.st_size));

  s	= sread();
  switch (*s)
    {
    case 'o':
      close(fd);
      free(s);
      return;

    case 'a':
      if (fd<0)
	ex("!fd");
      if (lseek(fd, st.st_size, SEEK_SET)!=st.st_size)
	ex("lseek");
      break;

    case 'w':
      if (fd<0)
	ex("!fd");
      close(fd);
      fd	= -1;
      free(s);
      s	= newname(name);
      if (rename(name, s))
	ex("name");
    case 'c':
      if (fd>=0)
	ex("fd!");
      mkparent(name);
      if ((fd=open(name, O_WRONLY|O_CREAT|O_EXCL, 0644))<0)
	ex("create");
      break;

    default:
      ex("prot");
    }
  free(s);

  swrite("OK");

  if (docopy(sock, fd, 1))
    ex("broken stream");
  if (close(fd))
    ex("close");

  swrite("NEXT");
}
Ejemplo n.º 14
0
void   i3_send(const int32_t  sockfd, const buf_t&  buff) {
	swrite(sockfd, buff.data, buff.size);
}
Ejemplo n.º 15
0
/*
  sockfdp is a pointer to an established stream or CURL_SOCKET_BAD

  if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must
  accept()
*/
static int juggle(curl_socket_t *sockfdp,
                  curl_socket_t listenfd,
                  enum sockmode *mode)
{
  struct timeval timeout;
  fd_set fds_read;
  fd_set fds_write;
  fd_set fds_err;
  curl_socket_t sockfd;
  curl_socket_t maxfd;
  ssize_t rc;
  ssize_t nread_stdin;
  ssize_t nread_socket;
  ssize_t bytes_written;
  ssize_t buffer_len;
  unsigned char buffer[256]; /* FIX: bigger buffer */
  char data[256];

  timeout.tv_sec = 120;
  timeout.tv_usec = 0;

  FD_ZERO(&fds_read);
  FD_ZERO(&fds_write);
  FD_ZERO(&fds_err);

  FD_SET(fileno(stdin), &fds_read);

  switch(*mode) {

  case PASSIVE_LISTEN:

    /* server mode */
    sockfd = listenfd;
    /* there's always a socket to wait for */
    FD_SET(sockfd, &fds_read);
    maxfd = sockfd;
    break;

  case PASSIVE_CONNECT:

    sockfd = *sockfdp;
    if(CURL_SOCKET_BAD == sockfd) {
      /* eeek, we are supposedly connected and then this cannot be -1 ! */
      logmsg("socket is -1! on %s:%d", __FILE__, __LINE__);
      maxfd = 0; /* stdin */
    }
    else {
      /* there's always a socket to wait for */
      FD_SET(sockfd, &fds_read);
      maxfd = sockfd;
    }
    break;

  case ACTIVE:

    sockfd = *sockfdp;
    /* sockfd turns CURL_SOCKET_BAD when our connection has been closed */
    if(CURL_SOCKET_BAD != sockfd) {
      FD_SET(sockfd, &fds_read);
      maxfd = sockfd;
    }
    else {
      logmsg("No socket to read on");
      maxfd = 0;
    }
    break;

  case ACTIVE_DISCONNECT:

    logmsg("disconnected, no socket to read on");
    maxfd = 0;
    sockfd = CURL_SOCKET_BAD;
    break;

  } /* switch(*mode) */

  do {
    rc = select(maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
  } while((rc == -1) && (SOCKERRNO == EINTR));

  switch(rc) {
  case -1:
    return FALSE;

  case 0: /* timeout! */
    return TRUE;
  }


  if(FD_ISSET(fileno(stdin), &fds_read)) {
    /* read from stdin, commands/data to be dealt with and possibly passed on
       to the socket

       protocol:

       4 letter command + LF [mandatory]

       4-digit hexadecimal data length + LF [if the command takes data]
       data                       [the data being as long as set above]

       Commands:

       DATA - plain pass-thru data
    */
    nread_stdin = read(fileno(stdin), buffer, 5);
    if(5 == nread_stdin) {

      logmsg("Received %c%c%c%c (on stdin)",
             buffer[0], buffer[1], buffer[2], buffer[3] );

      if(!memcmp("PING", buffer, 4)) {
        /* send reply on stdout, just proving we are alive */
        write(fileno(stdout), "PONG\n", 5);
      }

      else if(!memcmp("PORT", buffer, 4)) {
        /* Question asking us what PORT number we are listening to.
           Replies to PORT with "IPv[num]/[port]" */
        sprintf((char *)buffer, "IPv%d/%d\n", use_ipv6?6:4, (int)port);
        buffer_len = (ssize_t)strlen((char *)buffer);
        sprintf(data, "PORT\n%04x\n", buffer_len);
        write(fileno(stdout), data, 10);
        write(fileno(stdout), buffer, buffer_len);
      }
      else if(!memcmp("QUIT", buffer, 4)) {
        /* just die */
        logmsg("quits");
        return FALSE;
      }
      else if(!memcmp("DATA", buffer, 4)) {
        /* data IN => data OUT */

        if(5 != read(fileno(stdin), buffer, 5))
          return FALSE;
        buffer[5] = '\0';

        buffer_len = (ssize_t)strtol((char *)buffer, NULL, 16);
        if (buffer_len > (ssize_t)sizeof(buffer)) {
          logmsg("Buffer size %d too small for data size %d", 
                   (int)sizeof(buffer), buffer_len);
          return FALSE;
        }
        nread_stdin = read(fileno(stdin), buffer, buffer_len);
        if(nread_stdin != buffer_len)
          return FALSE;

        logmsg("> %d bytes data, server => client", buffer_len);
        lograw(buffer, buffer_len);

        if(*mode == PASSIVE_LISTEN) {
          logmsg("*** We are disconnected!");
          write(fileno(stdout), "DISC\n", 5);
        }
        else {
          /* send away on the socket */
          bytes_written = swrite(sockfd, buffer, buffer_len);
          if(bytes_written != buffer_len) {
            logmsg("Not all data was sent. Bytes to send: %d sent: %d", 
                   buffer_len, bytes_written);
          }
        }
      }
      else if(!memcmp("DISC", buffer, 4)) {
        /* disconnect! */
        write(fileno(stdout), "DISC\n", 5);
        if(sockfd != CURL_SOCKET_BAD) {
          logmsg("====> Client forcibly disconnected");
          sclose(sockfd);
          *sockfdp = CURL_SOCKET_BAD;
          if(*mode == PASSIVE_CONNECT)
            *mode = PASSIVE_LISTEN;
          else
            *mode = ACTIVE_DISCONNECT;
        }
        else
          logmsg("attempt to close already dead connection");
        return TRUE;
      }
    }
    else if(-1 == nread_stdin) {
      logmsg("read %d from stdin, exiting", nread_stdin);
      return FALSE;
    }
  }


  if((sockfd != CURL_SOCKET_BAD) && (FD_ISSET(sockfd, &fds_read)) ) {

    if(*mode == PASSIVE_LISTEN) {
      /* there's no stream set up yet, this is an indication that there's a
         client connecting. */
      sockfd = accept(sockfd, NULL, NULL);
      if(CURL_SOCKET_BAD == sockfd)
        logmsg("accept() failed");
      else {
        logmsg("====> Client connect");
        write(fileno(stdout), "CNCT\n", 5);
        *sockfdp = sockfd; /* store the new socket */
        *mode = PASSIVE_CONNECT; /* we have connected */
      }
      return TRUE;
    }

    /* read from socket, pass on data to stdout */
    nread_socket = sread(sockfd, buffer, sizeof(buffer));

    if(nread_socket <= 0) {
      logmsg("====> Client disconnect");
      write(fileno(stdout), "DISC\n", 5);
      sclose(sockfd);
      *sockfdp = CURL_SOCKET_BAD;
      if(*mode == PASSIVE_CONNECT)
        *mode = PASSIVE_LISTEN;
      else
        *mode = ACTIVE_DISCONNECT;
      return TRUE;
    }

    sprintf(data, "DATA\n%04x\n", nread_socket);
    write(fileno(stdout), data, 10);
    write(fileno(stdout), buffer, nread_socket);

    logmsg("< %d bytes data, client => server", nread_socket);
    lograw(buffer, nread_socket);
  }

  return TRUE;
}
Ejemplo n.º 16
0
static CURLcode ntlm_wb_response(struct connectdata *conn,
                                 const char *input, curlntlm state)
{
  char *buf = malloc(NTLM_BUFSIZE);
  size_t len_in = strlen(input), len_out = 0;

  if(!buf)
    return CURLE_OUT_OF_MEMORY;

  while(len_in > 0) {
    ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
    if(written == -1) {
      /* Interrupted by a signal, retry it */
      if(errno == EINTR)
        continue;
      /* write failed if other errors happen */
      goto done;
    }
    input += written;
    len_in -= written;
  }
  /* Read one line */
  while(1) {
    ssize_t size;
    char *newbuf;

    size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
    if(size == -1) {
      if(errno == EINTR)
        continue;
      goto done;
    }
    else if(size == 0)
      goto done;

    len_out += size;
    if(buf[len_out - 1] == '\n') {
      buf[len_out - 1] = '\0';
      break;
    }
    newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
    if(!newbuf) {
      free(buf);
      return CURLE_OUT_OF_MEMORY;
    }
    buf = newbuf;
  }

  /* Samba/winbind installed but not configured */
  if(state == NTLMSTATE_TYPE1 &&
     len_out == 3 &&
     buf[0] == 'P' && buf[1] == 'W')
    goto done;
  /* invalid response */
  if(len_out < 4)
    goto done;
  if(state == NTLMSTATE_TYPE1 &&
     (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
    goto done;
  if(state == NTLMSTATE_TYPE2 &&
     (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') &&
     (buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
    goto done;

  conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
  free(buf);
  return CURLE_OK;
done:
  free(buf);
  return CURLE_REMOTE_ACCESS_DENIED;
}
Ejemplo n.º 17
0
Archivo: rtspd.c Proyecto: 2px/curl
/* returns -1 on failure */
static int send_doc(curl_socket_t sock, struct httprequest *req)
{
  ssize_t written;
  size_t count;
  const char *buffer;
  char *ptr=NULL;
  FILE *stream;
  char *cmd=NULL;
  size_t cmdsize=0;
  FILE *dump;
  bool persistant = TRUE;
  bool sendfailure = FALSE;
  size_t responsesize;
  int error = 0;
  int res;

  static char weare[256];

  char partbuf[80]="data";

  logmsg("Send response number %ld part %ld", req->testno, req->partno);

  switch(req->rcmd) {
  default:
  case RCMD_NORMALREQ:
    break; /* continue with business as usual */
  case RCMD_STREAM:
#define STREAMTHIS "a string to stream 01234567890\n"
    count = strlen(STREAMTHIS);
    for(;;) {
      written = swrite(sock, STREAMTHIS, count);
      if(got_exit_signal)
        return -1;
      if(written != (ssize_t)count) {
        logmsg("Stopped streaming");
        break;
      }
    }
    return -1;
  case RCMD_IDLE:
    /* Do nothing. Sit idle. Pretend it rains. */
    return 0;
  }

  req->open = FALSE;

  if(req->testno < 0) {
    size_t msglen;
    char msgbuf[64];

    switch(req->testno) {
    case DOCNUMBER_QUIT:
      logmsg("Replying to QUIT");
      buffer = docquit;
      break;
    case DOCNUMBER_WERULEZ:
      /* we got a "friends?" question, reply back that we sure are */
      logmsg("Identifying ourselves as friends");
      snprintf(msgbuf, sizeof(msgbuf), "RTSP_SERVER WE ROOLZ: %ld\r\n",
               (long)getpid());
      msglen = strlen(msgbuf);
      snprintf(weare, sizeof(weare),
               "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
               msglen, msgbuf);
      buffer = weare;
      break;
    case DOCNUMBER_INTERNAL:
      logmsg("Bailing out due to internal error");
      return -1;
    case DOCNUMBER_CONNECT:
      logmsg("Replying to CONNECT");
      buffer = docconnect;
      break;
    case DOCNUMBER_BADCONNECT:
      logmsg("Replying to a bad CONNECT");
      buffer = docbadconnect;
      break;
    case DOCNUMBER_404:
    default:
      logmsg("Replying to with a 404");
      if(req->protocol == RPROT_HTTP) {
        buffer = doc404_HTTP;
      }
      else {
        buffer = doc404_RTSP;
      }
      break;
    }

    count = strlen(buffer);
  }
  else {
    char *filename = test2file(req->testno);

    if(0 != req->partno)
      snprintf(partbuf, sizeof(partbuf), "data%ld", req->partno);

    stream=fopen(filename, "rb");
    if(!stream) {
      error = errno;
      logmsg("fopen() failed with error: %d %s", error, strerror(error));
      logmsg("Error opening file: %s", filename);
      logmsg("Couldn't open test file");
      return 0;
    }
    else {
      error = getpart(&ptr, &count, "reply", partbuf, stream);
      fclose(stream);
      if(error) {
        logmsg("getpart() failed with error: %d", error);
        return 0;
      }
      buffer = ptr;
    }

    if(got_exit_signal) {
      free(ptr);
      return -1;
    }

    /* re-open the same file again */
    stream=fopen(filename, "rb");
    if(!stream) {
      error = errno;
      logmsg("fopen() failed with error: %d %s", error, strerror(error));
      logmsg("Error opening file: %s", filename);
      logmsg("Couldn't open test file");
      free(ptr);
      return 0;
    }
    else {
      /* get the custom server control "commands" */
      error = getpart(&cmd, &cmdsize, "reply", "postcmd", stream);
      fclose(stream);
      if(error) {
        logmsg("getpart() failed with error: %d", error);
        free(ptr);
        return 0;
      }
    }
  }

  if(got_exit_signal) {
    free(ptr);
    free(cmd);
    return -1;
  }

  /* If the word 'swsclose' is present anywhere in the reply chunk, the
     connection will be closed after the data has been sent to the requesting
     client... */
  if(strstr(buffer, "swsclose") || !count) {
    persistant = FALSE;
    logmsg("connection close instruction \"swsclose\" found in response");
  }
  if(strstr(buffer, "swsbounce")) {
    prevbounce = TRUE;
    logmsg("enable \"swsbounce\" in the next request");
  }
  else
    prevbounce = FALSE;

  dump = fopen(RESPONSE_DUMP, "ab");
  if(!dump) {
    error = errno;
    logmsg("fopen() failed with error: %d %s", error, strerror(error));
    logmsg("Error opening file: %s", RESPONSE_DUMP);
    logmsg("couldn't create logfile: " RESPONSE_DUMP);
    free(ptr);
    free(cmd);
    return -1;
  }

  responsesize = count;
  do {
    /* Ok, we send no more than 200 bytes at a time, just to make sure that
       larger chunks are split up so that the client will need to do multiple
       recv() calls to get it and thus we exercise that code better */
    size_t num = count;
    if(num > 200)
      num = 200;
    written = swrite(sock, buffer, num);
    if(written < 0) {
      sendfailure = TRUE;
      break;
    }
    else {
      logmsg("Sent off %zd bytes", written);
    }
    /* write to file as well */
    fwrite(buffer, 1, (size_t)written, dump);
    if(got_exit_signal)
      break;

    count -= written;
    buffer += written;
  } while(count>0);

  /* Send out any RTP data */
  if(req->rtp_buffer) {
    logmsg("About to write %zu RTP bytes", req->rtp_buffersize);
    count = req->rtp_buffersize;
    do {
      size_t num = count;
      if(num > 200)
        num = 200;
      written = swrite(sock, req->rtp_buffer + (req->rtp_buffersize - count),
                       num);
      if(written < 0) {
        sendfailure = TRUE;
        break;
      }
      count -= written;
    } while(count > 0);

    free(req->rtp_buffer);
    req->rtp_buffersize = 0;
  }

  do {
    res = fclose(dump);
  } while(res && ((error = errno) == EINTR));
  if(res)
    logmsg("Error closing file %s error: %d %s",
           RESPONSE_DUMP, error, strerror(error));

  if(got_exit_signal) {
    free(ptr);
    free(cmd);
    return -1;
  }

  if(sendfailure) {
    logmsg("Sending response failed. Only (%zu bytes) of "
           "(%zu bytes) were sent",
           responsesize-count, responsesize);
    free(ptr);
    free(cmd);
    return -1;
  }

  logmsg("Response sent (%zu bytes) and written to " RESPONSE_DUMP,
         responsesize);
  free(ptr);

  if(cmdsize > 0) {
    char command[32];
    int quarters;
    int num;
    ptr=cmd;
    do {
      if(2 == sscanf(ptr, "%31s %d", command, &num)) {
        if(!strcmp("wait", command)) {
          logmsg("Told to sleep for %d seconds", num);
          quarters = num * 4;
          while(quarters > 0) {
            quarters--;
            res = wait_ms(250);
            if(got_exit_signal)
              break;
            if(res) {
              /* should not happen */
              error = errno;
              logmsg("wait_ms() failed with error: (%d) %s",
                     error, strerror(error));
              break;
            }
          }
          if(!quarters)
            logmsg("Continuing after sleeping %d seconds", num);
        }
        else
          logmsg("Unknown command in reply command section");
      }
      ptr = strchr(ptr, '\n');
      if(ptr)
        ptr++;
      else
        ptr = NULL;
    } while(ptr && *ptr);
  }
  free(cmd);
  req->open = persistant;

  prevtestno = req->testno;
  prevpartno = req->partno;

  return 0;
}