示例#1
0
/*
 * Callback for when data is available on the standard output handle of
 * a process channel that is interactive mode
 */
DWORD process_channel_interact_notify(Remote *remote, Channel *channel)
{

	ProcessChannelContext *ctx = (ProcessChannelContext *)channel->ops.stream.native.context;
	DWORD bytesRead, bytesAvail = 0;
	CHAR buffer[16384];
	DWORD result = ERROR_SUCCESS;

#ifdef _WIN32
	if( PeekNamedPipe( ctx->pStdout, NULL, 0, NULL, &bytesAvail, NULL ) )
	{
		if( bytesAvail )
		{
			if( ReadFile( ctx->pStdout, buffer, sizeof(buffer) - 1, &bytesRead, NULL ) )
			{
				return channel_write( channel, remote, NULL, 0, buffer, bytesRead, NULL );
			}
		}
		else
		{
			// sf: if no data is available on the pipe we sleep to avoid running a tight loop
			// in this thread, as anonymous pipes won't block for data to arrive.
			Sleep( 100 );
		}
	}
#else
	bytesRead = read ( ctx->pStdout, buffer, sizeof(buffer) - 1);

	if ( bytesRead > 0 ) 

	{
		dprintf("bytesRead: %d, errno: %d", bytesRead, errno);

		result = channel_write ( channel, remote, NULL, 0, buffer, bytesRead, NULL );
	} 

	if(bytesRead == -1) {
		if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
			errno = ERROR_SUCCESS;
		}
	}

	if(bytesRead == 0) {
		errno = ECONNRESET;
	}

	if(bytesRead <= 0) result = errno;

#endif
	if( GetLastError() != ERROR_SUCCESS )
	{
		dprintf("Closing down socket: errno: %d\n", errno);
		process_channel_close( channel, NULL, ctx );
		channel_close( channel, remote, NULL, 0, NULL );
	}

	return result;
}
示例#2
0
static void remmina_nx_session_send_command(RemminaNXSession *nx, const gchar *cmdfmt, ...)
{
	va_list args;
	gchar *cmd;

	va_start (args, cmdfmt);
	cmd = g_strdup_vprintf (cmdfmt, args);
	channel_write (nx->channel, cmd, strlen (cmd));
	g_free(cmd);

	ssh_set_fd_towrite (nx->session);
	channel_write (nx->channel, "\n", 1);
}
示例#3
0
文件: scp.c 项目: CUEBoxer/OpenStudio
/** @brief creates a directory in a scp in sink mode
 * @param scp the scp handle.
 * @param dirname Name of the directory being created.
 * @param mode  Unix permissions for the new directory, e.g. 0755.
 * @returns SSH_OK if the directory was created.
 * @returns SSH_ERROR if an error happened.
 * @see ssh_scp_leave_directory
 */
int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){
  char buffer[1024];
  int r;
  uint8_t code;
  char *dir;
  char *perms;
  if(scp->state != SSH_SCP_WRITE_INITED){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_directory called under invalid state");
    return SSH_ERROR;
  }
  dir=ssh_basename(dirname);
  perms=ssh_scp_string_mode(mode);
  snprintf(buffer, sizeof(buffer), "D%s 0 %s\n", perms, dir);
  SAFE_FREE(dir);
  SAFE_FREE(perms);
  r=channel_write(scp->channel,buffer,strlen(buffer));
  if(r==SSH_ERROR){
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  r=channel_read(scp->channel,&code,1,0);
  if(code != 0){
    ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  return SSH_OK;
}
示例#4
0
文件: scp.c 项目: CUEBoxer/OpenStudio
/** @brief initializes the sending of a file to a scp in sink mode
 * @param scp the scp handle.
 * @param filename Name of the file being sent. It should not contain any path indicator
 * @param size Exact size in bytes of the file being sent.
 * @param mode Unix permissions for the new file, e.g. 0644
 * @returns SSH_OK if the file is ready to be sent.
 * @returns SSH_ERROR if an error happened.
 */
int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode){
  char buffer[1024];
  int r;
  uint8_t code;
  char *file;
  char *perms;
  if(scp->state != SSH_SCP_WRITE_INITED){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_file called under invalid state");
    return SSH_ERROR;
  }
  file=ssh_basename(filename);
  perms=ssh_scp_string_mode(mode);
  ssh_log(scp->session,SSH_LOG_PROTOCOL,"SCP pushing file %s, size %" PRIdS " with permissions '%s'",file,size,perms);
  snprintf(buffer, sizeof(buffer), "C%s %" PRIdS " %s\n", perms, size, file);
  SAFE_FREE(file);
  SAFE_FREE(perms);
  r=channel_write(scp->channel,buffer,strlen(buffer));
  if(r==SSH_ERROR){
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  r=channel_read(scp->channel,&code,1,0);
  if(code != 0){
    ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  scp->filelen = size;
  scp->processed = 0;
  scp->state=SSH_SCP_WRITE_WRITING;
  return SSH_OK;
}
示例#5
0
static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data)
{
    char buf[BUF_SIZE];
    struct serial_proxy *prx = data;
    GIOChannel *dest;
    GIOError err;
    size_t rbytes;

    if (cond & G_IO_NVAL)
        return FALSE;

    dest = (chan == prx->rfcomm) ? prx->local : prx->rfcomm;

    if (cond & (G_IO_HUP | G_IO_ERR)) {
        /* Try forward remaining data */
        do {
            rbytes = 0;
            err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes);
            if (err != G_IO_ERROR_NONE || rbytes == 0)
                break;

            err = channel_write(dest, buf, rbytes);
        } while (err == G_IO_ERROR_NONE);

        g_io_channel_shutdown(prx->local, TRUE, NULL);
        g_io_channel_unref(prx->local);
        prx->local = NULL;

        g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
        g_io_channel_unref(prx->rfcomm);
        prx->rfcomm = NULL;

        return FALSE;
    }

    rbytes = 0;
    err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes);
    if (err != G_IO_ERROR_NONE)
        return FALSE;

    err = channel_write(dest, buf, rbytes);
    if (err != G_IO_ERROR_NONE)
        return FALSE;

    return TRUE;
}
示例#6
0
int terminal_write(const uchar_t *buf, size_t len)
{
#ifdef ENABLE_SSH
	return channel_write(ssh_chan, buf, len);
#else // ENABLE_SSH
	return file_write(STDIN_FILENO, buf, len);
#endif // ENABLE_SSH

}
示例#7
0
文件: main.c 项目: V-E-O/rdp2tcp
static int ping(time_t *now)
{

	time(now);
	if (!last_ping || (last_ping + RDP2TCP_PING_DELAY - 1 < *now)) {
		last_ping = *now;
		return channel_write(R2TCMD_PING, 0, NULL, 0);
	}

	return 0;
}
示例#8
0
文件: sshclient.cpp 项目: aopui/gnash
int
SSHClient::sshWrite(const std::uint8_t *buf, size_t size)
{
    GNASH_REPORT_FUNCTION;
    
    int ret = channel_write(_channel, buf, size);
    if (ret < 0) {
 	log_error(_("SSH write error was: \"%s\"!"), ssh_get_error(_session));
    }
    return ret;
}
示例#9
0
void *thr_fn(void *id) {
	int i;

	for (i = (uintptr_t) id; i < COUNT; i += THREADS_N) {
		if (channel_write(chan, (char *) &i, sizeof(i)) == -1) {
			perror("channel_write() failed");
			return NULL;
		}
	}

	return NULL;
}
示例#10
0
int
sdb_channel_write(sdb_channel_t *chan, const void *data)
{
	int status;

	if ((! chan) || (! data))
		return -1;

	pthread_mutex_lock(&chan->lock);
	status = channel_write(chan, data);
	pthread_mutex_unlock(&chan->lock);
	return status;
} /* sdb_channel_write */
示例#11
0
文件: sshclient.cpp 项目: aopui/gnash
int 
SSHClient::writeChannel(ssh_channel channel, cygnal::Buffer &buf)
{
//    GNASH_REPORT_FUNCTION;
    int ret = -1;

    if (channel) {
	ret = channel_write(channel, buf.reference(), buf.size());
    } else {
	log_error(_("Can't write to a non-existent channel!"));
    }

    return ret;
}
示例#12
0
文件: scp.c 项目: CUEBoxer/OpenStudio
int ssh_scp_init(ssh_scp scp){
  int r;
  char execbuffer[1024];
  uint8_t code;
  if(scp->state != SSH_SCP_NEW){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_init called under invalid state");
    return SSH_ERROR;
  }
  ssh_log(scp->session,SSH_LOG_PROTOCOL,"Initializing scp session %s %son location '%s'",
		  scp->mode==SSH_SCP_WRITE?"write":"read",
				  scp->recursive?"recursive ":"",
						  scp->location);
  scp->channel=channel_new(scp->session);
  if(scp->channel == NULL){
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  r= channel_open_session(scp->channel);
  if(r==SSH_ERROR){
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  if(scp->mode == SSH_SCP_WRITE)
    snprintf(execbuffer,sizeof(execbuffer),"scp -t %s %s",
    		scp->recursive ? "-r":"", scp->location);
  else
    snprintf(execbuffer,sizeof(execbuffer),"scp -f %s %s",
    		scp->recursive ? "-r":"", scp->location);
  if(channel_request_exec(scp->channel,execbuffer) == SSH_ERROR){
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  if(scp->mode == SSH_SCP_WRITE){
	  r=channel_read(scp->channel,&code,1,0);
	  if(code != 0){
		  ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
		  scp->state=SSH_SCP_ERROR;
		  return SSH_ERROR;
	  }
  } else {
	  channel_write(scp->channel,"",1);
  }
  if(scp->mode == SSH_SCP_WRITE)
    scp->state=SSH_SCP_WRITE_INITED;
  else
    scp->state=SSH_SCP_READ_INITED;
  return SSH_OK;
}
示例#13
0
文件: scp.c 项目: CUEBoxer/OpenStudio
/**
 * @brief denies the transfer of a file or creation of a directory
 *  coming from the remote party
 *  @param scp the scp handle.
 *  @param reason nul-terminated string with a human-readable explanation
 *  of the deny
 *  @returns SSH_OK the message was sent
 *  @returns SSH_ERROR Error sending the message, or sending it in a bad state
 */
int ssh_scp_deny_request(ssh_scp scp, const char *reason){
  char buffer[4096];
  int err;
  if(scp->state != SSH_SCP_READ_REQUESTED){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state");
    return SSH_ERROR;
  }
  snprintf(buffer,sizeof(buffer),"%c%s\n",2,reason);
  err=channel_write(scp->channel,buffer,strlen(buffer));
  if(err==SSH_ERROR) {
    return SSH_ERROR;
  }
  else {
    scp->state=SSH_SCP_READ_INITED;
    return SSH_OK;
  }
}
示例#14
0
文件: scp.c 项目: CUEBoxer/OpenStudio
/**
 * @brief accepts transfer of a file or creation of a directory
 *  coming from the remote party
 *  @param scp the scp handle.
 *  @returns SSH_OK the message was sent
 *  @returns SSH_ERROR Error sending the message, or sending it in a bad state
 */
int ssh_scp_accept_request(ssh_scp scp){
  char buffer[]={0x00};
  int err;
  if(scp->state != SSH_SCP_READ_REQUESTED){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_deny_request called under invalid state");
    return SSH_ERROR;
  }
  err=channel_write(scp->channel,buffer,1);
  if(err==SSH_ERROR) {
    return SSH_ERROR;
  }
  if(scp->request_type==SSH_SCP_REQUEST_NEWFILE)
    scp->state=SSH_SCP_READ_READING;
  else
    scp->state=SSH_SCP_READ_INITED;
  return SSH_OK;
}
示例#15
0
/*
 * Callback for when data is available on the standard output handle of
 * a process channel that is interactive mode
 */
DWORD process_channel_interact_notify(Remote *remote, LPVOID entryContext, LPVOID threadContext)
{
	Channel *channel = (Channel*)entryContext;
	ProcessChannelContext *ctx = (ProcessChannelContext *)threadContext;
	DWORD bytesRead, bytesAvail = 0;
	CHAR buffer[16384];
	DWORD result = ERROR_SUCCESS;

	if (!channel_exists(channel) || ctx == NULL)
	{
		return result;
	}
	if( PeekNamedPipe( ctx->pStdout, NULL, 0, NULL, &bytesAvail, NULL ) )
	{
		if( bytesAvail )
		{
			if( ReadFile( ctx->pStdout, buffer, sizeof(buffer) - 1, &bytesRead, NULL ) )
			{
				return channel_write( channel, remote, NULL, 0, buffer, bytesRead, NULL );
			}
			result = GetLastError();
		}
		else
		{
			// sf: if no data is available on the pipe we sleep to avoid running a tight loop
			// in this thread, as anonymous pipes won't block for data to arrive.
			Sleep( 100 );
		}
	}
	else
	{
		result = GetLastError();
	}

	if( result != ERROR_SUCCESS )
	{
		dprintf("Closing down socket: result: %d\n", result);
		process_channel_close( channel, NULL, ctx );
		channel_close( channel, remote, NULL, 0, NULL );
	}

	return result;
}
示例#16
0
/*
 * Notification handler for when a client connection has data
 */
DWORD portfwd_local_client_notify(Remote *remote,
		PortForwardClientContext *pcctx)
{
	UCHAR buf[8192];
	LONG bytesRead;

	// Reset the notification event
	ResetEvent(pcctx->notify);

	// Read data from the client connection
	if (((bytesRead = recv(pcctx->clientFd, buf, sizeof(buf), 0)) 
			== SOCKET_ERROR) || 
	    (bytesRead == 0))
		channel_close(pcctx->channel, pcctx->remote, NULL, 0, NULL);
		//portfwd_destroy_client(pcctx);
	else if (pcctx->channel)
		channel_write(pcctx->channel, pcctx->remote, NULL, 0, buf, bytesRead, 0);
	
	return ERROR_SUCCESS;
}
示例#17
0
文件: scp.c 项目: CUEBoxer/OpenStudio
/** @brief Read from a remote scp file
 * @param scp the scp handle.
 * @param buffer Destination buffer
 * @param size Size of the buffer
 * @returns Number of bytes read
 * @returns SSH_ERROR An error happened while reading
 */
int ssh_scp_read(ssh_scp scp, void *buffer, size_t size){
  int r;
  int code;
  if(scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE){
    r=ssh_scp_accept_request(scp);
    if(r==SSH_ERROR)
      return r;
  }
  if(scp->state != SSH_SCP_READ_READING){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_read called under invalid state");
    return SSH_ERROR;
  }
  if(scp->processed + size > scp->filelen)
    size = scp->filelen - scp->processed;
  if(size > 65536)
    size=65536; /* avoid too large reads */
  r=channel_read(scp->channel,buffer,size,0);
  if(r != SSH_ERROR)
    scp->processed += r;
  else {
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  /* Check if we arrived at end of file */
  if(scp->processed == scp->filelen) {
    scp->processed=scp->filelen=0;
    channel_write(scp->channel,"",1);
    code=ssh_scp_response(scp,NULL);
    if(code == 0){
    	scp->state=SSH_SCP_READ_INITED;
    	return r;
    }
    if(code==1){
    	scp->state=SSH_SCP_READ_INITED;
    	return SSH_ERROR;
    }
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  return r;
}
示例#18
0
文件: scp.c 项目: CUEBoxer/OpenStudio
/**
 * @brief Leaves a directory
 * @returns SSH_OK if the directory was created.
 * @returns SSH_ERROR if an error happened.
 * @see ssh_scp_push_directory
 */
 int ssh_scp_leave_directory(ssh_scp scp){
  char buffer[]="E\n";
  int r;
  uint8_t code;
  if(scp->state != SSH_SCP_WRITE_INITED){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_leave_directory called under invalid state");
    return SSH_ERROR;
  }
  r=channel_write(scp->channel,buffer,strlen(buffer));
  if(r==SSH_ERROR){
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  r=channel_read(scp->channel,&code,1,0);
  if(code != 0){
    ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
    scp->state=SSH_SCP_ERROR;
    return SSH_ERROR;
  }
  return SSH_OK;
}
示例#19
0
文件: tcp.c 项目: lizard007/msf3
/*
 * Callback for when there is data available on the local side of the TCP
 * client connection
 */
static DWORD tcp_channel_client_local_notify(Remote *remote, 
		TcpClientContext *ctx)
{
	struct timeval tv;
	fd_set set;
	UCHAR  buf[16384];
	LONG   bytesRead;

	// Reset the notification event
	ResetEvent(ctx->notify);

	tv.tv_sec  = 0;
	tv.tv_usec = 0;

	// We select in a loop with a zero second timeout because it's possible
	// that we could get a recv notification and a close notification at once,
	// so we need some way to make sure that we see them both, otherwise the
	// event handle wont get re set to notify us.
	do
	{
		FD_ZERO(&set);
		FD_SET(ctx->fd, &set);

		// Read data from the client connection
		if (((bytesRead = recv(ctx->fd, buf, sizeof(buf), 0)) 
				== SOCKET_ERROR) || 
			 (bytesRead == 0))
		{
			channel_close(ctx->channel, ctx->remote, NULL, 0, NULL);

			break;
		}
		else if (ctx->channel)
			channel_write(ctx->channel, ctx->remote, NULL, 0, buf, bytesRead, 0);
	
	} while (select(0, &set, NULL, NULL, &tv) > 0);
	
	return ERROR_SUCCESS;
}
示例#20
0
文件: scp.c 项目: CUEBoxer/OpenStudio
/** @brief Write into a remote scp file
 * @param scp the scp handle.
 * @param buffer the buffer to write
 * @param len the number of bytes to write
 * @returns SSH_OK the write was successful
 * @returns SSH_ERROR an error happened while writing
 */
int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
  int w;
  //int r;
  //uint8_t code;
  if(scp->state != SSH_SCP_WRITE_WRITING){
    ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_write called under invalid state");
    return SSH_ERROR;
  }
  if(scp->processed + len > scp->filelen)
    len = scp->filelen - scp->processed;
  /* hack to avoid waiting for window change */
  channel_poll(scp->channel,0);
  w=channel_write(scp->channel,buffer,len);
  if(w != SSH_ERROR)
    scp->processed += w;
  else {
    scp->state=SSH_SCP_ERROR;
    //return=channel_get_exit_status(scp->channel);
    return SSH_ERROR;
  }
  /* Check if we arrived at end of file */
  if(scp->processed == scp->filelen) {
/*    r=channel_read(scp->channel,&code,1,0);
    if(r==SSH_ERROR){
      scp->state=SSH_SCP_ERROR;
      return SSH_ERROR;
    }
    if(code != 0){
      ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
      scp->state=SSH_SCP_ERROR;
      return SSH_ERROR;
    }
*/
    scp->processed=scp->filelen=0;
    scp->state=SSH_SCP_WRITE_INITED;
  }
  return SSH_OK;
}
示例#21
0
文件: event.c 项目: monkey/monkey
int process_cgi_data(struct cgi_request *r)
{
    int ret;
    int len;
    int status;
    char *buf = r->in_buf;
    char *outptr = r->in_buf;
    char *end;
    char *endl;
    unsigned char advance;

    mk_api->socket_cork_flag(r->cs->socket, TCP_CORK_OFF);
    if (!r->status_done && r->in_len >= 8) {
        if (memcmp(buf, "Status: ", 8) == 0) {
            status = atoi(buf + 8);
            mk_api->header_set_http_status(r->sr, status);
            endl = memchr(buf + 8, '\n', r->in_len - 8);
            if (!endl) {
                return MK_PLUGIN_RET_EVENT_OWNED;
            }
            else {
                endl++;
                outptr = endl;
                r->in_len -= endl - buf;
            }
        }
        else if (memcmp(buf, "HTTP", 4) == 0) {
            status = atoi(buf + 9);
            mk_api->header_set_http_status(r->sr, status);

            endl = memchr(buf + 8, '\n', r->in_len - 8);
            if (!endl) {
                return MK_PLUGIN_RET_EVENT_OWNED;
            }
            else {
                endl++;
                outptr = endl;
                r->in_len -= endl - buf;
            }
        }
        mk_api->header_prepare(r->plugin, r->cs, r->sr);
        r->status_done = 1;
    }

    if (!r->all_headers_done) {
        advance = 4;

        /* Write the rest of the headers without chunking */
        end = getearliestbreak(outptr, r->in_len, &advance);
        if (!end) {
            /* Let's return until we have the headers break */
            return MK_PLUGIN_RET_EVENT_OWNED;
        }
        end += advance;
        len = end - outptr;
        channel_write(r, outptr, len);
        outptr += len;
        r->in_len -= len;

        r->all_headers_done = 1;
        if (r->in_len == 0) {
            return MK_PLUGIN_RET_EVENT_OWNED;
        }
    }

    if (r->chunked) {
        char tmp[16];
        len = snprintf(tmp, 16, "%x\r\n", r->in_len);
        ret = channel_write(r, tmp, len);
        if (ret < 0)
            return MK_PLUGIN_RET_EVENT_CLOSE;
    }

    ret = channel_write(r, outptr, r->in_len);
    if (ret < 0) {
        return MK_PLUGIN_RET_EVENT_CLOSE;
    }

    r->in_len = 0;
    if (r->chunked) {
        channel_write(r, MK_CRLF, 2);
    }
    return MK_PLUGIN_RET_EVENT_OWNED;
}
示例#22
0
/*
 * Callback for when there is data available on the local side of the TCP client connection
 */
DWORD tcp_channel_client_local_notify( Remote * remote, TcpClientContext * ctx )
{
	struct timeval tv  = {0};
	fd_set set         = {0};
	UCHAR  buf[16384]  = {0};
	LONG   dwBytesRead = 0;

	// We select in a loop with a zero second timeout because it's possible
	// that we could get a recv notification and a close notification at once,
	// so we need some way to make sure that we see them both, otherwise the
	// event handle wont get re set to notify us.
	do
	{
		// Reset the notification event
		ResetEvent( ctx->notify );

		FD_ZERO( &set );
		FD_SET( ctx->fd, &set );
		
		tv.tv_sec  = 0;
		tv.tv_usec = 0;

		// Read data from the client connection
		dwBytesRead = recv( ctx->fd, buf, sizeof(buf), 0 );
		
		if( dwBytesRead == SOCKET_ERROR )
		{
			DWORD dwError = WSAGetLastError();
			
			// WSAECONNRESET: The connection was forcibly closed by the remote host.
			// WSAECONNABORTED: The connection was terminated due to a time-out or other failure.
			if( dwError == WSAECONNRESET || dwError == WSAECONNABORTED )
			{
				dprintf( "[TCP] tcp_channel_client_local_notify. [error] closing down channel gracefully. WSAGetLastError=%d", dwError );
				// By setting bytesRead to zero, we can ensure we close down the channel gracefully...
				dwBytesRead = 0;
			}
			else if( dwError == WSAEWOULDBLOCK )
			{
				dprintf( "[TCP] tcp_channel_client_local_notify. channel=0x%08X. recv generated a WSAEWOULDBLOCK", ctx->channel );
				// break and let the scheduler notify us again if needed.
				break;
			}
			else
			{
				dprintf( "[TCP] tcp_channel_client_local_notify. [error] channel=0x%08X read=0x%.8x (ignored). WSAGetLastError=%d", ctx->channel, dwBytesRead, dwError );
				// we loop again because bytesRead is -1.
			}
		}

		if( dwBytesRead == 0 )
		{
			dprintf( "[TCP] tcp_channel_client_local_notify. [closed] channel=0x%08X read=0x%.8x", ctx->channel, dwBytesRead );

			// Set the native channel operations context to NULL
			channel_set_native_io_context( ctx->channel, NULL );
			
			// Sleep for a quarter second
			Sleep( 250 );

			// Free the context
			free_tcp_client_context( ctx );

			// Stop processing
			break;
		}
		else if( dwBytesRead > 0 )
		{
			if( ctx->channel )
			{
				dprintf( "[TCP] tcp_channel_client_local_notify. [data] channel=0x%08X read=%d", ctx->channel, dwBytesRead );
				channel_write( ctx->channel, ctx->remote, NULL, 0, buf, dwBytesRead, 0 );
			}
			else
			{
				dprintf( "[TCP] tcp_channel_client_local_notify. [data] channel=<invalid> read=0x%.8x", dwBytesRead );
			}
		}

	} while( select( 1, &set, NULL, NULL, &tv ) > 0 );
	
	return ERROR_SUCCESS;
}
示例#23
0
文件: tinysshd.c 项目: akerl/tinyssh
int main(int argc, char **argv) {

    char *x;
    const char *keydir = 0;
    long long i;
    struct pollfd p[6];
    struct pollfd *q;
    struct pollfd *watch0;
    struct pollfd *watch1;
    struct pollfd *watchtochild;
    struct pollfd *watchfromchild1;
    struct pollfd *watchfromchild2;
    struct pollfd *watchselfpipe;
    int exitsignal, exitcode;

    signal(SIGPIPE, SIG_IGN);
    signal(SIGALRM, timeout);

    log_init(0, "tinysshd", 0, 0);

    if (argc < 2) die_usage(USAGE);
    if (!argv[0]) die_usage(USAGE);
    for (;;) {
        if (!argv[1]) break;
        if (argv[1][0] != '-') break;
        x = *++argv;
        if (x[0] == '-' && x[1] == 0) break;
        if (x[0] == '-' && x[1] == '-' && x[2] == 0) break;
        while (*++x) {
            if (*x == 'q') { flagverbose = 0; continue; }
            if (*x == 'Q') { flagverbose = 1; continue; }
            if (*x == 'v') { if (flagverbose >= 2) flagverbose = 3; else flagverbose = 2; continue; }
            if (*x == 'o') { cryptotypeselected |= sshcrypto_TYPEOLDCRYPTO; continue; }
            if (*x == 'O') { cryptotypeselected &= ~sshcrypto_TYPEOLDCRYPTO; continue; }
            if (*x == 's') { cryptotypeselected |= sshcrypto_TYPENEWCRYPTO; continue; }
            if (*x == 'S') { cryptotypeselected &= ~sshcrypto_TYPENEWCRYPTO; continue; }
            if (*x == 'p') { cryptotypeselected |= sshcrypto_TYPEPQCRYPTO; continue; }
            if (*x == 'P') { cryptotypeselected &= ~sshcrypto_TYPEPQCRYPTO; continue; }
            if (*x == 'l') { flaglogger = 1; continue; }
            if (*x == 'L') { flaglogger = 0; continue; }
            if (*x == 'x') {
                if (x[1]) { channel_subsystem_add(x + 1); break; }
                if (argv[1]) { channel_subsystem_add(*++argv); break; }
            }

            die_usage(USAGE);
        }
    }
    keydir = *++argv; if (!keydir) die_usage(USAGE);

    log_init(flagverbose, "tinysshd", 1, flaglogger);

    connectioninfo(channel.localip, channel.localport, channel.remoteip, channel.remoteport);
    log_i4("connection from ", channel.remoteip, ":", channel.remoteport);

    channel_subsystem_log();

    global_init();

    blocking_disable(0);
    blocking_disable(1);
    blocking_disable(2);

    /* get server longterm keys */
    fdwd = open_cwd();
    if (fdwd == -1) die_fatal("unable to open current directory", 0, 0);
    if (chdir(keydir) == -1) die_fatal("unable to chdir to", keydir, 0);

    for (i = 0; sshcrypto_keys[i].name; ++i) sshcrypto_keys[i].sign_flagserver |= sshcrypto_kexs[i].cryptotype & cryptotypeselected;
    for (i = 0; sshcrypto_keys[i].name; ++i) sshcrypto_keys[i].sign_flagclient |= sshcrypto_kexs[i].cryptotype & cryptotypeselected;
    for (i = 0; sshcrypto_kexs[i].name; ++i) sshcrypto_kexs[i].flagenabled |= sshcrypto_kexs[i].cryptotype & cryptotypeselected;
    for (i = 0; sshcrypto_ciphers[i].name; ++i) sshcrypto_ciphers[i].flagenabled |= sshcrypto_ciphers[i].cryptotype & cryptotypeselected;

    /* read public keys */
    for (i = 0; sshcrypto_keys[i].name; ++i) {
        if (!sshcrypto_keys[i].sign_flagserver) continue;
        if (load(sshcrypto_keys[i].sign_publickeyfilename, sshcrypto_keys[i].sign_publickey, sshcrypto_keys[i].sign_publickeybytes) == -1) {
            sshcrypto_keys[i].sign_flagserver = 0;
            if (errno == ENOENT) continue;
            die_fatal("unable to read public key from file", keydir, sshcrypto_keys[i].sign_publickeyfilename);
        }
    }

    if (fchdir(fdwd) == -1) die_fatal("unable to change directory to working directory", 0, 0);
    close(fdwd);

    /* set timeout */
    alarm(60);

    /* send and receive hello */
    if (!packet_hello_send()) die_fatal("unable to send hello-string", 0, 0);
    if (!packet_hello_receive()) die_fatal("unable to receive hello-string", 0, 0);

    /* send and receive kex */
    if (!packet_kex_send()) die_fatal("unable to send kex-message", 0, 0);
    if (!packet_kex_receive()) die_fatal("unable to receive kex-message", 0, 0);

rekeying:
    /* rekeying */
    alarm(60);
    if (packet.flagrekeying == 1) {
        buf_purge(&packet.kexrecv);
        buf_put(&packet.kexrecv, b1.buf, b1.len);
        if (!packet_kex_send()) die_fatal("unable to send kex-message", 0, 0);
    }

    /* send and receive kexdh */
    if (!packet_kexdh(keydir, &b1, &b2)) die_fatal("unable to subprocess kexdh", 0, 0);

    if (packet.flagkeys) log_d1("rekeying: done");
    packet.flagkeys = 1;

    /* note: comunication is encrypted */

    /* authentication + authorization */
    if (packet.flagauthorized == 0) {
        if (!packet_auth(&b1, &b2)) die_fatal("authentication failed", 0, 0);
        packet.flagauthorized = 1;
    }

    /* note: user is authenticated and authorized */
    alarm(3600);

    /* main loop */
    for (;;) {
        if (channel_iseof())
            if (!packet.sendbuf.len)
                if (packet.flagchanneleofreceived)
                    break;

        watch0 = watch1 = 0;
        watchtochild = watchfromchild1 = watchfromchild2 = 0;
        watchselfpipe = 0;

        q = p;

        if (packet_sendisready()) { watch1 = q; q->fd = 1; q->events = POLLOUT; ++q; }
        if (packet_recvisready()) { watch0 = q; q->fd = 0; q->events = POLLIN;  ++q; }

        if (channel_writeisready()) { watchtochild = q; q->fd = channel_getfd0(); q->events = POLLOUT; ++q; }
        if (channel_readisready() && packet_putisready()) { watchfromchild1 = q; q->fd = channel_getfd1(); q->events = POLLIN; ++q; }
        if (channel_extendedreadisready() && packet_putisready()) { watchfromchild2 = q; q->fd = channel_getfd2(); q->events = POLLIN; ++q; }

        if (selfpipe[0] != -1) { watchselfpipe = q; q->fd = selfpipe[0]; q->events = POLLIN; ++q; }

        if (poll(p, q - p, 60000) < 0) {
            watch0 = watch1 = 0;
            watchtochild = watchfromchild1 = watchfromchild2 = 0;
            watchselfpipe = 0;
        }

        else {
            if (watch0) if (!watch0->revents) watch0 = 0;
            if (watch1) if (!watch1->revents) watch1 = 0;
            if (watchfromchild1) if (!watchfromchild1->revents) watchfromchild1 = 0;
            if (watchfromchild2) if (!watchfromchild2->revents) watchfromchild2 = 0;
            if (watchtochild) if (!watchtochild->revents) watchtochild = 0;
            if (watchselfpipe) if (!watchselfpipe->revents) watchselfpipe = 0;
        }

        if (watchtochild) {

            /* write data to child */
            if (!channel_write()) die_fatal("unable to write data to child", 0, 0);

            /* try to adjust window */
            if (!packet_channel_send_windowadjust(&b1)) die_fatal("unable to send data to network", 0, 0);
        }

        /* read data from child */
        if (watchfromchild1) packet_channel_send_data(&b2);
        if (watchfromchild2) packet_channel_send_extendeddata(&b2);

        /* check child */
        if (channel_iseof()) {
            if (selfpipe[0] == -1) if (open_pipe(selfpipe) == -1) die_fatal("unable to open pipe", 0, 0);
            signal(SIGCHLD, trigger);
            if (channel_waitnohang(&exitsignal, &exitcode)) {
                packet_channel_send_eof(&b2);
                if (!packet_channel_send_close(&b2, exitsignal, exitcode)) die_fatal("unable to close channel", 0, 0);
            }
        }

        /* send data to network */
        if (watch1) if (!packet_send()) die_fatal("unable to send data to network", 0, 0);

        /* receive data from network */
        if (watch0) {
            alarm(3600); /* refresh timeout */
            if (!packet_recv()) {
                if (channel_iseof()) break; /* XXX */
                die_fatal("unable to receive data from network", 0, 0);
            }
        }

        /* process packets */
        for (;;) {

            if (!packet_get(&b1, 0)) {
                if (!errno) break;
                die_fatal("unable to get packets from network", 0, 0);
            }
            if (b1.len < 1) break; /* XXX */

            switch (b1.buf[0]) {
                case SSH_MSG_CHANNEL_OPEN:
                    if (!packet_channel_open(&b1, &b2)) die_fatal("unable to open channel", 0, 0);
                    break;
                case SSH_MSG_CHANNEL_REQUEST:
                    if (!packet_channel_request(&b1, &b2)) die_fatal("unable to handle channel-request", 0, 0);
                    break;
                case SSH_MSG_CHANNEL_DATA:
                    if (!packet_channel_recv_data(&b1)) die_fatal("unable to handle channel-data", 0, 0);
                    break;
                case SSH_MSG_CHANNEL_EXTENDED_DATA:
                    if (!packet_channel_recv_extendeddata(&b1)) die_fatal("unable to handle channel-extended-data", 0, 0);
                    break;
                case SSH_MSG_CHANNEL_WINDOW_ADJUST:
                    if (!packet_channel_recv_windowadjust(&b1)) die_fatal("unable to handle channel-window-adjust", 0, 0);
                    break;
                case SSH_MSG_CHANNEL_EOF:
                    if (!packet_channel_recv_eof(&b1)) die_fatal("unable to handle channel-eof", 0, 0);
                    break;
                case SSH_MSG_CHANNEL_CLOSE:
                    if (!packet_channel_recv_close(&b1)) die_fatal("unable to handle channel-close", 0, 0);
                    break;
                case SSH_MSG_KEXINIT:
                    goto rekeying;
                default:
                    if (!packet_unimplemented(&b1)) die_fatal("unable to send SSH_MSG_UNIMPLEMENTED message", 0, 0);
            }
        }
    }

    log_i1("finished");
    global_die(0); return 111;
}
示例#24
0
/*
 * Reads in data from the input device, potentially calling the 
 * command processing function if a complete command has been read.
 */
VOID console_read_buffer(Remote *remote)
{
	DWORD newInputBufferLength, stringLength, offset;
	Channel *interactiveChannel;
	PCHAR newInputBuffer;
	BOOL process = FALSE;
	CHAR buf[4096];
	PCHAR eoln, eolr;
	LONG bytesRead;

	// Ensure null termination
	buf[sizeof(buf) - 1] = 0;

	do
	{
		// Is there data available?
		if (WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), INFINITE) 
				!= WAIT_OBJECT_0)
			break;

		// If a console escape character was sent and we're currently interactive,
		// break out of interactive mode
		if ((console_check_escape_sent()) &&
		    (console_get_interactive_channel()))
		{
			console_set_interactive_channel(remote, NULL);

			console_write_output(
					"\n"
					"\n"
					"Exiting interactive mode..\n");
			console_write_prompt();
		}

		// Read the command
		if ((!ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
				buf, sizeof(buf) - 1, &bytesRead, NULL)) || (bytesRead <= 0))
			break;

		buf[bytesRead] = 0;

		// If an interactive channel is in use, write directly to it.
		if ((interactiveChannel = console_get_interactive_channel()))
		{
			channel_write(interactiveChannel, remote, NULL, 0, buf, 
					bytesRead, NULL);
			break;
		}

		if ((eoln = strchr(buf, '\n')))
		{
			*eoln = 0;

			process = TRUE;
		}

		// Remove end of line characters
		if ((eolr = strchr(buf, '\r')))
			*eolr = 0;

		// Calculate lengths
		stringLength         = strlen(buf);
		newInputBufferLength = inputBufferLength + stringLength;

		if (inputBuffer)
			newInputBuffer = (PCHAR)realloc(inputBuffer, 
					newInputBufferLength);
		else
			newInputBuffer = (PCHAR)malloc(++newInputBufferLength);

		// Allocation failure?
		if (!newInputBuffer)
			break;

		if ((offset = inputBufferLength))
			offset--;

		// Copy the string
		memcpy(newInputBuffer + offset, buf, stringLength);

		// Update the input buffer
		inputBuffer       = newInputBuffer;
		inputBufferLength = newInputBufferLength;

		// Process the full command line if it's completed
		if (process)
		{
			inputBuffer[inputBufferLength - 1] = 0;

			client_acquire_lock();
			console_process_command(remote);
			client_release_lock();

			free(inputBuffer);

			inputBuffer       = NULL;
			inputBufferLength = 0;

			console_write_prompt();
		}

	} while (0);
}
示例#25
0
int
sdb_channel_select(sdb_channel_t *chan, int *wantread, void *read_data,
		int *wantwrite, void *write_data, const struct timespec *timeout)
{
	int status = 0;

	if (! chan) {
		errno = EINVAL;
		return -1;
	}

	if ((! wantread) && (! read_data) && (! wantwrite) && (! write_data)) {
		errno = EINVAL;
		return -1;
	}

	pthread_mutex_lock(&chan->lock);
	while (! status) {
		int read_status, write_status;

		read_status = channel_read(chan, read_data);
		write_status = channel_write(chan, write_data);

		if ((! read_status) || (! write_status)) {
			if (wantread)
				*wantread = read_status == 0;
			if (wantwrite)
				*wantwrite = write_status == 0;

			if (((wantread || read_data) && (! read_status))
					|| ((wantwrite || write_data) && (! write_status)))
				break;
		}

		if (chan->shutdown) {
			if (read_status)
				status = EBADF;
			break;
		}

		if (timeout) {
			struct timespec abstime;

			if (clock_gettime(CLOCK_REALTIME, &abstime)) {
				pthread_mutex_unlock(&chan->lock);
				return -1;
			}

			abstime.tv_sec += timeout->tv_sec;
			abstime.tv_nsec += timeout->tv_nsec;

			if (abstime.tv_nsec > 1000000000) {
				abstime.tv_nsec -= 1000000000;
				abstime.tv_sec += 1;
			}

			status = pthread_cond_timedwait(&chan->cond, &chan->lock,
					&abstime);
		}
		else
			status = pthread_cond_wait(&chan->cond, &chan->lock);
	}
	pthread_mutex_unlock(&chan->lock);

	if (status) {
		errno = status;
		return -1;
	}
	return 0;
} /* sdb_channel_select */
示例#26
0
static gpointer
remmina_ssh_tunnel_main_thread_proc (gpointer data)
{
	RemminaSSHTunnel *tunnel = (RemminaSSHTunnel*) data;
	gchar *ptr;
	ssize_t len = 0, lenw = 0;
	fd_set set;
	struct timeval timeout;
	GTimeVal t1, t2;
	glong diff;
	ssh_channel channel = NULL;
	gboolean first = TRUE;
	gboolean disconnected;
	gint sock;
	gint maxfd;
	gint i;
	gint ret;
	struct sockaddr_in sin;

	g_get_current_time (&t1);
	t2 = t1;

	switch (tunnel->tunnel_type)
	{
		case REMMINA_SSH_TUNNEL_OPEN:
		/* Accept a local connection */
		sock = accept (tunnel->server_sock, NULL, NULL);
		if (sock < 0)
		{
			REMMINA_SSH (tunnel)->error = g_strdup ("Failed to accept local socket");
			tunnel->thread = 0;
			return NULL;
		}

		if ((channel = channel_new (tunnel->ssh.session)) == NULL)
		{
			close (sock);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), "Failed to createt channel : %s");
			tunnel->thread = 0;
			return NULL;
		}
		/* Request the SSH server to connect to the destination */
		if (channel_open_forward (channel, tunnel->dest, tunnel->port, "127.0.0.1", 0) != SSH_OK)
		{
			close (sock);
			channel_close (channel);
			channel_free (channel);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), _("Failed to connect to the SSH tunnel destination: %s"));
			tunnel->thread = 0;
			return NULL;
		}
		remmina_ssh_tunnel_add_channel (tunnel, channel, sock);
		break;

		case REMMINA_SSH_TUNNEL_X11:
		if ((tunnel->x11_channel = channel_new (tunnel->ssh.session)) == NULL)
		{
			remmina_ssh_set_error (REMMINA_SSH (tunnel), "Failed to create channel : %s");
			tunnel->thread = 0;
			return NULL;
		}
		if (!remmina_public_get_xauth_cookie (tunnel->localdisplay, &ptr))
		{
			remmina_ssh_set_application_error (REMMINA_SSH (tunnel), "%s", ptr);
			g_free(ptr);
			tunnel->thread = 0;
			return NULL;
		}
		if (channel_open_session (tunnel->x11_channel) ||
				channel_request_x11 (tunnel->x11_channel, TRUE, NULL, ptr,
						gdk_screen_get_number (gdk_screen_get_default ())))
		{
			g_free(ptr);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), "Failed to open channel : %s");
			tunnel->thread = 0;
			return NULL;
		}
		g_free(ptr);
		if (channel_request_exec (tunnel->x11_channel, tunnel->dest))
		{
			ptr = g_strdup_printf(_("Failed to execute %s on SSH server : %%s"), tunnel->dest);
			remmina_ssh_set_error (REMMINA_SSH (tunnel), ptr);
			g_free(ptr);
			tunnel->thread = 0;
			return NULL;
		}

		if (tunnel->init_func &&
				! (*tunnel->init_func) (tunnel, tunnel->callback_data))
		{
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		break;

		case REMMINA_SSH_TUNNEL_XPORT:
		/* Detect the next available port starting from 6010 on the server */
		for (i = 10; i <= MAX_X_DISPLAY_NUMBER; i++)
		{
			if (channel_forward_listen (REMMINA_SSH (tunnel)->session,
							(tunnel->bindlocalhost ? "localhost" : NULL), 6000 + i, NULL))
			{
				continue;
			}
			else
			{
				tunnel->remotedisplay = i;
				break;
			}
		}
		if (tunnel->remotedisplay < 1)
		{
			remmina_ssh_set_error (REMMINA_SSH (tunnel), _("Failed to request port forwarding : %s"));
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		if (tunnel->init_func &&
				! (*tunnel->init_func) (tunnel, tunnel->callback_data))
		{
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		break;

		case REMMINA_SSH_TUNNEL_REVERSE:
		if (channel_forward_listen (REMMINA_SSH (tunnel)->session, NULL, tunnel->port, NULL))
		{
			remmina_ssh_set_error (REMMINA_SSH (tunnel), _("Failed to request port forwarding : %s"));
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		if (tunnel->init_func &&
				! (*tunnel->init_func) (tunnel, tunnel->callback_data))
		{
			if (tunnel->disconnect_func)
			{
				(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
			}
			tunnel->thread = 0;
			return NULL;
		}

		break;
	}

	tunnel->buffer_len = 10240;
	tunnel->buffer = g_malloc (tunnel->buffer_len);

	/* Start the tunnel data transmittion */
	while (tunnel->running)
	{
		if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_XPORT ||
				tunnel->tunnel_type == REMMINA_SSH_TUNNEL_X11 ||
				tunnel->tunnel_type == REMMINA_SSH_TUNNEL_REVERSE)
		{
			if (first)
			{
				first = FALSE;
				/* Wait for a period of time for the first incoming connection */
				if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_X11)
				{
					channel = channel_accept_x11 (tunnel->x11_channel, 15000);
				}
				else
				{
					channel = channel_forward_accept (REMMINA_SSH (tunnel)->session, 15000);
				}
				if (!channel)
				{
					remmina_ssh_set_application_error (REMMINA_SSH (tunnel), _("No response from the server."));
					if (tunnel->disconnect_func)
					{
						(*tunnel->disconnect_func) (tunnel, tunnel->callback_data);
					}
					tunnel->thread = 0;
					return NULL;
				}
				if (tunnel->connect_func)
				{
					(*tunnel->connect_func) (tunnel, tunnel->callback_data);
				}
				if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_REVERSE)
				{
					/* For reverse tunnel, we only need one connection. */
					channel_forward_cancel (REMMINA_SSH (tunnel)->session, NULL, tunnel->port);
				}
			}
			else if (tunnel->tunnel_type != REMMINA_SSH_TUNNEL_REVERSE)
			{
				/* Poll once per some period of time if no incoming connections.
				 * Don't try to poll continuously as it will significantly slow down the loop */
				g_get_current_time (&t1);
				diff = (t1.tv_sec - t2.tv_sec) * 10 + (t1.tv_usec - t2.tv_usec) / 100000;
				if (diff > 1)
				{
					if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_X11)
					{
						channel = channel_accept_x11 (tunnel->x11_channel, 0);
					}
					else
					{
						channel = channel_forward_accept (REMMINA_SSH (tunnel)->session, 0);
					}
					if (channel == NULL)
					{
						t2 = t1;
					}
				}
			}

			if (channel)
			{
				if (tunnel->tunnel_type == REMMINA_SSH_TUNNEL_REVERSE)
				{
					sin.sin_family = AF_INET;
					sin.sin_port = htons (tunnel->localport);
					sin.sin_addr.s_addr = inet_addr ("127.0.0.1");
					sock = socket (AF_INET, SOCK_STREAM, 0);
					if (connect (sock, (struct sockaddr *) &sin, sizeof (sin)) < 0)
					{
						remmina_ssh_set_application_error (REMMINA_SSH (tunnel),
								"Cannot connect to local port %i.", tunnel->localport);
						close (sock);
						sock = -1;
					}
				}
				else
				{
					sock = remmina_public_open_xdisplay (tunnel->localdisplay);
				}
				if (sock >= 0)
				{
					remmina_ssh_tunnel_add_channel (tunnel, channel, sock);
				}
				else
				{
					/* Failed to create unix socket. Will this happen? */
					channel_close (channel);
					channel_free (channel);
				}
				channel = NULL;
			}
		}

		if (tunnel->num_channels <= 0)
		{
			/* No more connections. We should quit */
			break;
		}

		timeout.tv_sec = 0;
		timeout.tv_usec = 200000;

		FD_ZERO (&set);
		maxfd = 0;
		for (i = 0; i < tunnel->num_channels; i++)
		{
			if (tunnel->sockets[i] > maxfd)
			{
				maxfd = tunnel->sockets[i];
			}
			FD_SET (tunnel->sockets[i], &set);
		}

		ret = ssh_select (tunnel->channels, tunnel->channels_out, maxfd + 1, &set, &timeout);
		if (!tunnel->running) break;
		if (ret == SSH_EINTR) continue;
		if (ret == -1) break;

		i = 0;
		while (tunnel->running && i < tunnel->num_channels)
		{
			disconnected = FALSE;
			if (FD_ISSET (tunnel->sockets[i], &set))
			{
				while (!disconnected &&
						(len = read (tunnel->sockets[i], tunnel->buffer, tunnel->buffer_len)) > 0)
				{
					for (ptr = tunnel->buffer, lenw = 0; len > 0; len -= lenw, ptr += lenw)
					{
						lenw = channel_write (tunnel->channels[i], (char*) ptr, len);
						if (lenw <= 0)
						{
							disconnected = TRUE;
							break;
						}
					}
				}
				if (len == 0) disconnected = TRUE;
			}
			if (disconnected)
			{
				remmina_ssh_tunnel_remove_channel (tunnel, i);
				continue;
			}
			i++;
		}
		if (!tunnel->running) break;

		i = 0;
		while (tunnel->running && i < tunnel->num_channels)
		{
			disconnected = FALSE;

			if (!tunnel->socketbuffers[i])
			{
				len = channel_poll (tunnel->channels[i], 0);
				if (len == SSH_ERROR || len == SSH_EOF)
				{
					disconnected = TRUE;
				}
				else if (len > 0)
				{
					tunnel->socketbuffers[i] = remmina_ssh_tunnel_buffer_new (len);
					len = channel_read_nonblocking (tunnel->channels[i], tunnel->socketbuffers[i]->data, len, 0);
					if (len <= 0)
					{
						disconnected = TRUE;
					}
					else
					{
						tunnel->socketbuffers[i]->len = len;
					}
				}
			}

			if (!disconnected && tunnel->socketbuffers[i])
			{
				for (lenw = 0; tunnel->socketbuffers[i]->len > 0;
						tunnel->socketbuffers[i]->len -= lenw, tunnel->socketbuffers[i]->ptr += lenw)
				{
					lenw = write (tunnel->sockets[i], tunnel->socketbuffers[i]->ptr, tunnel->socketbuffers[i]->len);
					if (lenw == -1 && errno == EAGAIN && tunnel->running)
					{
						/* Sometimes we cannot write to a socket (always EAGAIN), probably because it's internal
						 * buffer is full. We need read the pending bytes from the socket first. so here we simply
						 * break, leave the buffer there, and continue with other data */
						break;
					}
					if (lenw <= 0)
					{
						disconnected = TRUE;
						break;
					}
				}
				if (tunnel->socketbuffers[i]->len <= 0)
				{
					remmina_ssh_tunnel_buffer_free (tunnel->socketbuffers[i]);
					tunnel->socketbuffers[i] = NULL;
				}
			}

			if (disconnected)
			{
				remmina_ssh_tunnel_remove_channel (tunnel, i);
				continue;
			}
			i++;
		}
	}

	remmina_ssh_tunnel_close_all_channels (tunnel);

	return NULL;
}
示例#27
0
static gpointer
remmina_ssh_shell_thread (gpointer data)
{
	RemminaSSHShell *shell = (RemminaSSHShell*) data;
	fd_set fds;
	struct timeval timeout;
	ssh_channel channel = NULL;
	ssh_channel ch[2], chout[2];
	gchar *buf = NULL;
	gint buf_len;
	gint len;
	gint i, ret;

	LOCK_SSH (shell)

	if ((channel = channel_new (REMMINA_SSH (shell)->session)) == NULL ||
			channel_open_session (channel))
	{
		UNLOCK_SSH (shell)
		remmina_ssh_set_error (REMMINA_SSH (shell), "Failed to open channel : %s");
		if (channel) channel_free (channel);
		shell->thread = 0;
		return NULL;
	}

	channel_request_pty (channel);
	if (shell->exec && shell->exec[0])
	{
		ret = channel_request_exec (channel, shell->exec);
	}
	else
	{
		ret = channel_request_shell (channel);
	}
	if (ret)
	{
		UNLOCK_SSH (shell)
		remmina_ssh_set_error (REMMINA_SSH (shell), "Failed to request shell : %s");
		channel_close (channel);
		channel_free (channel);
		shell->thread = 0;
		return NULL;
	}

	shell->channel = channel;

	UNLOCK_SSH (shell)

	buf_len = 1000;
	buf = g_malloc (buf_len + 1);

	ch[0] = channel;
	ch[1] = NULL;

	while (!shell->closed)
	{
		timeout.tv_sec = 1;
		timeout.tv_usec = 0;

		FD_ZERO (&fds);
		FD_SET (shell->master, &fds);

		ret = ssh_select (ch, chout, shell->master + 1, &fds, &timeout);
		if (ret == SSH_EINTR) continue;
		if (ret == -1) break;

		if (FD_ISSET (shell->master, &fds))
		{
			len = read (shell->master, buf, buf_len);
			if (len <= 0) break;
			LOCK_SSH (shell)
			channel_write (channel, buf, len);
			UNLOCK_SSH (shell)
		}
		for (i = 0; i < 2; i++)
		{
			LOCK_SSH (shell)
			len = channel_poll (channel, i);
			UNLOCK_SSH (shell)
			if (len == SSH_ERROR || len == SSH_EOF)
			{
				shell->closed = TRUE;
				break;
			}
			if (len <= 0) continue;
			if (len > buf_len)
			{
				buf_len = len;
				buf = (gchar*) g_realloc (buf, buf_len + 1);
			}
			LOCK_SSH (shell)
			len = channel_read_nonblocking (channel, buf, len, i);
			UNLOCK_SSH (shell)
			if (len <= 0)
			{
				shell->closed = TRUE;
				break;
			}
			while (len > 0)
			{
				ret = write (shell->master, buf, len);
				if (ret <= 0) break;
				len -= ret;
			}
		}
	}
示例#28
0
static gpointer remmina_nx_session_tunnel_main_thread(gpointer data)
{
	RemminaNXSession *nx = (RemminaNXSession*) data;
	gchar *ptr;
	ssize_t len = 0, lenw = 0;
	fd_set set;
	struct timeval timeout;
	ssh_channel channels[2];
	ssh_channel channels_out[2];
	gint sock;
	gint ret;
	gchar buffer[10240];
	gchar socketbuffer[10240];
	gchar *socketbuffer_ptr = NULL;
	gint socketbuffer_len = 0;

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	/* Accept a local connection */
	sock = accept(nx->server_sock, NULL, NULL);
	if (sock < 0)
	{
		remmina_nx_session_set_application_error(nx, "Failed to accept local socket");
		nx->thread = 0;
		return NULL;
	}
	close(nx->server_sock);
	nx->server_sock = -1;

	channels[0] = nx->channel;
	channels[1] = NULL;

	/* Start the tunnel data transmittion */
	while (nx->running)
	{
		timeout.tv_sec = 1;
		timeout.tv_usec = 0;

		FD_ZERO(&set);
		FD_SET(sock, &set);

		ret = ssh_select(channels, channels_out, sock + 1, &set, &timeout);
		if (!nx->running)
			break;
		if (ret == SSH_EINTR)
			continue;
		if (ret == -1)
			break;

		if (FD_ISSET(sock, &set))
		{
			len = read(sock, buffer, sizeof(buffer));
			if (len == 0)
				nx->running = FALSE;
			else
				if (len > 0)
				{
					for (ptr = buffer, lenw = 0; len > 0; len -= lenw, ptr += lenw)
					{
						ssh_set_fd_towrite(nx->session);
						lenw = channel_write(channels[0], (char*) ptr, len);
						if (lenw <= 0)
						{
							nx->running = FALSE;
							break;
						}
					}
				}
		}

		if (!nx->running)
			break;

		if (channels_out[0] && socketbuffer_len <= 0)
		{
			len = channel_read_nonblocking(channels_out[0], socketbuffer, sizeof(socketbuffer), 0);
			if (len == SSH_ERROR || len == SSH_EOF)
			{
				nx->running = FALSE;
				break;
			}
			else
				if (len > 0)
				{
					socketbuffer_ptr = socketbuffer;
					socketbuffer_len = len;
				}
				else
				{
					/* Clean up the stderr buffer in case FreeNX send something there */
					len = channel_read_nonblocking(channels_out[0], buffer, sizeof(buffer), 1);
				}
		}

		if (nx->running && socketbuffer_len > 0)
		{
			for (lenw = 0; socketbuffer_len > 0; socketbuffer_len -= lenw, socketbuffer_ptr += lenw)
			{
				lenw = write(sock, socketbuffer_ptr, socketbuffer_len);
				if (lenw == -1 && errno == EAGAIN && nx->running)
				{
					/* Sometimes we cannot write to a socket (always EAGAIN), probably because it's internal
					 * buffer is full. We need read the pending bytes from the socket first. so here we simply
					 * break, leave the buffer there, and continue with other data */
					break;
				}
				if (lenw <= 0)
				{
					nx->running = FALSE;
					break;
				}
			}
		}
	}

	nx->thread = 0;

	return NULL;
}
示例#29
0
文件: xfer.c 项目: hdm/framework2
/*
 * Channel write complete handler for writing data to the remote endpoint
 * during a file upload.
 */
DWORD file_upload_write_complete(Remote *remote, Channel *channel,
		LPVOID context, DWORD result, ULONG bytesWritten)
{
	FileUploadContext *ctx = (FileUploadContext *)context;
	ChannelCompletionRoutine complete;
	DWORD res = ERROR_SUCCESS;
	BOOL textPrinted = TRUE;
	CHAR buffer[8192];
	LONG bytesRead;

	do
	{
		// If the result was not successful, no sense in continuing
		if ((!channel) || 
		    (result != ERROR_SUCCESS))
		{
			console_write_output(
					"\n"
					INBOUND_PREFIX " FS: file_upload_write failed, result %lu.\n",
					result);
			res = result;
			break;
		}

		// Try to read more data from the local file
		bytesRead = fread(buffer, 1, sizeof(buffer), ctx->fd);

		// If there are no more bytes in the file, send a channel close
		// notification.
		if (bytesRead <= 0)
		{
			console_write_output(
					"\n"
					INBOUND_PREFIX " FS: Upload to '%s' completed.\n", ctx->source);

			channel_close(channel, remote, NULL, 0, NULL);
			break;
		}

		textPrinted = FALSE;

		// Keep writing to the channel until it's done with
		memset(&complete, 0, sizeof(complete));

		complete.context       = (LPVOID)ctx;
		complete.routine.write = file_upload_write_complete;

		// Write the buffer to the wire
		res = channel_write(channel, remote, NULL, 0,
				(PUCHAR)buffer, bytesRead, &complete);

	} while (0);

	// If the result was not successful, clean up the context here
	if (result != ERROR_SUCCESS)
	{
		if (channel)
			channel_close(channel, remote, NULL, 0, NULL);

		// Deallocate the passed in context
		if (ctx->fd)
			fclose(ctx->fd);

		free(ctx);
	}

	if (textPrinted)
		console_write_prompt();

	return res;
}
/*
 * core_channel_read
 * -----------------
 *
 * From from the local buffer and write back to the requester
 *
 * Takes TLVs:
 *
 * req: TLV_TYPE_CHANNEL_ID -- The channel identifier to read from
 * req: TLV_TYPE_LENGTH     -- The number of bytes to read
 */
DWORD remote_request_core_channel_read(Remote *remote, Packet *packet)
{
	DWORD res = ERROR_SUCCESS, bytesToRead, bytesRead, channelId;
	Packet *response = packet_create_response(packet);
	PUCHAR temporaryBuffer = NULL;
	Channel *channel = NULL;

	do
	{
		if (!response)
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Get the number of bytes to read
		bytesToRead = packet_get_tlv_value_uint(packet, TLV_TYPE_LENGTH);
		channelId   = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_ID);

		// Try to locate the specified channel
		if (!(channel = channel_find_by_id(channelId)))
		{
			res = ERROR_NOT_FOUND;
			break;
		}

		lock_acquire( channel->lock );

		// Allocate temporary storage
		if (!(temporaryBuffer = (PUCHAR)malloc(bytesToRead)))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		switch (channel_get_class(channel))
		{
			// If it's buffered, read from the local buffer and either transmit 
			// the buffer in the response or write it back asynchronously
			// depending on the mode of the channel.
			case CHANNEL_CLASS_BUFFERED:
				// Read in from local
				res = channel_read_from_buffered(channel, temporaryBuffer, 
				    bytesToRead, (PULONG)&bytesRead);
				break;
			// Handle read I/O for the pool class
			case CHANNEL_CLASS_POOL:
				// If the channel has a read handler
				if (channel->ops.pool.read)
					res = channel->ops.pool.read(channel, packet, 
							channel->ops.pool.native.context, temporaryBuffer, 
							bytesToRead, &bytesRead);
				else
					res = ERROR_NOT_SUPPORTED;
				break;
			default:
				res = ERROR_NOT_SUPPORTED;
		}

		// If we've so far been successful and we have a temporary buffer...
		if ((res == ERROR_SUCCESS) &&(temporaryBuffer) && (bytesRead))
		{
			// If the channel should operate synchronously, add the data to theresponse
			if (channel_is_flag(channel, CHANNEL_FLAG_SYNCHRONOUS))
			{
				// if the channel data is ment to be compressed, compress it!
				if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
					packet_add_tlv_raw(response, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, temporaryBuffer, bytesRead);
				else
					packet_add_tlv_raw(response, TLV_TYPE_CHANNEL_DATA, temporaryBuffer, bytesRead);

				res = ERROR_SUCCESS;
			}
			// Otherwise, asynchronously write the buffer to the remote endpoint
			else
			{
				if ((res = channel_write(channel, remote, NULL, 0, temporaryBuffer, bytesRead, NULL)) != ERROR_SUCCESS)
					break;
			}
		}

	} while (0);
	
	if( channel )
		lock_release( channel->lock );

	if (temporaryBuffer)
		free(temporaryBuffer);

	// Transmit the acknowledgement
	if (response)
	{
		packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
		packet_add_tlv_uint(response, TLV_TYPE_LENGTH, bytesRead);
		packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channelId);

		res = packet_transmit(remote, response, NULL);
	}

	return res;
}