Initial commit. It's far from finished.
This commit is contained in:
17
CREDITS
Normal file
17
CREDITS
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# This file is intended to show my gratitude
|
||||||
|
# to the people who made contribtions to this
|
||||||
|
# project one way or another. The fields are:
|
||||||
|
# name (N), email (E), web-address (W), PGP
|
||||||
|
# key ID or fingerprint (P), description (D),
|
||||||
|
# and other notes (O)
|
||||||
|
|
||||||
|
N: mancha
|
||||||
|
E: N/A
|
||||||
|
D: Triage in SSL/TLS communication issues. Thank you!
|
||||||
|
O: Enthusiast in #openssl (on freenode IRC server)
|
||||||
|
|
||||||
|
N: Borislav Nikolov
|
||||||
|
E: borislav@otkachalki.net
|
||||||
|
W: https://git.otkachalki.net/
|
||||||
|
D: For general knowledge and best practice advises in C programming
|
||||||
|
|
||||||
44
Makefile
Normal file
44
Makefile
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
CC ?= cc
|
||||||
|
CCFLAGS ?= -O2
|
||||||
|
CCFLAGS += -Wall \
|
||||||
|
-Wextra \
|
||||||
|
-pipe \
|
||||||
|
-Wmissing-declarations \
|
||||||
|
-pedantic \
|
||||||
|
-fstack-protector-strong
|
||||||
|
|
||||||
|
LDFLAGS = -O1 -lcrypto -lssl -lpthread
|
||||||
|
LDFLAGS += -Wl,-z,relro,-z,now
|
||||||
|
|
||||||
|
SOURCES = main.c \
|
||||||
|
confparser.c \
|
||||||
|
rmps.c \
|
||||||
|
enum_functions.c \
|
||||||
|
log_trace.c \
|
||||||
|
thread_pool.c
|
||||||
|
|
||||||
|
OBJECTS = $(SOURCES:.c=.o)
|
||||||
|
EXECUTABLE = rmpsd
|
||||||
|
INSTALLDIR := $(DESTDIR)/usr/bin
|
||||||
|
|
||||||
|
all: $(SOURCES) $(EXECUTABLE)
|
||||||
|
|
||||||
|
$(EXECUTABLE): $(OBJECTS)
|
||||||
|
@echo ' LD $@'
|
||||||
|
@$(CC) $(LDFLAGS) $(OBJECTS) -o $@
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@echo ' CC $@'
|
||||||
|
@$(CC) $(CCFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECTS) $(EXECUTABLE)
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
rm -rf $(OBJECTS)
|
||||||
|
|
||||||
|
install:
|
||||||
|
install -m755 -D $(EXECUTABLE) "$(INSTALLDIR)/$(EXECUTABLE)"
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f "$(INSTALLDIR)/$(EXECUTABLE)"
|
||||||
26
agent/LSBs
Normal file
26
agent/LSBs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
###### UBUNTU ######
|
||||||
|
127 « smirky » ~ » cat /etc/os-release
|
||||||
|
NAME="Ubuntu"
|
||||||
|
VERSION="14.04.2 LTS, Trusty Tahr"
|
||||||
|
ID=ubuntu
|
||||||
|
ID_LIKE=debian
|
||||||
|
PRETTY_NAME="Ubuntu 14.04.2 LTS"
|
||||||
|
VERSION_ID="14.04"
|
||||||
|
HOME_URL="http://www.ubuntu.com/"
|
||||||
|
SUPPORT_URL="http://help.ubuntu.com/"
|
||||||
|
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
|
||||||
|
0 « smirky » ~ » cat /etc/lsb-release
|
||||||
|
DISTRIB_ID=Ubuntu
|
||||||
|
DISTRIB_RELEASE=14.04
|
||||||
|
DISTRIB_CODENAME=trusty
|
||||||
|
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"
|
||||||
|
|
||||||
|
|
||||||
|
###### DEBIAN ######
|
||||||
|
PRETTY_NAME="Debian GNU/Linux stretch/sid"
|
||||||
|
NAME="Debian GNU/Linux"
|
||||||
|
ID=debian
|
||||||
|
HOME_URL="https://www.debian.org/"
|
||||||
|
SUPPORT_URL="https://www.debian.org/support"
|
||||||
|
BUG_REPORT_URL="https://bugs.debian.org/"
|
||||||
|
|
||||||
35
agent/Makefile
Normal file
35
agent/Makefile
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
CC ?= cc
|
||||||
|
CCFLAGS ?= -O2
|
||||||
|
CCFLAGS += -Wall \
|
||||||
|
-Wextra \
|
||||||
|
-pipe \
|
||||||
|
-Wmissing-declarations \
|
||||||
|
-pedantic \
|
||||||
|
-fstack-protector-strong
|
||||||
|
|
||||||
|
LDFLAGS = -O1, -lcrypto -lssl -lpthread
|
||||||
|
LDFLAGS += -Wl,-z,relro,-z,now
|
||||||
|
|
||||||
|
SOURCES = agent.c \
|
||||||
|
agent_ssl.c \
|
||||||
|
job.c
|
||||||
|
|
||||||
|
OBJECTS = $(SOURCES:.c=.o)
|
||||||
|
EXECUTABLE = agent
|
||||||
|
|
||||||
|
all: $(SOURCES) $(EXECUTABLE)
|
||||||
|
|
||||||
|
$(EXECUTABLE): $(OBJECTS)
|
||||||
|
@echo ' LD $@'
|
||||||
|
@$(CC) $(LDFLAGS) $(OBJECTS) -o $@
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@echo ' CC $@'
|
||||||
|
@$(CC) $(CCFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECTS) $(EXECUTABLE)
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
rm -rf $(OBJECTS)
|
||||||
|
|
||||||
203
agent/agent.c
Normal file
203
agent/agent.c
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "job.h"
|
||||||
|
#include "../protocol.h"
|
||||||
|
#include "agent_ssl.h"
|
||||||
|
|
||||||
|
#define FAIL -1
|
||||||
|
|
||||||
|
static struct job_args *args;
|
||||||
|
static pthread_t *job_thread;
|
||||||
|
|
||||||
|
static short get_job_slot();
|
||||||
|
|
||||||
|
static short get_job_slot()
|
||||||
|
{
|
||||||
|
unsigned short i;
|
||||||
|
for (i = 0; i < MAX_AGENT_JOBS; i++)
|
||||||
|
if (args[i].slot != FULL)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static short find_job(unsigned id)
|
||||||
|
{
|
||||||
|
unsigned short i;
|
||||||
|
for (i = 0; i < MAX_AGENT_JOBS; i++)
|
||||||
|
if (args[i].buf.meta.id == id)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int count, char *strings[])
|
||||||
|
{
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
int server;
|
||||||
|
SSL *ssl;
|
||||||
|
int bytes, i;
|
||||||
|
char *hostname, *portnum;
|
||||||
|
|
||||||
|
if (count != 6) {
|
||||||
|
printf("usage: %s <hostname> <portnum> <key> <cert> <CA>\n", strings[0]);
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
hostname=strings[1];
|
||||||
|
portnum=strings[2];
|
||||||
|
if ((ctx = init_ctx()) == NULL)
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
server = connect_to_rmps(hostname, atoi(portnum));
|
||||||
|
if (!server) {
|
||||||
|
fprintf(stderr, "Failed to connect to RMPS: %s:%d\n", hostname, atoi(portnum));
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
load_certs(ctx, strings[3], strings[4], strings[5]);
|
||||||
|
ssl = SSL_new(ctx); /* create new SSL connection state */
|
||||||
|
SSL_set_fd(ssl, server); /* attach the socket descriptor */
|
||||||
|
|
||||||
|
if (SSL_connect(ssl) == FAIL) { /* perform the connection */
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
close(server);
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
|
||||||
|
show_certs(ssl);
|
||||||
|
if (!(args = (struct job_args*)calloc(1, sizeof(struct job_args) * MAX_AGENT_JOBS))) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Failed to calloc() %d bytes for job_args! Exiting...\n",
|
||||||
|
(int)sizeof(struct job_args) * MAX_AGENT_JOBS );
|
||||||
|
SSL_shutdown(ssl);
|
||||||
|
SSL_free(ssl);
|
||||||
|
close(server);
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!(job_thread = (pthread_t*)calloc(1, sizeof(pthread_t) * MAX_AGENT_JOBS))) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Failed to calloc() %d bytes for job_threads! Exiting...\n",
|
||||||
|
(int)sizeof(pthread_t) * MAX_AGENT_JOBS );
|
||||||
|
SSL_shutdown(ssl);
|
||||||
|
SSL_free(ssl);
|
||||||
|
close(server);
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
free(args);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_AGENT_JOBS; i++) {
|
||||||
|
args[i].slot = FREE;
|
||||||
|
args[i].ssl = ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
struct msg buf;
|
||||||
|
memset(&buf, 0, sizeof(struct msg));
|
||||||
|
bytes = SSL_read(ssl, &buf, sizeof(struct msg));
|
||||||
|
if (bytes > 0) {
|
||||||
|
short index;
|
||||||
|
if (bytes != sizeof(struct msg)) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Received non-standard data from server!\n" );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (buf.chunk.id == 0) {
|
||||||
|
if ((index = get_job_slot()) == FAIL) {
|
||||||
|
buf.chunk.id = -1; /* ID -1 means reject (full) */
|
||||||
|
sprintf((char*)buf.chunk.data, "The agent's queue is full!");
|
||||||
|
SSL_write(ssl, &buf, sizeof(struct msg));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
args[index].slot = FULL;
|
||||||
|
memcpy(&args[index].buf, &buf, sizeof(struct msg));
|
||||||
|
switch (args[index].buf.meta.type) {
|
||||||
|
case UNIX:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
exec_unix,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case INSTALL_PKG:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
install_pkg,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case QUERY_PKG:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
query_pkg,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case DELETE_PKG:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
delete_pkg,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case LIST_PKGS:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
list_pkgs,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case UPDATE_PKG:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
update_pkg,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case UPDATE_PKGS:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
update_pkgs,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case GET_OS:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
get_os,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case GET_KERNEL:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
get_kernel,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case GET_UPTIME:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
get_uptime,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
case GET_MEMORY:
|
||||||
|
pthread_create( &job_thread[index],
|
||||||
|
NULL,
|
||||||
|
get_memory,
|
||||||
|
&args[index] );
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
buf.chunk.id = -1;
|
||||||
|
sprintf( (char*)buf.chunk.data,
|
||||||
|
"Unsupported job type with ID: %d",
|
||||||
|
buf.meta.type );
|
||||||
|
SSL_write(ssl, &buf, sizeof(struct msg));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
index = find_job(buf.meta.id);
|
||||||
|
if (index == FAIL) {
|
||||||
|
sprintf( (char*)buf.chunk.data,
|
||||||
|
"Data was sent for an invalid job ID" );
|
||||||
|
SSL_write(ssl, &buf, sizeof(struct msg));
|
||||||
|
} else
|
||||||
|
memcpy(&args[index].buf, &buf, sizeof(struct msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_shutdown(ssl);
|
||||||
|
SSL_free(ssl); /* release connection state */
|
||||||
|
} while (bytes);
|
||||||
|
close(server); /* close socket */
|
||||||
|
SSL_CTX_free(ctx); /* release context */
|
||||||
|
}
|
||||||
126
agent/agent_ssl.c
Normal file
126
agent/agent_ssl.c
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include "agent_ssl.h"
|
||||||
|
|
||||||
|
#define FAIL -1
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
/*--- OpenConnection - create socket and connect to server. ---*/
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
int connect_to_rmps(const char *hostname, int port)
|
||||||
|
{
|
||||||
|
int sd;
|
||||||
|
struct hostent *host;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
|
||||||
|
if ((host = gethostbyname(hostname)) == NULL) {
|
||||||
|
perror(hostname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sd = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_addr.s_addr = *(long*)(host->h_addr);
|
||||||
|
if (connect(sd, (struct sockaddr*)&addr, sizeof(addr)) == FAIL) {
|
||||||
|
close(sd);
|
||||||
|
perror(hostname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------*/
|
||||||
|
/*--- Initialize the SSL engine. ---*/
|
||||||
|
/*----------------------------------*/
|
||||||
|
SSL_CTX* init_ctx(void)
|
||||||
|
{
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
char ciphers[2048];
|
||||||
|
|
||||||
|
//OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
|
||||||
|
//OpenSSL_add_all_ciphers(); /* Load cryptos, et.al. */
|
||||||
|
SSL_load_error_strings(); /* Bring in and register error messages */
|
||||||
|
SSL_library_init();
|
||||||
|
ctx = SSL_CTX_new(TLSv1_2_method()); /* Create new context */
|
||||||
|
ciphers[0] = 0;
|
||||||
|
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback);
|
||||||
|
strcat(ciphers, "-ALL");
|
||||||
|
if (!SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256:AES256-SHA")) {
|
||||||
|
fprintf(stderr, "Failed to set the cipher list. Exiting...\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (ctx == NULL) {
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verify_callback (int ok, X509_STORE_CTX *store)
|
||||||
|
{
|
||||||
|
char data[256];
|
||||||
|
if (!ok) {
|
||||||
|
X509 *cert = X509_STORE_CTX_get_current_cert(store);
|
||||||
|
int depth = X509_STORE_CTX_get_error_depth(store);
|
||||||
|
int err = X509_STORE_CTX_get_error(store);
|
||||||
|
fprintf(stderr, "-Error with certificate at depth: %i\n", depth);
|
||||||
|
X509_NAME_oneline(X509_get_issuer_name(cert), data, 256);
|
||||||
|
fprintf(stderr, " issuer = %s\n", data);
|
||||||
|
X509_NAME_oneline(X509_get_subject_name(cert), data, 256);
|
||||||
|
fprintf(stderr, " subject = %s\n", data);
|
||||||
|
fprintf(stderr, " err %i:%s\n", err, X509_verify_cert_error_string(err) );
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------*/
|
||||||
|
/*--- Print out the certificates. ---*/
|
||||||
|
/*-----------------------------------*/
|
||||||
|
void show_certs(SSL* ssl)
|
||||||
|
{
|
||||||
|
X509 *cert;
|
||||||
|
char *line;
|
||||||
|
char *cipher;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
|
||||||
|
|
||||||
|
if (cert != NULL) {
|
||||||
|
printf("Server certificates:\n");
|
||||||
|
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
||||||
|
printf("Subject: %s\n", line);
|
||||||
|
free(line); /* free the malloc'ed string */
|
||||||
|
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
|
||||||
|
printf("Issuer: %s\n", line);
|
||||||
|
free(line); /* free the malloc'ed string */
|
||||||
|
X509_free(cert); /* free the malloc'ed certificate copy */
|
||||||
|
} else
|
||||||
|
printf("No certificates.\n");
|
||||||
|
|
||||||
|
do {
|
||||||
|
cipher = (char*)SSL_get_cipher_list(ssl, index);
|
||||||
|
if (cipher) {
|
||||||
|
printf("Cipher = %s\n", cipher);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
} while (cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_certs(SSL_CTX *ctx, char *key, char *cert, char *ca)
|
||||||
|
{
|
||||||
|
SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM);
|
||||||
|
SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM);
|
||||||
|
if (!SSL_CTX_check_private_key(ctx)) {
|
||||||
|
fprintf(stderr, "Private key doesn't match the cert!\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca));
|
||||||
|
SSL_CTX_load_verify_locations(ctx, ca, NULL);
|
||||||
|
if (SSL_CTX_get_client_CA_list(ctx) == NULL) {
|
||||||
|
fprintf(stderr, "Could not set client CA list from %s\n", ca);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
agent/agent_ssl.h
Normal file
13
agent/agent_ssl.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef AGENT_SSL
|
||||||
|
#define AGENT_SSL
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
int connect_to_rmps(const char *hostname, int port);
|
||||||
|
SSL_CTX* init_ctx();
|
||||||
|
int verify_callback (int ok, X509_STORE_CTX *store);
|
||||||
|
void show_certs(SSL* ssl);
|
||||||
|
void load_certs(SSL_CTX *ctx, char *key, char *cert, char *ca);
|
||||||
|
|
||||||
|
#endif /* AGENT_SSL */
|
||||||
33
agent/detect-unix.sh
Executable file
33
agent/detect-unix.sh
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Detects which OS and if it is Linux then it will detect which Linux Distribution.
|
||||||
|
|
||||||
|
OS=$(uname -s)
|
||||||
|
MARCH=$(uname -m)
|
||||||
|
|
||||||
|
if [ "${OS}" = "SunOS" ] ; then
|
||||||
|
OS=Solaris
|
||||||
|
ARCH=$(uname -p)
|
||||||
|
OSSTR="${OS} ${REV}(${ARCH} $(uname -v))"
|
||||||
|
elif [ "${OS}" = "AIX" ] ; then
|
||||||
|
OSSTR="${OS} $(oslevel) ($(oslevel -r))"
|
||||||
|
elif [ "${OS}" = "Linux" ] ; then
|
||||||
|
KERNEL=$(uname -r)
|
||||||
|
if [ -f /etc/redhat-release ] ; then
|
||||||
|
DIST="$(cat /etc/redhat-release)"
|
||||||
|
elif [ -f /etc/SuSE-release ] ; then
|
||||||
|
DIST=$(tr "\n" ' ' < /etc/SuSE-release | sed s/VERSION.*//)
|
||||||
|
elif [ -f /etc/debian_version ] ; then
|
||||||
|
DIST="Debian $(cat /etc/debian_version)"
|
||||||
|
elif [ -f /etc/slackware-version ] ; then
|
||||||
|
DIST="$(cat /etc/slackware-version)"
|
||||||
|
elif [ -f /etc/os-release ] ; then
|
||||||
|
DIST=$(grep PRETTY_NAME /etc/os-release | tr -d '"=' | sed 's/PRETTY_NAME//')
|
||||||
|
else
|
||||||
|
DIST="$OS $MARCH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
OSSTR="${DIST}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
printf "%s" "${OSSTR}"
|
||||||
152
agent/job.c
Normal file
152
agent/job.c
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "job.h"
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
|
||||||
|
struct job_t {
|
||||||
|
long id;
|
||||||
|
long parent_id;
|
||||||
|
int type;
|
||||||
|
char code[8192];
|
||||||
|
char std_out[8192];
|
||||||
|
char std_err[8192];
|
||||||
|
short ret_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gen_fname_hash(char *s, const int len)
|
||||||
|
{
|
||||||
|
static const char alphanum[] =
|
||||||
|
"0123456789"
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz";
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
|
||||||
|
s[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* exec_unix(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* install_pkg(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* query_pkg(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* delete_pkg(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* list_pkgs(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* update_pkg(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* update_pkgs(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* get_os(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
char cmd[40], dump_path[14];
|
||||||
|
int fd;
|
||||||
|
sprintf(dump_path, "/tmp/");
|
||||||
|
gen_fname_hash(&dump_path[5], 8);
|
||||||
|
sprintf(cmd, "sh detect-unix.sh > %s", dump_path);
|
||||||
|
system(cmd); /* TODO: set proper path */
|
||||||
|
if ((fd = open(dump_path, O_RDONLY)) == -1) {
|
||||||
|
fprintf(stderr, "Cannot open file: %s\n", dump_path);
|
||||||
|
job->buf.meta.len = sprintf((char*)job->buf.chunk.data, "Unknown");
|
||||||
|
SSL_write(job->ssl, &job->buf, sizeof(struct msg));
|
||||||
|
} else {
|
||||||
|
job->buf.meta.len = read(fd, job->buf.chunk.data, sizeof(job->buf.chunk.data));
|
||||||
|
if ((signed)job->buf.meta.len == -1) {
|
||||||
|
perror("Failed to read from file: ");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
SSL_write(job->ssl, &job->buf, sizeof(struct msg));
|
||||||
|
job->slot = FREE;
|
||||||
|
}
|
||||||
|
unlink(dump_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* get_kernel(void *args)
|
||||||
|
{
|
||||||
|
struct utsname name;
|
||||||
|
struct job_args *job = args;
|
||||||
|
if (uname(&name) == -1) {
|
||||||
|
job->buf.meta.len = sprintf((char*)job->buf.chunk.data, "Unknown");
|
||||||
|
SSL_write(job->ssl, &job->buf, sizeof(struct msg));
|
||||||
|
} else {
|
||||||
|
job->buf.meta.len = sprintf( (char*)job->buf.chunk.data,
|
||||||
|
"%s %s %s %s %s",
|
||||||
|
name.sysname,
|
||||||
|
name.nodename,
|
||||||
|
name.release,
|
||||||
|
name.version,
|
||||||
|
name.machine );
|
||||||
|
SSL_write(job->ssl, &job->buf, sizeof(struct msg));
|
||||||
|
}
|
||||||
|
job->slot = FREE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* get_uptime(void *args)
|
||||||
|
{
|
||||||
|
struct job_args *job = args;
|
||||||
|
struct sysinfo sys;
|
||||||
|
|
||||||
|
if (sysinfo(&sys) != 0) {
|
||||||
|
job->buf.meta.len = sprintf((char*)job->buf.chunk.data, "Unknown");
|
||||||
|
SSL_write(job->ssl, &job->buf, sizeof(struct msg));
|
||||||
|
} else {
|
||||||
|
memcpy(&job->buf.chunk.data, &sys.uptime, sizeof(long));
|
||||||
|
//sprintf((char*)&job->buf.chunk.data, "%ld", sys.uptime);
|
||||||
|
SSL_write(job->ssl, &job->buf, sizeof(struct msg));
|
||||||
|
}
|
||||||
|
job->slot = FREE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* get_memory(void *args)
|
||||||
|
{
|
||||||
|
long pages, pagesize, freepages;
|
||||||
|
struct job_args *job = args;
|
||||||
|
|
||||||
|
pages = sysconf(_SC_PHYS_PAGES);
|
||||||
|
pagesize = sysconf (_SC_PAGESIZE);
|
||||||
|
freepages = sysconf(_SC_AVPHYS_PAGES);
|
||||||
|
job->buf.meta.len = sprintf( (char*)job->buf.chunk.data,
|
||||||
|
"%ld / %ld (MB)",
|
||||||
|
(freepages * pagesize) / 1048576 /* 1024*1024 */,
|
||||||
|
(pages * pagesize) / 1048576 );
|
||||||
|
SSL_write(job->ssl, &job->buf, sizeof(struct msg));
|
||||||
|
job->slot = FREE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
30
agent/job.h
Normal file
30
agent/job.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef JOB_H
|
||||||
|
#define JOB_H
|
||||||
|
|
||||||
|
#include "agent_ssl.h"
|
||||||
|
#include "../protocol.h"
|
||||||
|
|
||||||
|
enum pthread_state { WAIT, WORK };
|
||||||
|
enum job_slot_state { FREE, FULL };
|
||||||
|
|
||||||
|
struct job_args {
|
||||||
|
struct msg buf;
|
||||||
|
unsigned short slot;
|
||||||
|
SSL *ssl;
|
||||||
|
};
|
||||||
|
|
||||||
|
void* exec_unix(void *args);
|
||||||
|
void* install_pkg(void *args);
|
||||||
|
void* query_pkg(void *args);
|
||||||
|
void* delete_pkg(void *args);
|
||||||
|
void* list_pkgs(void *args);
|
||||||
|
void* update_pkg(void *args);
|
||||||
|
void* update_pkgs(void *args);
|
||||||
|
void* get_os(void *args);
|
||||||
|
void* get_kernel(void *args);
|
||||||
|
void* get_uptime(void *args);
|
||||||
|
void* get_memory(void *args);
|
||||||
|
|
||||||
|
#define MAX_AGENT_JOBS 10
|
||||||
|
|
||||||
|
#endif /* JOB_H */
|
||||||
27
agent/pkgctl.sh
Executable file
27
agent/pkgctl.sh
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
OS=`sh detect-unix.sh`
|
||||||
|
|
||||||
|
# Determine task
|
||||||
|
#case $1 in
|
||||||
|
# install)
|
||||||
|
# remove)
|
||||||
|
# update)
|
||||||
|
# query)
|
||||||
|
#esac
|
||||||
|
|
||||||
|
# Determine package manager
|
||||||
|
case "$OS" in
|
||||||
|
"Arch Linux") PM="pacman" ;;
|
||||||
|
"Fedora") PM="yum" ;;
|
||||||
|
"Red Hat") PM="yum" ;;
|
||||||
|
"CentOS") PM="yum" ;;
|
||||||
|
"SUSE") PM="yum" ;;
|
||||||
|
"Ubuntu") PM="apt" ;;
|
||||||
|
"Debian") PM="apt" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
#if [ "$OS" = "Arch Linux" ] ; then
|
||||||
|
# PM="pacman"
|
||||||
|
#fi
|
||||||
|
echo $PM
|
||||||
2
agent/runme.sh
Executable file
2
agent/runme.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
./agent localhost 7000 /etc/rmps/certs/client_1/client.key /etc/rmps/certs/client_1/client.crt /etc/rmps/certs/ca.pem
|
||||||
356
confparser.c
Normal file
356
confparser.c
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "log_trace.h"
|
||||||
|
#include "confparser.h"
|
||||||
|
#include "enum_functions.h"
|
||||||
|
|
||||||
|
static int test_conf_perms();
|
||||||
|
static int test_conf_syntax();
|
||||||
|
|
||||||
|
struct conf_table conf = {
|
||||||
|
{
|
||||||
|
"", /* db.type */
|
||||||
|
"", /* db.hostname */
|
||||||
|
"" /* db.port */
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"127.0.0.1", /* rmps.bind_on_ip */
|
||||||
|
"7000", /* rmps.bind_on_port */
|
||||||
|
"/var/log/rmps/rmpsd.log",
|
||||||
|
"/var/log/rmps/rmpsd.err",
|
||||||
|
'1', /* rmps.loglevel */
|
||||||
|
"/run/rmps/rmpsd.pid",
|
||||||
|
"/etc/rmps/cert.pem",
|
||||||
|
"/etc/rmps/key.pem",
|
||||||
|
"/etc/rmps/ca.crt",
|
||||||
|
"", /* rmps.cipherlist */
|
||||||
|
2 /* rmps.threadpoolsize */
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0 /* nfs -> TODO */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void confexport()
|
||||||
|
{
|
||||||
|
printf( "db.type=%s\n"
|
||||||
|
"db.hostname=%s\n"
|
||||||
|
"db.port=%s\n"
|
||||||
|
"rmps.bind_on_ip=%s\n"
|
||||||
|
"rmps.bind_on_port=%s\n"
|
||||||
|
"rmps.logfile=%s\n"
|
||||||
|
"rmps.errlog=%s\n"
|
||||||
|
"rmps.loglevel=%c\n"
|
||||||
|
"rmps.pidfile=%s\n"
|
||||||
|
"rmps.certfile=%s\n"
|
||||||
|
"rmps.keyfile=%s\n"
|
||||||
|
"rmps.cafile=%s\n"
|
||||||
|
"rmps.cipherlist=%s\n"
|
||||||
|
"rmps.threadpoolsize=%d\n",
|
||||||
|
conf.db.type,
|
||||||
|
conf.db.hostname,
|
||||||
|
conf.db.port,
|
||||||
|
conf.rmps.bind_on_ip,
|
||||||
|
conf.rmps.bind_on_port,
|
||||||
|
conf.rmps.logfile,
|
||||||
|
conf.rmps.errlog,
|
||||||
|
conf.rmps.loglevel,
|
||||||
|
conf.rmps.pidfile,
|
||||||
|
conf.rmps.certfile,
|
||||||
|
conf.rmps.keyfile,
|
||||||
|
conf.rmps.cafile,
|
||||||
|
conf.rmps.cipherlist,
|
||||||
|
conf.rmps.threadpoolsize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fopen_and_mkdir(const char *dir) {
|
||||||
|
char tmp[256];
|
||||||
|
char *p = NULL;
|
||||||
|
size_t len;
|
||||||
|
FILE *fd;
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp),"%s",dir);
|
||||||
|
len = strlen(tmp);
|
||||||
|
if(tmp[len - 1] == '/')
|
||||||
|
tmp[len - 1] = 0;
|
||||||
|
for (p = tmp + 1; *p; p++)
|
||||||
|
if(*p == '/') {
|
||||||
|
*p = 0;
|
||||||
|
if (mkdir(tmp, S_IRWXU) == -1 && errno != EEXIST) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Permission denied to create directory: %s\n",
|
||||||
|
tmp );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*p = '/';
|
||||||
|
}
|
||||||
|
fd = fopen(dir, "a");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "Permission denied to write into: %s\n", dir);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_conf_perms()
|
||||||
|
{
|
||||||
|
struct stat s;
|
||||||
|
char confresult[128];
|
||||||
|
int err = stat("/etc/rmps", &s);
|
||||||
|
|
||||||
|
if (err == -1) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
enumtostr(confresult, CONF_DIR_MISSING);
|
||||||
|
log_trace(ERROR, confresult);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!S_ISDIR(s.st_mode)) {
|
||||||
|
enumtostr(confresult, CONF_DIR_NOTDIR);
|
||||||
|
log_trace(ERROR, confresult);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ( !(S_IRUSR & s.st_mode) ||
|
||||||
|
!(S_IXUSR & s.st_mode) ) {
|
||||||
|
enumtostr(confresult, CONF_DIR_PERM);
|
||||||
|
log_trace(ERROR, confresult);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (s.st_uid != 0) {
|
||||||
|
enumtostr(confresult, CONF_DIR_UID_INSECURE);
|
||||||
|
log_trace(WARNING, confresult);
|
||||||
|
}
|
||||||
|
else if (s.st_gid != 0) {
|
||||||
|
enumtostr(confresult, CONF_DIR_GID_INSECURE);
|
||||||
|
log_trace(WARNING, confresult);
|
||||||
|
}
|
||||||
|
else if ( (S_IROTH & s.st_mode) ||
|
||||||
|
(S_IWOTH & s.st_mode) ) {
|
||||||
|
enumtostr(confresult, CONF_DIR_PERM_INSECURE);
|
||||||
|
log_trace(WARNING, confresult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = stat("/etc/rmps/rmps.conf", &s);
|
||||||
|
|
||||||
|
if (err == -1) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
enumtostr(confresult, CONF_MISSING);
|
||||||
|
log_trace(ERROR, confresult);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!S_ISREG(s.st_mode)) {
|
||||||
|
enumtostr(confresult, CONF_NOTFILE);
|
||||||
|
log_trace(ERROR, confresult);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!(S_IRUSR & s.st_mode)) {
|
||||||
|
enumtostr(confresult, CONF_PERM);
|
||||||
|
log_trace(ERROR, confresult);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (s.st_uid != 0) {
|
||||||
|
enumtostr(confresult, CONF_FILE_UID_INSECURE);
|
||||||
|
log_trace(WARNING, confresult);
|
||||||
|
}
|
||||||
|
else if (s.st_gid != 0) {
|
||||||
|
enumtostr(confresult, CONF_FILE_GID_INSECURE);
|
||||||
|
log_trace(WARNING, confresult);
|
||||||
|
}
|
||||||
|
else if ( (S_IROTH & s.st_mode) ||
|
||||||
|
(S_IWOTH & s.st_mode) ) {
|
||||||
|
enumtostr(confresult, CONF_FILE_PERM_INSECURE);
|
||||||
|
log_trace(WARNING, confresult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* conf is readable */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_conf_syntax()
|
||||||
|
{
|
||||||
|
int i, j = 0, ok = 1, failed = 0;
|
||||||
|
char buf[CFGLINESIZE], *tmp;
|
||||||
|
FILE *fd = fopen("/etc/rmps/rmps.conf", "r");
|
||||||
|
|
||||||
|
if (fd == NULL) {
|
||||||
|
log_trace(ERROR, "Failed to read /etc/rmps/rmps.conf");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(buf, CFGLINESIZE, fd) != NULL) {
|
||||||
|
j++;
|
||||||
|
/* kill comments and ignore BLANK lines */
|
||||||
|
if ((tmp = strstr(buf, "#")))
|
||||||
|
*tmp = '\0';
|
||||||
|
if (buf[strspn(buf, " \t\v\r\n")] == '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If we have "=", it's a possible var */
|
||||||
|
if ((tmp = strstr(buf, "=")))
|
||||||
|
*tmp = '\0';
|
||||||
|
else {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Bad entry in /etc/rmps/rmps.conf, line %d: %s\n",
|
||||||
|
j, buf );
|
||||||
|
ok = 0;
|
||||||
|
failed = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Check if there actually is a value after '=' */
|
||||||
|
i = strlen(tmp + 1);
|
||||||
|
if (tmp[i] == '\n')
|
||||||
|
tmp[i] = '\0';
|
||||||
|
if (tmp[strspn(tmp + 1, " \t\v\r\n") + 1] == '\0') {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Specified entry without value, line %d: %s\n",
|
||||||
|
j, buf );
|
||||||
|
failed = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Here we check every single entry manually */
|
||||||
|
if (!strcmp(buf, "db.type")) {
|
||||||
|
if (!strcmp(tmp + 1, "mysql")) {
|
||||||
|
/* || !strcmp(tmp[1], "postgresql") */
|
||||||
|
/* || !strcmp(tmp[1], "oracle") */
|
||||||
|
strcpy(conf.db.type, tmp + 1);
|
||||||
|
if (conf.db.port[0] == '\0')
|
||||||
|
strcpy(conf.db.port, "3306");
|
||||||
|
} else {
|
||||||
|
ok = 0;
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(buf, "db.hostname"))
|
||||||
|
/* Just save it, launch_rmps will check it */
|
||||||
|
strcpy(conf.db.hostname, tmp + 1);
|
||||||
|
else if (!strcmp(buf, "db.port")) {
|
||||||
|
if ((i = strlen(tmp + 1)) < 6) {
|
||||||
|
if ((signed int)strspn(tmp + 1, "1234567890") == i) {
|
||||||
|
i = atoi(tmp + 1);
|
||||||
|
if (i > 0 && i < 65536) {
|
||||||
|
strcpy(conf.db.port, tmp + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok = 0;
|
||||||
|
failed = 1;
|
||||||
|
} else if (!strcmp(buf, "rmps.bind_on_ip")) {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
} else if (!strcmp(buf, "rmps.bind_on_port")) {
|
||||||
|
if ((i = strlen(tmp + 1)) < 6) {
|
||||||
|
if ((signed int)strspn(tmp + 1, "1234567890") == i) {
|
||||||
|
i = atoi(tmp + 1);
|
||||||
|
if (i > 0 && i < 65536) {
|
||||||
|
strcpy(conf.rmps.bind_on_port, tmp + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok = 0;
|
||||||
|
failed = 1;
|
||||||
|
} else if (!strcmp(buf, "rmps.logfile")) {
|
||||||
|
strcpy(conf.rmps.logfile, tmp + 1);
|
||||||
|
if (fopen_and_mkdir(conf.rmps.logfile) != 0)
|
||||||
|
failed = 1;
|
||||||
|
} else if (!strcmp(buf, "rmps.errlog")) {
|
||||||
|
strcpy(conf.rmps.errlog, tmp + 1);
|
||||||
|
if (fopen_and_mkdir(conf.rmps.errlog) != 0)
|
||||||
|
failed = 1;
|
||||||
|
} else if (!strcmp(buf, "rmps.pidfile")) {
|
||||||
|
strcpy(conf.rmps.pidfile, tmp + 1);
|
||||||
|
/*if (fopen_and_mkdir(conf.rmps.pidfile) != 0)
|
||||||
|
failed = 1;*/
|
||||||
|
} else if (!strcmp(buf, "rmps.loglevel")) {
|
||||||
|
if (strlen(tmp + 1) == 1 && (tmp[1] > '0' && tmp[1] < '5'))
|
||||||
|
conf.rmps.loglevel = tmp[1];
|
||||||
|
else
|
||||||
|
failed = 1;
|
||||||
|
} else if (!strcmp(buf, "rmps.certfile")) {
|
||||||
|
if (access(tmp + 1, F_OK) == -1) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s is missing\n", tmp + 1);
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
else if (access(tmp + 1, R_OK) == -1) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s is not readable\n",
|
||||||
|
tmp + 1
|
||||||
|
);
|
||||||
|
failed = 1;
|
||||||
|
} else
|
||||||
|
strncpy(conf.rmps.certfile, tmp + 1, sizeof(conf.rmps.certfile));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!strcmp(buf, "rmps.keyfile")) {
|
||||||
|
if (access(tmp + 1, F_OK) == -1) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s is missing\n", conf.rmps.keyfile);
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
else if (access(tmp + 1, R_OK) == -1) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s is not readable\n",
|
||||||
|
tmp + 1
|
||||||
|
);
|
||||||
|
failed = 1;
|
||||||
|
} else
|
||||||
|
strncpy(conf.rmps.keyfile, tmp + 1, sizeof(conf.rmps.keyfile));
|
||||||
|
} else if (!strcmp(buf, "rmps.cipherlist")) {
|
||||||
|
strncpy(conf.rmps.cipherlist, tmp + 1, sizeof(conf.rmps.cipherlist));
|
||||||
|
} else if (!strcmp(buf, "rmps.cafile")) {
|
||||||
|
if (access(tmp + 1, F_OK) == -1) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s is missing\n", tmp + 1);
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
else if (access(tmp + 1, R_OK) == -1) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s is not readable\n",
|
||||||
|
tmp + 1
|
||||||
|
);
|
||||||
|
failed = 1;
|
||||||
|
} else
|
||||||
|
strncpy(conf.rmps.cafile, tmp + 1, sizeof(conf.rmps.cafile));
|
||||||
|
} else
|
||||||
|
fprintf( stderr,
|
||||||
|
"Unknown config entry on line %d: %s\n",
|
||||||
|
j, buf );
|
||||||
|
if (!ok) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Invalid value for \"%s\", line %d: \"%s\"\n",
|
||||||
|
buf, j, tmp + 1 );
|
||||||
|
ok = !ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
if (failed)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int confparse()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = test_conf_perms();
|
||||||
|
if (result)
|
||||||
|
return 1; /* Bad conf perms */
|
||||||
|
|
||||||
|
result = test_conf_syntax();
|
||||||
|
if (result != 0)
|
||||||
|
return 1; /* Bad conf syntax */
|
||||||
|
|
||||||
|
return 0; /* seems legit */
|
||||||
|
}
|
||||||
43
confparser.h
Normal file
43
confparser.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef CONFPARSER_H
|
||||||
|
#define CONFPARSER_H
|
||||||
|
|
||||||
|
#define MAXPATHSIZE 256
|
||||||
|
#define HOSTNAMESIZE 128
|
||||||
|
#define CFGLINESIZE 300
|
||||||
|
|
||||||
|
struct conf_db {
|
||||||
|
char type[15];
|
||||||
|
char hostname[HOSTNAMESIZE];
|
||||||
|
char port[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct conf_rmps {
|
||||||
|
char bind_on_ip[13];
|
||||||
|
char bind_on_port[6];
|
||||||
|
char logfile[MAXPATHSIZE];
|
||||||
|
char errlog[MAXPATHSIZE];
|
||||||
|
char loglevel;
|
||||||
|
char pidfile[MAXPATHSIZE];
|
||||||
|
char certfile[MAXPATHSIZE];
|
||||||
|
char keyfile[MAXPATHSIZE];
|
||||||
|
char cafile[MAXPATHSIZE];
|
||||||
|
char cipherlist[1024];
|
||||||
|
int threadpoolsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct conf_nfs {
|
||||||
|
int TODO;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct conf_table {
|
||||||
|
struct conf_db db;
|
||||||
|
struct conf_rmps rmps;
|
||||||
|
struct conf_nfs nfs;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct conf_table conf;
|
||||||
|
extern int confparse();
|
||||||
|
extern void confexport();
|
||||||
|
|
||||||
|
#endif /* CONFPARSER_H */
|
||||||
|
|
||||||
26
db_scripts/readme
Normal file
26
db_scripts/readme
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
##### static_groups #####
|
||||||
|
ID | NAME | CREATED | OWNER(FK-users) | LAST_MOD_TIME | LAST_MOD_USER | COMMENT
|
||||||
|
|
||||||
|
##### dynamic_groups #####
|
||||||
|
|
||||||
|
|
||||||
|
##### managed_servers #####
|
||||||
|
ID | NAME | IP | MAC | FQDN | OS | ADDED | ACTIVE | COMMENT
|
||||||
|
|
||||||
|
##### scripts #####
|
||||||
|
ID | NAME | TYPE(FK-script_types) | CREATED | OWNER(FK-users) | LAST_MOD_TIME | CONTENT | COMMENT
|
||||||
|
|
||||||
|
##### script_types #####
|
||||||
|
ID | DESCR
|
||||||
|
|
||||||
|
##### script_logs #####
|
||||||
|
ID | JID | STARTED | ENDED | STDOUT | STDERR | EXIT_CODE
|
||||||
|
|
||||||
|
##### jobs #####
|
||||||
|
ID | TYPEID(FK-jobs_types) | OWNER(FK-users) | STARTED | ENDED | STATUS
|
||||||
|
|
||||||
|
##### job_types #####
|
||||||
|
ID | TYPE
|
||||||
|
|
||||||
|
##### users #####
|
||||||
|
ID | USERNAME | NAME | ADDED | LAST_LOG | LAST_OUT | EMAIL | COMMENT
|
||||||
15
enum_codes
Normal file
15
enum_codes
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Error codes
|
||||||
|
100:CONF_DIR_MISSING:"Config directory /etc/rmps is missing!"
|
||||||
|
101:CONF_DIR_PERM:"Config dir /etc/rmps cannot be accessed, check permissions!"
|
||||||
|
102:CONF_DIR_NOTDIR:"It appears that /etc/rmps is a file. Should be a directory!"
|
||||||
|
103:CONF_MISSING:"Config file /etc/rmps/rmps.conf is missing!"
|
||||||
|
104:CONF_PERM:"Config file /etc/rmps/rmps.conf cannot be accessed, check permissions!"
|
||||||
|
105:CONF_NOTFILE:"It appears that /etc/rmps/rmps.conf is not a regular file!"
|
||||||
|
|
||||||
|
# Warning codes
|
||||||
|
200:CONF_DIR_GUI_INSECURE:"Insecure group for /etc/rmps. Should be 'rmps'!"
|
||||||
|
201:CONF_DIR_UID_INSECURE:"Insecure owner for /etc/rmps. Should be 'root'!"
|
||||||
|
202:CONF_DIR_PERM_INSECURE:"Insecure global permissions for /etc/rmps. Should be 0770!"
|
||||||
|
203:CONF_FILE_GID_INSECURE:"Insecure group for /etc/rmps/rmps.conf. Should be 'rmps'!"
|
||||||
|
204:CONF_FILE_UID_INSECURE:"Insecure owner for /etc/rmps/rmps.conf. Should be 'root'!"
|
||||||
|
205:CONF_FILE_PERM_INSECURE:"Insecure global permissions /etc/rmps/rmps.conf". Shold be 0660!"
|
||||||
29
enum_functions.c
Normal file
29
enum_functions.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "enum_functions.h"
|
||||||
|
#include "log_trace.h"
|
||||||
|
|
||||||
|
void enumtostr(char *scode, int code)
|
||||||
|
{
|
||||||
|
char line[128];
|
||||||
|
FILE *fd;
|
||||||
|
|
||||||
|
snprintf(scode, 10, "%d", code);
|
||||||
|
|
||||||
|
fd = fopen("/usr/lib/rmps/resources/enum_codes", "r");
|
||||||
|
if (fd == NULL) {
|
||||||
|
log_trace(ERROR, "Failed to fetch error enum code!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (fgets(line, sizeof(line), fd) != NULL)
|
||||||
|
if (strstr(line, scode) != NULL) {
|
||||||
|
sprintf(scode, "%s", line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strncpy( scode,
|
||||||
|
memchr(scode, '\"', strlen(scode)),
|
||||||
|
strlen(scode) );
|
||||||
|
fclose(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
24
enum_functions.h
Normal file
24
enum_functions.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef ENUM_FUNCTIONS_H
|
||||||
|
#define ENUM_FUNCTIONS_H
|
||||||
|
|
||||||
|
enum ERROR_CODES {
|
||||||
|
CONF_DIR_MISSING = 100,
|
||||||
|
CONF_DIR_PERM, /* 101 */
|
||||||
|
CONF_DIR_NOTDIR, /* 102 */
|
||||||
|
CONF_MISSING, /* 103 */
|
||||||
|
CONF_PERM, /* 104 */
|
||||||
|
CONF_NOTFILE /* 105 */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum WARN_CODES {
|
||||||
|
CONF_DIR_GID_INSECURE = 200,
|
||||||
|
CONF_DIR_UID_INSECURE,
|
||||||
|
CONF_DIR_PERM_INSECURE,
|
||||||
|
CONF_FILE_GID_INSECURE,
|
||||||
|
CONF_FILE_UID_INSECURE,
|
||||||
|
CONF_FILE_PERM_INSECURE
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void enumtostr(char *scode, int code);
|
||||||
|
|
||||||
|
#endif /* ENUM_FUNCTIONS_H */
|
||||||
64
log_trace.c
Normal file
64
log_trace.c
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "log_trace.h"
|
||||||
|
#include "confparser.h"
|
||||||
|
|
||||||
|
void log_trace(LOG_LEVEL lvl, char *fmt, ... )
|
||||||
|
{
|
||||||
|
LOG_LEVEL cur_lvl = conf.rmps.loglevel - '0';
|
||||||
|
if (lvl <= cur_lvl) {
|
||||||
|
va_list list;
|
||||||
|
int fallback = 0;
|
||||||
|
FILE *fd;
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm tm = *localtime(&t);
|
||||||
|
if (lvl == ERROR || lvl == WARNING) {
|
||||||
|
fd = fopen(conf.rmps.errlog, "a");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Failed to append errlog: %s. Redirecting to stderr:\n",
|
||||||
|
conf.rmps.errlog );
|
||||||
|
fd = stderr;
|
||||||
|
fallback = 1;
|
||||||
|
}
|
||||||
|
fprintf( fd,
|
||||||
|
"[%d-%02d-%02d %02d:%02d:%02d] %s: ",
|
||||||
|
tm.tm_year + 1900,
|
||||||
|
tm.tm_mon + 1,
|
||||||
|
tm.tm_mday,
|
||||||
|
tm.tm_hour,
|
||||||
|
tm.tm_min,
|
||||||
|
tm.tm_sec,
|
||||||
|
lvl == ERROR ? "ERROR" : "WARNING" );
|
||||||
|
} else {
|
||||||
|
fd = fopen(conf.rmps.logfile, "a");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf( stderr,
|
||||||
|
"Failed to append logfile: %s. Redirecting to stderr:\n",
|
||||||
|
conf.rmps.logfile );
|
||||||
|
fd = stderr;
|
||||||
|
fallback = 1;
|
||||||
|
}
|
||||||
|
fprintf( fd,
|
||||||
|
"[%d-%02d-%02d %02d:%02d:%02d] %s: ",
|
||||||
|
tm.tm_year + 1900,
|
||||||
|
tm.tm_mon + 1,
|
||||||
|
tm.tm_mday,
|
||||||
|
tm.tm_hour,
|
||||||
|
tm.tm_min,
|
||||||
|
tm.tm_sec,
|
||||||
|
lvl == INFO ? "INFO" : "VERBOSE" );
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(list, fmt);
|
||||||
|
vfprintf(fd, fmt, list);
|
||||||
|
fprintf(fd, "\n");
|
||||||
|
va_end(list);
|
||||||
|
if (!fallback)
|
||||||
|
fclose(fd);
|
||||||
|
} else
|
||||||
|
return;
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
13
log_trace.h
Normal file
13
log_trace.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef LOG_TRACE_H
|
||||||
|
#define LOG_TRACE_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ERROR = 1, /* Errors only */
|
||||||
|
WARNING, /* Errors & warnings */
|
||||||
|
INFO, /* Errors, warnings & events */
|
||||||
|
VERBOSE, /* Errors, warnings, events & more? */
|
||||||
|
} LOG_LEVEL;
|
||||||
|
|
||||||
|
void log_trace(LOG_LEVEL lvl, char *fmt, ... );
|
||||||
|
|
||||||
|
#endif /* LOG_TRACE_H */
|
||||||
94
main.c
Normal file
94
main.c
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "confparser.h"
|
||||||
|
#include "log_trace.h"
|
||||||
|
#include "rmps.h"
|
||||||
|
|
||||||
|
static void usage(char *argv)
|
||||||
|
{
|
||||||
|
fprintf( stderr,
|
||||||
|
"Usage:\n%s start|stop|restart [--daemonize=yes|no]\n",
|
||||||
|
argv );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fork_flag = 1, task;
|
||||||
|
|
||||||
|
if (argc < 2 || argc > 3) {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "start"))
|
||||||
|
task = 1;
|
||||||
|
else if (!strcmp(argv[1], "stop"))
|
||||||
|
task = 2;
|
||||||
|
else if (!strcmp(argv[1], "restart"))
|
||||||
|
task = 3;
|
||||||
|
else {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 3) {
|
||||||
|
if (!strcmp("--daemonize=yes", argv[2]));
|
||||||
|
else if (!strcmp("--daemonize=no", argv[2]))
|
||||||
|
fork_flag = 0;
|
||||||
|
else {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (confparse() != 0) {
|
||||||
|
fprintf(stderr, "Failed to parse the conf!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
//confexport();
|
||||||
|
|
||||||
|
if (task == 2 || task == 3) {
|
||||||
|
char buf[10];
|
||||||
|
int pid;
|
||||||
|
FILE *fd;
|
||||||
|
if (task == 2)
|
||||||
|
log_trace(VERBOSE, "We got a stop signal!");
|
||||||
|
else if (task == 3)
|
||||||
|
log_trace(VERBOSE, "We got a restart signal!");
|
||||||
|
|
||||||
|
fd = fopen(conf.rmps.pidfile, "r");
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EEXIST:
|
||||||
|
if (!fgets(buf, 10, fd)) {
|
||||||
|
log_trace(ERROR, "Failed to read %s!", conf.rmps.pidfile);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
pid = strtol(buf, NULL, 10);
|
||||||
|
kill(pid, SIGTERM);
|
||||||
|
//waitpid(TODO);
|
||||||
|
break;
|
||||||
|
case EACCES:
|
||||||
|
log_trace(ERROR, "Permission denied to read PID. Exiting!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
case ENOENT:
|
||||||
|
if (task == 2)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_trace( ERROR,
|
||||||
|
"Unhandled errno while opening PID: %d. Exiting!",
|
||||||
|
errno
|
||||||
|
);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (task == 1 || task == 3) {
|
||||||
|
launch_rmps(&conf, fork_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
3
protocol.c
Normal file
3
protocol.c
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
|
|
||||||
40
protocol.h
Normal file
40
protocol.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef PROTOCOL_H
|
||||||
|
#define PROTOCOL_H
|
||||||
|
|
||||||
|
#define CHUNKSIZE 2048
|
||||||
|
|
||||||
|
enum msg_types {
|
||||||
|
UNIX,
|
||||||
|
POWERSHELL,
|
||||||
|
INSTALL_PKG,
|
||||||
|
QUERY_PKG,
|
||||||
|
DELETE_PKG,
|
||||||
|
LIST_PKGS,
|
||||||
|
UPDATE_PKG,
|
||||||
|
UPDATE_PKGS,
|
||||||
|
GET_OS,
|
||||||
|
GET_KERNEL,
|
||||||
|
GET_UPTIME,
|
||||||
|
GET_MEMORY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msg_meta {
|
||||||
|
unsigned short id; /* Agent job ID */
|
||||||
|
unsigned short type; /* Data type */
|
||||||
|
unsigned len; /* Data size to expect in buffer */
|
||||||
|
unsigned chunks;
|
||||||
|
short is_recv;
|
||||||
|
short locking;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msg_chunk {
|
||||||
|
int id;
|
||||||
|
unsigned char data[CHUNKSIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msg {
|
||||||
|
struct msg_meta meta;
|
||||||
|
struct msg_chunk chunk;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* PROTOCOL_H */
|
||||||
298
rmps.c
Normal file
298
rmps.c
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
#include "log_trace.h"
|
||||||
|
#include "confparser.h"
|
||||||
|
#include "thread_pool.h"
|
||||||
|
#include "rmps.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
/* included for openssl and sockets */
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <resolv.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
static void rmps_shutdown();
|
||||||
|
static void signal_handler(int sig);
|
||||||
|
static void set_env();
|
||||||
|
static void daemonize(const char *rundir);
|
||||||
|
static void spawn_pidfile(const char *pidfile);
|
||||||
|
static inline int set_reuse_addr(int sockfd);
|
||||||
|
static int open_listener(int port);
|
||||||
|
static void cleanup();
|
||||||
|
static void signal_handler(int sig);
|
||||||
|
//static void show_certs(SSL *ssl);
|
||||||
|
static void load_certificates(SSL_CTX *ctx, const char *certfile,
|
||||||
|
const char *keyfile, const char *cafile);
|
||||||
|
static SSL_CTX* init_server_ctx(const char *cipherlist);
|
||||||
|
//static void servlet(SSL *ssl);
|
||||||
|
|
||||||
|
static int pid_file_handle;
|
||||||
|
|
||||||
|
static void cleanup()
|
||||||
|
{
|
||||||
|
log_trace(VERBOSE, "Deleting pidfile %s", conf.rmps.pidfile);
|
||||||
|
if (unlink(conf.rmps.pidfile) != 0)
|
||||||
|
log_trace( WARNING,
|
||||||
|
"Failed to delete pidfile %s. Reason code: %d",
|
||||||
|
conf.rmps.pidfile, errno );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void signal_handler(int sig)
|
||||||
|
{
|
||||||
|
switch (sig) {
|
||||||
|
case SIGHUP:
|
||||||
|
log_trace(WARNING, "Received SIGHUP signal. Ignoring...");
|
||||||
|
break;
|
||||||
|
case SIGINT:
|
||||||
|
case SIGTERM:
|
||||||
|
log_trace(INFO, "Received SIGTERM signal.");
|
||||||
|
log_trace(INFO, "RMPS is shutting down...");
|
||||||
|
rmps_shutdown();
|
||||||
|
log_trace(INFO, "RMPS has been stopped properly.");
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_trace(WARNING, "Unhandled signal %s", strsignal(sig));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rmps_shutdown()
|
||||||
|
{
|
||||||
|
close(pid_file_handle);
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_env()
|
||||||
|
{
|
||||||
|
struct sigaction new_sigaction;
|
||||||
|
sigset_t new_sigset;
|
||||||
|
|
||||||
|
/* Set signal mask - signals we want to block */
|
||||||
|
sigemptyset(&new_sigset);
|
||||||
|
sigaddset(&new_sigset, SIGCHLD); /* ignore child - i.e. we don't need to wait for it */
|
||||||
|
sigaddset(&new_sigset, SIGTSTP); /* ignore Tty stop signals */
|
||||||
|
sigaddset(&new_sigset, SIGTTOU); /* ignore Tty background writes */
|
||||||
|
sigaddset(&new_sigset, SIGTTIN); /* ignore Tty background reads */
|
||||||
|
sigprocmask(SIG_BLOCK, &new_sigset, NULL); /* Block the above specified signals */
|
||||||
|
|
||||||
|
/* Set up a signal handler */
|
||||||
|
new_sigaction.sa_handler = signal_handler;
|
||||||
|
sigemptyset(&new_sigaction.sa_mask);
|
||||||
|
new_sigaction.sa_flags = 0;
|
||||||
|
|
||||||
|
/* Signals to handle */
|
||||||
|
sigaction(SIGHUP, &new_sigaction, NULL); /* catch hangup signal */
|
||||||
|
sigaction(SIGTERM, &new_sigaction, NULL); /* catch term signal */
|
||||||
|
sigaction(SIGINT, &new_sigaction, NULL); /* catch interrupt signal */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void daemonize(const char *rundir)
|
||||||
|
{
|
||||||
|
int pid, sid, i;
|
||||||
|
/* Check if parent process id is set */
|
||||||
|
if (getppid() == 1) {
|
||||||
|
/* PPID exists, therefore we are already a daemon */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Fork*/
|
||||||
|
pid = fork();
|
||||||
|
/*printf("fork() = %d\n", pid);*/
|
||||||
|
if (pid < 0) {
|
||||||
|
/* Could not fork */
|
||||||
|
log_trace(ERROR, "Failed to fork the parent process. Exiting!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (pid > 0) {
|
||||||
|
/* Child created ok, so exit parent process */
|
||||||
|
log_trace(INFO, "Child process created: %d", pid);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
/* Child continues */
|
||||||
|
umask(027); /* Set file permissions 750 */
|
||||||
|
/* Get a new process group */
|
||||||
|
sid = setsid();
|
||||||
|
if (sid < 0) {
|
||||||
|
log_trace(ERROR, "Failed to create a process group. Exiting!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
/* Close all file descriptors because we fork */
|
||||||
|
for (i = getdtablesize(); i >= 0; --i)
|
||||||
|
close(i);
|
||||||
|
|
||||||
|
/* Route I/O connections */
|
||||||
|
/* Open STDIN */
|
||||||
|
i = open("/dev/null", O_RDWR);
|
||||||
|
/* STDOUT */
|
||||||
|
dup(i);
|
||||||
|
/* STDERR */
|
||||||
|
dup(i);
|
||||||
|
chdir(rundir); /* change running directory */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spawn_pidfile(const char *pidfile)
|
||||||
|
{
|
||||||
|
char str[10];
|
||||||
|
/* Ensure only one copy */
|
||||||
|
pid_file_handle = open(pidfile, O_RDWR|O_CREAT, 0600);
|
||||||
|
if (pid_file_handle == -1) {
|
||||||
|
/* Couldn't open lock file */
|
||||||
|
log_trace(ERROR, "Could not create PID file %s - Exiting!", pidfile);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to lock file */
|
||||||
|
if (lockf(pid_file_handle, F_TLOCK, 0) == -1) {
|
||||||
|
/* Couldn't get lock on lock file */
|
||||||
|
log_trace(ERROR, "Could not lock PID file %s - Exiting!", pidfile);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get and format PID */
|
||||||
|
sprintf(str, "%d\n", getpid());
|
||||||
|
/* write pid to lockfile */
|
||||||
|
write(pid_file_handle, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int set_reuse_addr(int sockfd)
|
||||||
|
{
|
||||||
|
int yes = 1;
|
||||||
|
return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
&yes, sizeof(yes));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_listener(int port)
|
||||||
|
{
|
||||||
|
int sd;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
sd = socket(addr.sin_family, SOCK_STREAM, 0);
|
||||||
|
if (sd < 0) {
|
||||||
|
log_trace(ERROR, "Failed to create socket");
|
||||||
|
log_trace(INFO, "RMPS failed to start, shutting down...");
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
if (set_reuse_addr(sd) < 0) {
|
||||||
|
log_trace(ERROR, "Failed to set reuse on address - Aborting...", port);
|
||||||
|
log_trace(INFO, "RMPS failed to start, shutting down...");
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
if (bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
|
||||||
|
log_trace(ERROR, "Failed to bind on port: %d - Aborting...", port);
|
||||||
|
log_trace(INFO, "RMPS failed to start, shutting down...");
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
if (listen(sd, 10) != 0) {
|
||||||
|
log_trace(ERROR, "Failed to start listener on port %d - Aborting...", port);
|
||||||
|
log_trace(INFO, "RMPS failed to start, shutting down...");
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init server and create context */
|
||||||
|
static SSL_CTX* init_server_ctx(const char *cipherlist)
|
||||||
|
{
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
char ciphers[1024];
|
||||||
|
|
||||||
|
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
|
||||||
|
OpenSSL_add_all_ciphers(); /* load & register all cryptos, etc. */
|
||||||
|
SSL_load_error_strings(); /* load all error messages */
|
||||||
|
SSL_library_init();
|
||||||
|
|
||||||
|
ctx = SSL_CTX_new(TLSv1_2_method()); /* create new context from method */
|
||||||
|
if (ctx == NULL) {
|
||||||
|
log_trace(ERROR, "SSL_CTX_new() returned NULL - Aborting...");
|
||||||
|
log_trace(ERROR, "RMPS failed to start, shutting down...");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
SSL_CTX_set_verify( ctx, SSL_VERIFY_PEER |
|
||||||
|
SSL_VERIFY_CLIENT_ONCE |
|
||||||
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
ciphers[0] = 0;
|
||||||
|
strcat(ciphers, "-ALL"); /* Disable any ciphers we have by default */
|
||||||
|
strcat(ciphers, cipherlist);
|
||||||
|
/* This is very delicate, try to understand the ciphers */
|
||||||
|
SSL_CTX_set_cipher_list(ctx, cipherlist);
|
||||||
|
log_trace(VERBOSE, "cipherlist = %s", cipherlist);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
/*--- LoadCertificates - load from files. ---*/
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
void load_certificates(SSL_CTX* ctx, const char *certfile,
|
||||||
|
const char *keyfile, const char *cafile)
|
||||||
|
{
|
||||||
|
long ssl_errnum;
|
||||||
|
char ssl_errstr[2048];
|
||||||
|
/* set the local certificate from certfile */
|
||||||
|
if (SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM) <= 0) {
|
||||||
|
ssl_errnum = ERR_get_error();
|
||||||
|
ERR_error_string_n(ssl_errnum, ssl_errstr, sizeof(ssl_errstr));
|
||||||
|
log_trace(ERROR, "Failed to load certfile! SSL error below:\n%s", ssl_errstr);
|
||||||
|
log_trace(INFO, "RMPS failed to start, shutting down...");
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
/* set the private key from KeyFile (may be the same as CertFile) */
|
||||||
|
if (SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM) <= 0) {
|
||||||
|
ssl_errnum = ERR_get_error();
|
||||||
|
ERR_error_string_n(ssl_errnum, ssl_errstr, sizeof(ssl_errstr));
|
||||||
|
log_trace(ERROR, "Failed to load keyfile! SSL error below:\n%s", ssl_errstr);
|
||||||
|
log_trace(INFO, "RMPS failed to start, shutting down...");
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
/* verify private key */
|
||||||
|
if (!SSL_CTX_check_private_key(ctx)) {
|
||||||
|
log_trace(ERROR, "Private key does not match the public certificate.");
|
||||||
|
log_trace(INFO, "RMPS failed to start, shutting down...");
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
if (cafile != NULL) {
|
||||||
|
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cafile));
|
||||||
|
SSL_CTX_load_verify_locations(ctx, cafile, NULL);
|
||||||
|
//SSL_CTX_set_verify_depth(ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int launch_rmps(struct conf_table *conf, int fork_flag)
|
||||||
|
{
|
||||||
|
int server;
|
||||||
|
log_trace(INFO, "Starting up RMPS...");
|
||||||
|
|
||||||
|
/* Set signal handling */
|
||||||
|
set_env();
|
||||||
|
/* Deamonize */
|
||||||
|
if (fork_flag)
|
||||||
|
daemonize("/tmp/");
|
||||||
|
/* Spawn & lock pidfile */
|
||||||
|
spawn_pidfile(conf->rmps.pidfile);
|
||||||
|
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
ctx = init_server_ctx(conf->rmps.cipherlist);
|
||||||
|
/* openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX -nodes
|
||||||
|
* -nodes is for not protecing with a passphrase
|
||||||
|
* http://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl
|
||||||
|
*/
|
||||||
|
log_trace(VERBOSE, "Loading crypto certs and keys.");
|
||||||
|
load_certificates(ctx, conf->rmps.certfile, conf->rmps.keyfile, conf->rmps.cafile);
|
||||||
|
|
||||||
|
log_trace(VERBOSE, "Starting listener on port: %d", atoi(conf->rmps.bind_on_port));
|
||||||
|
server = open_listener(atoi(conf->rmps.bind_on_port));
|
||||||
|
|
||||||
|
log_trace(VERBOSE, "Creating mutex for thread pool.");
|
||||||
|
ssl_pt_mutex(server, ctx, conf->rmps.threadpoolsize);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
32
rmps.conf
Normal file
32
rmps.conf
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# This is a configuration file for the
|
||||||
|
# Remote Management and Provisioning Server
|
||||||
|
#
|
||||||
|
# NOTE: In order to apply changes, the server
|
||||||
|
# must be restarted afterwards.
|
||||||
|
|
||||||
|
# RMPS DB settings
|
||||||
|
# db.type=[mysql|postgresql|oracle]
|
||||||
|
# NOTE: Only "mysql" is implemented so far.
|
||||||
|
db.type=mysql
|
||||||
|
db.hostname=127.0.0.1
|
||||||
|
db.port=3306
|
||||||
|
|
||||||
|
# RMPS Core settings
|
||||||
|
rmps.bind_on_ip=127.0.0.1
|
||||||
|
rmps.bind_on_port=7000
|
||||||
|
# Loglevel modes: 1:ERROR,2:WARNING,3:INFO,4:VERBOSE
|
||||||
|
# The default is 2.
|
||||||
|
rmps.loglevel=4
|
||||||
|
rmps.logfile=/home/smirky/stuff/projects/rmps/tmp/rmpsd.log
|
||||||
|
rmps.errlog=/home/smirky/stuff/projects/rmps/tmp/rmpsd.err
|
||||||
|
rmps.pidfile=/home/smirky/stuff/projects/rmps/tmp/rmpsd.pig
|
||||||
|
#rmps.pidfile=/home/smirky/stuff/projects/rmps/rmpsd/rmpsd.pid
|
||||||
|
|
||||||
|
# Cryptography settings
|
||||||
|
rmps.certfile=/etc/rmps/certs/server/server.crt
|
||||||
|
rmps.keyfile=/etc/rmps/certs/server/server.key
|
||||||
|
rmps.cafile=/etc/rmps/certs/ca.pem
|
||||||
|
rmps.cipherlist=ECDHE-RSA-AES128-SHA256:AES256-SHA:RSA
|
||||||
|
|
||||||
|
# NFS settings TODO
|
||||||
|
|
||||||
6
rmps.h
Normal file
6
rmps.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef RMPS_H
|
||||||
|
#define RMPS_H
|
||||||
|
|
||||||
|
extern int launch_rmps(struct conf_table *conf, int fork_flag);
|
||||||
|
|
||||||
|
#endif /* RMPS_H */
|
||||||
14
rmpsd.service
Normal file
14
rmpsd.service
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Remote Management and Provisioning Server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
#PIDFile=/run/rmps/rmpsd.pid
|
||||||
|
ExecStart=/usr/bin/rmpsd start --daemonize=no
|
||||||
|
ExecStop=/usr/bin/rmpsd stop
|
||||||
|
ExecReload=/usr/bin/rmpsd reload
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
167
thread_pool.c
Normal file
167
thread_pool.c
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#include "thread_pool.h"
|
||||||
|
#include "log_trace.h"
|
||||||
|
#include "protocol.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define MAXJOBS 10
|
||||||
|
|
||||||
|
struct agent_args {
|
||||||
|
int busy;
|
||||||
|
SSL *ssl;
|
||||||
|
int sd;
|
||||||
|
char ip[16]; /* IPv4 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void show_certs(SSL *ssl);
|
||||||
|
static void* servlet(void *args);
|
||||||
|
static void send_reject_msg(SSL *ssl);
|
||||||
|
|
||||||
|
static void show_certs(SSL *ssl)
|
||||||
|
{
|
||||||
|
X509 *cert;
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
|
||||||
|
if (SSL_get_verify_result(ssl)==X509_V_OK)
|
||||||
|
log_trace(VERBOSE, "get_verify_result == ok");
|
||||||
|
if (cert != NULL) {
|
||||||
|
log_trace(VERBOSE, "Server certificates:");
|
||||||
|
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
||||||
|
log_trace(VERBOSE, "Subject: %s", line);
|
||||||
|
free(line);
|
||||||
|
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
|
||||||
|
log_trace(VERBOSE, "Issuer: %s", line);
|
||||||
|
free(line);
|
||||||
|
X509_free(cert);
|
||||||
|
} else
|
||||||
|
log_trace(VERBOSE, "No certificates from peer");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* servlet(void *args) /* Serve the connection -- threadable */
|
||||||
|
{
|
||||||
|
struct msg buf;
|
||||||
|
char reply[2048];
|
||||||
|
int bytes, ret;
|
||||||
|
//unsigned short job[MAXJOBS] = { 0 };
|
||||||
|
struct agent_args *agent = (struct agent_args*)args;
|
||||||
|
|
||||||
|
SSL_load_error_strings();
|
||||||
|
ret = SSL_accept(agent->ssl);
|
||||||
|
/* We check for unclean (ret < 0) and clean (ret == 0) failures */
|
||||||
|
if (ret <= 0) {
|
||||||
|
char ret_str[1024];
|
||||||
|
ERR_error_string_n(SSL_get_error(agent->ssl, ret), ret_str, sizeof(ret_str));
|
||||||
|
log_trace(INFO, "SSL_accept() failed. Reason below:\n%s", ret_str);
|
||||||
|
} else {
|
||||||
|
show_certs(agent->ssl);
|
||||||
|
do {
|
||||||
|
buf.meta.type = GET_MEMORY;
|
||||||
|
sleep(1);
|
||||||
|
SSL_write(agent->ssl, &buf, sizeof(buf));
|
||||||
|
bytes = SSL_read(agent->ssl, &buf, sizeof(buf));
|
||||||
|
if (bytes > 0) {
|
||||||
|
if (bytes != sizeof(struct msg)) {
|
||||||
|
log_trace( WARNING,
|
||||||
|
"Agent [%s] sent non-standard data!",
|
||||||
|
agent->ip );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//buf.chunk.data[bytes] = 0;
|
||||||
|
|
||||||
|
log_trace(VERBOSE, "Client msg: \"%s\"", buf.chunk.data);
|
||||||
|
SSL_write(agent->ssl, buf.chunk.data, buf.meta.len); /* send reply */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (SSL_get_shutdown(agent->ssl) == SSL_RECEIVED_SHUTDOWN)
|
||||||
|
log_trace(VERBOSE, "SSL_RECEIVED_SHUTDOWN from agent [%s]", agent->ip);
|
||||||
|
else {
|
||||||
|
char ssl_errstr[2048];
|
||||||
|
long ssl_errnum = ERR_get_error();
|
||||||
|
ERR_error_string_n(ssl_errnum, ssl_errstr, sizeof(ssl_errstr));
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
log_trace( VERBOSE,
|
||||||
|
"Client didn't send data! SSL error below:\n%s",
|
||||||
|
ssl_errstr);
|
||||||
|
sprintf(reply, "%s", "Where's the data, m8?");
|
||||||
|
SSL_write(agent->ssl, reply, strlen(reply));
|
||||||
|
}
|
||||||
|
log_trace(INFO, "Agent [%s] disconnected.", agent->ip);
|
||||||
|
} while (bytes);
|
||||||
|
}
|
||||||
|
SSL_free(agent->ssl); /* release SSL state */
|
||||||
|
close(agent->sd); /* close connection */
|
||||||
|
agent->busy = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_reject_msg(SSL *ssl)
|
||||||
|
{
|
||||||
|
char *reply = "FAILURE - The connection queue is full!\n";
|
||||||
|
SSL_write(ssl, reply, strlen(reply));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssl_pt_mutex(int srv, SSL_CTX *ctx, int poolsize)
|
||||||
|
{
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_t *agent_thread = (pthread_t*)malloc(poolsize * sizeof(pthread_t));
|
||||||
|
struct agent_args *agent_struct =
|
||||||
|
(struct agent_args*)malloc(poolsize * sizeof(struct agent_args));
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(agent_thread, 0, sizeof(pthread_t) * poolsize);
|
||||||
|
memset(agent_struct, 0, sizeof(struct agent_args) * poolsize);
|
||||||
|
|
||||||
|
pthread_mutex_init(&mutex, NULL);
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
char address[INET6_ADDRSTRLEN];
|
||||||
|
socklen_t len = sizeof(addr);
|
||||||
|
SSL *ssl;
|
||||||
|
int agent = accept(srv, (struct sockaddr*)&addr, &len);
|
||||||
|
log_trace( VERBOSE,
|
||||||
|
"Connection: %s:%d",
|
||||||
|
inet_ntop(AF_INET, &addr.sin_addr, address, sizeof(address)),
|
||||||
|
ntohs(addr.sin_port)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (i = 0; i < poolsize; i++) {
|
||||||
|
if (!agent_struct[i].busy) {
|
||||||
|
agent_struct[i].busy = 1;
|
||||||
|
agent_struct[i].ssl = SSL_new(ctx);
|
||||||
|
agent_struct[i].sd = agent;
|
||||||
|
memcpy( agent_struct[i].ip,
|
||||||
|
inet_ntop(AF_INET, &addr.sin_addr, address, sizeof(address)),
|
||||||
|
sizeof(agent_struct[i].ip) );
|
||||||
|
SSL_set_fd(agent_struct[i].ssl, agent_struct[i].sd);
|
||||||
|
pthread_create( &agent_thread[i],
|
||||||
|
&attr,
|
||||||
|
servlet,
|
||||||
|
&agent_struct[i] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == poolsize) {
|
||||||
|
log_trace( WARNING,
|
||||||
|
"Agent [%s] dropped. Poolsize limit reached.",
|
||||||
|
inet_ntop(AF_INET, &addr.sin_addr, address, sizeof(address))
|
||||||
|
);
|
||||||
|
ssl = SSL_new(ctx);
|
||||||
|
SSL_set_fd(ssl, agent);
|
||||||
|
if (SSL_accept(ssl) == FAIL) {
|
||||||
|
SSL_free(ssl);
|
||||||
|
close(agent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
send_reject_msg(ssl);
|
||||||
|
SSL_free(ssl);
|
||||||
|
close(agent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
}
|
||||||
15
thread_pool.h
Normal file
15
thread_pool.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef THREAD_POOL_H
|
||||||
|
#define THREAD_POOL_H
|
||||||
|
|
||||||
|
/* included for openssl and sockets */
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <resolv.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
#define FAIL -1
|
||||||
|
|
||||||
|
void ssl_pt_mutex(int srv, SSL_CTX *ctx, int poolsize);
|
||||||
|
|
||||||
|
#endif /* THREAD_POOL_H */
|
||||||
Reference in New Issue
Block a user