boost::optional<NATPortMapping> NATPMPInterface::addPortForward(int localPort, int publicPort) {
	NATPortMapping mapping(localPort, publicPort, NATPortMapping::TCP);
	if (sendnewportmappingrequest(&p->natpmp, mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, mapping.getLeaseInSeconds(), mapping.getPublicPort(), mapping.getLocalPort()) < 0) {
			SWIFT_LOG(debug) << "Failed to send NAT-PMP port forwarding request!" << std::endl;
			return boost::optional<NATPortMapping>();
	}

	int r = 0;
	natpmpresp_t response;
	do {
		fd_set fds;
		struct timeval timeout;
		FD_ZERO(&fds);
		FD_SET(p->natpmp.s, &fds);
		getnatpmprequesttimeout(&p->natpmp, &timeout);
		select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
		r = readnatpmpresponseorretry(&p->natpmp, &response);
	} while(r == NATPMP_TRYAGAIN);

	if (r == 0) {
		NATPortMapping result(response.pnu.newportmapping.privateport, response.pnu.newportmapping.mappedpublicport, NATPortMapping::TCP, response.pnu.newportmapping.lifetime);
		return result;
	}
	else {
		SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl;
		return boost::optional<NATPortMapping>();
	}
}
boost::optional<HostAddress> NATPMPInterface::getPublicIP() {
	if (sendpublicaddressrequest(&p->natpmp) < 0) {
		SWIFT_LOG(debug) << "Failed to send NAT-PMP public address request!" << std::endl;
		return boost::optional<HostAddress>();
	}

	int r = 0;
	natpmpresp_t response;
	do {
	  fd_set fds;
	  struct timeval timeout;
	  FD_ZERO(&fds);
	  FD_SET(p->natpmp.s, &fds);
	  getnatpmprequesttimeout(&p->natpmp, &timeout);
	  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
	  r = readnatpmpresponseorretry(&p->natpmp, &response);
	} while (r == NATPMP_TRYAGAIN);

	if (r == 0) {
		return boost::optional<HostAddress>(HostAddress(reinterpret_cast<const unsigned char*>(&(response.pnu.publicaddress.addr)), 4));
	}
	else {
		SWIFT_LOG(debug) << "Inavlid NAT-PMP response." << std::endl;
		return boost::optional<HostAddress>();
	}
}
bool NATPMPInterface::removePortForward(const NATPortMapping& mapping) {
	if (sendnewportmappingrequest(&p->natpmp, mapping.getProtocol() == NATPortMapping::TCP ? NATPMP_PROTOCOL_TCP : NATPMP_PROTOCOL_UDP, 0, 0, mapping.getLocalPort()) < 0) {
		SWIFT_LOG(debug) << "Failed to send NAT-PMP remove forwarding request!" << std::endl;
		return false;
	}

	int r = 0;
	natpmpresp_t response;
	do {
	  fd_set fds;
	  struct timeval timeout;
	  FD_ZERO(&fds);
	  FD_SET(p->natpmp.s, &fds);
	  getnatpmprequesttimeout(&p->natpmp, &timeout);
	  select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
	  r = readnatpmpresponseorretry(&p->natpmp, &response);
	} while(r == NATPMP_TRYAGAIN);

	if (r == 0) {
		return true;
	}
	else {
		SWIFT_LOG(debug) << "Invalid NAT-PMP response." << std::endl;
		return false;
	}
}
		virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, IBB::ref ibb) {
			if (from == session->from && ibb->getStreamID() == session->id) {
				if (ibb->getAction() == IBB::Data) {
					if (sequenceNumber == ibb->getSequenceNumber()) {
						session->onDataReceived(ibb->getData());
						receivedSize += ibb->getData().size();
						sequenceNumber++;
						sendResponse(from, id, IBB::ref());
						if (receivedSize >= session->size) {
							if (receivedSize > session->size) {
								std::cerr << "Warning: Received more data than expected" << std::endl;
							}
							session->finish(boost::optional<FileTransferError>());
						}
					}
					else {
						SWIFT_LOG(warning) << "Received data out of order" << std::endl;
						sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel);
						session->finish(FileTransferError(FileTransferError::ClosedError));
					}
				}
				else if (ibb->getAction() == IBB::Open) {
					SWIFT_LOG(debug) << "IBB open received" << std::endl;
					sendResponse(from, id, IBB::ref());
				}
				else if (ibb->getAction() == IBB::Close) {
					SWIFT_LOG(debug) << "IBB close received" << std::endl;
					sendResponse(from, id, IBB::ref());
					session->finish(FileTransferError(FileTransferError::ClosedError));
				}
				return true;
			}
			SWIFT_LOG(debug) << "wrong from/sessionID: " << from << " == " << session->from << " / " <<ibb->getStreamID() << " == " << session->id << std::endl;
			return false;
		}
NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() const {
#ifdef HAVE_LIBMINIUPNPC
	if (boost::logic::indeterminate(miniUPnPSupported)) {
		miniUPnPInterface = new MiniUPnPInterface();
		miniUPnPSupported = miniUPnPInterface->isAvailable();
	}
	SWIFT_LOG(debug) << "UPnP NAT traversal supported: " << miniUPnPSupported << std::endl;
	if (miniUPnPSupported) {
		return miniUPnPInterface;
	}
#endif

#ifdef HAVE_LIBNATPMP
	if (boost::logic::indeterminate(natPMPSupported)) {
		natPMPInterface = new NATPMPInterface();
		natPMPSupported = natPMPInterface->isAvailable();
	}
	SWIFT_LOG(debug) << "NAT-PMP NAT traversal supported: " << natPMPSupported << std::endl;
	if (natPMPSupported) {
		return natPMPInterface;
	}
#endif

	return nullNATTraversalInterface;
}
예제 #6
0
void CoreClient::forceReset() {
    if (connector_) {
        SWIFT_LOG(warning) << "Client not disconnected properly: Connector still active" << std::endl;
        resetConnector();
    }
    if (sessionStream_ || connection_) {
        SWIFT_LOG(warning) << "Client not disconnected properly: Session still active" << std::endl;
        resetSession();
    }
}
DWORD WindowsServicePrincipalName::dsMakeSpn(DWORD* length, wchar_t* value) {
    DWORD status;

#ifdef UNICODE
    SWIFT_LOG(debug) << "UNICODE is defined" << std::endl;
#else
    SWIFT_LOG(debug) << "UNICODE is not defined" << std::endl;
#endif

    SWIFT_LOG(debug) << "serviceClass_: " << convertWStringToString(serviceClass_.c_str()) << std::endl;
    SWIFT_LOG(debug) << "serviceName_: " << convertWStringToString(serviceName_.c_str()) << std::endl;
    SWIFT_LOG(debug) << "instanceName_: " << convertWStringToString(instanceName_.c_str()) << std::endl;
    SWIFT_LOG(debug) << "referrer_: " << convertWStringToString(referrer_.c_str()) << std::endl;
    SWIFT_LOG(debug) << "instancePort_: " << instancePort_ << std::endl;
    SWIFT_LOG(debug) << "length: " << *length << std::endl;

    /* Call the Unicode function because that is recommended:
https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407%28v=vs.85%29.aspx */
    status =  DsMakeSpnW(
            serviceClass_.c_str(),
            serviceName_.c_str(),
            instanceName_.empty() ? NULL : instanceName_.c_str(),
            instancePort_,
            referrer_.empty() ? NULL : referrer_.c_str(),
            length,
            value);
    if (status != ERROR_SUCCESS) {
        boost::system::error_code errorCode(status, boost::system::system_category());

        SWIFT_LOG(debug) << std::hex << "status: 0x" << status << ": " << errorCode.message() << std::endl;
    }

    return status;
}
void WindowsGSSAPIClientAuthenticator::buildSecurityContext(const boost::optional<ByteArray>& inputToken) {
    ULONG contextSupported;

    /* An XMPP server may not support Kerberos encryption or SASL security layer so not requesting integrity or confidentiality */
    errorCode_ = initializeSecurityContext(inputToken, servicePrincipalNameString_, &credentialsHandle_, haveContextHandle_, &contextHandle_, ISC_REQ_MUTUAL_AUTH, &contextSupported, &haveCompleteContext_, response_);
    if (isError()) {
        return;
    }

    haveContextHandle_ = true;

    if (!haveCompleteContext_) {
        return;
    }

    if (contextSupported & ISC_REQ_MUTUAL_AUTH == 0) {
        SWIFT_LOG(debug) << "Mutual authentication not supported" << std::endl;
        error_ = true;
        return;
    }

    errorCode_ = queryContextAttributes(&contextHandle_, SECPKG_ATTR_SIZES, &sizes_);
    if (isError()) {
        return;
    }

    /* Commenting this out as it gives the error code 0x80090302: The function requested is not supported
    errorCode_ = queryContextAttributes(&contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_);
    if (isError()) {
        return;
    }*/

    SecPkgContext_Names names;
    errorCode_ = queryContextAttributes(&contextHandle_, SECPKG_ATTR_NAMES, &names);
    if (isError()) {
        return;
    }

    userName_ = names.sUserName;
    SWIFT_LOG(debug) << "User name: " << userName_ << std::endl;

    std::size_t position = userName_.find("\\");
    clientName_ = userName_.substr(position + 1);
    SWIFT_LOG(debug) << "Client name: " << clientName_ << std::endl;

    serverName_ = userName_.substr(0, position);
    SWIFT_LOG(debug) << "Server name: " << serverName_ << std::endl;

    freeContextBuffer(names.sUserName);
    step_ = SecurityLayerNegotiation;
}
예제 #9
0
boost::optional<std::string> CombinedAvatarProvider::getCombinedAvatarAndCache(const JID& jid) const {
	SWIFT_LOG(debug) << "JID: " << jid << std::endl;
	boost::optional<std::string> hash;
	for (size_t i = 0; i < providers.size() && !hash; ++i) {
		hash = providers[i]->getAvatarHash(jid);
		SWIFT_LOG(debug) << "Provider " << providers[i] << ": " << (hash ? hash.get() : "NULL") << std::endl;
	}
	if (hash) {
		avatars[jid] = *hash;
	} else {
		avatars[jid] = "";
	}
	return hash;
}
예제 #10
0
void Connector::tryConnect(const HostAddressPort& target) {
	assert(!currentConnection);
	SWIFT_LOG(debug) << "Trying to connect to " << target.getAddress().toString() << ":" << target.getPort() << std::endl;
	currentConnection = connectionFactory->createConnection();
	currentConnection->onConnectFinished.connect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1));
	currentConnection->connect(target);
}
예제 #11
0
void ClientSessionStanzaChannel::send(std::shared_ptr<Stanza> stanza) {
    if (!isAvailable()) {
        SWIFT_LOG(warning) << "Client: Trying to send a stanza while disconnected." << std::endl;
        return;
    }
    session->sendStanza(stanza);
}
예제 #12
0
QString QtScaledAvatarCache::getScaledAvatarPath(const QString& path) {
	QFileInfo avatarFile(path);
	if (avatarFile.exists()) {
		if (!avatarFile.dir().exists(QString::number(size))) {
			if (!avatarFile.dir().mkdir(QString::number(size))) {
				return path;
			}
		}
		QDir targetDir(avatarFile.dir().absoluteFilePath(QString::number(size)));
		QString targetFile = targetDir.absoluteFilePath(avatarFile.baseName());
		if (!QFileInfo(targetFile).exists()) {
			QPixmap avatarPixmap;
			if (avatarPixmap.load(path)) {
				QPixmap maskedAvatar(avatarPixmap.size());
				maskedAvatar.fill(QColor(0, 0, 0, 0));
				QPainter maskPainter(&maskedAvatar);
				maskPainter.setBrush(Qt::black);
				maskPainter.drawRoundedRect(maskedAvatar.rect(), 25.0, 25.0, Qt::RelativeSize);
				maskPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
				maskPainter.drawPixmap(0, 0, avatarPixmap);
				maskPainter.end();

				if (!maskedAvatar.scaled(size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation).save(targetFile, "PNG")) {
					return path;
				}
			} else {
				SWIFT_LOG(debug) << "Failed to load " << Q2PSTRING(path) << std::endl;
			}
		}
		return targetFile;
	}
	else {
		return path;
	}
}
void LocalJingleTransportCandidateGenerator::handleS5BServerInitialized(bool success) {
    if (s5bServerResourceUser_) {
        s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1));
    }
    triedServerInit_ = true;
    if (success) {
        if (options_.isAssistedAllowed()) {
            // try to setup port forwarding
            s5bServerPortForwardingUser_ = s5bServerManager->aquirePortForwardingUser();
            s5bServerPortForwardingUser_->onSetup.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1));
            if (s5bServerPortForwardingUser_->isForwardingSetup()) {
                handlePortForwardingSetup(true);
            }
        }
    }
    else {
        SWIFT_LOG(warning) << "Unable to start SOCKS5 server" << std::endl;
        if (s5bServerResourceUser_) {
            s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1));
        }
        s5bServerResourceUser_.reset();
        handlePortForwardingSetup(false);
    }
    checkS5BCandidatesReady();
}
예제 #14
0
파일: Connector.cpp 프로젝트: swift/swift
void Connector::start() {
    SWIFT_LOG(debug) << "Starting connector for " << hostname << std::endl;
    assert(!currentConnection);
    assert(!serviceQuery);
    assert(!timer);
    queriedAllServices = false;
    auto hostAddress = HostAddress::fromString(hostname);
    if (timeoutMilliseconds > 0) {
        timer = timerFactory->createTimer(timeoutMilliseconds);
        timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this()));
    }
    if (serviceLookupPrefix) {
        serviceQuery = resolver->createServiceQuery(*serviceLookupPrefix, hostname);
        serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1));
        serviceQuery->run();
    }
    else if (hostAddress) {
        // hostname is already a valid address; skip name lookup.
        foundSomeDNS = true;
        addressQueryResults.push_back(hostAddress.get());
        tryNextAddress();
    } else {
        queryAddress(hostname);
    }
}
예제 #15
0
bool IncomingFileTransferManager::handleIncomingJingleSession(
        JingleSession::ref session,
        const std::vector<JingleContentPayload::ref>& contents,
        const JID& recipient) {
    if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) {
        if (content->getTransport<JingleS5BTransportPayload>() || content->getTransport<JingleIBBTransportPayload>()) {
            JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>();
            if (description) {
                IncomingJingleFileTransfer::ref transfer = std::make_shared<IncomingJingleFileTransfer>(
                        recipient, session, content, transporterFactory, timerFactory, crypto);
                onIncomingFileTransfer(transfer);
            }
            else {
                SWIFT_LOG(warning) << "Received a file-transfer request with no file description.";
                session->sendTerminate(JinglePayload::Reason::FailedApplication);
            }
        }
        else {
            session->sendTerminate(JinglePayload::Reason::UnsupportedTransports);
        }
        return true;
    }
    else {
        return false;
    }
}
예제 #16
0
void Connector::tryNextServiceOrFallback() {
	if (queriedAllServices) {
		SWIFT_LOG(debug) << "Queried all services" << std::endl;
		finish(boost::shared_ptr<Connection>());
	}
	else if (serviceQueryResults.empty()) {
		SWIFT_LOG(debug) << "Falling back on A resolution" << std::endl;
		// Fall back on simple address resolving
		queriedAllServices = true;
		queryAddress(hostname);
	}
	else {
		SWIFT_LOG(debug) << "Querying next address" << std::endl;
		queryAddress(serviceQueryResults.front().hostname);
	}
}
예제 #17
0
std::string WindowsServicePrincipalName::toString() {
    DWORD length = 512;
    DWORD status = ERROR_BUFFER_OVERFLOW;
    bool firstCall = true;
    std::string str;

    while (status == ERROR_BUFFER_OVERFLOW) {
        std::vector<wchar_t> value(length);

        /* length after this call will contain the required length if current length is not enough - so the next call should succeed */
        status = dsMakeSpn(&length, vecptr(value));
        if (status == ERROR_SUCCESS) {
            str = convertWStringToString(std::wstring(vecptr(value), length-1 /* trailing 0 character */));
            break;
        }

        if ((firstCall == false) || (status != ERROR_BUFFER_OVERFLOW)) {
            std::stringstream errorString;
            boost::system::error_code errorCode(status, boost::system::system_category());

            errorString << "Error creating Service Principal Name: status: 0x" << std::hex << status << ": " << errorCode.message();

            /* Any other error will be a programming error */
            throw std::runtime_error(errorString.str());
        }

        firstCall = false;
    }

    SWIFT_LOG(debug) << "SPN: " << str << std::endl;
    return str;
}
void SOCKS5BytestreamClientSession::handleConnectFinished(bool error) {
	connectFinishedConnection.disconnect();
	if (error) {
		SWIFT_LOG(debug) << "Failed to connect via TCP to " << addressPort.toString() << "." << std::endl;
		finish(true);
	} else {
		SWIFT_LOG(debug) << "Successfully connected via TCP" << addressPort.toString() << "." << std::endl;
		disconnectedConnection = connection->onDisconnected.connect(
				boost::bind(&SOCKS5BytestreamClientSession::handleDisconnected, this, _1));
		dataReadConnection = connection->onDataRead.connect(
				boost::bind(&SOCKS5BytestreamClientSession::handleDataRead, this, _1));
		weFailedTimeout->stop();
		weFailedTimeout->start();
		process();
	}
}
void SOCKS5BytestreamClientSession::start() {
	assert(state == Initial);
	SWIFT_LOG(debug) << "Trying to connect via TCP to " << addressPort.toString() << "." << std::endl;
	weFailedTimeout->start();
	connectFinishedConnection = connection->onConnectFinished.connect(
			boost::bind(&SOCKS5BytestreamClientSession::handleConnectFinished, this, _1));
	connection->connect(addressPort);
}
예제 #20
0
bool BOSHConnection::setClientCertificate(CertificateWithKey::ref cert) {
    if (tlsLayer_) {
        SWIFT_LOG(debug) << "set client certificate" << std::endl;
        return tlsLayer_->setClientCertificate(cert);
    }
    else {
        return false;
    }
}
예제 #21
0
void Connector::handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result) {
	SWIFT_LOG(debug) << result.size() << " SRV result(s)" << std::endl;
	serviceQueryResults = std::deque<DomainNameServiceQuery::Result>(result.begin(), result.end());
	serviceQuery.reset();
	if (!serviceQueryResults.empty()) {
		foundSomeDNS = true;
	}
	tryNextServiceOrFallback();
}
예제 #22
0
void BoostConnection::handleConnectFinished(const boost::system::error_code& error) {
	SWIFT_LOG(debug) << "Connect finished: " << error << std::endl;
	if (!error) {
		eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), false), shared_from_this());
		doRead();
	}
	else if (error != boost::asio::error::operation_aborted) {
		eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), true), shared_from_this());
	}
}
void IBBReceiveSession::stop() {
	SWIFT_LOG(debug) << "receive session stopped" << std::endl;
	responder->stop();
	if (active) {
		if (router->isAvailable()) {
			IBBRequest::create(to, from, IBB::createIBBClose(id), router)->send();
		}
		finish(boost::optional<FileTransferError>());
	}
}
void SOCKS5BytestreamClientSession::handleDataRead(boost::shared_ptr<SafeByteArray> data) {
	SWIFT_LOG(debug) << "state: " << state << " data.size() = " << data->size() << std::endl;
	if (state != Reading) {
		append(unprocessedData, *data);
		process();
	}
	else {
		writeBytestream->write(createByteArray(vecptr(*data), data->size()));
		//onBytesReceived(data->size());
	}
}
void SOCKS5BytestreamClientSession::startSending(boost::shared_ptr<ReadBytestream> readStream) {
	if (state == Ready) {
		state = Writing;
		readBytestream = readStream;
		dataWrittenConnection = connection->onDataWritten.connect(
				boost::bind(&SOCKS5BytestreamClientSession::sendData, this));
		sendData();
	} else {
		SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl;
	}
}
void SOCKS5BytestreamClientSession::startReceiving(boost::shared_ptr<WriteBytestream> writeStream) {
	if (state == Ready) {
		state = Reading;
		writeBytestream = writeStream;
		writeBytestream->write(unprocessedData);
		//onBytesReceived(unprocessedData.size());
		unprocessedData.clear();
	} else {
		SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl;
	}
}
void SOCKS5BytestreamClientSession::authenticate() {
	SWIFT_LOG(debug) << std::endl;
	SafeByteArray header = createSafeByteArray("\x05\x01\x00\x03", 4);
	SafeByteArray message = header;
	append(message, createSafeByteArray(boost::numeric_cast<char>(destination.size())));
	authenticateAddress = createByteArray(destination);
	append(message, authenticateAddress);
	append(message, createSafeByteArray("\x00\x00", 2)); // 2 byte for port
	connection->write(message);
	state = Authenticating;
}
예제 #28
0
CoreComponent::~CoreComponent() {
    if (session_ || connection_) {
        SWIFT_LOG(warning) << "Component not disconnected properly" << std::endl;
    }
    delete iqRouter_;

    stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1));
    stanzaChannel_->onMessageReceived.disconnect(boost::ref(onMessageReceived));
    stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived));
    delete stanzaChannel_;
}
예제 #29
0
void BOSHConnection::write(const SafeByteArray& data, bool streamRestart, bool terminate) {
    assert(connectionReady_);
    assert(!sid_.empty());

    SafeByteArray safeHeader = createHTTPRequest(data, streamRestart, terminate, rid_, sid_, boshURL_).first;

    onBOSHDataWritten(safeHeader);
    writeData(safeHeader);
    pending_ = true;

    SWIFT_LOG(debug) << "write data: " << safeByteArrayToString(safeHeader) << std::endl;
}
void SOCKS5BytestreamClientSession::stop() {
	SWIFT_LOG(debug) << std::endl;
	if (state < Ready) {
		weFailedTimeout->stop();
	}
	if (state == Finished) {
		return;
	}
	closeConnection();
	readBytestream.reset();
	state = Finished;
}