From 61dfcc04f73e45082f51945a7b98b7838da56da8 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Thu, 24 Jan 2013 12:05:29 -0600 Subject: User management console now functional --- servers/admin_user_mgmt_server_lin/aclocal.m4 | 10 +- servers/admin_user_mgmt_server_lin/doc/Makefile.in | 35 +- .../admin_user_mgmt_server_lin/doc/en/Makefile.in | 24 +- servers/admin_user_mgmt_server_lin/po/Makefile.in | 24 +- servers/admin_user_mgmt_server_lin/src/Makefile.am | 2 +- .../src/admin_sys_ctl.cpp | 486 ---------------- .../admin_user_mgmt_server_lin/src/admin_sys_ctl.h | 106 ---- .../src/admin_user_mgmt.cpp | 633 +++++++++++++++++++++ .../src/admin_user_mgmt.h | 111 ++++ servers/admin_user_mgmt_server_lin/src/main.cpp | 4 +- 10 files changed, 825 insertions(+), 610 deletions(-) delete mode 100644 servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.cpp delete mode 100644 servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.h create mode 100644 servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.cpp create mode 100644 servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.h (limited to 'servers/admin_user_mgmt_server_lin') diff --git a/servers/admin_user_mgmt_server_lin/aclocal.m4 b/servers/admin_user_mgmt_server_lin/aclocal.m4 index a7f0dd4..6135e5b 100644 --- a/servers/admin_user_mgmt_server_lin/aclocal.m4 +++ b/servers/admin_user_mgmt_server_lin/aclocal.m4 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.11.3 -*- Autoconf -*- +# generated automatically by aclocal 1.11.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, @@ -14,8 +14,8 @@ m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, -[m4_warning([this file was generated for autoconf 2.68. +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) @@ -664,7 +664,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.3], [], +m4_if([$1], [1.11.6], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -680,7 +680,7 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.3])dnl +[AM_AUTOMAKE_VERSION([1.11.6])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) diff --git a/servers/admin_user_mgmt_server_lin/doc/Makefile.in b/servers/admin_user_mgmt_server_lin/doc/Makefile.in index 9435987..fc4ffec 100644 --- a/servers/admin_user_mgmt_server_lin/doc/Makefile.in +++ b/servers/admin_user_mgmt_server_lin/doc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11.3 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # KDE tags expanded automatically by am_edit - $Revision$ # @configure_input@ @@ -19,6 +19,23 @@ # the SUBDIRS is filled automatically by am_edit. If files are # in this directory they are installed into the english dir VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -66,6 +83,11 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive nmcheck-recursive bcheck-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ @@ -592,13 +614,10 @@ distdir: $(DISTFILES) done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ diff --git a/servers/admin_user_mgmt_server_lin/doc/en/Makefile.in b/servers/admin_user_mgmt_server_lin/doc/en/Makefile.in index 586e134..5269784 100644 --- a/servers/admin_user_mgmt_server_lin/doc/en/Makefile.in +++ b/servers/admin_user_mgmt_server_lin/doc/en/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11.3 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # KDE tags expanded automatically by am_edit - $Revision$ # @configure_input@ @@ -16,6 +16,23 @@ @SET_MAKE@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -48,6 +65,11 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac #>- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) #>+ 1 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST) diff --git a/servers/admin_user_mgmt_server_lin/po/Makefile.in b/servers/admin_user_mgmt_server_lin/po/Makefile.in index 3e4f5d3..1af59b1 100644 --- a/servers/admin_user_mgmt_server_lin/po/Makefile.in +++ b/servers/admin_user_mgmt_server_lin/po/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11.3 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # KDE tags expanded automatically by am_edit - $Revision$ # @configure_input@ @@ -16,6 +16,23 @@ @SET_MAKE@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -48,6 +65,11 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac #>- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) #>+ 1 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST) diff --git a/servers/admin_user_mgmt_server_lin/src/Makefile.am b/servers/admin_user_mgmt_server_lin/src/Makefile.am index 6e2c003..481bdc2 100644 --- a/servers/admin_user_mgmt_server_lin/src/Makefile.am +++ b/servers/admin_user_mgmt_server_lin/src/Makefile.am @@ -3,7 +3,7 @@ KDE_CXXFLAGS = $(USE_EXCEPTIONS) bin_PROGRAMS = remotefpga_adminsysctlserver -remotefpga_adminsysctlserver_SOURCES = main.cpp admin_sys_ctl.cpp +remotefpga_adminsysctlserver_SOURCES = main.cpp admin_user_mgmt.cpp remotefpga_adminsysctlserver_METASOURCES = AUTO remotefpga_adminsysctlserver_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor -ltdekrbsocket -ltqtrla diff --git a/servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.cpp b/servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.cpp deleted file mode 100644 index bfb83bc..0000000 --- a/servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.cpp +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Remote Laboratory User Management Server - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (c) 2013 Timothy Pearson - * Raptor Engineering - * http://www.raptorengineeringinc.com - */ - -#include /* perror() */ -#include /* atoi() */ -#include -#include -#include /* read() */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "admin_sys_ctl.h" - -#define ABORT_SOCKET(s) s->close(); \ - s->disconnect(); \ - delete s; \ - s = NULL; - -#define NETWORK_COMM_TIMEOUT_MS 5000 - -/* exception handling */ -struct exit_exception { - int c; - exit_exception(int c):c(c) { } -}; - -enum connectionStates { - StateIdle = 0 -}; - -/* - The SysCtlSocket class provides a socket that is connected with a client. - For every client that connects to the server, the server creates a new - instance of this class. -*/ -SysCtlSocket::SysCtlSocket(int sock, TQObject *parent, const char *name) : - TDEKerberosServerSocket(parent, name), m_criticalSection(0), m_loopTimer(NULL), m_config(static_cast(parent)->m_config), m_terminals_database(NULL), m_workspaces_database(NULL), m_commandLoopState(StateIdle) -{ - - // Initialize timers - m_kerberosInitTimer = new TQTimer(); - connect(m_kerberosInitTimer, SIGNAL(timeout()), this, SLOT(finishKerberosHandshake())); - m_servClientTimeout = new TQTimer(); - - setServiceName("remotefpga"); - - line = 0; - connect(this, SIGNAL(connectionClosed()), SLOT(connectionClosedHandler())); - connect(this, SIGNAL(connectionClosed()), parent, SLOT(remoteConnectionClosed())); - setSocket(sock); - - if (connectToDatabase() != 0) { - exit(1); - } -} - -SysCtlSocket::~SysCtlSocket() { - if (m_servClientTimeout) { - m_servClientTimeout->stop(); - delete m_servClientTimeout; - m_servClientTimeout = NULL; - } - if (m_kerberosInitTimer) { - m_kerberosInitTimer->stop(); - delete m_kerberosInitTimer; - m_kerberosInitTimer = NULL; - } - if (m_loopTimer) { - m_loopTimer->stop(); - delete m_loopTimer; - m_loopTimer = NULL; - } -} - -void SysCtlSocket::close() { - if (state() == TQSocket::Connected) { - TDEKerberosServerSocket::close(); - connectionClosedHandler(); - TQTimer::singleShot(0, parent(), SLOT(remoteConnectionClosed())); - } -} - -void SysCtlSocket::connectionClosedHandler() { - printf("[DEBUG] Connection from %s closed\n\r", m_remoteHost.ascii()); - - if (m_criticalSection > 0) { - throw exit_exception(-1); - } -} - -void SysCtlSocket::initiateKerberosHandshake() { - setUsingKerberos(true); - m_kerberosInitTimer->start(100, TRUE); -} - -void SysCtlSocket::finishKerberosHandshake() { - if (kerberosStatus() == TDEKerberosServerSocket::KerberosInitializing) { - m_kerberosInitTimer->start(100, TRUE); - return; - } - if (kerberosStatus() == TDEKerberosServerSocket::KerberosInUse) { - m_config->setGroup("Security"); - TQString masterUser = m_config->readEntry("masteruser"); - TQString masterRealm = m_config->readEntry("masterrealm"); - if (masterRealm == "") { - masterRealm = "(NULL)"; - } - if ((m_authenticatedUserName != masterUser) || (m_authenticatedRealmName != masterRealm)) { - printf("[DEBUG] Connection from %s closed due to authentication failure (attempted connection as user %s@%s)\n\r", m_remoteHost.ascii(), m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); - close(); - return; - } - - setDataTimeout(NETWORK_COMM_TIMEOUT_MS); - - TQDataStream ds(this); - ds.setPrintableData(true); - ds << TQString("OK"); - writeEndOfFrame(); - - enterCommandLoop(); - return; - } - else { - printf("[DEBUG] Connection from %s closed due to Kerberos failure\n\r", m_remoteHost.ascii()); fflush(stdout); - close(); - return; - } -} - -void SysCtlSocket::commandLoop() { - bool transferred_data; - - m_criticalSection++; - try { - transferred_data = false; - if (state() == TQSocket::Connected) { - if (m_commandLoopState == StateIdle) { - // Certain commands can come in at any time during some operations - if (canReadLine()) { - processPendingData(); - } - if (canReadFrame()) { - TQDataStream ds(this); - ds.setPrintableData(true); - TQString command; - ds >> command; - if (command == "USERS") { - TQString subCommand; - ds >> subCommand; - if (subCommand == "TERMINALS") { - clearFrameTail(); - ds << TQString("OK"); - TerminalServiceStatusList list; - TQSqlCursor databaseActivityCursor("sessions", TRUE, m_terminals_database); - databaseActivityCursor.select(); - while (databaseActivityCursor.next()) { - TerminalServiceStatusType status; - - status.protocolVersion = 1; - status.sessionID = databaseActivityCursor.value("pk").toInt(); - status.username = databaseActivityCursor.value("username").toString(); - status.serverName = databaseActivityCursor.value("servername").toString(); - status.serverPID = databaseActivityCursor.value("server_pid").toInt(); - status.wmPID = databaseActivityCursor.value("wm_pid").toInt(); - status.state = databaseActivityCursor.value("state").toInt(); - status.display = databaseActivityCursor.value("display").toInt(); - status.loginStamp.setTime_t(databaseActivityCursor.value("stamp_start").toLongLong()); - status.activityStamp.setTime_t(databaseActivityCursor.value("stamp_statechange").toLongLong()); - - list.append(status); - } - ds << list; - writeEndOfFrame(); - } - else if (subCommand == "WORKSPACES") { - clearFrameTail(); - ds << TQString("OK"); - WorkspaceServiceStatusList list; - TQSqlCursor databaseActivityCursor("activity", TRUE, m_workspaces_database); - databaseActivityCursor.select(); - while (databaseActivityCursor.next()) { - WorkspaceServiceStatusType status; - - status.protocolVersion = 1; - status.sessionID = databaseActivityCursor.value("pk").toInt(); - status.stationID = databaseActivityCursor.value("station").toInt(); - status.username = databaseActivityCursor.value("username").toString(); - status.realmname = databaseActivityCursor.value("realmname").toString(); - status.serverID = databaseActivityCursor.value("serverid").toInt(); - status.serviceID = databaseActivityCursor.value("serviceid").toInt(); - status.stationID = databaseActivityCursor.value("station").toInt(); - TQSqlCursor databaseStationsCursor("stations", TRUE, m_workspaces_database); - databaseStationsCursor.select(TQString("pk=%1").arg(status.stationID)); - if (databaseStationsCursor.next()) { - status.stationName = databaseStationsCursor.value("name").toString(); - } - status.loginStamp.setTime_t(databaseActivityCursor.value("logontime").toLongLong()); - status.terminateStamp.setTime_t(databaseActivityCursor.value("terminate").toLongLong()); - - list.append(status); - } - ds << list; - writeEndOfFrame(); - } - else { - clearFrameTail(); - ds << TQString("ERRINVCMD"); - writeEndOfFrame(); - } - } - else if (command == "SESSION") { - TQString subCommand; - TQString sessionID; - ds >> subCommand; - ds >> sessionID; - if (subCommand == "LOGOFF_TERMINAL") { - TQ_UINT32 delay; - ds >> delay; - clearFrameTail(); - // FIXME UNIMPLEMENTED - ds << TQString("ERRINVCMD"); - writeEndOfFrame(); - } - else if (subCommand == "CANCEL_LOGOFF_TERMINAL") { - clearFrameTail(); - // FIXME UNIMPLEMENTED - ds << TQString("ERRINVCMD"); - writeEndOfFrame(); - } - else if (subCommand == "KILL_TERMINAL") { - clearFrameTail(); - TQSqlCursor databaseActivityCursor("sessions", TRUE, m_terminals_database); - databaseActivityCursor.select(TQString("pk=%1").arg(sessionID)); - if (databaseActivityCursor.next()) { - // Gather server information - TQString server_name = databaseActivityCursor.value("servername").toString(); - int server_pid = databaseActivityCursor.value("server_pid").toInt(); - // Kill server process - TQString command = TQString("ssh root@%1 'kill -9 %2'").arg(server_name).arg(server_pid); - if (system(command.ascii()) == 0) { - // Remove database entry - databaseActivityCursor.select(TQString("pk=%1").arg(sessionID)); - if (databaseActivityCursor.next()) { - databaseActivityCursor.primeDelete(); - databaseActivityCursor.del(true); - } - ds << TQString("OK"); - } - else { - ds << TQString("ERRFAILED"); - } - writeEndOfFrame(); - } - else { - ds << TQString("ERRINVCMD"); - } - writeEndOfFrame(); - } - else if (subCommand == "KILL_WORKSPACE") { - TQ_INT32 terminationOffset; - ds >> terminationOffset; - clearFrameTail(); - TQDateTime terminationTime = TQDateTime::currentDateTime(); - terminationTime = terminationTime.addSecs(terminationOffset*60); - TQSqlCursor databaseActivityCursor("activity", TRUE, m_workspaces_database); - databaseActivityCursor.select(TQString("pk=%1").arg(sessionID)); - if (databaseActivityCursor.next()) { - TQSqlRecord *buffer = databaseActivityCursor.primeUpdate(); - if (terminationOffset > -2) { - buffer->setValue("terminate", terminationTime.toTime_t()); - } - else { - buffer->setValue("terminate", 0); - } - databaseActivityCursor.update(); - - ds << TQString("OK"); - } - else { - ds << TQString("ERRINVCMD"); - } - writeEndOfFrame(); - } - else if (subCommand == "CANCEL_KILL_WORKSPACE") { - clearFrameTail(); - TQSqlCursor databaseActivityCursor("activity", TRUE, m_workspaces_database); - databaseActivityCursor.select(TQString("pk=%1").arg(sessionID)); - if (databaseActivityCursor.next()) { - TQSqlRecord *buffer = databaseActivityCursor.primeUpdate(); - buffer->setValue("terminate", 0); - databaseActivityCursor.update(); - - ds << TQString("OK"); - } - else { - ds << TQString("ERRINVCMD"); - } - writeEndOfFrame(); - } - else { - clearFrameTail(); - ds << TQString("ERRINVCMD"); - writeEndOfFrame(); - } - } - else { - clearFrameTail(); - } - transferred_data = true; - } - } - } - m_criticalSection--; - if (transferred_data) { - if (m_loopTimer) m_loopTimer->start(0, TRUE); - } - else { - if (m_loopTimer) m_loopTimer->start(100, TRUE); - } - return; - } - catch (...) { - m_criticalSection--; - return; - } -} - -int SysCtlSocket::enterCommandLoop() { - m_commandLoopState = StateIdle; - if (!m_loopTimer) { - m_loopTimer = new TQTimer(); - connect(m_loopTimer, SIGNAL(timeout()), this, SLOT(commandLoop())); - } - if (m_loopTimer) m_loopTimer->start(0, TRUE); - return 0; -} - -int SysCtlSocket::connectToDatabase() { - if ((m_terminals_database) && (m_workspaces_database)) { - return -2; - } - - m_terminals_database = TQSqlDatabase::database("terminals"); - m_workspaces_database = TQSqlDatabase::database("workspaces"); - if ((!m_terminals_database) || (!m_workspaces_database)) { - printf("[ERROR] Databases were not constructed by the application\n\r"); fflush(stdout); - return -1; - } - - return 0; -} - -/* - The UserMgmtServer class handles new connections to the server. For every - client that connects, it creates a new SysCtlSocket -- that instance is now - responsible for the communication with that client. -*/ -UserMgmtServer::UserMgmtServer(TQObject* parent, int port, KSimpleConfig* config) : - TQServerSocket( port, 1, parent ), m_config(config), m_numberOfConnections(0), m_terminals_database(NULL), m_workspaces_database(NULL), m_sqlPingTimer(NULL) { - - if (connectToDatabase() != 0) { - exit(1); - } - - if ( !ok() ) { - printf("[ERROR] Failed to bind to port %d\n\r", port); - exit(1); - } - - printf("[INFO] Server started on port %d\n\r", port); fflush(stdout); -} - -UserMgmtServer::~UserMgmtServer() { - if (m_sqlPingTimer) { - m_sqlPingTimer->stop(); - delete m_sqlPingTimer; - m_sqlPingTimer = NULL; - } - if (m_terminals_database) { - TQSqlDatabase::removeDatabase(m_terminals_database); - m_terminals_database = NULL; - } - if (m_workspaces_database) { - TQSqlDatabase::removeDatabase(m_workspaces_database); - m_workspaces_database = NULL; - } -} - -int UserMgmtServer::connectToDatabase() { - m_config->setGroup("Terminals Database"); - - m_terminals_database = TQSqlDatabase::addDatabase(m_config->readEntry("driver"), "terminals"); - m_terminals_database->setDatabaseName(m_config->readEntry("database")); - m_terminals_database->setUserName(m_config->readEntry("username")); - m_terminals_database->setPassword(m_config->readEntry("password")); - m_terminals_database->setHostName(m_config->readEntry("server")); - - if(!m_terminals_database->open()) { - printf("[ERROR] Failed to connect to control database on server '%s' [%s]\n\r", m_terminals_database->hostName().ascii(), m_terminals_database->lastError().text().ascii()); fflush(stdout); - TQSqlDatabase::removeDatabase(m_terminals_database); - m_terminals_database = NULL; - return -1; - } - - m_config->setGroup("Workspaces Database"); - - m_workspaces_database = TQSqlDatabase::addDatabase(m_config->readEntry("driver"), "workspaces"); - m_workspaces_database->setDatabaseName(m_config->readEntry("database")); - m_workspaces_database->setUserName(m_config->readEntry("username")); - m_workspaces_database->setPassword(m_config->readEntry("password")); - m_workspaces_database->setHostName(m_config->readEntry("server")); - - if(!m_workspaces_database->open()) { - printf("[ERROR] Failed to connect to control database on server '%s' [%s]\n\r", m_workspaces_database->hostName().ascii(), m_workspaces_database->lastError().text().ascii()); fflush(stdout); - TQSqlDatabase::removeDatabase(m_workspaces_database); - m_workspaces_database = NULL; - return -1; - } - - // FIXME - // We currently have no way to handle something as simple as the database server going offline! - - // Start database ping process - m_sqlPingTimer = new TQTimer(); - connect(m_sqlPingTimer, SIGNAL(timeout()), this, SLOT(pingSQLServer())); - m_sqlPingTimer->start(60*1000); - - return 0; -} - -void UserMgmtServer::pingSQLServer() { - TQSqlQuery terminals_query(TQString::null, m_terminals_database); - terminals_query.exec("SELECT * FROM sessions"); - TQSqlQuery workspaces_query(TQString::null, m_workspaces_database); - workspaces_query.exec("SELECT * FROM activity"); -} - -void UserMgmtServer::newConnection(int socket) { - SysCtlSocket *s = new SysCtlSocket(socket, this); - s->m_remoteHost = s->peerAddress().toString(); - printf("[DEBUG] New connection from %s\n\r", s->m_remoteHost.ascii()); - if (m_numberOfConnections > 0) { - printf("[DEBUG] Connection from %s closed due to multiple access attempt\n\r", s->m_remoteHost.ascii()); - ABORT_SOCKET(s) - return; - } - connect(s, SIGNAL(connectionClosed()), s, SLOT(deleteLater())); - s->initiateKerberosHandshake(); - emit newConnect(s); -} - -void UserMgmtServer::remoteConnectionClosed() { - m_numberOfConnections--; -} diff --git a/servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.h b/servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.h deleted file mode 100644 index 4812424..0000000 --- a/servers/admin_user_mgmt_server_lin/src/admin_sys_ctl.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Remote Laboratory User Management Server - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (c) 2013 Timothy Pearson - * Raptor Engineering - * http://www.raptorengineeringinc.com - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#define MAGIC_NUMBER 1 -#define PROTOCOL_VERSION 1 - -class SysCtlSocket : public TDEKerberosServerSocket -{ - Q_OBJECT - - public: - SysCtlSocket(int sock, TQObject *parent=0, const char *name=0); - ~SysCtlSocket(); - - public: - void close(); - void initiateKerberosHandshake(); - int enterCommandLoop(); - - private slots: - void finishKerberosHandshake(); - void connectionClosedHandler(); - void commandLoop(); - int connectToDatabase(); - - private: - int line; - int m_criticalSection; - TQString m_remoteHost; - - TQTimer* m_kerberosInitTimer; - TQTimer* m_loopTimer; - TQTimer* m_servClientTimeout; - - KSimpleConfig* m_config; - TQSqlDatabase* m_terminals_database; - TQSqlDatabase* m_workspaces_database; - int m_commandLoopState; - - friend class UserMgmtServer; -}; - -class UserMgmtServer : public TQServerSocket -{ - Q_OBJECT - - public: - UserMgmtServer(TQObject* parent=0, int port=0, KSimpleConfig* config=0); - ~UserMgmtServer(); - - void newConnection(int socket); - - private slots: - void remoteConnectionClosed(); - int connectToDatabase(); - void pingSQLServer(); - - signals: - void newConnect(SysCtlSocket*); - - private: - KSimpleConfig* m_config; - int m_numberOfConnections; - TQSqlDatabase* m_terminals_database; - TQSqlDatabase* m_workspaces_database; - TQTimer* m_sqlPingTimer; - - friend class SysCtlSocket; - -}; \ No newline at end of file diff --git a/servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.cpp b/servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.cpp new file mode 100644 index 0000000..687a1e5 --- /dev/null +++ b/servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.cpp @@ -0,0 +1,633 @@ +/* + * Remote Laboratory User Management Server + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (c) 2013 Timothy Pearson + * Raptor Engineering + * http://www.raptorengineeringinc.com + */ + +#include /* perror() */ +#include /* atoi() */ +#include +#include +#include /* read() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "admin_user_mgmt.h" + +#define ABORT_SOCKET(s) s->close(); \ + s->disconnect(); \ + delete s; \ + s = NULL; + +#define NETWORK_COMM_TIMEOUT_MS 5000 + +/* exception handling */ +struct exit_exception { + int c; + exit_exception(int c):c(c) { } +}; + +enum connectionStates { + StateIdle = 0 +}; + +/* + The SysCtlSocket class provides a socket that is connected with a client. + For every client that connects to the server, the server creates a new + instance of this class. +*/ +SysCtlSocket::SysCtlSocket(int sock, TQObject *parent, const char *name) : + TDEKerberosServerSocket(parent, name), m_criticalSection(0), m_loopTimer(NULL), m_config(static_cast(parent)->m_config), m_terminals_database(NULL), m_workspaces_database(NULL), m_commandLoopState(StateIdle) +{ + + // Initialize timers + m_kerberosInitTimer = new TQTimer(); + connect(m_kerberosInitTimer, SIGNAL(timeout()), this, SLOT(finishKerberosHandshake())); + m_servClientTimeout = new TQTimer(); + + setServiceName("remotefpga"); + + line = 0; + connect(this, SIGNAL(connectionClosed()), SLOT(connectionClosedHandler())); + connect(this, SIGNAL(connectionClosed()), parent, SLOT(remoteConnectionClosed())); + setSocket(sock); + + if (connectToDatabase() != 0) { + exit(1); + } + + m_minGID = m_config->readNumEntry("MinimumGID", 500); + m_maxGID = m_config->readNumEntry("MaximumGID", 65533); +} + +SysCtlSocket::~SysCtlSocket() { + if (m_servClientTimeout) { + m_servClientTimeout->stop(); + delete m_servClientTimeout; + m_servClientTimeout = NULL; + } + if (m_kerberosInitTimer) { + m_kerberosInitTimer->stop(); + delete m_kerberosInitTimer; + m_kerberosInitTimer = NULL; + } + if (m_loopTimer) { + m_loopTimer->stop(); + delete m_loopTimer; + m_loopTimer = NULL; + } +} + +void SysCtlSocket::close() { + if (state() == TQSocket::Connected) { + TDEKerberosServerSocket::close(); + connectionClosedHandler(); + TQTimer::singleShot(0, parent(), SLOT(remoteConnectionClosed())); + } +} + +void SysCtlSocket::connectionClosedHandler() { + printf("[DEBUG] Connection from %s closed\n\r", m_remoteHost.ascii()); + + if (m_criticalSection > 0) { + throw exit_exception(-1); + } +} + +void SysCtlSocket::initiateKerberosHandshake() { + setUsingKerberos(true); + m_kerberosInitTimer->start(100, TRUE); +} + +void SysCtlSocket::finishKerberosHandshake() { + if (kerberosStatus() == TDEKerberosServerSocket::KerberosInitializing) { + m_kerberosInitTimer->start(100, TRUE); + return; + } + if (kerberosStatus() == TDEKerberosServerSocket::KerberosInUse) { + m_config->setGroup("Security"); + TQString masterUser = m_config->readEntry("masteruser"); + TQString masterRealm = m_config->readEntry("masterrealm"); + if (masterRealm == "") { + masterRealm = "(NULL)"; + } + if ((m_authenticatedUserName != masterUser) || (m_authenticatedRealmName != masterRealm)) { + printf("[DEBUG] Connection from %s closed due to authentication failure (attempted connection as user %s@%s)\n\r", m_remoteHost.ascii(), m_authenticatedUserName.ascii(), m_authenticatedRealmName.ascii()); + close(); + return; + } + + setDataTimeout(NETWORK_COMM_TIMEOUT_MS); + + TQDataStream ds(this); + ds.setPrintableData(true); + ds << TQString("OK"); + writeEndOfFrame(); + + enterCommandLoop(); + return; + } + else { + printf("[DEBUG] Connection from %s closed due to Kerberos failure\n\r", m_remoteHost.ascii()); fflush(stdout); + close(); + return; + } +} + +void SysCtlSocket::commandLoop() { + bool transferred_data; + + m_criticalSection++; + try { + transferred_data = false; + if (state() == TQSocket::Connected) { + if (m_commandLoopState == StateIdle) { + // Certain commands can come in at any time during some operations + if (canReadLine()) { + processPendingData(); + } + if (canReadFrame()) { + TQDataStream ds(this); + ds.setPrintableData(true); + TQString command; + ds >> command; + if (command == "LIST") { + TQString subCommand; + ds >> subCommand; + if (subCommand == "TERMINALS") { + clearFrameTail(); + ds << TQString("OK"); + TQStringList list; + TQSqlCursor databaseServersCursor("servers", TRUE, m_terminals_database); + databaseServersCursor.select(); + while (databaseServersCursor.next()) { + list.append(databaseServersCursor.value("name").toString()); + } + ds << list; + writeEndOfFrame(); + } + else if (subCommand == "WORKSPACES") { + clearFrameTail(); + ds << TQString("OK"); + + StationList list; + TQSqlCursor databaseStationsCursor("stations", TRUE, m_workspaces_database); + TQSqlCursor databaseServicesCursor("services", TRUE, m_workspaces_database); + TQSqlCursor databaseServiceTypesCursor("servicetypes", TRUE, m_workspaces_database); + databaseStationsCursor.select(); + while (databaseStationsCursor.next()) { + StationType st; + st.id = databaseStationsCursor.value("pk").toInt(); + st.name = databaseStationsCursor.value("name").toString(); + st.description = databaseStationsCursor.value("description").toString(); + databaseServicesCursor.select(TQString("station=%1").arg(databaseStationsCursor.value("pk").toInt())); + while (databaseServicesCursor.next()) { + databaseServiceTypesCursor.select(TQString("serviceid=%1").arg(databaseServicesCursor.value("servicetype").toInt())); + ServiceType svt; + if (databaseServiceTypesCursor.next()) { + svt.type = databaseServiceTypesCursor.value("serviceid").toInt(); + svt.name = databaseServiceTypesCursor.value("name").toString(); + svt.description = databaseServiceTypesCursor.value("description").toString(); + svt.clientLibrary = databaseServiceTypesCursor.value("client_library").toString(); + svt.version = databaseServiceTypesCursor.value("version").toInt(); + char tempchar; + tempchar = databaseServiceTypesCursor.value("single_instance").toInt(); + svt.singleInstance = (tempchar != 0); + } + if (svt.name == "") { + svt.name = i18n(""); + } + if (svt.description == "") { + svt.description = i18n(""); + } + st.services.append(svt); + } + + list.append(st); + } + ds << list; + writeEndOfFrame(); + } + else { + clearFrameTail(); + ds << TQString("ERRINVCMD"); + writeEndOfFrame(); + } + } + else if (command == "LISTGROUPACCESS") { + TQString subCommand; + ds >> subCommand; + if (subCommand == "TERMINALS") { + clearFrameTail(); + ds << TQString("OK"); + TerminalServiceAuthGroupList list; + + // First search the database for groups... + TQSqlCursor databasePermissionsCursor("allowed_servers", TRUE, m_terminals_database); + databasePermissionsCursor.select(); + while (databasePermissionsCursor.next()) { + TerminalServiceAuthGroupType agt; + TerminalServiceAuthGroupList::iterator it = list.findByName(databasePermissionsCursor.value("groupname").toString()); + if (it != list.end()) { + agt = *it; + list.remove(it); + } + else { + agt.protocolVersion = 1; + agt.groupName = databasePermissionsCursor.value("groupname").toString(); + } + agt.allowedServerNames.append(databasePermissionsCursor.value("server").toString()); + + list.append(agt); + } + + // ...then search LDAP for groups that were not already in the database + struct group* group; + setgrent(); + while ((group = getgrent())) { + if ((group->gr_gid >= m_minGID) && (group->gr_gid <= m_maxGID)) { + TerminalServiceAuthGroupType agt; + TerminalServiceAuthGroupList::iterator it = list.findByName(TQString(group->gr_name)); + if (it == list.end()) { + agt.protocolVersion = 1; + agt.groupName = TQString(group->gr_name); + list.append(agt); + } + } + } + endgrent(); + + ds << list; + writeEndOfFrame(); + } + else if (subCommand == "WORKSPACES") { + clearFrameTail(); + ds << TQString("OK"); + + WorkspaceServiceAuthGroupList list; + + // First search the database for groups... + TQSqlCursor databasePermissionsCursor("permissions", TRUE, m_workspaces_database); + databasePermissionsCursor.select(); + while (databasePermissionsCursor.next()) { + WorkspaceServiceAuthGroupType agt; + WorkspaceServiceAuthGroupList::iterator it = list.findByName(databasePermissionsCursor.value("groupname").toString()); + if (it != list.end()) { + agt = *it; + list.remove(it); + } + else { + agt.protocolVersion = 1; + agt.groupName = databasePermissionsCursor.value("groupname").toString(); + } + agt.allowedStationIDs.append(databasePermissionsCursor.value("station").toUInt()); + + list.append(agt); + } + + // ...then search LDAP for groups that were not already in the database + struct group* group; + setgrent(); + while ((group = getgrent())) { + if ((group->gr_gid >= m_minGID) && (group->gr_gid <= m_maxGID)) { + WorkspaceServiceAuthGroupType agt; + WorkspaceServiceAuthGroupList::iterator it = list.findByName(TQString(group->gr_name)); + if (it == list.end()) { + agt.protocolVersion = 1; + agt.groupName = TQString(group->gr_name); + list.append(agt); + } + } + } + endgrent(); + + ds << list; + writeEndOfFrame(); + } + else { + clearFrameTail(); + ds << TQString("ERRINVCMD"); + writeEndOfFrame(); + } + } + else if (command == "SETGROUPACCESS") { + TQString subCommand; + ds >> subCommand; + if (subCommand == "TERMINALS") { + TerminalServiceAuthGroupList list; + ds >> list; + clearFrameTail(); + + bool success = true; + TQSqlCursor databasePermissionsCursor("allowed_servers", TRUE, m_terminals_database); + TerminalServiceAuthGroupList::iterator it; + for (it = list.begin(); it != list.end(); ++it) { + TerminalServiceAuthGroupType agt = *it; + + // Delete all existing entries for this group in perparation for update + databasePermissionsCursor.select(TQString("groupname='%1'").arg(agt.groupName)); + while (databasePermissionsCursor.next()) { + databasePermissionsCursor.primeDelete(); + databasePermissionsCursor.del(false); + } + + // Insert all entries for this group from the information structure + TQStringList::iterator it2; + for (it2 = agt.allowedServerNames.begin(); it2 != agt.allowedServerNames.end(); ++it2) { + TQSqlRecord *buffer = databasePermissionsCursor.primeInsert(); + buffer->setValue("groupname", agt.groupName); + buffer->setValue("server", *it2); + databasePermissionsCursor.insert(); + } + } + + if (success) { + ds << TQString("OK"); + } + else { + ds << TQString("ERRFAILED"); + } + writeEndOfFrame(); + } + else if (subCommand == "WORKSPACES") { + WorkspaceServiceAuthGroupList list; + ds >> list; + clearFrameTail(); + + bool success = true; + TQSqlCursor databasePermissionsCursor("permissions", TRUE, m_workspaces_database); + WorkspaceServiceAuthGroupList::iterator it; + for (it = list.begin(); it != list.end(); ++it) { + WorkspaceServiceAuthGroupType agt = *it; + + // Delete all existing entries for this group in perparation for update + databasePermissionsCursor.select(TQString("groupname='%1'").arg(agt.groupName)); + while (databasePermissionsCursor.next()) { + databasePermissionsCursor.primeDelete(); + databasePermissionsCursor.del(false); + } + + // Insert all entries for this group from the information structure + TQInt32List::iterator it2; + for (it2 = agt.allowedStationIDs.begin(); it2 != agt.allowedStationIDs.end(); ++it2) { + TQSqlRecord *buffer = databasePermissionsCursor.primeInsert(); + buffer->setValue("groupname", agt.groupName); + buffer->setValue("station", *it2); + databasePermissionsCursor.insert(); + } + } + + if (success) { + ds << TQString("OK"); + } + else { + ds << TQString("ERRFAILED"); + } + writeEndOfFrame(); + } + else { + clearFrameTail(); + ds << TQString("ERRINVCMD"); + writeEndOfFrame(); + } + } + else if (command == "DELETEGROUPACCESS") { + TQString subCommand; + ds >> subCommand; + if (subCommand == "TERMINALS") { + TerminalServiceAuthGroupList list; + ds >> list; + clearFrameTail(); + + bool success = true; + TQSqlCursor databasePermissionsCursor("allowed_servers", TRUE, m_terminals_database); + TerminalServiceAuthGroupList::iterator it; + for (it = list.begin(); it != list.end(); ++it) { + TerminalServiceAuthGroupType agt = *it; + + // Delete all existing entries for this group + databasePermissionsCursor.select(TQString("groupname='%1'").arg(agt.groupName)); + while (databasePermissionsCursor.next()) { + databasePermissionsCursor.primeDelete(); + databasePermissionsCursor.del(false); + } + } + + if (success) { + ds << TQString("OK"); + } + else { + ds << TQString("ERRFAILED"); + } + writeEndOfFrame(); + } + else if (subCommand == "WORKSPACES") { + WorkspaceServiceAuthGroupList list; + ds >> list; + clearFrameTail(); + + bool success = true; + TQSqlCursor databasePermissionsCursor("permissions", TRUE, m_workspaces_database); + WorkspaceServiceAuthGroupList::iterator it; + for (it = list.begin(); it != list.end(); ++it) { + WorkspaceServiceAuthGroupType agt = *it; + + // Delete all existing entries for this group + databasePermissionsCursor.select(TQString("groupname='%1'").arg(agt.groupName)); + while (databasePermissionsCursor.next()) { + databasePermissionsCursor.primeDelete(); + databasePermissionsCursor.del(false); + } + } + + if (success) { + ds << TQString("OK"); + } + else { + ds << TQString("ERRFAILED"); + } + writeEndOfFrame(); + } + else { + clearFrameTail(); + ds << TQString("ERRINVCMD"); + writeEndOfFrame(); + } + } + else { + clearFrameTail(); + } + transferred_data = true; + } + } + } + m_criticalSection--; + if (transferred_data) { + if (m_loopTimer) m_loopTimer->start(0, TRUE); + } + else { + if (m_loopTimer) m_loopTimer->start(100, TRUE); + } + return; + } + catch (...) { + m_criticalSection--; + return; + } +} + +int SysCtlSocket::enterCommandLoop() { + m_commandLoopState = StateIdle; + if (!m_loopTimer) { + m_loopTimer = new TQTimer(); + connect(m_loopTimer, SIGNAL(timeout()), this, SLOT(commandLoop())); + } + if (m_loopTimer) m_loopTimer->start(0, TRUE); + return 0; +} + +int SysCtlSocket::connectToDatabase() { + if ((m_terminals_database) && (m_workspaces_database)) { + return -2; + } + + m_terminals_database = TQSqlDatabase::database("terminals"); + m_workspaces_database = TQSqlDatabase::database("workspaces"); + if ((!m_terminals_database) || (!m_workspaces_database)) { + printf("[ERROR] Databases were not constructed by the application\n\r"); fflush(stdout); + return -1; + } + + return 0; +} + +/* + The UserMgmtServer class handles new connections to the server. For every + client that connects, it creates a new SysCtlSocket -- that instance is now + responsible for the communication with that client. +*/ +UserMgmtServer::UserMgmtServer(TQObject* parent, int port, KSimpleConfig* config) : + TQServerSocket( port, 1, parent ), m_config(config), m_numberOfConnections(0), m_terminals_database(NULL), m_workspaces_database(NULL), m_sqlPingTimer(NULL) { + + if (connectToDatabase() != 0) { + exit(1); + } + + if ( !ok() ) { + printf("[ERROR] Failed to bind to port %d\n\r", port); + exit(1); + } + + printf("[INFO] Server started on port %d\n\r", port); fflush(stdout); +} + +UserMgmtServer::~UserMgmtServer() { + if (m_sqlPingTimer) { + m_sqlPingTimer->stop(); + delete m_sqlPingTimer; + m_sqlPingTimer = NULL; + } + if (m_terminals_database) { + TQSqlDatabase::removeDatabase(m_terminals_database); + m_terminals_database = NULL; + } + if (m_workspaces_database) { + TQSqlDatabase::removeDatabase(m_workspaces_database); + m_workspaces_database = NULL; + } +} + +int UserMgmtServer::connectToDatabase() { + m_config->setGroup("Terminals Database"); + + m_terminals_database = TQSqlDatabase::addDatabase(m_config->readEntry("driver"), "terminals"); + m_terminals_database->setDatabaseName(m_config->readEntry("database")); + m_terminals_database->setUserName(m_config->readEntry("username")); + m_terminals_database->setPassword(m_config->readEntry("password")); + m_terminals_database->setHostName(m_config->readEntry("server")); + + if(!m_terminals_database->open()) { + printf("[ERROR] Failed to connect to control database on server '%s' [%s]\n\r", m_terminals_database->hostName().ascii(), m_terminals_database->lastError().text().ascii()); fflush(stdout); + TQSqlDatabase::removeDatabase(m_terminals_database); + m_terminals_database = NULL; + return -1; + } + + m_config->setGroup("Workspaces Database"); + + m_workspaces_database = TQSqlDatabase::addDatabase(m_config->readEntry("driver"), "workspaces"); + m_workspaces_database->setDatabaseName(m_config->readEntry("database")); + m_workspaces_database->setUserName(m_config->readEntry("username")); + m_workspaces_database->setPassword(m_config->readEntry("password")); + m_workspaces_database->setHostName(m_config->readEntry("server")); + + if(!m_workspaces_database->open()) { + printf("[ERROR] Failed to connect to control database on server '%s' [%s]\n\r", m_workspaces_database->hostName().ascii(), m_workspaces_database->lastError().text().ascii()); fflush(stdout); + TQSqlDatabase::removeDatabase(m_workspaces_database); + m_workspaces_database = NULL; + return -1; + } + + // FIXME + // We currently have no way to handle something as simple as the database server going offline! + + // Start database ping process + m_sqlPingTimer = new TQTimer(); + connect(m_sqlPingTimer, SIGNAL(timeout()), this, SLOT(pingSQLServer())); + m_sqlPingTimer->start(60*1000); + + return 0; +} + +void UserMgmtServer::pingSQLServer() { + TQSqlQuery terminals_query(TQString::null, m_terminals_database); + terminals_query.exec("SELECT * FROM sessions"); + TQSqlQuery workspaces_query(TQString::null, m_workspaces_database); + workspaces_query.exec("SELECT * FROM activity"); +} + +void UserMgmtServer::newConnection(int socket) { + SysCtlSocket *s = new SysCtlSocket(socket, this); + s->m_remoteHost = s->peerAddress().toString(); + printf("[DEBUG] New connection from %s\n\r", s->m_remoteHost.ascii()); + if (m_numberOfConnections > 0) { + printf("[DEBUG] Connection from %s closed due to multiple access attempt\n\r", s->m_remoteHost.ascii()); + ABORT_SOCKET(s) + return; + } + connect(s, SIGNAL(connectionClosed()), s, SLOT(deleteLater())); + s->initiateKerberosHandshake(); + emit newConnect(s); +} + +void UserMgmtServer::remoteConnectionClosed() { + m_numberOfConnections--; +} diff --git a/servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.h b/servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.h new file mode 100644 index 0000000..d0f75a2 --- /dev/null +++ b/servers/admin_user_mgmt_server_lin/src/admin_user_mgmt.h @@ -0,0 +1,111 @@ +/* + * Remote Laboratory User Management Server + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (c) 2013 Timothy Pearson + * Raptor Engineering + * http://www.raptorengineeringinc.com + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#define MAGIC_NUMBER 1 +#define PROTOCOL_VERSION 1 + +class SysCtlSocket : public TDEKerberosServerSocket +{ + Q_OBJECT + + public: + SysCtlSocket(int sock, TQObject *parent=0, const char *name=0); + ~SysCtlSocket(); + + public: + void close(); + void initiateKerberosHandshake(); + int enterCommandLoop(); + + private slots: + void finishKerberosHandshake(); + void connectionClosedHandler(); + void commandLoop(); + int connectToDatabase(); + + private: + int line; + int m_criticalSection; + TQString m_remoteHost; + + TQTimer* m_kerberosInitTimer; + TQTimer* m_loopTimer; + TQTimer* m_servClientTimeout; + + KSimpleConfig* m_config; + TQSqlDatabase* m_terminals_database; + TQSqlDatabase* m_workspaces_database; + int m_commandLoopState; + + gid_t m_minGID; + gid_t m_maxGID; + + friend class UserMgmtServer; +}; + +class UserMgmtServer : public TQServerSocket +{ + Q_OBJECT + + public: + UserMgmtServer(TQObject* parent=0, int port=0, KSimpleConfig* config=0); + ~UserMgmtServer(); + + void newConnection(int socket); + + private slots: + void remoteConnectionClosed(); + int connectToDatabase(); + void pingSQLServer(); + + signals: + void newConnect(SysCtlSocket*); + + private: + KSimpleConfig* m_config; + int m_numberOfConnections; + TQSqlDatabase* m_terminals_database; + TQSqlDatabase* m_workspaces_database; + TQTimer* m_sqlPingTimer; + + friend class SysCtlSocket; + +}; \ No newline at end of file diff --git a/servers/admin_user_mgmt_server_lin/src/main.cpp b/servers/admin_user_mgmt_server_lin/src/main.cpp index b216a9b..d9aa95a 100644 --- a/servers/admin_user_mgmt_server_lin/src/main.cpp +++ b/servers/admin_user_mgmt_server_lin/src/main.cpp @@ -37,7 +37,7 @@ #include #include -#include "admin_sys_ctl.h" +#include "admin_user_mgmt.h" static const char description[] = I18N_NOOP("RemoteFPGA System Administration User Management Server"); @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) KSimpleConfig config("remotefpga_adminusermgmtserver.conf", false); config.setGroup("Server"); - SysCtlServer fpgasvr(0, config.readNumEntry("port", 4016), &config); + UserMgmtServer fpgasvr(0, config.readNumEntry("port", 4016), &config); return app.exec(); } -- cgit v1.2.1