Add support for a tls flag in sudo_parse_host_port().

If the string "(tls)" appears at the end, the tls flag is set to true
and the default tls port is used if necessary.
This commit is contained in:
Todd C. Miller
2020-05-04 11:28:23 -06:00
parent 82bc05d998
commit b5a317aeb9
5 changed files with 71 additions and 27 deletions

View File

@@ -208,8 +208,8 @@ __dso_public int sudo_getgrouplist2_v1(const char *name, gid_t basegid, GETGROUP
#define sudo_getgrouplist2(_a, _b, _c, _d) sudo_getgrouplist2_v1((_a), (_b), (_c), (_d))
/* host_port.c */
__dso_public bool sudo_parse_host_port_v1(char *str, char **hostp, char **portp, char *defport);
#define sudo_parse_host_port(_a, _b, _c, _d) sudo_parse_host_port_v1((_a), (_b), (_c), (_d))
__dso_public bool sudo_parse_host_port_v1(char *str, char **hostp, char **portp, bool *tlsp, char *defport, char *defport_tls);
#define sudo_parse_host_port(_a, _b, _c, _d, _e, _f) sudo_parse_host_port_v1((_a), (_b), (_c), (_d), (_e), (_f))
/* key_val.c */
__dso_public char *sudo_new_key_val_v1(const char *key, const char *value);

View File

@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2019 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "sudo_gettext.h" /* must be included before sudo_compat.h */
#include "sudo_compat.h"
@@ -40,10 +41,12 @@
* Fills in hostp and portp which may point within str, which is modified.
*/
bool
sudo_parse_host_port_v1(char *str, char **hostp, char **portp, char *defport)
sudo_parse_host_port_v1(char *str, char **hostp, char **portp, bool *tlsp,
char *defport, char *defport_tls)
{
char *port, *host = str;
char *flags, *port, *host = str;
bool ret = false;
bool tls = false;
debug_decl(sudo_parse_host_port, SUDO_DEBUG_UTIL);
/* Check for IPv6 address like [::0] followed by optional port */
@@ -56,11 +59,17 @@ sudo_parse_host_port_v1(char *str, char **hostp, char **portp, char *defport)
goto done;
}
*port++ = '\0';
if (*port == ':') {
port++;
} else if (*port == '\0') {
port = NULL; /* no port specified */
} else {
switch (*port) {
case ':':
port++;
break;
case '\0':
port = NULL; /* no port specified */
break;
case '(':
/* flag, handled below */
break;
default:
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"invalid IPv6 address %s", str);
goto done;
@@ -71,13 +80,24 @@ sudo_parse_host_port_v1(char *str, char **hostp, char **portp, char *defport)
*port++ = '\0';
}
/* Check for optional tls flag at the end. */
flags = strchr(port ? port : host, '(');
if (flags != NULL) {
if (strcasecmp(flags, "(tls)") == 0)
tls = true;
*flags = '\0';
if (port == flags)
port = NULL;
}
if (port == NULL)
port = defport;
port = tls ? defport_tls : defport;
else if (*port == '\0')
goto done;
*hostp = host;
*portp = port;
*tlsp = tls;
ret = true;

View File

@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2010 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -47,22 +47,34 @@ struct host_port_test {
const char *str; /* input string */
const char *host; /* parsed host */
const char *port; /* parsed port */
bool tls; /* parsed TLS flag */
char *defport; /* default port */
char *defport_tls; /* default port */
bool ret; /* return value */
};
static struct host_port_test test_data[] = {
{ "xerxes", "xerxes", "12345", "12345", true },
{ "xerxes:12345", "xerxes", "12345", "67890", true },
{ "127.0.0.1", "127.0.0.1", "12345", "12345", true },
{ "127.0.0.1:12345", "127.0.0.1", "12345", "67890", true },
{ "[::1]", "::1", "12345", "12345", true },
{ "[::1]:12345", "::1", "12345", "67890", true },
/* No TLS */
{ "xerxes", "xerxes", "12345", false, "12345", NULL, true },
{ "xerxes:12345", "xerxes", "12345", false, "67890", NULL, true },
{ "127.0.0.1", "127.0.0.1", "12345", false, "12345", NULL, true },
{ "127.0.0.1:12345", "127.0.0.1", "12345", false, "67890", NULL, true },
{ "[::1]", "::1", "12345", false, "12345", NULL, true },
{ "[::1]:12345", "::1", "12345", false, "67890", NULL, true },
{ "xerxes:", NULL, NULL, "12345", false }, /* missing port */
{ "127.0.0.1:", NULL, NULL, "12345", false }, /* missing port */
{ "[::1:12345", NULL, NULL, "67890", false }, /* missing bracket */
{ "[::1]:", NULL, NULL, "12345", false }, /* missing port */
/* With TLS */
{ "xerxes(tls)", "xerxes", "12345", true, "5678", "12345", true },
{ "xerxes:12345(tls)", "xerxes", "12345", true, "5678", "67890", true },
{ "127.0.0.1(tls)", "127.0.0.1", "12345", true, "5678", "12345", true },
{ "127.0.0.1:12345(tls)", "127.0.0.1", "12345", true, "5678", "67890", true },
{ "[::1](tls)", "::1", "12345", true, "5678", "12345", true },
{ "[::1]:12345(tls)", "::1", "12345", true, "5678", "67890", true },
/* Errors */
{ "xerxes:", NULL, NULL, false, "12345", NULL, false }, /* missing port */
{ "127.0.0.1:", NULL, NULL, false, "12345", NULL, false }, /* missing port */
{ "[::1:12345", NULL, NULL, false, "67890", NULL, false }, /* missing bracket */
{ "[::1]:", NULL, NULL, false, "12345", NULL, false }, /* missing port */
{ NULL }
};
@@ -71,18 +83,20 @@ main(int argc, char *argv[])
{
int i, errors = 0, ntests = 0;
char *host, *port, *copy = NULL;
bool ret;
bool ret, tls;
initprogname(argc > 0 ? argv[0] : "host_port_test");
for (i = 0; test_data[i].str != NULL; i++) {
host = port = NULL;
tls = false;
free(copy);
if ((copy = strdup(test_data[i].str)) == NULL)
sudo_fatal_nodebug(NULL);
ntests++;
ret = sudo_parse_host_port(copy, &host, &port, test_data[i].defport);
ret = sudo_parse_host_port(copy, &host, &port, &tls,
test_data[i].defport, test_data[i].defport_tls);
if (ret != test_data[i].ret) {
sudo_warnx_nodebug("test #%d: %s: returned %s, expected %s",
ntests, test_data[i].str, ret ? "true" : "false",
@@ -117,6 +131,13 @@ main(int argc, char *argv[])
errors++;
continue;
}
if (tls != test_data[i].tls) {
sudo_warnx_nodebug("test #%d: %s: bad tls, expected %s, got %s",
ntests, test_data[i].str, test_data[i].tls ? "true" : "false",
tls ? "true" : "false");
errors++;
continue;
}
}
free(copy);
if (ntests != 0) {

View File

@@ -379,7 +379,7 @@ cb_listen_address(struct logsrvd_config *config, const char *str)
{
struct addrinfo hints, *res, *res0 = NULL;
char *copy, *host, *port;
bool ret = false;
bool tls, ret = false;
int error;
debug_decl(cb_iolog_mode, SUDO_DEBUG_UTIL);
@@ -389,7 +389,8 @@ cb_listen_address(struct logsrvd_config *config, const char *str)
}
/* Parse host[:port] */
if (!sudo_parse_host_port(copy, &host, &port, DEFAULT_PORT_STR))
if (!sudo_parse_host_port(copy, &host, &port, &tls, DEFAULT_PORT_STR,
DEFAULT_PORT_STR))
goto done;
if (host[0] == '*' && host[1] == '\0')
host = NULL;

View File

@@ -215,11 +215,13 @@ log_server_connect(struct sudoers_str_list *servers, bool tcp_keepalive,
char *copy, *host, *port;
const char *cause = NULL;
int sock = -1;
bool tls;
debug_decl(restore_nproc, SUDOERS_DEBUG_UTIL);
STAILQ_FOREACH(server, servers, entries) {
copy = strdup(server->str);
if (!sudo_parse_host_port(copy, &host, &port, DEFAULT_PORT_STR)) {
if (!sudo_parse_host_port(copy, &host, &port, &tls, DEFAULT_PORT_STR,
DEFAULT_PORT_STR)) {
free(copy);
continue;
}