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;
}
예제 #2
0
void OpenSSLContext::sendPendingDataToApplication() {
	SafeByteArray data;
	data.resize(SSL_READ_BUFFERSIZE);
	int ret = SSL_read(handle_, vecptr(data), data.size());
	while (ret > 0) {
		data.resize(ret);
		onDataForApplication(data);
		data.resize(SSL_READ_BUFFERSIZE);
		ret = SSL_read(handle_, vecptr(data), data.size());
	}
	if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) {
		state_ = Error;
		onError(boost::make_shared<TLSError>());
	}
}
예제 #3
0
ByteArray OpenSSLContext::getFinishMessage() const {
	ByteArray data;
	data.resize(MAX_FINISHED_SIZE);
	size_t size = SSL_get_finished(handle_, vecptr(data), data.size());
	data.resize(size);
	return data;
}
예제 #4
0
void OpenSSLContext::handleDataFromApplication(const SafeByteArray& data) {
	if (SSL_write(handle_, vecptr(data), data.size()) >= 0) {
		sendPendingDataToNetwork();
	}
	else {
		state_ = Error;
		onError(boost::make_shared<TLSError>());
	}
}
예제 #5
0
void OpenSSLContext::sendPendingDataToNetwork() {
	int size = BIO_pending(writeBIO_);
	if (size > 0) {
		SafeByteArray data;
		data.resize(size);
		BIO_read(writeBIO_, vecptr(data), size);
		onDataForNetwork(data);
	}
}
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());
	}
}
예제 #7
0
void OpenSSLContext::handleDataFromNetwork(const SafeByteArray& data) {
	BIO_write(readBIO_, vecptr(data), data.size());
	switch (state_) {
		case Connecting:
			doConnect();
			break;
		case Connected:
			sendPendingDataToApplication();
			break;
		case Start: assert(false); break;
		case Error: /*assert(false);*/ break;
	}
}
예제 #8
0
SafeByteArray ZLibCodecompressor::process(const SafeByteArray& input) {
    SafeByteArray output;
    p->stream.avail_in = static_cast<unsigned int>(input.size());
    p->stream.next_in = reinterpret_cast<Bytef*>(const_cast<unsigned char*>(vecptr(input)));
    size_t outputPosition = 0;
    do {
        output.resize(outputPosition + CHUNK_SIZE);
        p->stream.avail_out = CHUNK_SIZE;
        p->stream.next_out = reinterpret_cast<Bytef*>(vecptr(output) + outputPosition);
        int result = processZStream();
        if (result != Z_OK && result != Z_BUF_ERROR) {
            throw ZLibException(/* p->stream.msg */);
        }
        outputPosition += CHUNK_SIZE;
    }
    while (p->stream.avail_out == 0);
    if (p->stream.avail_in != 0) {
        throw ZLibException();
    }
    output.resize(outputPosition - p->stream.avail_out);
    return output;
}
예제 #9
0
bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) {
	boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate);
	if (!pkcs12Certificate || pkcs12Certificate->isNull()) {
		return false;
	}

	// Create a PKCS12 structure
	BIO* bio = BIO_new(BIO_s_mem());
	BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size());
	boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free);
	BIO_free(bio);
	if (!pkcs12) {
		return false;
	}

	// Parse PKCS12
	X509 *certPtr = 0;
	EVP_PKEY* privateKeyPtr = 0;
	STACK_OF(X509)* caCertsPtr = 0;
	int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(pkcs12Certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr);
	if (result != 1) { 
		return false;
	}
	boost::shared_ptr<X509> cert(certPtr, X509_free);
	boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free);
	boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack);

	// Use the key & certificates
	if (SSL_CTX_use_certificate(context_, cert.get()) != 1) {
		return false;
	}
	if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) {
		return false;
	}
	for (int i = 0;  i < sk_X509_num(caCerts.get()); ++i) {
		SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i));
	}
	return true;
}
예제 #10
0
void CertificateFileStorage::addCertificate(Certificate::ref certificate) {
	boost::filesystem::path certificatePath = getCertificatePath(certificate);
	if (!boost::filesystem::exists(certificatePath.parent_path())) {
		try {
			boost::filesystem::create_directories(certificatePath.parent_path());
		}
		catch (const boost::filesystem::filesystem_error& e) {
			std::cerr << "ERROR: " << e.what() << std::endl;
		}
	}
	boost::filesystem::ofstream file(certificatePath, boost::filesystem::ofstream::binary|boost::filesystem::ofstream::out);
	ByteArray data = certificate->toDER();
	file.write(reinterpret_cast<const char*>(vecptr(data)), boost::numeric_cast<std::streamsize>(data.size()));
	file.close();
}
std::vector<NetworkInterface> WindowsNetworkEnvironment::getNetworkInterfaces()  const {
	std::vector<NetworkInterface> result;

	ByteArray adapters;
	ULONG bufferSize = 0;
	ULONG ret;
	ULONG flags = GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
	while ((ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, reinterpret_cast<IP_ADAPTER_ADDRESSES*>(vecptr(adapters)), &bufferSize)) == ERROR_BUFFER_OVERFLOW) {
		adapters.resize(bufferSize);
	};
	if (ret != ERROR_SUCCESS) {
		return result;
	}

	std::map<std::string,NetworkInterface> interfaces;
	for (IP_ADAPTER_ADDRESSES* adapter = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(vecptr(adapters)); adapter; adapter = adapter->Next) {
		std::string name(adapter->AdapterName);
		if (adapter->OperStatus != IfOperStatusUp) {
			continue;
		}
		for (IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress; address; address = address->Next) {
			boost::optional<HostAddress> hostAddress;
			if (address->Address.lpSockaddr->sa_family == PF_INET) {
				sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(address->Address.lpSockaddr);
				hostAddress = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin_addr)), 4);
			}
			else if (address->Address.lpSockaddr->sa_family == PF_INET6) {
				sockaddr_in6* sa = reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
				hostAddress = HostAddress(reinterpret_cast<const unsigned char*>(&(sa->sin6_addr)), 16);
			}
			if (hostAddress) {
				std::map<std::string, NetworkInterface>::iterator i = interfaces.insert(std::make_pair(name, NetworkInterface(name, false))).first;
				i->second.addAddress(*hostAddress);
			}
		}
	}

	for (std::map<std::string,NetworkInterface>::const_iterator i = interfaces.begin(); i != interfaces.end(); ++i) {
		result.push_back(i->second);
	}
	return result;
}
예제 #12
0
PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName) {
	if (!boost::iequals(certName.substr(0, 5), "sha1:")) {

		// Find client certificate. Note that this sample just searches for a
		// certificate that contains the user name somewhere in the subject name.
		return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /*dwFindFlags*/ 0, CERT_FIND_SUBJECT_STR_A, /* *pvFindPara*/certName.c_str(), /*pPrevCertContext*/ NULL);
	}


	std::string hexstring = certName.substr(5);
	ByteArray byteArray = Hexify::unhexify(hexstring);
	CRYPT_HASH_BLOB HashBlob;

	if (byteArray.size() != SHA1_HASH_LEN) {
		return NULL;
	}
	HashBlob.cbData = SHA1_HASH_LEN;
	HashBlob.pbData = static_cast<BYTE *>(vecptr(byteArray));

	// Find client certificate. Note that this sample just searches for a
	// certificate that contains the user name somewhere in the subject name.
	return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /* dwFindFlags */ 0, CERT_FIND_HASH, &HashBlob, /* pPrevCertContext */ NULL);

}
예제 #13
0
boost::filesystem::path Paths::getExecutablePath() {
#if defined(SWIFTEN_PLATFORM_MACOSX)
	ByteArray path;
	uint32_t size = 4096;
	path.resize(size);
	if (_NSGetExecutablePath(const_cast<char*>(reinterpret_cast<const char*>(vecptr(path))), &size) == 0) {
		return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path();
	}
#elif defined(SWIFTEN_PLATFORM_LINUX)
	ByteArray path;
	path.resize(4096);
	ssize_t size = readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size());
	if (size > 0) {
		path.resize(size);
		return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path();
	}
#elif defined(SWIFTEN_PLATFORM_WINDOWS)
	ByteArray data;
	data.resize(2048);
	GetModuleFileName(NULL, reinterpret_cast<char*>(vecptr(data)), data.size());
	return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(data)), data.size()).c_str()).parent_path();
#endif
	return boost::filesystem::path();
}
bool WindowsGSSAPIClientAuthenticator::setChallenge(const boost::optional<ByteArray>& challengeData) {
    /* Following http://tools.ietf.org/html/rfc4752, https://msdn.microsoft.com/en-us/library/windows/desktop/aa380496%28v=vs.85%29.aspx */

    if (step_ == BuildingSecurityContext) {
        buildSecurityContext(challengeData);
    }
    else if (step_ == SecurityLayerNegotiation) {
        if (!challengeData) {
            SWIFT_LOG(debug) << "Empty message received from the server" << std::endl;
            error_ = true;
            return false;
        }

        SafeByteArray challenge;
        errorCode_ = decryptMessage(&contextHandle_, challengeData.get(), challenge);
        if (isError()) {
            return false;
        }

        if (challenge.size() != 4) {
            SWIFT_LOG(debug) << "Token received from the server of incorrect length: " << challenge.size() << std::endl;
            error_ = true;
            return false;
        }

        unsigned char* challengePointer = vecptr(challenge);

        unsigned char serverSecurityLayer = challengePointer[0];
        if (serverSecurityLayer == 0) {
            SWIFT_LOG(debug) << "Server supports unknown security layer, assuming no security layer" << std::endl;
            serverSecurityLayer = SECURITY_LAYER_NONE;
        }
        else if (serverSecurityLayer == SECURITY_LAYER_NONE) {
            SWIFT_LOG(debug) << "Server supports no security layer" << std::endl;
        }
        else {
            SWIFT_LOG(debug) << "Server supports security layer" << std::endl;
        }

        unsigned int serverMaximumBuffer = (challengePointer[1] << 16) |
                        (challengePointer[2] << 8) |
                        (challengePointer[3] << 0);

        if ((serverSecurityLayer == SECURITY_LAYER_NONE) && (serverMaximumBuffer != 0)) {
            SWIFT_LOG(debug) << "Server supports no security layer but has maximum buffer size" << serverMaximumBuffer << std::endl;
            error_ = true;
            return false;
        }

        SafeByteArray message(4);

        /* Commenting this out as streamSizes was not obtained before
        if (message.size() > streamSizes_.cbMaximumMessage) {
            error_ = true;
            return false;
        } */

        unsigned char* messagePointer = vecptr(message);
        messagePointer[0] = SECURITY_LAYER_NONE;

        /* The next 3 bytes indicate the client's maximum size buffer which is set to 0 as we do not support a security layer */
        messagePointer[1] = 0;
        messagePointer[2] = 0;
        messagePointer[3] = 0;

        /* The authorization identity is omitted as it is the same as the authentication identity */

        errorCode_ = encryptMessage(&contextHandle_, sizes_, message, response_);
        if (isError()) {
            return false;
        }

        step_ = ServerAuthenticated;
    }

    if (isError()) {
        return false;
    }

    return true;
}
예제 #15
0
std::vector<unsigned char> MD5::getHash() {
	ByteArray digest;
	digest.resize(16);
	md5_finish(state, reinterpret_cast<md5_byte_t*>(vecptr(digest)));
	return digest;
}
예제 #16
0
MD5& MD5::update(const std::vector<unsigned char>& input) {
	md5_append(state, reinterpret_cast<const md5_byte_t*>(vecptr(input)), input.size());
	return *this;
}
void SOCKS5BytestreamClientSession::process() {
	SWIFT_LOG(debug) << "unprocessedData.size(): " << unprocessedData.size() << std::endl;
	ByteArray bndAddress;
	switch(state) {
		case Initial:
			hello();
			break;
		case Hello:
			if (unprocessedData.size() > 1) {
				unsigned char version = unprocessedData[0];
				unsigned char authMethod = unprocessedData[1];
				if (version != 5 || authMethod != 0) {
					// signal failure to upper level
					finish(true);
					return;
				}
				unprocessedData.clear();
				authenticate();
			}
			break;
		case Authenticating:
			if (unprocessedData.size() < 5) {
				// need more data to start progressing
				break;
			}
			if (unprocessedData[0] != '\x05') {
				// wrong version
				// disconnect & signal failure
				finish(true);
				break;
			}
			if (unprocessedData[1] != '\x00') {
				// no success
				// disconnect & signal failure
				finish(true);
				break;
			}
			if (unprocessedData[3] != '\x03') {
				// we expect x'03' = DOMAINNAME here
				// discconect & signal failure
				finish(true);
				break;
			}
			if (static_cast<size_t>(unprocessedData[4]) + 1 > unprocessedData.size() + 5) {
				// complete domainname and port not available yet
				break;
			}
			bndAddress = createByteArray(&vecptr(unprocessedData)[5], unprocessedData[4]);
			if (unprocessedData[unprocessedData[4] + 5] != 0 && bndAddress == createByteArray(destination)) {
				// we expect a 0 as port
				// disconnect and fail
				finish(true);
			}
			unprocessedData.clear();
			state = Ready;
			SWIFT_LOG(debug) << "session ready" << std::endl;
			// issue ready signal so the bytestream can be used for reading or writing
			weFailedTimeout->stop();
			onSessionReady(false);
			break;
		case Ready:
			SWIFT_LOG(debug) << "Received further data in Ready state." << std::endl;
			break;
		case Reading:
		case Writing:
		case Finished:
			SWIFT_LOG(debug) << "Unexpected receive of data. Current state: " << state << std::endl;
			SWIFT_LOG(debug) << "Data: " << Hexify::hexify(unprocessedData) << std::endl;
			unprocessedData.clear();
			//assert(false);
	}
}
void PlatformDomainNameServiceQuery::runBlocking() {
	if (!serviceValid) {
		emitError();
		return;
	}

	SWIFT_LOG(debug) << "Querying " << service << std::endl;

	std::vector<DomainNameServiceQuery::Result> records;

#if defined(SWIFTEN_PLATFORM_WINDOWS)
	DNS_RECORD* responses;
	// FIXME: This conversion doesn't work if unicode is deffed above
	if (DnsQuery(service.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &responses, NULL) != ERROR_SUCCESS) {
		emitError();
		return;
	}

	DNS_RECORD* currentEntry = responses;
	while (currentEntry) {
		if (currentEntry->wType == DNS_TYPE_SRV) {
			DomainNameServiceQuery::Result record;
			record.priority = currentEntry->Data.SRV.wPriority;
			record.weight = currentEntry->Data.SRV.wWeight;
			record.port = currentEntry->Data.SRV.wPort;
				
			// The pNameTarget is actually a PCWSTR, so I would have expected this 
			// conversion to not work at all, but it does.
			// Actually, it doesn't. Fix this and remove explicit cast
			// Remove unicode undef above as well
			record.hostname = std::string((const char*) currentEntry->Data.SRV.pNameTarget);
			records.push_back(record);
		}
		currentEntry = currentEntry->pNext;
	}
	DnsRecordListFree(responses, DnsFreeRecordList);

#else
	// Make sure we reinitialize the domain list every time
	res_init();

	ByteArray response;
	response.resize(NS_PACKETSZ);
	int responseLength = res_query(const_cast<char*>(service.c_str()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(vecptr(response)), response.size());
	if (responseLength == -1) {
		SWIFT_LOG(debug) << "Error" << std::endl;
		emitError();
		return;
	}

	// Parse header
	HEADER* header = reinterpret_cast<HEADER*>(vecptr(response));
	unsigned char* messageStart = vecptr(response);
	unsigned char* messageEnd = messageStart + responseLength;
	unsigned char* currentEntry = messageStart + NS_HFIXEDSZ;

	// Skip over the queries
	int queriesCount = ntohs(header->qdcount);
	while (queriesCount > 0) {
		int entryLength = dn_skipname(currentEntry, messageEnd);
		if (entryLength < 0) {
			emitError();
			return;
		}
		currentEntry += entryLength + NS_QFIXEDSZ;
		queriesCount--;
	}

	// Process the SRV answers
	int answersCount = ntohs(header->ancount);
	while (answersCount > 0) {
		DomainNameServiceQuery::Result record;

		int entryLength = dn_skipname(currentEntry, messageEnd);
		currentEntry += entryLength;
		currentEntry += NS_RRFIXEDSZ;

		// Priority
		if (currentEntry + 2 >= messageEnd) {
			emitError();
			return;
		}
		record.priority = boost::numeric_cast<int>(ns_get16(currentEntry));
		currentEntry += 2;

		// Weight
		if (currentEntry + 2 >= messageEnd) {
			emitError();
			return;
		}
		record.weight = boost::numeric_cast<int>(ns_get16(currentEntry));
		currentEntry += 2;

		// Port
		if (currentEntry + 2 >= messageEnd) {
			emitError();
			return;
		}
		record.port = boost::numeric_cast<int>(ns_get16(currentEntry));
		currentEntry += 2; 

		// Hostname
		if (currentEntry >= messageEnd) {
			emitError();
			return;
		}
		ByteArray entry;
		entry.resize(NS_MAXDNAME);
		entryLength = dn_expand(messageStart, messageEnd, currentEntry, reinterpret_cast<char*>(vecptr(entry)), entry.size());
		if (entryLength < 0) {
			emitError();
			return;
		}
		record.hostname = std::string(reinterpret_cast<const char*>(vecptr(entry)));
		records.push_back(record);
		currentEntry += entryLength;
		answersCount--;
	}
#endif

	BoostRandomGenerator generator;
	DomainNameServiceQuery::sortResults(records, generator);
	//std::cout << "Sending out " << records.size() << " SRV results " << std::endl;
	eventLoop->postEvent(boost::bind(boost::ref(onResult), records), shared_from_this());
}
예제 #19
0
BOSHBodyExtractor::BOSHBodyExtractor(XMLParserFactory* parserFactory, const ByteArray& data) {
    // Look for the opening body element
    ByteArray::const_iterator i = data.begin();
    while (i < data.end() && isWhitespace(*i)) {
        ++i;
    }
    if (std::distance(i, data.end()) < 6 || *i != '<' || *(i+1) != 'b' || *(i+2) != 'o' || *(i+3) != 'd' || *(i+4) != 'y' || !(isWhitespace(*(i+5)) || *(i+5) == '>' || *(i+5) == '/')) {
        return;
    }
    i += 5;

    // Parse until end of element
    bool inSingleQuote = false;
    bool inDoubleQuote = false;
    bool endStartTagSeen = false;
    bool endElementSeen = false;
    for (; i != data.end(); ++i) {
        char c = static_cast<char>(*i);
        if (inSingleQuote) {
            if (c == '\'') {
                inSingleQuote = false;
            }
        }
        else if (inDoubleQuote) {
            if (c == '"') {
                    inDoubleQuote = false;
                }
        }
        else if (c == '\'') {
            inSingleQuote = true;
        }
        else if (c == '"') {
            inDoubleQuote = true;
        }
        else if (c == '/') {
            if (i + 1 == data.end() || *(i+1) != '>') {
                return;
            }
            else {
                endElementSeen = true;
                endStartTagSeen = true;
                i += 2;
                break;
            }
        }
        else if (c == '>') {
            endStartTagSeen = true;
            i += 1;
            break;
        }
    }

    if (!endStartTagSeen) {
        return;
    }

    // Look for the end of the element
    ByteArray::const_reverse_iterator j = data.rbegin();
    if (!endElementSeen) {
        while (isWhitespace(*j) && j < data.rend()) {
            ++j;
        }

        if (j == data.rend() || *j != '>') {
            return;
        }
        ++j;

        while (j < data.rend() && isWhitespace(*j)) {
            ++j;
        }

        if (std::distance(j, data.rend()) < 6 || *(j+5) != '<' || *(j+4) != '/' || *(j+3) != 'b' || *(j+2) != 'o' || *(j+1) != 'd' || *j != 'y') {
            return;
        }
        j += 6;
    }

    body = BOSHBody();
    if (!endElementSeen) {
        body->content = std::string(
                reinterpret_cast<const char*>(vecptr(data) + std::distance(data.begin(), i)),
                boost::numeric_cast<size_t>(std::distance(i, j.base())));
    }

    // Parse the body element
    BOSHBodyParserClient parserClient(this);
    std::shared_ptr<XMLParser> parser(parserFactory->createXMLParser(&parserClient));
    if (!parser->parse(std::string(
            reinterpret_cast<const char*>(vecptr(data)),
            boost::numeric_cast<size_t>(std::distance(data.begin(), i))))) {
        /* TODO: This needs to be only validating the BOSH <body> element, so that XMPP parsing errors are caught at
           the correct higher layer */
        body = boost::optional<BOSHBody>();
        return;
    }
}