mirror of
https://github.com/eddyem/eddys_snippets.git
synced 2025-12-06 02:35:12 +03:00
SSL socket snippet, server checks client's certificates
This commit is contained in:
parent
5260ddb3bb
commit
80f078c5a9
79
SSL_Socket_snippet/Makefile
Normal file
79
SSL_Socket_snippet/Makefile
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# run `make DEF=...` to add extra defines
|
||||||
|
CLIENT := sslclient
|
||||||
|
SERVER := sslserver
|
||||||
|
LDFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
|
||||||
|
LDFLAGS += -lusefull_macros -lssl -lcrypto
|
||||||
|
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
|
||||||
|
SOBJDIR := mkserver
|
||||||
|
COBJDIR := mkclient
|
||||||
|
CFLAGS += -O2 -Wall -Wextra -Wno-trampolines -pthread
|
||||||
|
COMMSRCS := sslsock.c daemon.c cmdlnopts.c main.c
|
||||||
|
SSRC := server.c $(COMMSRCS)
|
||||||
|
CSRC := client.c $(COMMSRCS)
|
||||||
|
SOBJS := $(addprefix $(SOBJDIR)/, $(SSRC:%.c=%.o))
|
||||||
|
COBJS := $(addprefix $(COBJDIR)/, $(CSRC:%.c=%.o))
|
||||||
|
SDEPS := $(SOBJS:.o=.d)
|
||||||
|
CDEPS := $(COBJS:.o=.d)
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
TARGFILE := build.target
|
||||||
|
|
||||||
|
ifeq ($(shell test -e $(TARGFILE) && echo -n yes),yes)
|
||||||
|
TARGET := $(file < $(TARGFILE))
|
||||||
|
else
|
||||||
|
TARGET := RELEASE
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET), DEBUG)
|
||||||
|
.DEFAULT_GOAL := debug
|
||||||
|
endif
|
||||||
|
|
||||||
|
release: CFLAGS += -flto
|
||||||
|
release: LDFLAGS += -flto
|
||||||
|
release: $(TARGFILE) $(CLIENT) $(SERVER)
|
||||||
|
|
||||||
|
debug: CFLAGS += -DEBUG -Werror
|
||||||
|
debug: TARGET := DEBUG
|
||||||
|
debug: $(TARGFILE) $(CLIENT) $(SERVER)
|
||||||
|
|
||||||
|
$(TARGFILE):
|
||||||
|
@echo -e "\tTARGET: $(TARGET)\n"
|
||||||
|
@echo "$(TARGET)" > $(TARGFILE)
|
||||||
|
|
||||||
|
$(CLIENT) : DEFINES += -DCLIENT
|
||||||
|
$(CLIENT) : $(COBJDIR) $(COBJS)
|
||||||
|
@echo -e "\tLD $(CLIENT)"
|
||||||
|
$(CC) $(LDFLAGS) $(COBJS) -o $(CLIENT)
|
||||||
|
|
||||||
|
|
||||||
|
$(SERVER) : DEFINES += -DSERVER
|
||||||
|
$(SERVER) : $(SOBJDIR) $(SOBJS)
|
||||||
|
@echo -e "\tLD $(SERVER)"
|
||||||
|
$(CC) $(LDFLAGS) $(SOBJS) -o $(SERVER)
|
||||||
|
|
||||||
|
$(SOBJDIR):
|
||||||
|
@mkdir $(SOBJDIR)
|
||||||
|
|
||||||
|
$(COBJDIR):
|
||||||
|
@mkdir $(COBJDIR)
|
||||||
|
|
||||||
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
|
-include $(DEPS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(COBJDIR)/%.o: %.c
|
||||||
|
@echo -e "\tCC $<"
|
||||||
|
$(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $<
|
||||||
|
|
||||||
|
$(SOBJDIR)/%.o: %.c
|
||||||
|
@echo -e "\t\tCC $<"
|
||||||
|
$(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo -e "\t\tCLEAN"
|
||||||
|
@rm -rf $(SOBJDIR) $(COBJDIR) $(TARGFILE) 2>/dev/null || true
|
||||||
|
|
||||||
|
xclean: clean
|
||||||
|
@rm -f $(PROGRAM)
|
||||||
|
|
||||||
|
.PHONY: clean xclean
|
||||||
1
SSL_Socket_snippet/Readme
Normal file
1
SSL_Socket_snippet/Readme
Normal file
@ -0,0 +1 @@
|
|||||||
|
Client/server snippet using SSL-protected TCP-socket connection between client and server (check certs from both sides)
|
||||||
49
SSL_Socket_snippet/ca/gen.sh
Executable file
49
SSL_Socket_snippet/ca/gen.sh
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# https://gist.github.com/zapstar/4b51d7cfa74c7e709fcdaace19233443
|
||||||
|
mkdir -p ca/private
|
||||||
|
chmod 700 ca/private
|
||||||
|
# NOTE: I'm using -nodes, this means that once anybody gets
|
||||||
|
# their hands on this particular key, they can become this CA.
|
||||||
|
openssl req \
|
||||||
|
-x509 \
|
||||||
|
-nodes \
|
||||||
|
-days 36524 \
|
||||||
|
-newkey rsa:4096 \
|
||||||
|
-keyout ca/private/ca_key.pem \
|
||||||
|
-out ca/ca_cert.pem \
|
||||||
|
-subj "/C=RU/ST=KChR/L=Bukovo/O=SAO RAS/CN=sao.ru"
|
||||||
|
|
||||||
|
# Create server private key and certificate request
|
||||||
|
mkdir -p server/private
|
||||||
|
chmod 700 ca/private
|
||||||
|
openssl genrsa -out server/private/server_key.pem 4096
|
||||||
|
openssl req -new \
|
||||||
|
-key server/private/server_key.pem \
|
||||||
|
-out server/server.csr \
|
||||||
|
-subj "/C=RU/ST=KChR/L=Bukovo/O=SAO RAS"
|
||||||
|
|
||||||
|
# Create client private key and certificate request
|
||||||
|
mkdir -p client/private
|
||||||
|
chmod 700 client/private
|
||||||
|
openssl genrsa -out client/private/client_key.pem 4096
|
||||||
|
openssl req -new \
|
||||||
|
-key client/private/client_key.pem \
|
||||||
|
-out client/client.csr \
|
||||||
|
-subj "/C=RU/ST=KChR/L=Bukovo/O=SAO RAS"
|
||||||
|
|
||||||
|
# Generate certificates
|
||||||
|
openssl x509 -req -days 36524 -in server/server.csr \
|
||||||
|
-CA ca/ca_cert.pem -CAkey ca/private/ca_key.pem \
|
||||||
|
-CAcreateserial -out server/server_cert.pem
|
||||||
|
openssl x509 -req -days 36524 -in client/client.csr \
|
||||||
|
-CA ca/ca_cert.pem -CAkey ca/private/ca_key.pem \
|
||||||
|
-CAcreateserial -out client/client_cert.pem
|
||||||
|
|
||||||
|
# Now test both the server and the client
|
||||||
|
# On one shell, run the following
|
||||||
|
# openssl s_server -CAfile ca/ca_cert.pem -cert server/server_cert.pem -key server/private/server_key.pem -Verify 1
|
||||||
|
# On another shell, run the following
|
||||||
|
# openssl s_client -CAfile ca/ca_cert.pem -cert client/client_cert.pem -key client/private/client_key.pem
|
||||||
|
# Once the negotiation is complete, any line you type is sent over to the other side.
|
||||||
|
# By line, I mean some text followed by a keyboard return press.
|
||||||
1
SSL_Socket_snippet/ca_cert.pem
Symbolic link
1
SSL_Socket_snippet/ca_cert.pem
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ca/ca/ca_cert.pem
|
||||||
79
SSL_Socket_snippet/client.c
Normal file
79
SSL_Socket_snippet/client.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
static int SSL_nbread(SSL *ssl, char *buf, int bufsz){
|
||||||
|
struct pollfd fds = {0};
|
||||||
|
int fd = SSL_get_fd(ssl);
|
||||||
|
fds.fd = fd;
|
||||||
|
fds.events = POLLIN;
|
||||||
|
if(poll(&fds, 1, 1) < 0){ // wait no more than 1ms
|
||||||
|
LOGWARN("SSL_nbread(): poll() failed");
|
||||||
|
WARNX("poll()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(fds.revents == POLLIN){
|
||||||
|
// DBG("Got info in fd #%d", fd);
|
||||||
|
int l = read_string(ssl, buf, bufsz);
|
||||||
|
// DBG("read %d bytes", l);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientproc(SSL_CTX *ctx, int fd){
|
||||||
|
FNAME();
|
||||||
|
SSL *ssl;
|
||||||
|
char buf[1024];
|
||||||
|
char acClientRequest[1024] = {0};
|
||||||
|
int bytes;
|
||||||
|
ssl = SSL_new(ctx);
|
||||||
|
SSL_set_fd(ssl, fd);
|
||||||
|
int c = SSL_connect(ssl);
|
||||||
|
if(c < 0){
|
||||||
|
LOGERR("SSL_connect()");
|
||||||
|
ERRX("SSL_connect() error: %d", SSL_get_error(ssl, c));
|
||||||
|
}
|
||||||
|
int enable = 1;
|
||||||
|
if(ioctl(fd, FIONBIO, (void *)&enable) < 0){
|
||||||
|
LOGERR("Can't make socket nonblocking");
|
||||||
|
ERRX("ioctl()");
|
||||||
|
}
|
||||||
|
double t0 = dtime();
|
||||||
|
int N = 0;
|
||||||
|
while(1){
|
||||||
|
if(dtime() - t0 > 3.){
|
||||||
|
// DBG("Sent test message");
|
||||||
|
sprintf(acClientRequest, "Test connection #%d\n", ++N);
|
||||||
|
SSL_write(ssl, acClientRequest, strlen(acClientRequest));
|
||||||
|
t0 = dtime();
|
||||||
|
}
|
||||||
|
bytes = SSL_nbread(ssl, buf, sizeof(buf));
|
||||||
|
if(bytes > 0){
|
||||||
|
buf[bytes] = 0;
|
||||||
|
printf("Received: \"%s\"\n", buf);
|
||||||
|
}else if(bytes < 0){
|
||||||
|
LOGWARN("Server disconnected or other error");
|
||||||
|
ERRX("Disconnected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SSL_free(ssl);
|
||||||
|
}
|
||||||
23
SSL_Socket_snippet/client.h
Normal file
23
SSL_Socket_snippet/client.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sslsock.h"
|
||||||
|
|
||||||
|
void clientproc(SSL_CTX *ctx, int fd);
|
||||||
1
SSL_Socket_snippet/client_cert.pem
Symbolic link
1
SSL_Socket_snippet/client_cert.pem
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ca/client/client_cert.pem
|
||||||
1
SSL_Socket_snippet/client_key.pem
Symbolic link
1
SSL_Socket_snippet/client_key.pem
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ca/client/private/client_key.pem
|
||||||
92
SSL_Socket_snippet/cmdlnopts.c
Normal file
92
SSL_Socket_snippet/cmdlnopts.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "cmdlnopts.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* here are global parameters initialisation
|
||||||
|
*/
|
||||||
|
static int help;
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
#define DEFCERT "server_cert.pem"
|
||||||
|
#define DEFKEY "server_key.pem"
|
||||||
|
#else
|
||||||
|
#define DEFCERT "client_cert.pem"
|
||||||
|
#define DEFKEY "client_key.pem"
|
||||||
|
#endif
|
||||||
|
#define DEFCA "ca_cert.pem"
|
||||||
|
// default global parameters
|
||||||
|
glob_pars G = {
|
||||||
|
.pidfile = DEFAULT_PIDFILE,
|
||||||
|
.port = DEFAULT_PORT,
|
||||||
|
.cert = DEFCERT,
|
||||||
|
.key = DEFKEY,
|
||||||
|
.ca = DEFCA
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define command line options by filling structure:
|
||||||
|
* name has_arg flag val type argptr help
|
||||||
|
*/
|
||||||
|
static myoption cmdlnopts[] = {
|
||||||
|
// common options
|
||||||
|
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
|
||||||
|
{"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("file to save logs")},
|
||||||
|
{"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfile), _("pidfile (default: " DEFAULT_PIDFILE ")")},
|
||||||
|
{"certificate",NEED_ARG,NULL, 'c', arg_string, APTR(&G.cert), _("path to SSL sertificate (default: " DEFCERT ")")},
|
||||||
|
{"key", NEED_ARG, NULL, 'k', arg_string, APTR(&G.key), _("path to SSL key (default: " DEFKEY ")")},
|
||||||
|
{"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("port to open (default: " DEFAULT_PORT ")")},
|
||||||
|
{"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&G.verbose), _("increase log verbose level (default: LOG_WARN)")},
|
||||||
|
{"ca", NEED_ARG, NULL, 'a', arg_string, APTR(&G.ca), _("path to SSL ca - base cert (default:" DEFCA ")")},
|
||||||
|
#ifdef CLIENT
|
||||||
|
{"server", NEED_ARG, NULL, 's', arg_string, APTR(&G.serverhost), _("server IP address or name")},
|
||||||
|
#endif
|
||||||
|
end_option
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse command line options and return dynamically allocated structure
|
||||||
|
* to global parameters
|
||||||
|
* @param argc - copy of argc from main
|
||||||
|
* @param argv - copy of argv from main
|
||||||
|
*/
|
||||||
|
void parse_args(int argc, char **argv){
|
||||||
|
int i;
|
||||||
|
size_t hlen = 1024;
|
||||||
|
char helpstring[1024], *hptr = helpstring;
|
||||||
|
snprintf(hptr, hlen, "Usage: %%s [args]\n\n\tWhere args are:\n");
|
||||||
|
// format of help: "Usage: progname [args]\n"
|
||||||
|
change_helpstring(helpstring);
|
||||||
|
// parse arguments
|
||||||
|
parseargs(&argc, &argv, cmdlnopts);
|
||||||
|
if(help) showhelp(-1, cmdlnopts);
|
||||||
|
if(argc > 0){
|
||||||
|
red("Ignored options:\n");
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
printf("\t%s\n", argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
48
SSL_Socket_snippet/cmdlnopts.h
Normal file
48
SSL_Socket_snippet/cmdlnopts.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// default PID filename:
|
||||||
|
#ifndef DEFAULT_PIDFILE
|
||||||
|
#define DEFAULT_PIDFILE "/tmp/sslsock.pid"
|
||||||
|
#endif
|
||||||
|
#ifndef DEFAULT_PORT
|
||||||
|
#define DEFAULT_PORT "4444"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* here are some typedef's for global data
|
||||||
|
*/
|
||||||
|
typedef struct{
|
||||||
|
char *pidfile; // name of PID file
|
||||||
|
char *logfile; // logging to this file
|
||||||
|
char *cert; // sertificate
|
||||||
|
char *key; // key
|
||||||
|
char *port; // port number
|
||||||
|
int verbose; // logfile verbose level
|
||||||
|
char *ca; // ca
|
||||||
|
#ifdef CLIENT
|
||||||
|
char *serverhost; // server IP address
|
||||||
|
#endif
|
||||||
|
} glob_pars;
|
||||||
|
|
||||||
|
extern glob_pars G;
|
||||||
|
|
||||||
|
void parse_args(int argc, char **argv);
|
||||||
|
|
||||||
103
SSL_Socket_snippet/daemon.c
Normal file
103
SSL_Socket_snippet/daemon.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/prctl.h> // prctl
|
||||||
|
#include <sys/wait.h> // wait
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "cmdlnopts.h"
|
||||||
|
#include "daemon.h"
|
||||||
|
#include "sslsock.h"
|
||||||
|
|
||||||
|
static pid_t childpid = -1;
|
||||||
|
|
||||||
|
void signals(int sig){
|
||||||
|
if(childpid == 0){
|
||||||
|
LOGWARN("Child killed with sig=%d", sig);
|
||||||
|
exit(sig); // slave process
|
||||||
|
}
|
||||||
|
// master process
|
||||||
|
if(sig){
|
||||||
|
signal(sig, SIG_IGN);
|
||||||
|
LOGERR("Exit with signal %d", sig);
|
||||||
|
}else LOGERR("Exit");
|
||||||
|
if(G.pidfile) unlink(G.pidfile);
|
||||||
|
exit(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief start_daemon - daemonize
|
||||||
|
* @param self - self name of process
|
||||||
|
* @return error code or 0
|
||||||
|
*/
|
||||||
|
int start_daemon(_U_ char *self){
|
||||||
|
// check args
|
||||||
|
int port = atoi(G.port);
|
||||||
|
if(port < 1024 || port > 65535){
|
||||||
|
LOGERR("Wrong port value: %d", port);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FILE *f = fopen(G.cert, "r");
|
||||||
|
if(!f) ERR("Can't open certificate file %s", G.cert);
|
||||||
|
fclose(f);
|
||||||
|
f = fopen(G.key, "r");
|
||||||
|
if(!f) ERR("Can't open certificate key file %s", G.key);
|
||||||
|
fclose(f);
|
||||||
|
#ifdef EBUG
|
||||||
|
printf("cert: %s, key: %s\n", G.cert, G.key);
|
||||||
|
#endif
|
||||||
|
#ifdef CLIENT
|
||||||
|
//DBG("server: %s", G.serverhost);
|
||||||
|
if(!G.serverhost) ERRX("Point server name");
|
||||||
|
#endif
|
||||||
|
if(G.logfile){
|
||||||
|
int lvl = LOGLEVEL_WARN + G.verbose;
|
||||||
|
DBG("level = %d", lvl);
|
||||||
|
if(lvl > LOGLEVEL_ANY) lvl = LOGLEVEL_ANY;
|
||||||
|
green("Log file %s @ level %d\n", G.logfile, lvl);
|
||||||
|
OPENLOG(G.logfile, lvl, 1);
|
||||||
|
}
|
||||||
|
signal(SIGTERM, signals); // kill (-15) - quit
|
||||||
|
signal(SIGHUP, SIG_IGN); // hup - ignore
|
||||||
|
signal(SIGINT, signals); // ctrl+C - quit
|
||||||
|
signal(SIGQUIT, signals); // ctrl+\ - quit
|
||||||
|
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
|
||||||
|
#ifdef SERVER
|
||||||
|
check4running(self, G.pidfile);
|
||||||
|
#endif
|
||||||
|
LOGMSG("Started");
|
||||||
|
#ifndef EBUG
|
||||||
|
while(1){
|
||||||
|
childpid = fork();
|
||||||
|
if(childpid){ // master
|
||||||
|
LOGMSG("Created child with pid %d", childpid);
|
||||||
|
wait(NULL);
|
||||||
|
LOGWARN("Child %d died", childpid);
|
||||||
|
sleep(1); // wait a little before respawn
|
||||||
|
}else{ // slave
|
||||||
|
prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// parent should never reach this part of code
|
||||||
|
return open_socket();
|
||||||
|
}
|
||||||
22
SSL_Socket_snippet/daemon.h
Normal file
22
SSL_Socket_snippet/daemon.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int start_daemon(char *self);
|
||||||
|
|
||||||
30
SSL_Socket_snippet/main.c
Normal file
30
SSL_Socket_snippet/main.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "daemon.h"
|
||||||
|
#include "cmdlnopts.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
char *self = argv[0];
|
||||||
|
initial_setup();
|
||||||
|
parse_args(argc, argv);
|
||||||
|
return start_daemon(self);
|
||||||
|
}
|
||||||
137
SSL_Socket_snippet/server.c
Normal file
137
SSL_Socket_snippet/server.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
static const char *maxcl = "Max client number reached, connect later\n";
|
||||||
|
static const char *sslerr = "SSL error occured\n";
|
||||||
|
|
||||||
|
// return 0 if client disconnected
|
||||||
|
static int handle_connection(SSL *ssl){
|
||||||
|
char buf[1024];
|
||||||
|
int r = read_string(ssl, buf, 1024);
|
||||||
|
if(r < 0) return 0;
|
||||||
|
int sd = SSL_get_fd(ssl);
|
||||||
|
printf("Client %d msg: \"%s\"\n", sd, buf);
|
||||||
|
LOGDBG("fd=%d, message=%s", sd, buf);
|
||||||
|
snprintf(buf, 1024, "Hello, yout FD=%d\n", sd);
|
||||||
|
SSL_write(ssl, buf, strlen(buf));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief timeouted_sslaccept - SSL_accept with timeout
|
||||||
|
* @param ssl - SSL
|
||||||
|
* @return 1 if connection ready or 0 if error
|
||||||
|
*/
|
||||||
|
static int timeouted_sslaccept(SSL *ssl){
|
||||||
|
double t0 = dtime();
|
||||||
|
while(dtime() - t0 < ACCEPT_TIMEOUT){
|
||||||
|
int x = SSL_accept(ssl);
|
||||||
|
if(x < 0){
|
||||||
|
int sslerr = SSL_get_error(ssl, x);
|
||||||
|
if(SSL_ERROR_WANT_READ == sslerr ||
|
||||||
|
SSL_ERROR_WANT_WRITE == sslerr) continue;
|
||||||
|
DBG("SSL error %d", sslerr);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else return TRUE;
|
||||||
|
}
|
||||||
|
DBG("Timeout");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverproc(SSL_CTX *ctx, int fd){
|
||||||
|
char buf[64];
|
||||||
|
int P = 0;
|
||||||
|
int enable = 1;
|
||||||
|
if(ioctl(fd, FIONBIO, (void *)&enable) < 0){
|
||||||
|
LOGERR("Can't make socket nonblocking");
|
||||||
|
ERRX("ioctl()");
|
||||||
|
}
|
||||||
|
int nfd = 1; // only one listening socket @start
|
||||||
|
struct pollfd poll_set[BACKLOG+1];
|
||||||
|
memset(poll_set, 0, sizeof(poll_set));
|
||||||
|
poll_set[0].fd = fd;
|
||||||
|
poll_set[0].events = POLLIN;
|
||||||
|
SSL *ssls[BACKLOG+1] = {0}; // !!! start from 1 - like in poll_set !!!
|
||||||
|
double t0 = dtime(), tstart = t0;
|
||||||
|
while(1){
|
||||||
|
if(dtime() - t0 > 5. && nfd > 1){ // broadcasting message
|
||||||
|
//DBG("send ping");
|
||||||
|
snprintf(buf, 63, "ping #%d; t=%g\n", ++P, dtime() - tstart);
|
||||||
|
int l = strlen(buf);
|
||||||
|
for(int i = nfd-1; i > 0; --i){
|
||||||
|
//DBG("To fd[%d]=%d", i, poll_set[i].fd);
|
||||||
|
SSL_write(ssls[i], buf, l);
|
||||||
|
}
|
||||||
|
t0 = dtime();
|
||||||
|
}
|
||||||
|
poll(poll_set, nfd, 1); // max timeout - 1ms
|
||||||
|
// check for accept()
|
||||||
|
if(poll_set[0].revents & POLLIN){
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
socklen_t len = sizeof(addr);
|
||||||
|
int client = accept4(fd, (struct sockaddr*)&addr, &len, SOCK_NONBLOCK); // non-blocking for timeout of SSL_accept
|
||||||
|
DBG("Connection: %s @ %d (fd=%d)\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), client);
|
||||||
|
LOGMSG("Client %s connected to port %d (fd=%d)", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), client);
|
||||||
|
if(nfd == BACKLOG + 1){
|
||||||
|
LOGWARN("Max amount of connections: disconnect fd=%d", client);
|
||||||
|
WARNX("Limit of connections reached");
|
||||||
|
send(client, maxcl, sizeof(maxcl)-1, MSG_NOSIGNAL);
|
||||||
|
close(client);
|
||||||
|
}else{
|
||||||
|
DBG("New ssl");
|
||||||
|
SSL *ssl = SSL_new(ctx);
|
||||||
|
SSL_set_fd(ssl, client);
|
||||||
|
DBG("Accept");
|
||||||
|
if(timeouted_sslaccept(ssl)){
|
||||||
|
DBG("OK");
|
||||||
|
ssls[nfd] = ssl;
|
||||||
|
memset(&poll_set[nfd], 0, sizeof(struct pollfd));
|
||||||
|
poll_set[nfd].fd = client;
|
||||||
|
poll_set[nfd].events = POLLIN;
|
||||||
|
++nfd;
|
||||||
|
}else{
|
||||||
|
LOGERR("SSL_accept()");
|
||||||
|
WARNX("SSL_accept()");
|
||||||
|
SSL_free(ssl);
|
||||||
|
send(client, sslerr, sizeof(sslerr)-1, MSG_NOSIGNAL);
|
||||||
|
close(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// scan connections
|
||||||
|
for(int fdidx = 1; fdidx < nfd; ++fdidx){
|
||||||
|
if((poll_set[fdidx].revents & POLLIN) == 0) continue;
|
||||||
|
int fd = poll_set[fdidx].fd;
|
||||||
|
if(!handle_connection(ssls[fdidx])){ // socket closed
|
||||||
|
SSL_free(ssls[fdidx]);
|
||||||
|
DBG("Client fd=%d disconnected", fd);
|
||||||
|
LOGMSG("Client fd=%d disconnected", fd);
|
||||||
|
close(fd);
|
||||||
|
if(--nfd > fdidx){ // move last FD to current position
|
||||||
|
poll_set[fdidx] = poll_set[nfd];
|
||||||
|
ssls[fdidx] = ssls[nfd];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
SSL_Socket_snippet/server.h
Normal file
27
SSL_Socket_snippet/server.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sslsock.h"
|
||||||
|
|
||||||
|
// timeout of SSL_accept (seconds)
|
||||||
|
#define ACCEPT_TIMEOUT (0.1)
|
||||||
|
|
||||||
|
|
||||||
|
void serverproc(SSL_CTX *ctx, int fd);
|
||||||
1
SSL_Socket_snippet/server_cert.pem
Symbolic link
1
SSL_Socket_snippet/server_cert.pem
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ca/server/server_cert.pem
|
||||||
1
SSL_Socket_snippet/server_key.pem
Symbolic link
1
SSL_Socket_snippet/server_key.pem
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ca/server/private/server_key.pem
|
||||||
184
SSL_Socket_snippet/sslsock.c
Normal file
184
SSL_Socket_snippet/sslsock.c
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <resolv.h>
|
||||||
|
#include <signal.h> // pthread_kill
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "cmdlnopts.h"
|
||||||
|
#include "sslsock.h"
|
||||||
|
#ifdef SERVER
|
||||||
|
#include "server.h"
|
||||||
|
#else
|
||||||
|
#include "client.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
static int OpenConn(int port){
|
||||||
|
int sd = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
if(sd < 0){
|
||||||
|
LOGERR("Can't open socket");
|
||||||
|
ERRX("socket()");
|
||||||
|
}
|
||||||
|
int enable = 1;
|
||||||
|
// allow reuse of descriptor
|
||||||
|
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (void *)&enable, sizeof(int)) < 0){
|
||||||
|
LOGERR("Can't apply SO_REUSEADDR to socket");
|
||||||
|
ERRX("setsockopt()");
|
||||||
|
}
|
||||||
|
struct sockaddr_in addr = {0};
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
if(bind(sd, (struct sockaddr*)&addr, sizeof(addr))){
|
||||||
|
LOGWARN("Can't bind port %d", port);
|
||||||
|
ERRX("bind()");
|
||||||
|
}
|
||||||
|
if(listen(sd, BACKLOG)){
|
||||||
|
LOGWARN("Can't listen()");
|
||||||
|
ERRX("listen()");
|
||||||
|
}
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int OpenConn(int port){
|
||||||
|
FNAME();
|
||||||
|
int sd;
|
||||||
|
struct hostent *host;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
if((host = gethostbyname(G.serverhost)) == NULL ){
|
||||||
|
LOGWARN("gethostbyname(%s) error", G.serverhost);
|
||||||
|
ERRX("gethostbyname()");
|
||||||
|
}
|
||||||
|
sd = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
DBG("sd=%d", sd);
|
||||||
|
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))){
|
||||||
|
close(sd);
|
||||||
|
LOGWARN("Can't connect to %s", G.serverhost);
|
||||||
|
ERRX("connect()");
|
||||||
|
}
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SSL_CTX* InitCTX(void){
|
||||||
|
const SSL_METHOD *method;
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
SSL_load_error_strings();
|
||||||
|
method =
|
||||||
|
#ifdef CLIENT
|
||||||
|
TLS_client_method();
|
||||||
|
#else
|
||||||
|
TLS_server_method();
|
||||||
|
#endif
|
||||||
|
ctx = SSL_CTX_new(method);
|
||||||
|
if(!ctx){
|
||||||
|
LOGWARN("Can't create SSL context");
|
||||||
|
ERRX("SSL_CTX_new()");
|
||||||
|
}
|
||||||
|
if(SSL_CTX_load_verify_locations(ctx, G.ca, NULL) != 1){
|
||||||
|
LOGWARN("Could not set the CA file location\n");
|
||||||
|
ERRX("Could not set the CA file location\n");
|
||||||
|
}
|
||||||
|
#ifdef SERVER
|
||||||
|
|
||||||
|
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(G.ca));
|
||||||
|
#endif
|
||||||
|
if(SSL_CTX_use_certificate_file(ctx, G.cert, SSL_FILETYPE_PEM) <= 0){
|
||||||
|
LOGWARN("Can't use SSL certificate %s", G.cert);
|
||||||
|
ERRX("Can't use SSL certificate %s", G.cert);
|
||||||
|
}
|
||||||
|
if(SSL_CTX_use_PrivateKey_file(ctx, G.key, SSL_FILETYPE_PEM) <= 0){
|
||||||
|
LOGWARN("Can't use SSL key %s", G.key);
|
||||||
|
ERRX("Can't use SSL key %s", G.key);
|
||||||
|
}
|
||||||
|
if(!SSL_CTX_check_private_key(ctx)){
|
||||||
|
LOGWARN("Private key does not match the public certificate\n");
|
||||||
|
ERRX("Private key does not match the public certificate\n");
|
||||||
|
}
|
||||||
|
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
|
||||||
|
#ifdef SERVER
|
||||||
|
SSL_CTX_set_verify(ctx, // Specify that we need to verify the client as well
|
||||||
|
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||||
|
NULL);
|
||||||
|
#else
|
||||||
|
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||||
|
#endif
|
||||||
|
SSL_CTX_set_verify_depth(ctx, 1); // We accept only certificates signed only by the CA himself
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_socket(){
|
||||||
|
int fd;
|
||||||
|
SSL_library_init();
|
||||||
|
SSL_CTX *ctx = InitCTX();
|
||||||
|
fd = OpenConn(atoi(G.port));
|
||||||
|
#ifdef SERVER
|
||||||
|
serverproc(ctx, fd);
|
||||||
|
#else
|
||||||
|
clientproc(ctx, fd);
|
||||||
|
#endif
|
||||||
|
// newer reached
|
||||||
|
close(fd);
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int geterrcode(SSL *ssl, int errcode){
|
||||||
|
int sslerr = SSL_get_error(ssl, errcode);
|
||||||
|
if(SSL_ERROR_WANT_READ == sslerr ||
|
||||||
|
SSL_ERROR_WANT_WRITE == sslerr) return 0; // empty call
|
||||||
|
int sd = SSL_get_fd(ssl);
|
||||||
|
LOGERR("SSL error %d @client %d", sslerr, sd);
|
||||||
|
WARNX("SSL error %d @client %d", sslerr, sd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief read_string - read '\n'-terminated string from SSL
|
||||||
|
* @param ssl - SSL
|
||||||
|
* @param buf - buffer for text
|
||||||
|
* @param l - max buf length (including zero)
|
||||||
|
* @return amount of bytes read or -1 if client disconnected
|
||||||
|
*/
|
||||||
|
int read_string(SSL *ssl, char *buf, int l){
|
||||||
|
if(!ssl || l < 1) return 0;
|
||||||
|
int bytes = SSL_peek(ssl, buf, l);
|
||||||
|
// DBG("Peek: %d (bufsz %d); buf=%s", bytes, l, buf);
|
||||||
|
if(bytes < 1){ // nothing to read or error
|
||||||
|
return geterrcode(ssl, bytes);
|
||||||
|
}
|
||||||
|
if(bytes < l && buf[bytes-1] != '\n'){ // string not ready, no buffer overfull
|
||||||
|
return 0; // wait a rest of string
|
||||||
|
}
|
||||||
|
bytes = SSL_read(ssl, buf, l);
|
||||||
|
// DBG("Read: %d", bytes);
|
||||||
|
if(bytes < 1){ // error
|
||||||
|
return geterrcode(ssl, bytes);
|
||||||
|
}
|
||||||
|
buf[bytes-1] = 0; // replace '\n' with 0
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
41
SSL_Socket_snippet/sslsock.h
Normal file
41
SSL_Socket_snippet/sslsock.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the sslsosk project.
|
||||||
|
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <arpa/inet.h> // inet_ntop
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netdb.h> // addrinfo
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#if ! defined CLIENT && ! defined SERVER
|
||||||
|
#error "Define CLIENT or SERVER before including this file"
|
||||||
|
#endif
|
||||||
|
#if defined CLIENT && defined SERVER
|
||||||
|
#error "Both CLIENT and SERVER defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BACKLOG 10
|
||||||
|
|
||||||
|
int open_socket();
|
||||||
|
int read_string(SSL *ssl, char *buf, int l);
|
||||||
1
SSL_Socket_snippet/sslsosk.cflags
Normal file
1
SSL_Socket_snippet/sslsosk.cflags
Normal file
@ -0,0 +1 @@
|
|||||||
|
-std=c17
|
||||||
7
SSL_Socket_snippet/sslsosk.config
Normal file
7
SSL_Socket_snippet/sslsosk.config
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#define _XOPEN_SOURCE 1111
|
||||||
|
#define CLIENT
|
||||||
|
#define EBUG
|
||||||
|
|
||||||
|
//#define SERVER
|
||||||
|
|
||||||
1
SSL_Socket_snippet/sslsosk.creator
Normal file
1
SSL_Socket_snippet/sslsosk.creator
Normal file
@ -0,0 +1 @@
|
|||||||
|
[General]
|
||||||
1
SSL_Socket_snippet/sslsosk.cxxflags
Normal file
1
SSL_Socket_snippet/sslsosk.cxxflags
Normal file
@ -0,0 +1 @@
|
|||||||
|
-std=c++17
|
||||||
11
SSL_Socket_snippet/sslsosk.files
Normal file
11
SSL_Socket_snippet/sslsosk.files
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
client.c
|
||||||
|
client.h
|
||||||
|
cmdlnopts.c
|
||||||
|
cmdlnopts.h
|
||||||
|
daemon.c
|
||||||
|
daemon.h
|
||||||
|
main.c
|
||||||
|
server.c
|
||||||
|
server.h
|
||||||
|
sslsock.c
|
||||||
|
sslsock.h
|
||||||
1
SSL_Socket_snippet/sslsosk.includes
Normal file
1
SSL_Socket_snippet/sslsosk.includes
Normal file
@ -0,0 +1 @@
|
|||||||
|
.
|
||||||
Loading…
x
Reference in New Issue
Block a user