static void ssh_channel_cb(obfsproxyssh_client_session_t *session) { static const char socks_4_resp[] = { 0x00, /* VN */ SOCKS_4_REQUEST_GRANTED, /* CD */ 0x00, 0x00, /* DSTPORT */ 0x00 ,0x00, 0x00, 0x00 /* DSTIP */ }; obfsproxyssh_t *state = session->client->state; session->ssh_channel = libssh2_channel_direct_tcpip(session->ssh_session, "127.0.0.1", session->orport); if (NULL == session->ssh_channel) { if (LIBSSH2_ERROR_EAGAIN == libssh2_session_last_errno(session->ssh_session)) return; else { log_f(state, "SSH: Error: %s Failed to initialize direct-tcp channel", bdata(session->ssh_addr)); libssh2_session_free(session->ssh_session); session->ssh_session = NULL; session_free(session); return; } } /* Send the SOCKS 4 response */ bufferevent_write(session->socks_ev, socks_4_resp, SOCKS_4_CONNECT_RESPONSE_LEN); /* Renable reading/writing on the buffer event */ bufferevent_enable(session->socks_ev, EV_READ); bufferevent_setcb(session->socks_ev, socks_relay_cb, NULL, socks_event_cb, session); session->socks_is_valid = 1; /* Change the event callback to something that does channel cleanup */ bufferevent_setcb(session->ssh_ev, ssh_read_cb, ssh_write_cb, ssh_relay_event_cb, session); session->libssh2_cb = ssh_relay_cb; }
bool QxtSshChannelPrivate::activate(){ //session if(d_state==1){ d_channel=libssh2_channel_open_session(d_session); if(d_channel==NULL){ if(libssh2_session_last_error(d_session,NULL,NULL,0)==LIBSSH2_ERROR_EAGAIN) { return true; }else{ return false; } } #ifdef QXT_DEBUG_SSH qDebug("session opened"); #endif d_state=2; return activate(); //transition to allow early cmd }else if (d_state==2){ if(!d_next_actions.isEmpty()){ d_state=d_next_actions.takeFirst(); return activate(); }else{ return true; } //request pty }else if (d_state==5){ int r=libssh2_channel_request_pty(d_channel,d_pty.data()); if(r){ if(r==LIBSSH2_ERROR_EAGAIN){ return true; }else{ qWarning("QxtSshChannel: pty allocation failed"); return false; } } #ifdef QXT_DEBUG_SSH qDebug("pty opened"); #endif d_state=2; return activate(); //start }else if (d_state==3){ int r=libssh2_channel_exec(d_channel,qPrintable(d_cmd)); if(r){ if(r==LIBSSH2_ERROR_EAGAIN){ return true; }else{ #ifdef QXT_DEBUG_SSH qDebug("exec failed"); #endif return false; } } #ifdef QXT_DEBUG_SSH qDebug("exec opened"); #endif p->setOpenMode(QIODevice::ReadWrite); d_state=66; emit p->connected(); return true; //start shell }else if (d_state==4){ int r=libssh2_channel_shell(d_channel); if(r){ if(r==LIBSSH2_ERROR_EAGAIN){ return true; }else{ #ifdef QXT_DEBUG_SSH qDebug("exec failed"); #endif return false; } } #ifdef QXT_DEBUG_SSH qDebug("shell opened"); #endif p->setOpenMode(QIODevice::ReadWrite); d_state=9999; emit p->connected(); return true; // tcp channel }else if (d_state==10){ d_channel=libssh2_channel_direct_tcpip(d_session, qPrintable(d_host),d_port); if(d_channel==NULL){ if(libssh2_session_last_error(d_session,NULL,NULL,0)==LIBSSH2_ERROR_EAGAIN) { return true; }else{ return false; } } #ifdef QXT_DEBUG_SSH qDebug("tcp channel opened"); #endif p->setOpenMode(QIODevice::ReadWrite); d_state=9999; return activate(); //read channel }else if (d_state==9999){ emit p->readyRead(); } return true; }
static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout, const char *source_addr) { #ifdef FASTOREDIS if(c->session){ if (!(c->channel = libssh2_channel_direct_tcpip(c->session, addr, port))) { __redisSetError(c, REDIS_ERR_OTHER, "Unable to open a ssh session"); return REDIS_ERR; } c->flags |= REDIS_CONNECTED; return REDIS_OK; } #endif int s, rv, n; char _port[6]; /* strlen("65535"); */ struct addrinfo hints, *servinfo, *bservinfo, *p, *b; int blocking = (c->flags & REDIS_BLOCK); int reuseaddr = (c->flags & REDIS_REUSEADDR); int reuses = 0; snprintf(_port, 6, "%d", port); memset(&hints,0,sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; /* Try with IPv6 if no IPv4 address was found. We do it in this order since * in a Redis client you can't afford to test if you have IPv6 connectivity * as this would add latency to every connect. Otherwise a more sensible * route could be: Use IPv6 if both addresses are available and there is IPv6 * connectivity. */ if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { hints.ai_family = AF_INET6; if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); return REDIS_ERR; } } for (p = servinfo; p != NULL; p = p->ai_next) { addrretry: if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) continue; c->fd = s; if (redisSetBlocking(c,0) != REDIS_OK) goto error; if (source_addr) { int bound = 0; /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) { char buf[128]; snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv)); __redisSetError(c,REDIS_ERR_OTHER,buf); goto error; } if (reuseaddr) { n = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &n, sizeof(n)) < 0) { goto error; } } for (b = bservinfo; b != NULL; b = b->ai_next) { if (bind(s,b->ai_addr,b->ai_addrlen) != -1) { bound = 1; break; } } freeaddrinfo(bservinfo); if (!bound) { char buf[128]; snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno)); __redisSetError(c,REDIS_ERR_OTHER,buf); goto error; } } if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { if (errno == EHOSTUNREACH) { redisContextCloseFd(c); continue; } else if (errno == EINPROGRESS && !blocking) { /* This is ok. */ } else if (errno == EADDRNOTAVAIL && reuseaddr) { if (++reuses >= REDIS_CONNECT_RETRIES) { goto error; } else { goto addrretry; } } else { if (redisContextWaitReady(c,timeout) != REDIS_OK) goto error; } } if (blocking && redisSetBlocking(c,1) != REDIS_OK) goto error; if (redisSetTcpNoDelay(c) != REDIS_OK) goto error; c->flags |= REDIS_CONNECTED; rv = REDIS_OK; goto end; } if (p == NULL) { char buf[128]; snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); __redisSetError(c,REDIS_ERR_OTHER,buf); goto error; } error: rv = REDIS_ERR; end: freeaddrinfo(servinfo); return rv; // Need to return REDIS_OK if alright }