mirror of
https://github.com/yrutschle/sslh.git
synced 2025-04-17 01:12:21 +03:00
Add support for wildcard ALPN/SNI values
This commit is contained in:
commit
21f524f711
2
Makefile
2
Makefile
@ -67,6 +67,8 @@ version.h:
|
||||
|
||||
sslh: sslh-fork sslh-select
|
||||
|
||||
$(OBJS): version.h
|
||||
|
||||
sslh-fork: version.h $(OBJS) sslh-fork.o Makefile common.h
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o sslh-fork sslh-fork.o $(OBJS) $(LIBS)
|
||||
#strip sslh-fork
|
||||
|
60
common.c
60
common.c
@ -37,6 +37,7 @@ int probing_timeout = 2;
|
||||
int inetd = 0;
|
||||
int foreground = 0;
|
||||
int background = 0;
|
||||
int transparent = 0;
|
||||
int numeric = 0;
|
||||
const char *user_name, *pid_file;
|
||||
|
||||
@ -47,8 +48,13 @@ struct addrinfo *addr_listen = NULL; /* what addresses do we listen to? */
|
||||
int allow_severity =0, deny_severity = 0;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CR_DIE,
|
||||
CR_WARN
|
||||
} CR_ACTION;
|
||||
|
||||
/* check result and die, printing the offending address and error */
|
||||
void check_res_dumpdie(int res, struct addrinfo *addr, char* syscall)
|
||||
void check_res_dump(CR_ACTION act, int res, struct addrinfo *addr, char* syscall)
|
||||
{
|
||||
char buf[NI_MAXHOST];
|
||||
|
||||
@ -57,7 +63,9 @@ void check_res_dumpdie(int res, struct addrinfo *addr, char* syscall)
|
||||
sprintaddr(buf, sizeof(buf), addr),
|
||||
syscall,
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
|
||||
if (act == CR_DIE)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,28 +126,28 @@ int start_listen_sockets(int *sockfd[], struct addrinfo *addr_list)
|
||||
saddr = (struct sockaddr_storage*)addr->ai_addr;
|
||||
|
||||
(*sockfd)[i] = socket(saddr->ss_family, SOCK_STREAM, 0);
|
||||
check_res_dumpdie((*sockfd)[i], addr, "socket");
|
||||
check_res_dump(CR_DIE, (*sockfd)[i], addr, "socket");
|
||||
|
||||
one = 1;
|
||||
res = setsockopt((*sockfd)[i], SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one));
|
||||
check_res_dumpdie(res, addr, "setsockopt(SO_REUSEADDR)");
|
||||
check_res_dump(CR_DIE, res, addr, "setsockopt(SO_REUSEADDR)");
|
||||
|
||||
if (addr->ai_flags & SO_KEEPALIVE) {
|
||||
res = setsockopt((*sockfd)[i], SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(one));
|
||||
check_res_dumpdie(res, addr, "setsockopt(SO_KEEPALIVE)");
|
||||
check_res_dump(CR_DIE, res, addr, "setsockopt(SO_KEEPALIVE)");
|
||||
printf("set up keepalive\n");
|
||||
}
|
||||
|
||||
if (IP_FREEBIND) {
|
||||
res = setsockopt((*sockfd)[i], IPPROTO_IP, IP_FREEBIND, (char*)&one, sizeof(one));
|
||||
check_res_dumpdie(res, addr, "setsockopt(IP_FREEBIND)");
|
||||
}
|
||||
check_res_dump(CR_WARN, res, addr, "setsockopt(IP_FREEBIND)");
|
||||
}
|
||||
|
||||
res = bind((*sockfd)[i], addr->ai_addr, addr->ai_addrlen);
|
||||
check_res_dumpdie(res, addr, "bind");
|
||||
check_res_dump(CR_DIE, res, addr, "bind");
|
||||
|
||||
res = listen ((*sockfd)[i], 50);
|
||||
check_res_dumpdie(res, addr, "listen");
|
||||
check_res_dump(CR_DIE, res, addr, "listen");
|
||||
|
||||
}
|
||||
|
||||
@ -236,7 +244,7 @@ int connect_addr(struct connection *cnx, int fd_from)
|
||||
|
||||
for (a = cnx->proto->saddr; a; a = a->ai_next) {
|
||||
/* When transparent, make sure both connections use the same address family */
|
||||
if (cnx->proto->transparent && a->ai_family != from.ai_addr->sa_family)
|
||||
if (transparent && a->ai_family != from.ai_addr->sa_family)
|
||||
continue;
|
||||
if (verbose)
|
||||
fprintf(stderr, "connecting to %s family %d len %d\n",
|
||||
@ -249,7 +257,7 @@ int connect_addr(struct connection *cnx, int fd_from)
|
||||
log_message(LOG_ERR, "forward to %s failed:socket: %s\n",
|
||||
cnx->proto->description, strerror(errno));
|
||||
} else {
|
||||
if (cnx->proto->transparent) {
|
||||
if (transparent) {
|
||||
res = bind_peer(fd, fd_from);
|
||||
CHECK_RES_RETURN(res, "bind_peer");
|
||||
}
|
||||
@ -434,16 +442,31 @@ char* sprintaddr(char* buf, size_t size, struct addrinfo *a)
|
||||
|
||||
/* Turns a hostname and port (or service) into a list of struct addrinfo
|
||||
* returns 0 on success, -1 otherwise and logs error
|
||||
*
|
||||
* *host gets modified
|
||||
**/
|
||||
int resolve_split_name(struct addrinfo **out, const char* host, const char* serv)
|
||||
int resolve_split_name(struct addrinfo **out, char* host, const char* serv)
|
||||
{
|
||||
struct addrinfo hint;
|
||||
char *end;
|
||||
int res;
|
||||
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
hint.ai_family = PF_UNSPEC;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
/* If it is a RFC-Compliant IPv6 address ("[1234::12]:443"), remove brackets
|
||||
* around IP address */
|
||||
if (host[0] == '[') {
|
||||
end = strrchr(host, ']');
|
||||
if (!end) {
|
||||
fprintf(stderr, "%s: no closing bracket in IPv6 address?\n", host);
|
||||
}
|
||||
host++; /* skip first bracket */
|
||||
*end = 0; /* remove last bracket */
|
||||
}
|
||||
|
||||
|
||||
res = getaddrinfo(host, serv, &hint, out);
|
||||
if (res)
|
||||
log_message(LOG_ERR, "%s `%s:%s'\n", gai_strerror(res), host, serv);
|
||||
@ -456,7 +479,7 @@ fullname: input string -- it gets clobbered
|
||||
*/
|
||||
void resolve_name(struct addrinfo **out, char* fullname)
|
||||
{
|
||||
char *serv, *host, *end;
|
||||
char *serv, *host;
|
||||
int res;
|
||||
|
||||
/* Find port */
|
||||
@ -470,17 +493,6 @@ void resolve_name(struct addrinfo **out, char* fullname)
|
||||
|
||||
host = fullname;
|
||||
|
||||
/* If it is a RFC-Compliant IPv6 address ("[1234::12]:443"), remove brackets
|
||||
* around IP address */
|
||||
if (host[0] == '[') {
|
||||
end = strrchr(host, ']');
|
||||
if (!end) {
|
||||
fprintf(stderr, "%s: no closing bracket in IPv6 address?\n", host);
|
||||
}
|
||||
host++; /* skip first bracket */
|
||||
*end = 0; /* remove last bracket */
|
||||
}
|
||||
|
||||
res = resolve_split_name(out, host, serv);
|
||||
if (res) {
|
||||
fprintf(stderr, "%s `%s'\n", gai_strerror(res), fullname);
|
||||
|
5
common.h
5
common.h
@ -106,14 +106,15 @@ void drop_privileges(const char* user_name);
|
||||
void write_pid_file(const char* pidfile);
|
||||
void log_message(int type, char* msg, ...);
|
||||
void dump_connection(struct connection *cnx);
|
||||
int resolve_split_name(struct addrinfo **out, const char* hostname, const char* port);
|
||||
int resolve_split_name(struct addrinfo **out, char* hostname, const char* port);
|
||||
|
||||
int start_listen_sockets(int *sockfd[], struct addrinfo *addr_list);
|
||||
|
||||
int defer_write(struct queue *q, void* data, int data_size);
|
||||
int flush_deferred(struct queue *q);
|
||||
|
||||
extern int probing_timeout, verbose, inetd, foreground, background, numeric;
|
||||
extern int probing_timeout, verbose, inetd, foreground,
|
||||
background, transparent, numeric;
|
||||
extern struct sockaddr_storage addr_ssl, addr_ssh, addr_openvpn;
|
||||
extern struct addrinfo *addr_listen;
|
||||
extern const char* USAGE_STRING;
|
||||
|
@ -74,6 +74,9 @@ protocols:
|
||||
{ name: "regex"; host: "localhost"; port: "1194"; regex_patterns: [ "^\x00[\x0D-\xFF]$", "^\x00[\x0D-\xFF]\x38" ]; },
|
||||
# Jabber
|
||||
{ name: "regex"; host: "localhost"; port: "5222"; regex_patterns: [ "jabber" ]; },
|
||||
|
||||
# Let's Encrypt (tls-sni-* challenges)
|
||||
{ name: "tls"; host: "localhost"; port: "letsencrypt-client"; sni_hostnames: [ "*.*.acme.invalid" ]; log_level: 0;},
|
||||
|
||||
# Catch-all
|
||||
{ name: "regex"; host: "localhost"; port: "443"; regex_patterns: [ "" ]; },
|
||||
|
20
probe.c
20
probe.c
@ -45,16 +45,16 @@ static int is_true(const char *p, int len, struct proto* proto) { return 1; }
|
||||
/* Table of protocols that have a built-in probe
|
||||
*/
|
||||
static struct proto builtins[] = {
|
||||
/* description service saddr log_level keepalive transparent probe */
|
||||
{ "ssh", "sshd", NULL, 1, 0, 0, is_ssh_protocol},
|
||||
{ "openvpn", NULL, NULL, 1, 0, 0, is_openvpn_protocol },
|
||||
{ "tinc", NULL, NULL, 1, 0, 0, is_tinc_protocol },
|
||||
{ "xmpp", NULL, NULL, 1, 0, 0, is_xmpp_protocol },
|
||||
{ "http", NULL, NULL, 1, 0, 0, is_http_protocol },
|
||||
{ "ssl", NULL, NULL, 1, 0, 0, is_tls_protocol },
|
||||
{ "tls", NULL, NULL, 1, 0, 0, is_tls_protocol },
|
||||
{ "adb", NULL, NULL, 1, 0, 0, is_adb_protocol },
|
||||
{ "anyprot", NULL, NULL, 1, 0, 0, is_true }
|
||||
/* description service saddr log_level keepalive probe */
|
||||
{ "ssh", "sshd", NULL, 1, 0, is_ssh_protocol},
|
||||
{ "openvpn", NULL, NULL, 1, 0, is_openvpn_protocol },
|
||||
{ "tinc", NULL, NULL, 1, 0, is_tinc_protocol },
|
||||
{ "xmpp", NULL, NULL, 1, 0, is_xmpp_protocol },
|
||||
{ "http", NULL, NULL, 1, 0, is_http_protocol },
|
||||
{ "ssl", NULL, NULL, 1, 0, is_tls_protocol },
|
||||
{ "tls", NULL, NULL, 1, 0, is_tls_protocol },
|
||||
{ "adb", NULL, NULL, 1, 0, is_adb_protocol },
|
||||
{ "anyprot", NULL, NULL, 1, 0, is_true }
|
||||
};
|
||||
|
||||
static struct proto *protocols;
|
||||
|
1
probe.h
1
probe.h
@ -24,7 +24,6 @@ struct proto {
|
||||
* 1: Log incoming connection
|
||||
*/
|
||||
int keepalive; /* 0: No keepalive ; 1: Set Keepalive for this connection */
|
||||
int transparent; /* 0: opaque proxy ; 1: transparent proxy */
|
||||
|
||||
/* function to probe that protocol; parameters are buffer and length
|
||||
* containing the data to probe, and a pointer to the protocol structure */
|
||||
|
14
sslh-main.c
14
sslh-main.c
@ -61,14 +61,11 @@ const char* USAGE_STRING =
|
||||
/* Constants for options that have no one-character shorthand */
|
||||
#define OPT_ONTIMEOUT 257
|
||||
|
||||
/* Global setting for transparent proxying */
|
||||
int g_transparent = 0;
|
||||
|
||||
static struct option const_options[] = {
|
||||
{ "inetd", no_argument, &inetd, 1 },
|
||||
{ "foreground", no_argument, &foreground, 1 },
|
||||
{ "background", no_argument, &background, 1 },
|
||||
{ "transparent", no_argument, &g_transparent, 1 },
|
||||
{ "transparent", no_argument, &transparent, 1 },
|
||||
{ "numeric", no_argument, &numeric, 1 },
|
||||
{ "verbose", no_argument, &verbose, 1 },
|
||||
{ "user", required_argument, 0, 'u' },
|
||||
@ -126,16 +123,14 @@ static void printsettings(void)
|
||||
|
||||
for (p = get_first_protocol(); p; p = p->next) {
|
||||
fprintf(stderr,
|
||||
"%s addr: %s. libwrap service: %s log_level: %d family %d %d [%s%s]\n",
|
||||
"%s addr: %s. libwrap service: %s log_level: %d family %d %d [%s]\n",
|
||||
p->description,
|
||||
sprintaddr(buf, sizeof(buf), p->saddr),
|
||||
p->service,
|
||||
p->log_level,
|
||||
p->saddr->ai_family,
|
||||
p->saddr->ai_addr->sa_family,
|
||||
p->keepalive ? "keepalive " : "",
|
||||
p->transparent ? "transparent" : ""
|
||||
);
|
||||
p->keepalive ? "keepalive" : "");
|
||||
}
|
||||
fprintf(stderr, "listening on:\n");
|
||||
for (a = addr_listen; a; a = a->ai_next) {
|
||||
@ -312,7 +307,6 @@ static int config_protocols(config_t *config, struct proto **prots)
|
||||
p->description = name;
|
||||
config_setting_lookup_string(prot, "service", &(p->service));
|
||||
config_setting_lookup_bool(prot, "keepalive", &p->keepalive);
|
||||
config_setting_lookup_bool(prot, "transparent", &p->transparent);
|
||||
|
||||
if (config_setting_lookup_int(prot, "log_level", &p->log_level) == CONFIG_FALSE) {
|
||||
p->log_level = 1;
|
||||
@ -382,7 +376,7 @@ static int config_parse(char *filename, struct addrinfo **listen, struct proto *
|
||||
config_lookup_bool(&config, "inetd", &inetd);
|
||||
config_lookup_bool(&config, "foreground", &foreground);
|
||||
config_lookup_bool(&config, "numeric", &numeric);
|
||||
config_lookup_bool(&config, "transparent", &g_transparent);
|
||||
config_lookup_bool(&config, "transparent", &transparent);
|
||||
|
||||
if (config_lookup_int(&config, "timeout", (int *)&timeout) == CONFIG_TRUE) {
|
||||
probing_timeout = timeout;
|
||||
|
@ -5,9 +5,8 @@
|
||||
|
||||
|
||||
static char* resolve_listen(const char *hostname, const char *port) {
|
||||
|
||||
/* Need room in the strcat for \0 and :
|
||||
* the format in the socket unit file is hostname:port */
|
||||
/* Need room in the strcat for \0 and :
|
||||
* the format in the socket unit file is hostname:port */
|
||||
char *conn = (char*)malloc(strlen(hostname)+strlen(port)+2);
|
||||
strcpy(conn, hostname);
|
||||
strcat(conn, ":");
|
||||
@ -18,136 +17,130 @@ static char* resolve_listen(const char *hostname, const char *port) {
|
||||
}
|
||||
|
||||
|
||||
static int get_listen_from_conf(const char *filename, char **listen) {
|
||||
static int get_listen_from_conf(const char *filename, char **listen[]) {
|
||||
config_t config;
|
||||
config_setting_t *setting, *addr;
|
||||
const char *hostname, *port;
|
||||
int len = 0;
|
||||
|
||||
config_t config;
|
||||
config_setting_t *setting, *addr;
|
||||
const char *hostname, *port;
|
||||
int len = 0;
|
||||
|
||||
/* look up the listen stanzas in the config file so these
|
||||
* can be used in the socket file generated */
|
||||
|
||||
config_init(&config);
|
||||
if (config_read_file(&config, filename) == CONFIG_FALSE) {
|
||||
/* we don't care if file is missing, skip it */
|
||||
if (config_error_line(&config) != 0) {
|
||||
fprintf(stderr, "%s:%d:%s\n",
|
||||
filename,
|
||||
config_error_line(&config),
|
||||
config_error_text(&config));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
setting = config_lookup(&config, "listen");
|
||||
if (setting) {
|
||||
len = config_setting_length(setting);
|
||||
for (int i = 0; i < len; i++) {
|
||||
addr = config_setting_get_elem(setting, i);
|
||||
if (! (config_setting_lookup_string(addr, "host", &hostname) &&
|
||||
config_setting_lookup_string(addr, "port", &port))) {
|
||||
fprintf(stderr,
|
||||
"line %d:Incomplete specification (hostname and port required)\n",
|
||||
config_setting_source_line(addr));
|
||||
/* look up the listen stanzas in the config file so these
|
||||
* can be used in the socket file generated */
|
||||
config_init(&config);
|
||||
if (config_read_file(&config, filename) == CONFIG_FALSE) {
|
||||
/* we don't care if file is missing, skip it */
|
||||
if (config_error_line(&config) != 0) {
|
||||
fprintf(stderr, "%s:%d:%s\n",
|
||||
filename,
|
||||
config_error_line(&config),
|
||||
config_error_text(&config));
|
||||
return -1;
|
||||
} else {
|
||||
|
||||
listen[i] = malloc(strlen(resolve_listen(hostname, port)));
|
||||
strcpy(listen[i], resolve_listen(hostname, port));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setting = config_lookup(&config, "listen");
|
||||
if (setting) {
|
||||
len = config_setting_length(setting);
|
||||
*listen = malloc(len * sizeof(**listen));
|
||||
for (int i = 0; i < len; i++) {
|
||||
addr = config_setting_get_elem(setting, i);
|
||||
if (! (config_setting_lookup_string(addr, "host", &hostname) &&
|
||||
config_setting_lookup_string(addr, "port", &port))) {
|
||||
fprintf(stderr,
|
||||
"line %d:Incomplete specification (hostname and port required)\n",
|
||||
config_setting_source_line(addr));
|
||||
return -1;
|
||||
} else {
|
||||
(*listen)[i] = malloc(strlen(resolve_listen(hostname, port)));
|
||||
strcpy((*listen)[i], resolve_listen(hostname, port));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
static int write_socket_unit(FILE *socket, char **listen, int num_addr, const char *source) {
|
||||
static int write_socket_unit(FILE *socket, char *listen[], int num_addr, const char *source) {
|
||||
|
||||
fprintf(socket,
|
||||
"# Automatically generated by systemd-sslh-generator\n\n"
|
||||
"[Unit]\n"
|
||||
"Before=sslh.service\n"
|
||||
"SourcePath=%s\n"
|
||||
"Documentation=man:sslh(8) man:systemd-sslh-generator(8)\n\n"
|
||||
"[Socket]\n"
|
||||
"FreeBind=true\n",
|
||||
source);
|
||||
fprintf(socket,
|
||||
"# Automatically generated by systemd-sslh-generator\n\n"
|
||||
"[Unit]\n"
|
||||
"Before=sslh.service\n"
|
||||
"SourcePath=%s\n"
|
||||
"Documentation=man:sslh(8) man:systemd-sslh-generator(8)\n\n"
|
||||
"[Socket]\n"
|
||||
"FreeBind=true\n",
|
||||
source);
|
||||
|
||||
for (int i = 0; i < num_addr; i++) {
|
||||
fprintf(socket, "ListenStream=%s\n", listen[i]);
|
||||
}
|
||||
for (int i = 0; i < num_addr; i++) {
|
||||
fprintf(socket, "ListenStream=%s\n", listen[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen_sslh_config(char *runtime_unit_dir) {
|
||||
char *sslh_conf;
|
||||
int num_addr;
|
||||
FILE *config;
|
||||
char **listen;
|
||||
FILE *runtime_conf_fd = stdout;
|
||||
const char *unit_file;
|
||||
|
||||
char *sslh_conf;
|
||||
int num_addr;
|
||||
FILE *config;
|
||||
char **listen;
|
||||
FILE *runtime_conf_fd = stdout;
|
||||
const char *unit_file;
|
||||
/* There are two default locations so check both with first given preference */
|
||||
sslh_conf = "/etc/sslh.cfg";
|
||||
|
||||
/* There are two default locations so check both with first given preference */
|
||||
sslh_conf = "/etc/sslh.cfg";
|
||||
|
||||
config = fopen(sslh_conf, "r");
|
||||
if (config == NULL) {
|
||||
sslh_conf="/etc/sslh/sslh.cfg";
|
||||
config = fopen(sslh_conf, "r");
|
||||
if (config == NULL) {
|
||||
return -1;
|
||||
config = fopen(sslh_conf, "r");
|
||||
if (config == NULL) {
|
||||
sslh_conf="/etc/sslh/sslh.cfg";
|
||||
config = fopen(sslh_conf, "r");
|
||||
if (config == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(config);
|
||||
fclose(config);
|
||||
|
||||
num_addr = get_listen_from_conf(sslh_conf, &listen);
|
||||
if (num_addr < 0)
|
||||
return -1;
|
||||
|
||||
/* If this is run by systemd directly write to the location told to
|
||||
* otherwise write to standard out so that it's trivial to check what
|
||||
* will be written */
|
||||
if (runtime_unit_dir != "") {
|
||||
unit_file = "/sslh.socket";
|
||||
size_t uf_len = strlen(unit_file);
|
||||
size_t runtime_len = strlen(runtime_unit_dir) + uf_len + 1;
|
||||
char *runtime_conf = malloc(runtime_len);
|
||||
strcpy(runtime_conf, runtime_unit_dir);
|
||||
strcat(runtime_conf, unit_file);
|
||||
runtime_conf_fd = fopen(runtime_conf, "w");
|
||||
}
|
||||
|
||||
|
||||
num_addr = get_listen_from_conf(sslh_conf, listen);
|
||||
if (num_addr < 0)
|
||||
return -1;
|
||||
|
||||
/* If this is run by systemd directly write to the location told to
|
||||
* otherwise write to standard out so that it's trivial to check what
|
||||
* will be written */
|
||||
if (runtime_unit_dir != "") {
|
||||
unit_file = "/sslh.socket";
|
||||
size_t uf_len = strlen(unit_file);
|
||||
size_t runtime_len = strlen(runtime_unit_dir) + uf_len + 1;
|
||||
char *runtime_conf = malloc(runtime_len);
|
||||
strcpy(runtime_conf, runtime_unit_dir);
|
||||
strcat(runtime_conf, unit_file);
|
||||
runtime_conf_fd = fopen(runtime_conf, "w");
|
||||
}
|
||||
|
||||
|
||||
return write_socket_unit(runtime_conf_fd, listen, num_addr, sslh_conf);
|
||||
|
||||
return write_socket_unit(runtime_conf_fd, listen, num_addr, sslh_conf);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int r = 0;
|
||||
int k;
|
||||
char *runtime_unit_dest = "";
|
||||
|
||||
int r = 0;
|
||||
int k;
|
||||
char *runtime_unit_dest = "";
|
||||
if (argc > 1 && (argc != 4) ) {
|
||||
printf("This program takes three or no arguments.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc > 1 && (argc != 4) ) {
|
||||
printf("This program takes three or no arguments.\n");
|
||||
return -1;
|
||||
}
|
||||
if (argc > 1)
|
||||
runtime_unit_dest = argv[1];
|
||||
|
||||
if (argc > 1)
|
||||
runtime_unit_dest = argv[1];
|
||||
|
||||
k = gen_sslh_config(runtime_unit_dest);
|
||||
if (k < 0)
|
||||
r = k;
|
||||
|
||||
return r < 0 ? -1 : 0;
|
||||
k = gen_sslh_config(runtime_unit_dest);
|
||||
if (k < 0)
|
||||
r = k;
|
||||
|
||||
return r < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
|
3
tls.c
3
tls.c
@ -30,6 +30,7 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc() */
|
||||
#include <fnmatch.h> /* fnmatch() */
|
||||
#include "tls.h"
|
||||
|
||||
#define TLS_HEADER_LEN 5
|
||||
@ -290,7 +291,7 @@ has_match(char** list, const char* name, size_t name_len) {
|
||||
|
||||
for (item = list; *item; item++) {
|
||||
if (verbose) fprintf(stderr, "matching [%.*s] with [%s]\n", (int)name_len, name, *item);
|
||||
if(!strncmp(*item, name, name_len)) {
|
||||
if(!fnmatch(*item, name, 0)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user