Changeset - 8ef6fb320ae8
[Not reviewed]
0 2 0
Vitaly Takmazov - 9 years ago 2016-04-27 13:16:49
vitalyster@gmail.com
spectrum2_manager: enable SSL only when using OpenSSL library
2 files changed with 4 insertions and 2 deletions:
0 comments (0 inline, 0 general)
spectrum_manager/src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp *.c)
 

	
 
ADD_EXECUTABLE(spectrum2_manager ${SRC})
 

	
 
ADD_DEPENDENCIES(spectrum2_manager pb)
 
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
 

	
 
target_link_libraries(spectrum2_manager transport ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES})
 

	
 
if (${OPENSSL_FOUND})
 
add_definitions(-DMG_ENABLE_SSL)
 
endif()
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
target_link_libraries(spectrum2_manager ${OPENSSL_LIBRARIES})
 
endif()
 

	
 
if(APPLE)
 
target_link_libraries(spectrum2_manager transport ${APPLE_FRAMEWORKS})
 
endif()
 
INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin)
 

	
 
# IF(NOT EXISTS "/etc/spectrum2/spectrum_manager.cfg")
 
# INSTALL(FILES
 
# 	spectrum_manager.cfg
 
# 	DESTINATION /etc/spectrum2
 
# 	)
 
# ENDIF()
 

	
 
install(CODE "
 
if (NOT EXISTS \"/etc/spectrum2/spectrum_manager.cfg\")
 
file(INSTALL DESTINATION \"/etc/spectrum2\" TYPE FILES \"${CMAKE_CURRENT_SOURCE_DIR}/spectrum_manager.cfg\")
 
endif()
 
")
 

	
 

	
 

	
 
INSTALL(DIRECTORY
 
	html
 
	DESTINATION /var/lib/spectrum2_manager
 
	)
spectrum_manager/src/server.cpp
Show inline comments
 
#include "APIServer.h"
 
#include "server.h"
 
#include "methods.h"
 

	
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <assert.h>
 
#include <string.h>
 
#include <time.h>
 
#include <stdarg.h>
 
#include <pthread.h>
 
#include <fstream>
 
#include <string>
 
#include <cerrno>
 

	
 
#define SESSION_TTL 120
 

	
 
DEFINE_LOGGER(logger, "Server");
 

	
 
static struct mg_serve_http_opts s_http_server_opts;
 

	
 
static int has_prefix(const struct mg_str *uri, const char *prefix) {
 
	size_t prefix_len = strlen(prefix);
 
	return uri->len >= prefix_len && memcmp(uri->p, prefix, prefix_len) == 0;
 
}
 

	
 
static std::string get_http_var(const struct http_message *hm, const char *name) {
 
	char data[4096];
 
	data[0] = '\0';
 

	
 
	mg_get_http_var(&hm->body, name, data, sizeof(data));
 
	if (data[0] != '\0') {
 
		return data;
 
	}
 

	
 
	mg_get_http_var(&hm->query_string, name, data, sizeof(data));
 
	if (data[0] != '\0') {
 
		return data;
 
	}
 

	
 
	return "";
 
}
 

	
 
static void my_strlcpy(char *dst, const char *src, size_t len) {
 
  strncpy(dst, src, len);
 
  dst[len - 1] = '\0';
 
}
 

	
 
// Generate session ID. buf must be 33 bytes in size.
 
// Note that it is easy to steal session cookies by sniffing traffic.
 
// This is why all communication must be SSL-ed.
 
static void generate_session_id(char *buf, const char *random,
 
                                const char *user) {
 
  cs_md5(buf, random, strlen(random), user, strlen(user), NULL);
 
}
 

	
 
static void _event_handler(struct mg_connection *nc, int ev, void *p) {
 
	static_cast<Server *>(nc->mgr->user_data)->event_handler(nc, ev, p);
 
}
 

	
 
Server::Server(ManagerConfig *config, const std::string &config_file) {
 
	srand((unsigned) time(0));
 
	m_config = config;
 
	m_user = CONFIG_STRING(m_config, "service.admin_username");
 
	m_password = CONFIG_STRING(m_config, "service.admin_password");
 

	
 
	mg_mgr_init(&m_mgr, this);
 

	
 
	struct mg_bind_opts opts;
 
	memset(&opts, 0, sizeof(opts));
 
	const char *error_string;
 
	opts.error_string = &error_string;
 
	m_nc = mg_bind_opt(&m_mgr, std::string(":" + boost::lexical_cast<std::string>(CONFIG_INT(m_config, "service.port"))).c_str(), &_event_handler, opts);
 
	if (!m_nc) {
 
		std::cerr << "Error creating server: " << error_string << "\n";
 
		exit(1);
 
	}
 

	
 
#ifdef MG_ENABLE_SSL
 
	if (!CONFIG_STRING(m_config, "service.cert").empty()) {
 
		const char *err_str = mg_set_ssl(m_nc, CONFIG_STRING(m_config, "service.cert").c_str(), NULL);
 
		if (err_str) {
 
			std::cerr << "Error setting SSL certificate: " << err_str << "\n";
 
			exit(1);
 
		}
 
	}
 
#endif
 
	mg_set_protocol_http_websocket(m_nc);
 

	
 
	s_http_server_opts.document_root = CONFIG_STRING(m_config, "service.data_dir").c_str();
 

	
 
	std::ifstream header(std::string(CONFIG_STRING(m_config, "service.data_dir") + "/header.html").c_str(), std::ios::in);
 
	if (header) {
 
		header.seekg(0, std::ios::end);
 
		m_header.resize(header.tellg());
 
		header.seekg(0, std::ios::beg);
 
		header.read(&m_header[0], m_header.size());
 
		header.close();
 
	}
 

	
 
	std::ifstream footer(std::string(CONFIG_STRING(m_config, "service.data_dir") + "/footer.html").c_str(), std::ios::in);
 
	if (footer) {
 
		footer.seekg(0, std::ios::end);
 
		m_footer.resize(footer.tellg());
 
		footer.seekg(0, std::ios::beg);
 
		footer.read(&m_footer[0], m_footer.size());
 
		footer.close();
 
	}
 

	
 
	std::ofstream output;
 
	output.open(std::string(CONFIG_STRING(config, "service.data_dir") + "/js/config.js").c_str(), std::ios::out);
 
	if (output.fail()) {
 
		LOG4CXX_ERROR(logger, "Cannot open " << std::string(CONFIG_STRING(config, "service.data_dir") + "/js/config.js") << " for writing: " << strerror(errno));
 
	}
 
	output << "var BaseLocation = \"" << CONFIG_STRING(m_config, "service.base_location") << "\";\n";
 
	output.close();
 

	
 
	m_storageCfg = new Config();
 
	m_storageCfg->load(config_file);
 
	
 
	Logging::initManagerLogging(m_storageCfg);
 
	std::string error;
 
	m_storage = StorageBackend::createBackend(m_storageCfg, error);
 
	if (m_storage == NULL) {
 
		std::cerr << "Error creating StorageBackend! " << error << "\n";
 
		std::cerr << "Registering new Spectrum 2 manager users won't work" << "\n";
 
	}
 
	else if (!m_storage->connect()) {
 
		delete m_storage;
 
		m_storage = NULL;
 
		std::cerr << "Can't connect to database!\n";
 
	}
 

	
 
	m_apiServer = new APIServer(config, m_storage);
 
}
 

	
 
Server::~Server() {
 
	delete m_apiServer;
 

	
 
	mg_mgr_free(&m_mgr);
 
	if (m_storage) {
 
		delete m_storage;
 
	}
 
	delete m_storageCfg;
 
}
 

	
 
bool Server::start() {
 
	for (;;) {
 
		mg_mgr_poll(&m_mgr, 1000);
 
	}
 

	
 
	return true;
 
}
 

	
 
bool Server::check_password(const std::string &user, const std::string &password) {
 
	if (m_user == user && m_password == password) {
 
		return true;
 
	}
 

	
 
	UserInfo info;
 
	if (m_storage && m_storage->getUser(user, info) == true && info.password == password) {
 
		return true;
 
	}
 

	
 
	return false;
 
}
 

	
 
// Allocate new session object
 
Server::session *Server::new_session(const std::string &user) {
 
	Server::session *session = new Server::session;
 

	
 
	my_strlcpy(session->user, user.c_str(), sizeof(session->user));
 
	snprintf(session->random, sizeof(session->random), "%d", rand());
 
	generate_session_id(session->session_id, session->random, session->user);
 
	session->expire = time(0) + SESSION_TTL;
 
	session->admin = std::string(user) == m_user;
 

	
 
	sessions[session->session_id] = session;
 
	return session;
 
}
 

	
 
// Get session object for the connection. Caller must hold the lock.
 
Server::session *Server::get_session(struct http_message *hm) {
0 comments (0 inline, 0 general)