mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
So we can use TrustedCertificateFile=- to disable certificate checking for both utilities.
238 lines
6.7 KiB
C
238 lines
6.7 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include "af-list.h"
|
|
#include "extract-word.h"
|
|
#include "ip-protocol-list.h"
|
|
#include "log.h"
|
|
#include "parse-helpers.h"
|
|
#include "parse-util.h"
|
|
#include "path-util.h"
|
|
#include "utf8.h"
|
|
|
|
int path_simplify_and_warn(
|
|
char *path,
|
|
unsigned flag,
|
|
const char *unit,
|
|
const char *filename,
|
|
unsigned line,
|
|
const char *lvalue) {
|
|
|
|
bool fatal = flag & PATH_CHECK_FATAL;
|
|
|
|
assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
|
|
|
|
if (!utf8_is_valid(path))
|
|
return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
|
|
|
|
if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
|
|
bool absolute;
|
|
|
|
absolute = path_is_absolute(path);
|
|
|
|
if (!absolute && (flag & PATH_CHECK_ABSOLUTE))
|
|
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
|
|
"%s= path is not absolute%s: %s",
|
|
lvalue, fatal ? "" : ", ignoring", path);
|
|
|
|
if (absolute && (flag & PATH_CHECK_RELATIVE))
|
|
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
|
|
"%s= path is absolute%s: %s",
|
|
lvalue, fatal ? "" : ", ignoring", path);
|
|
}
|
|
|
|
path_simplify(path);
|
|
|
|
if (!path_is_valid(path))
|
|
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
|
|
"%s= path has invalid length (%zu bytes)%s.",
|
|
lvalue, strlen(path), fatal ? "" : ", ignoring");
|
|
|
|
if (!path_is_normalized(path))
|
|
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
|
|
"%s= path is not normalized%s: %s",
|
|
lvalue, fatal ? "" : ", ignoring", path);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int parse_af_token(
|
|
const char *token,
|
|
int *family,
|
|
int *ip_protocol,
|
|
uint16_t *nr_ports,
|
|
uint16_t *port_min) {
|
|
|
|
int af;
|
|
|
|
assert(token);
|
|
assert(family);
|
|
|
|
af = af_from_ipv4_ipv6(token);
|
|
if (af == AF_UNSPEC)
|
|
return -EINVAL;
|
|
|
|
*family = af;
|
|
return 0;
|
|
}
|
|
|
|
static int parse_ip_protocol_token(
|
|
const char *token,
|
|
int *family,
|
|
int *ip_protocol,
|
|
uint16_t *nr_ports,
|
|
uint16_t *port_min) {
|
|
|
|
int proto;
|
|
|
|
assert(token);
|
|
assert(ip_protocol);
|
|
|
|
proto = ip_protocol_from_tcp_udp(token);
|
|
if (proto < 0)
|
|
return -EINVAL;
|
|
|
|
*ip_protocol = proto;
|
|
return 0;
|
|
}
|
|
|
|
static int parse_ip_ports_token(
|
|
const char *token,
|
|
int *family,
|
|
int *ip_protocol,
|
|
uint16_t *nr_ports,
|
|
uint16_t *port_min) {
|
|
|
|
assert(token);
|
|
assert(nr_ports);
|
|
assert(port_min);
|
|
|
|
if (streq(token, "any"))
|
|
*nr_ports = *port_min = 0;
|
|
else {
|
|
uint16_t mn = 0, mx = 0;
|
|
int r = parse_ip_port_range(token, &mn, &mx);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
*nr_ports = mx - mn + 1;
|
|
*port_min = mn;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
typedef int (*parse_token_f)(
|
|
const char *,
|
|
int *,
|
|
int *,
|
|
uint16_t *,
|
|
uint16_t *);
|
|
|
|
int parse_socket_bind_item(
|
|
const char *str,
|
|
int *address_family,
|
|
int *ip_protocol,
|
|
uint16_t *nr_ports,
|
|
uint16_t *port_min) {
|
|
|
|
/* Order of token parsers is important. */
|
|
const parse_token_f parsers[] = {
|
|
&parse_af_token,
|
|
&parse_ip_protocol_token,
|
|
&parse_ip_ports_token,
|
|
};
|
|
parse_token_f const *parser_ptr = parsers;
|
|
int af = AF_UNSPEC, proto = 0, r;
|
|
uint16_t nr = 0, mn = 0;
|
|
const char *p = ASSERT_PTR(str);
|
|
|
|
assert(address_family);
|
|
assert(ip_protocol);
|
|
assert(nr_ports);
|
|
assert(port_min);
|
|
|
|
if (isempty(p))
|
|
return -EINVAL;
|
|
|
|
for (;;) {
|
|
_cleanup_free_ char *token = NULL;
|
|
|
|
r = extract_first_word(&p, &token, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
|
if (r == 0)
|
|
break;
|
|
if (r < 0)
|
|
return r;
|
|
|
|
if (isempty(token))
|
|
return -EINVAL;
|
|
|
|
while (parser_ptr != parsers + ELEMENTSOF(parsers)) {
|
|
r = (*parser_ptr)(token, &af, &proto, &nr, &mn);
|
|
if (r == -ENOMEM)
|
|
return r;
|
|
|
|
++parser_ptr;
|
|
/* Continue to next token if parsing succeeded,
|
|
* otherwise apply next parser to the same token.
|
|
*/
|
|
if (r >= 0)
|
|
break;
|
|
}
|
|
if (parser_ptr == parsers + ELEMENTSOF(parsers))
|
|
break;
|
|
}
|
|
|
|
/* Failed to parse a token. */
|
|
if (r < 0)
|
|
return r;
|
|
|
|
/* Parsers applied successfully, but end of the string not reached. */
|
|
if (p)
|
|
return -EINVAL;
|
|
|
|
*address_family = af;
|
|
*ip_protocol = proto;
|
|
*nr_ports = nr;
|
|
*port_min = mn;
|
|
return 0;
|
|
}
|
|
|
|
int config_parse_path_or_ignore(
|
|
const char *unit,
|
|
const char *filename,
|
|
unsigned line,
|
|
const char *section,
|
|
unsigned section_line,
|
|
const char *lvalue,
|
|
int ltype,
|
|
const char *rvalue,
|
|
void *data,
|
|
void *userdata) {
|
|
|
|
_cleanup_free_ char *n = NULL;
|
|
bool fatal = ltype;
|
|
char **s = ASSERT_PTR(data);
|
|
int r;
|
|
|
|
assert(filename);
|
|
assert(lvalue);
|
|
assert(rvalue);
|
|
|
|
if (isempty(rvalue))
|
|
goto finalize;
|
|
|
|
n = strdup(rvalue);
|
|
if (!n)
|
|
return log_oom();
|
|
|
|
if (streq(n, "-"))
|
|
goto finalize;
|
|
|
|
r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue);
|
|
if (r < 0)
|
|
return fatal ? -ENOEXEC : 0;
|
|
|
|
finalize:
|
|
return free_and_replace(*s, n);
|
|
}
|