Пример #1
0
/* Send req and get response */
int http_transaction(http_t *client, http_trans_t *trans)
{
	int rc = 0;

	ASSERT(client);
	ASSERT(trans);

	if (!client->initialized)
		return RC_HTTP_OBJECT_NOT_INITIALIZED;

	trans->rsp_len = 0;
	do {
#ifdef ENABLE_SSL
		if (client->ssl_enabled) {
			TRY(ssl_send(client, trans->p_req, trans->req_len));
			TRY(ssl_recv(client, trans->p_rsp, trans->max_rsp_len, &trans->rsp_len));
		}
		else
#endif
		{
			TRY(tcp_send(&client->tcp, trans->p_req, trans->req_len));
			TRY(tcp_recv(&client->tcp, trans->p_rsp, trans->max_rsp_len, &trans->rsp_len));
		}
	}
	while (0);

	trans->p_rsp[trans->rsp_len] = 0;
	http_response_parse(trans);

	return rc;
}
Пример #2
0
/*
 * Send data in buf to the socket in socket_fd.
 * Return value:
 *   Returns the number of bytes sent, or -1 on failure.
 */
size_t
socket_send(struct socket_in *s, const char *buf)
{
	size_t bytes = 0;
	
#ifdef OPENSSL_ENABLED
	if(s->ssl != NULL)
		bytes = ssl_send(s, buf);
	
	else
#endif /* OPENSSL_ENABLED */
	
	{
		int temp_bytes;
		size_t len = strlen(buf);
		do
		{
			if((temp_bytes = send(s->fd, buf+bytes, len-bytes, 0)) == -1)
				return -1;
			bytes += temp_bytes;
		}
		while(bytes < len);
	}
	
	return(bytes);
}
Пример #3
0
/*
** Send content over the wire.
*/
void transport_send(Blob *toSend){
  char *z = blob_buffer(toSend);
  int n = blob_size(toSend);
  transport.nSent += n;
  if( g.urlIsSsh ){
    int sent;
    sent = fwrite(z, 1, n, sshOut);
    fflush(sshOut);
    /* printf("sent %d of %d bytes\n", sent, n); fflush(stdout); */
  }else if( g.urlIsHttps ){
    #ifdef FOSSIL_ENABLE_SSL
    int sent;
    while( n>0 ){
      sent = ssl_send(0, z, n);
      /* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */
      if( sent<=0 ) break;
      n -= sent;
    }    
    #endif
  }else if( g.urlIsFile ){
    fwrite(z, 1, n, transport.pFile);
  }else{
    int sent;
    while( n>0 ){
      sent = socket_send(0, z, n);
      /* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */
      if( sent<=0 ) break;
      n -= sent;
    }
  }
}
Пример #4
0
/*
 * Sends AES-CBC-128 bit encrypted file to the receiver
 * SSL *conn                -> The SSL connection of the recipient
 * const char *fname        -> The name of the file to send
 * const unsigned char *key -> The already instantiated AES Key for decryption
 * const unsigned char *iv  -> The initialization vector for CBC that was
 *                             received from the sender
 * returns the total amount of bytes sent and encrypted
 */
ssize_t crypto_send_file(SSL *conn, const char *fname, const unsigned char *key,
                         const unsigned char *iv)
{
    int len, ciph_len=0, first=0;
    ssize_t total = 0;
    unsigned char plaintxt[BUFFSIZE];
    unsigned char ciphtxt[BUFFSIZE];
    FILE *file;
    if((file = fopen(fname, "rb")) == nullptr) return FILE_NOT_FOUND;

    EVP_CIPHER_CTX cntx;
    EVP_CipherInit(&cntx, EVP_aes_128_cbc(), key, iv, ENCRYPT);
    memcpy(plaintxt, iv, IV_LEN);
    while ((len = (int)fread(plaintxt+(first?0:16), sizeof(char),
                             sizeof(ciphtxt)-(first?0:16)-1, file)) > 0) {
        EVP_CipherUpdate(&cntx, ciphtxt+1,&ciph_len,plaintxt,len+(first?0:16));
        ssl_send(conn, (char *)ciphtxt, (size_t)ciph_len+1);
        /* Last transmission of the file */
        if(len < BUFFSIZE-1) {
            if(!first && len < BUFFSIZE-16-1) break;
        }
        first++;
    }
    ERRCHK(len, ==, -1, "send() failed");
    EVP_CipherFinal(&cntx, ciphtxt+1, &ciph_len);
    ssl_send(conn, (char *)ciphtxt, (size_t)ciph_len+1);
    SENDFIN(conn);
    ERRCHK(len, ==, -1, "send() failed");
    EVP_CIPHER_CTX_cleanup(&cntx);
    fclose(file);
    return total;

    seterrhandle(err);
    EVP_CIPHER_CTX_cleanup(&cntx);
    die_with_err(errmsg);
    return 1;
}
Пример #5
0
/*
 * Sends Plain Text file to the receiver
 * SSL *conn                -> The SSL connection of the recipient
 * const char *fname        -> The name of the file to send
 * returns the total amount of bytes sent and encrypted
 */
ssize_t ssl_send_file(SSL *conn, const char *fname)
{
    ssize_t len, total = 0;
    unsigned char buf[BUFFSIZE];
    buf[0] = 'T';
    FILE *file;
    if((file = fopen(fname, "rb")) == nullptr) return FILE_NOT_FOUND;
    while ((len = (int)fread(buf+1, sizeof(char), sizeof(buf)-1, file)) > 0) {
        total += (len = ssl_send(conn, (char *)buf, (size_t)len+1))-1;
        if (len < 0) break;
    }
    SENDACK(conn);
    fclose(file);
    if(len < 0) {
        perror("ssl_send() failed");
        return -1;
    }
    return total;
}
Пример #6
0
static ssize_t ssl_stream_file(IOBuf *iob, int fd, off_t len)
{
    ssize_t sent = 0;
    off_t total = 0;
    ssize_t amt = 0;
    ssize_t tosend = 0;
    int conn_fd = IOBuf_fd(iob);
    char buff[1024];

    for(total = 0; fdwait(conn_fd, 'w') == 0 && total < len; total += tosend) {
        tosend = pread(fd, buff, sizeof(buff), total);
        check_debug(tosend > 0, "Came up short in reading file %d\n", fd);

        // We do this in case the file somehow lengthened on us.  In general,
        // it shouldn't happen.
        if(tosend + total > len)
            tosend = len - total;

        sent = 0;
        while(sent < tosend) {
            amt = ssl_send(iob, buff, tosend);
            check_debug(amt > 0, "ssl_send failed in ssl_stream_file with "
                        "return code %zd", amt);
            sent += amt;
        }

        check(Register_write(iob->fd, sent) != -1, "Failed to record write, must have died.");
    }
    
    check(total <= len,
            "Wrote way too much, wrote %d but size was %zd",
            (int)total, len);

    check(total == len,
            "Sent other than expected, sent: %d, but expected: %zd", 
            (int)total, len);

    return total;

error:
    return -1;
}
Пример #7
0
/* Send req and get response */
int http_transaction(http_t *client, http_trans_t *trans)
{
	int rc = 0;

	ASSERT(client);
	ASSERT(trans);

	if (!client->initialized)
		return RC_HTTP_OBJECT_NOT_INITIALIZED;

	trans->rsp_len = 0;
	do {
		TRY(ssl_send(client, trans->req, trans->req_len));
		TRY(ssl_recv(client, trans->rsp, trans->max_rsp_len, &trans->rsp_len));
	}
	while (0);

	trans->rsp[trans->rsp_len] = 0;
	http_response_parse(trans);

	return rc;
}
Пример #8
0
/**
    Send a char buffer to the client. Traffic throttling is handled here.
*/
static int send_to_client(t_session *session, const char *buffer, int size) {
    /* HELP!! No socket open. */
    if (session->socket_open == false) {
        return -1;
    } else if ((buffer == NULL) || (size <= 0)) {
        return 0;
    }

    int bytes_sent = 0, total_sent = 0, can_send, rest;
    time_t new_time;

    if (session->directory != NULL) {
        if (session->directory->session_speed > 0) {
            session->throttle = session->directory->session_speed;
        }
    }

    do {
        rest = size - total_sent;
        if (session->throttle > 0) {
            do {
                new_time = time(NULL);
                if (session->throttle_timer < new_time) {
                    session->bytecounter = 0;
                    session->throttle_timer = new_time;
                }
                can_send = session->throttle - session->bytecounter;
                if (can_send <= 0) {
                    usleep(10000);
                }
            } while (can_send <= 0);
            if (can_send > rest) {
                can_send = rest;
            }
        } else {
            can_send = rest;
        }

#ifdef HAVE_SSL
        if (session->binding->use_ssl) {
            if ((bytes_sent = ssl_send(session->ssl_data, (char*)(buffer + total_sent), can_send)) <= 0) {
                bytes_sent = -1;
            }
        } else
#endif
            if ((bytes_sent = send(session->client_socket, (char*)(buffer + total_sent), can_send, 0)) <= 0) {
                bytes_sent = -1;
            }

        /* Handle read result */
        if (bytes_sent == -1) {
            if (errno != EINTR) {
                if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                    log_error(session, "send timeout");
                } else if ((errno != EPIPE) && (errno != ECONNRESET)) {
                    log_error(session, "socket error");
                }
                close_socket(session);
                session->keep_alive = false;
                return -1;
            }
        } else {
            total_sent += bytes_sent;
            session->bytecounter += bytes_sent;
        }
    } while (total_sent < size);

    return 0;
}
Пример #9
0
void cmd (void) 
{
  SECURITY_ATTRIBUTES sa;
  PROCESS_INFORMATION pi;
  STARTUPINFO         si;
  OVERLAPPED          lap;
  
  HANDLE              in[2], out[2];
  DWORD               p, e;
  
  sa.nLength              = sizeof (SECURITY_ATTRIBUTES);
  sa.lpSecurityDescriptor = NULL;
  sa.bInheritHandle       = TRUE;
  
  evt[stdout_evt = evt_cnt++] = CreateEvent (NULL, TRUE, TRUE, NULL);
  
  if (CreatePipe (&in[R_PIPE], &in[W_PIPE], &sa, 0)) 
  {  
    out[R_PIPE] = CreateNamedPipe ("\\\\.\\pipe\\0", 
        PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
        PIPE_TYPE_BYTE      | PIPE_READMODE_BYTE | PIPE_WAIT, 
        PIPE_UNLIMITED_INSTANCES, 0, 0, 0, &sa);
        
    if (out[R_PIPE] != INVALID_HANDLE_VALUE) 
    {  
      out[W_PIPE] = CreateFile ("\\\\.\\pipe\\0", GENERIC_WRITE, 
          0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
      
      if (out[W_PIPE] != INVALID_HANDLE_VALUE) 
      {
        ZeroMemory (&si, sizeof (si));
        ZeroMemory (&pi, sizeof (pi));

        SetHandleInformation (in[W_PIPE], HANDLE_FLAG_INHERIT, 0);
        SetHandleInformation (out[R_PIPE], HANDLE_FLAG_INHERIT, 0);
        
        si.cb              = sizeof (si);
        si.hStdInput       = in[R_PIPE];
        si.hStdError       = out[W_PIPE];
        si.hStdOutput      = out[W_PIPE];
        si.dwFlags         = STARTF_USESTDHANDLES;
        
        if (CreateProcess (NULL, "cmd", NULL, NULL, TRUE, 
            CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 
        {
          evt[proc_evt = evt_cnt++] = pi.hProcess;
          
          ZeroMemory (&lap, sizeof (lap));       
          lap.hEvent = evt[stdout_evt];
          
          p=0;
          
          do 
          {
            e=wait_evt();

            if (e==ctrl_evt) {
              printf ("  [ CTRL+C received\n");
              break;
            }
            if (e==proc_evt) {
              printf ("  [ cmd.exe terminated\n");
              break;
            }
            
            if (e == -1) break;

            // is this socket event?
            if (e == sck_evt) 
            {
              if (ReadDecrypt () != SEC_E_OK) 
                break;
              
              WriteFile (in[W_PIPE], pbDataIn, cbDataIn, &cbDataIn, 0);
              p--;  // we're ready to read again.              
            } else
           
            // data from cmd.exe?
            if (e == stdout_evt) 
            {
              if (p==0)  // still waiting for previous read to complete?
              {
                if (!ReadFile (out[R_PIPE], pbDataOut, cbBufferLen, &cbDataOut, &lap))
                {
                  if (GetLastError() != ERROR_IO_PENDING)
                  {
                    // problem...
                    break;
                  } else {
                    p++;
                  }
                } else {
                  p++;
                }
              } else {
                if (!GetOverlappedResult (out[R_PIPE], &lap, &cbDataOut, FALSE)) {
                  // problem...
                  break;
                }
                if (cbDataOut != 0)
                {
                  if (ssl_send() != SEC_E_OK) 
                    break;
                  p--;
                }
              }
            }
          } while (1);
          
          TerminateProcess (pi.hProcess, 0);
          
          CloseHandle (pi.hThread);
          CloseHandle (pi.hProcess);
          evt_cnt--;
        }
        CloseHandle (out[W_PIPE]);
      }
      CloseHandle (out[R_PIPE]);
    }
    CloseHandle (in[W_PIPE]);
    CloseHandle (in[R_PIPE]);
  }
  CloseHandle (evt[stdout_evt]);
  evt_cnt--;
}
Пример #10
0
static      time_t
check_pings(time_t currenttime)
{
aClient 	*cptr;
aConfItem 	*aconf = (aConfItem *) NULL;
int     	 killflag, zkillflag, ping = 0, i;
time_t      	 oldest = 0; /* timeout removed, see EXPLANATION below */
char       	*reason, *ktype, fbuf[512];
char 		*errtxt = "No response from %s, closing link";


   for (i = 0; i <= highest_fd; i++) 
   {
      if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr))
	 continue;

       /* Note: No need to notify opers here. It's 
	* already done when "FLAGS_DEADSOCKET" is set.
        */

      if (cptr->flags & FLAGS_DEADSOCKET) 
      {
	 (void) exit_client(cptr, cptr, &me, (cptr->flags & FLAGS_SENDQEX) ?
			    "SendQ exceeded" : "Dead socket");
	 i--;
	 continue;
      }

      killflag = NO;
      zkillflag = NO;

      if (rehashed) 
      {
	 if (zline_in_progress) 
	 {
	    if (IsPerson(cptr)) 
	    {
	       if ((aconf = find_zkill(cptr)))	
		  zkillflag = YES;
	    }
	 }
	 else 
	 {
	    if(IsPerson(cptr)) 
	    {
	       if((aconf = find_kill(cptr)))	
		  killflag = YES;	
	    }
	 }
      }

      /* Added a bit of code here to differentiate 
       * between K and Z-lines. -ThemBones
       */

      if (zkillflag || killflag)
      {
         ktype = zkillflag ? "Z-lined" : 
            ((aconf->status == CONF_KILL) ? "K-lined" : "Autokilled");

	 if (killflag) 
         {
	    sendto_ops("%s active for %s",
                       (aconf->status == CONF_KILL) ? "K-line" : "Autokill",
		       get_client_name(cptr, FALSE));
	    reason = aconf->passwd ? aconf->passwd : ktype;
	 }
	 else 
         {			/* its a Z line */
	    sendto_ops("Z-line active for %s",
		       get_client_name(cptr, FALSE));
	    reason = aconf->passwd ? aconf->passwd : "Z-lined";
	 }

	 sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP),
		    me.name, cptr->name, ktype);

         ircsprintf(fbuf, "%s: %s", ktype, reason);
	 (void) exit_client(cptr, cptr, &me, fbuf);
	 i--;			/* subtract out this fd so we check it again.. */			
	 continue;
      }

      if (IsRegistered(cptr))
	 ping = cptr->pingval;
      else
	 ping = CONNECTTIMEOUT;

      /*
       * Ok, so goto's are ugly and can be avoided here but this code
       * is already indented enough so I think its justified. -avalon
       *
       * justified by what? laziness? <g>
       * If the client pingtime is fine (ie, not larger than the client ping) 
       * skip over all the checks below. - lucas
       */

      if (ping < (currenttime - cptr->lasttime))
      {
         /*
          * If the server hasnt talked to us in 2*ping seconds and it has
          * a ping time, then close its connection. If the client is a
          * user and a KILL line was found to be active, close this
          * connection too.
          */
         if (((cptr->flags & FLAGS_PINGSENT) && ((currenttime - cptr->lasttime) >= (2 * ping))) ||
             ((!IsRegistered(cptr) && (currenttime - cptr->since) >= ping))) 
         {
	    if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr))) 
            {
	       if (cptr->authfd >= 0) 
	       {
	          (void) close(cptr->authfd);
	          cptr->authfd = -1;
	          cptr->count = 0;
	          *cptr->buffer = '\0';
	       }
#ifdef SHOW_HEADERS
	       if (DoingDNS(cptr))
	          ssl_send(cptr, REPORT_FAIL_DNS, R_fail_dns, 0);
	       if (DoingAuth(cptr))
	          ssl_send(cptr, REPORT_FAIL_ID, R_fail_id, 0);
#endif
	       Debug((DEBUG_NOTICE, "DNS/AUTH timeout %s",
	 	      get_client_name(cptr, TRUE)));
	       del_queries((char *) cptr);
	       ClearAuth(cptr);
	       ClearDNS(cptr);
	       SetAccess(cptr);
	       cptr->since = currenttime;
	       continue;
	    }

	    if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr)) 
	    {
	       ircsprintf(fbuf, "from %s: %s", me.name, errtxt);
	       sendto_gnotice(fbuf, get_client_name(cptr, HIDEME));
	       ircsprintf(fbuf, ":%s GNOTICE :%s", me.name, errtxt);                                
	       sendto_serv_butone(cptr, fbuf, get_client_name(cptr, HIDEME));
	    }

	    (void) exit_client(cptr, cptr, &me, "Ping timeout");
	    i--;			/* subtract out this fd so we check it again.. */			
	    continue;
         } /* don't send pings during a burst, as we send them already. */

         else if (!(cptr->flags & (FLAGS_PINGSENT|FLAGS_BURST))) {
	    /*
	     * if we havent PINGed the connection and we havent heard from
	     * it in a while, PING it to make sure it is still alive.
	     */
	    cptr->flags |= FLAGS_PINGSENT;
	    /*
	     * not nice but does the job 
	     */
	    cptr->lasttime = currenttime - ping;
	    sendto_one(cptr, "PING :%s", me.name);
         }
      }

      /* see EXPLANATION below
       *
       * timeout = cptr->lasttime + ping;
       * while (timeout <= currenttime)
       *  timeout += ping;
       * if (timeout < oldest || !oldest)
       *   oldest = timeout;
       */

      /*
       * Check UNKNOWN connections - if they have been in this state
       * for > 100s, close them.
       */
      if (IsUnknown(cptr))
	 if (cptr->firsttime ? ((timeofday - cptr->firsttime) > 100) : 0) 
	    (void) exit_client(cptr, cptr, &me, "Connection Timed Out");
   }

   rehashed = 0;
   zline_in_progress = 0;

   /* EXPLANATION
    * on a server with a large volume of clients, at any given point
    * there may be a client which needs to be pinged the next second,
    * or even right away (a second may have passed while running
    * check_pings). Preserving CPU time is more important than
    * pinging clients out at exact times, IMO. Therefore, I am going to make
    * check_pings always return currenttime + 9. This means that it may take
    * a user up to 9 seconds more than pingfreq to timeout. Oh well.
    * Plus, the number is 9 to 'stagger' our check_pings calls out over
    * time, to avoid doing it and the other tasks ircd does at the same time
    * all the time (which are usually done on intervals of 5 seconds or so). 
    * - lucas
    *
    *  if (!oldest || oldest < currenttime)
    *     oldest = currenttime + PINGFREQUENCY;
    */

   oldest = currenttime + 9;

   Debug((DEBUG_NOTICE, "Next check_ping() call at: %s, %d %d %d",
	  myctime(oldest), ping, oldest, currenttime));

   return oldest;
}
Пример #11
0
/* Send a char buffer to the client. Traffic throttling is handled here.
 */
static int send_to_client(t_session *session, const char *buffer, int size) {
	int bytes_sent = 0, total_sent = 0, can_send, rest;
	time_t new_time;

	/* Send buffer to browser.
	 */
	if (session->socket_open == false) {
		return -1;
	} else if ((buffer == NULL) || (size <= 0)) {
		return 0;
	}

	if (session->directory != NULL) {
		if (session->directory->session_speed > 0) {
			session->throttle = session->directory->session_speed;
		}
	}

	do {
		rest = size - total_sent;
		if (session->throttle > 0) {
			do {
				new_time = time(NULL);
				if (session->throttle_timer < new_time) {
					session->bytecounter = 0;
					session->throttle_timer = new_time;
				}
				can_send = session->throttle - session->bytecounter;
				if (can_send <= 0) {
					usleep(10000);
				}
			} while (can_send <= 0);
			if (can_send > rest) {
				can_send = rest;
			}
		} else {
			can_send = rest;
		}

#ifdef ENABLE_SSL
		if (session->binding->use_ssl) {
			if ((bytes_sent = ssl_send(&(session->ssl_context), (char*)(buffer + total_sent), can_send)) <= 0) {
				bytes_sent = -1;
			}
		} else
#endif
			if ((bytes_sent = send(session->client_socket, (char*)(buffer + total_sent), can_send, 0)) <= 0) {
				bytes_sent = -1;
			}

		/* Handle read result
		 */
		if (bytes_sent == -1) {
			if (errno != EINTR) {
				if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
					log_error(session, "send timeout");
				} else if ((errno != EPIPE) && (errno != ECONNRESET)) {
					log_error(session, "error while sending response");
				}
				close_socket(session);
				session->keep_alive = false;
				session->error_cause = ec_SOCKET_WRITE_ERROR;
				return -1;
			}
		} else {
			total_sent += bytes_sent;
			session->bytecounter += bytes_sent;
		}
	} while (total_sent < size);
#ifdef ENABLE_TOMAHAWK
	increment_transfer(TRANSFER_SEND, total_sent);
#endif

	return 0;
}