DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto, const std::string& domain, const LogSink& logInstance ) { const std::string dname = "_" + service + "._" + proto + "." + domain; bool error = false; DNS::HostMap servers; DNS_RECORD* pRecord; if( DnsQuery( dname.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pRecord, NULL ) == ERROR_SUCCESS ) { DNS_RECORD* pRec = pRecord; do { if( pRec->wType == DNS_TYPE_SRV ) { servers[pRec->Data.SRV.pNameTarget] = pRec->Data.SRV.wPort; } pRec = pRec->pNext; } while( pRec != NULL ); DnsRecordListFree( pRecord, DnsFreeRecordList ); } else error = true; if( error || !servers.size() ) { servers = defaultHostMap( domain, logInstance ); } return servers; }
void ConnectionSOCKS5Proxy::handleConnect( const ConnectionBase* /*connection*/ ) { if( m_connection ) { std::string server = m_server; int port = m_port; if( port == -1 ) { DNS::HostMap servers = DNS::resolve( m_server, m_logInstance ); if( servers.size() ) { server = (*(servers.begin())).first; port = (*(servers.begin())).second; } } m_logInstance.log( LogLevelDebug, LogAreaClassConnectionSOCKS5Proxy, "attempting to negotiate socks5 proxy connection" ); bool auth = !m_proxyUser.empty() && !m_proxyPassword.empty(); char *d = new char[auth ? 4 : 3]; d[0] = 0x05; // SOCKS version 5 if( auth ) { d[1] = 0x02; // two methods d[3] = 0x02; // method: username/password auth } else d[1] = 0x01; // one method d[2] = 0x00; // method: no auth if( !send( std::string( d, auth ? 4 : 3 ) ) ) { cleanup(); if( m_handler ) m_handler->handleDisconnect( this, ConnIoError ); } delete[] d; } }
DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto, const std::string& domain, const LogSink& logInstance ) { const std::string dname = "_" + service + "._" + proto + "." + domain; bool error = false; DNS::HostMap servers; DNS_RECORD* pRecord = NULL; DNS_STATUS status = DnsQuery_UTF8( dname.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pRecord, NULL ); if( status == ERROR_SUCCESS ) { // NOTE: DnsQuery_UTF8 and DnsQuery_A really should have been defined with // PDNS_RECORDA instead of PDNS_RECORD, since that's what it is (even with _UNICODE defined). // We'll correct for that mistake with a cast. DNS_RECORDA* pRec = (DNS_RECORDA*)pRecord; do { if( pRec->wType == DNS_TYPE_SRV ) { servers[pRec->Data.SRV.pNameTarget] = pRec->Data.SRV.wPort; } pRec = pRec->pNext; } while( pRec != NULL ); DnsRecordListFree( pRecord, DnsFreeRecordList ); } else { logInstance.warn( LogAreaClassDns, "DnsQuery_UTF8() failed: " + util::int2string( status ) ); error = true; } if( error || !servers.size() ) { servers = defaultHostMap( domain, logInstance ); } return servers; }
void jConnection::loadSettings() { if(m_state != StateDisconnected) { DEBUG("Try to load settings in %d state", (int)m_state); return; } DEBUG() << Q_FUNC_INFO; loadProxySettings(); m_hosts.clear(); QSettings settings(QSettings::defaultFormat(), QSettings::UserScope, "qutim/qutim."+m_profile_name+"/jabber."+m_account_name, "accountsettings"); settings.beginGroup("main"); JID jid(utils::toStd(m_account_name)); QString server = utils::fromStd(jid.server()); int port = settings.value("port",5222).toInt(); m_use_dns_srv = settings.value("usedns", true).toBool(); TLSPolicy tls_policy = TLSOptional; if(server=="qutim.org") { server="jabber.qutim.org"; port = 5222; m_use_dns_srv = false; } bool use_sasl = settings.value("usesasl", true).toBool(); bool compress = settings.value("compress", true).toBool(); server = settings.value("server",server).toString(); m_server = utils::toStd(server); m_port = port; if(!m_use_dns_srv) { if(port==-1) port = 5222; m_hosts << qMakePair( server, port ); } else { static LogSink logsink; DNS::HostMap hosts = DNS::resolve(m_server, logsink); DNS::HostMap::iterator h = hosts.begin(); for(;h!=hosts.end();h++) { QPair<QString, int> host( utils::fromStd(h->first), h->second ); static const QRegExp valid_hostname( "(\\w+\\.)+\\w+" ); Q_ASSERT_X(valid_hostname.isValid(),"jConnection::loadSettings()","Regexp is not valid"); if( valid_hostname.exactMatch( host.first ) || !QHostAddress( host.first ).isNull() ) m_hosts.append(host); } if( m_hosts.isEmpty() ) m_hosts << qMakePair( server, 5222 ); } switch(settings.value("tlspolicy",1).toInt()) { case 0: tls_policy = TLSDisabled; break; case 1: tls_policy = TLSOptional; break; case 2: tls_policy = TLSRequired; break; } settings.endGroup(); ClientBase *jClient = dynamic_cast<ClientBase*>(m_handler); if(!jClient) { DEBUG("Try to load settings, but handler is not ClientBase. Error os %d", (int)m_error); m_handler->handleDisconnect(this, m_error); if(!(jClient = dynamic_cast<ClientBase*>(m_handler))) { DEBUG("Try lo load settings, but handle disconnect go wrong"); return; } } jClient->setTls(tls_policy); jClient->setSasl(use_sasl); jClient->setCompression(compress); }
void ConnectionSOCKS5Proxy::negotiate() { m_s5state = S5StateNegotiating; char *d = new char[m_ip ? 10 : 6 + m_server.length() + 1]; int pos = 0; d[pos++] = 0x05; // SOCKS version 5 d[pos++] = 0x01; // command CONNECT d[pos++] = 0x00; // reserved int port = m_port; std::string server = m_server; if( m_ip ) // IP address { d[pos++] = 0x01; // IPv4 address std::string s; int j = server.length(); int l = 0; for( int k = 0; k < j && l < 4; ++k ) { if( server[k] != '.' ) s += server[k]; if( server[k] == '.' || k == j-1 ) { d[pos++] = atoi( s.c_str() ) & 0x0FF; s = ""; ++l; } } } else // hostname { if( port == -1 ) { DNS::HostMap servers = DNS::resolve( m_server, m_logInstance ); if( servers.size() ) { server = (*(servers.begin())).first; port = (*(servers.begin())).second; } } d[pos++] = 0x03; // hostname d[pos++] = m_server.length(); strncpy( d + pos, m_server.c_str(), m_server.length() ); pos += m_server.length(); } int nport = htons( port ); d[pos++] = nport; d[pos++] = nport >> 8; #ifndef _WIN32_WCE std::ostringstream oss; oss << "requesting socks5 proxy connection to " << server << ":" << port; m_logInstance.log( LogLevelDebug, LogAreaClassConnectionSOCKS5Proxy, oss.str() ); #endif if( !send( std::string( d, pos ) ) ) { cleanup(); m_handler->handleDisconnect( this, ConnIoError ); } delete[] d; }