mirror of https://gitee.com/openkylin/openssh.git
sshd-socket-generator
Gbp-Pq: Name sshd-socket-generator.patch
This commit is contained in:
parent
07d2d6338d
commit
c8ee260ebc
19
Makefile.in
19
Makefile.in
|
@ -17,6 +17,7 @@ srcdir=@srcdir@
|
|||
top_srcdir=@top_srcdir@
|
||||
abs_top_srcdir=@abs_top_srcdir@
|
||||
abs_top_builddir=@abs_top_builddir@
|
||||
systemd_system_generator_dir=$(shell pkg-config --variable=systemd_system_generator_dir systemd)
|
||||
|
||||
DESTDIR=
|
||||
VPATH=@srcdir@
|
||||
|
@ -69,7 +70,7 @@ MKDIR_P=@MKDIR_P@
|
|||
|
||||
.SUFFIXES: .lo
|
||||
|
||||
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT)
|
||||
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) sshd-socket-generator$(EXEEXT)
|
||||
|
||||
XMSS_OBJS=\
|
||||
ssh-xmss.o \
|
||||
|
@ -134,6 +135,16 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
|
|||
sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
|
||||
sandbox-solaris.o uidswap.o $(SKOBJS)
|
||||
|
||||
SSHD_SOCKET_GEN_OBJS=sshd-socket-generator.o \
|
||||
platform.o servconf.o groupaccess.o audit.o audit-linux.o \
|
||||
auth2.o auth2-none.o auth2-gss.o \
|
||||
auth2-passwd.o auth2-kbdint.o auth2-hostbased.o \
|
||||
auth-options.o uidswap.o auth2-pubkey.o auth.o \
|
||||
auth2-pubkeyfile.o auth-rhosts.o auth-passwd.o \
|
||||
gss-serv.o auth2-chall.o auth-pam.o gss-serv-krb5.o \
|
||||
loginrec.o auth-krb5.o auth-shadow.o \
|
||||
monitor.o monitor_wrap.o
|
||||
|
||||
SFTP_CLIENT_OBJS=sftp-common.o sftp-client.o sftp-glob.o
|
||||
|
||||
SCP_OBJS= scp.o progressmeter.o $(SFTP_CLIENT_OBJS)
|
||||
|
@ -210,6 +221,9 @@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
|
|||
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
|
||||
$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS)
|
||||
|
||||
sshd-socket-generator$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHD_SOCKET_GEN_OBJS)
|
||||
$(LD) -o $@ $(SSHD_SOCKET_GEN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS)
|
||||
|
||||
scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS)
|
||||
$(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||
|
||||
|
@ -392,6 +406,7 @@ install-files:
|
|||
$(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)5
|
||||
$(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)8
|
||||
$(MKDIR_P) $(DESTDIR)$(libexecdir)
|
||||
$(MKDIR_P) $(DESTDIR)$(systemd_system_generator_dir)
|
||||
$(MKDIR_P) -m 0755 $(DESTDIR)$(PRIVSEP_PATH)
|
||||
$(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT)
|
||||
$(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT)
|
||||
|
@ -421,6 +436,7 @@ install-files:
|
|||
$(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
|
||||
$(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
|
||||
$(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8
|
||||
$(INSTALL) -m 0755 $(STRIP_OPT) sshd-socket-generator$(EXEEXT) $(DESTDIR)$(systemd_system_generator_dir)/sshd-socket-generator$(EXEEXT)
|
||||
|
||||
install-sysconf:
|
||||
$(MKDIR_P) $(DESTDIR)$(sysconfdir)
|
||||
|
@ -478,6 +494,7 @@ uninstall:
|
|||
-rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(systemd_system_generator_dir)/sshd-socket-generator$(EXEEXT)
|
||||
-rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
|
||||
-rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
#include <errno.h>
|
||||
#include <linux/limits.h>
|
||||
#include <netdb.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "hostfile.h" /* Needs to be included before auth.h */
|
||||
#include "auth.h"
|
||||
#include "kex.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "monitor.h"
|
||||
#include "ssh-gss.h" /* Needs to be included before monitor_wrap.h */
|
||||
#include "monitor_wrap.h"
|
||||
#include "pathnames.h"
|
||||
#include "servconf.h"
|
||||
#include "sshbuf.h"
|
||||
|
||||
#define MAX_LISTEN_STREAMS (16)
|
||||
#define MAX_LISTEN_STREAM_LEN (NI_MAXHOST + NI_MAXSERV + sizeof("ListenAddress=[:]") + 1)
|
||||
typedef char listen_stream_set[MAX_LISTEN_STREAMS][MAX_LISTEN_STREAM_LEN];
|
||||
|
||||
/* Global variables required for sshd config parsing. */
|
||||
ServerOptions options = {};
|
||||
struct sshbuf *cfg = NULL;
|
||||
struct include_list includes = TAILQ_HEAD_INITIALIZER(includes);
|
||||
|
||||
/* Other global variables that are required for this to build, because of their
|
||||
* use throughout the codebase. We do NOT use these variables for the
|
||||
* generator. */
|
||||
Authctxt *the_authctxt = NULL;
|
||||
int privsep_is_preauth = 1;
|
||||
int use_privsep = -1;
|
||||
struct monitor *pmonitor = NULL;
|
||||
struct ssh *the_active_state = NULL;
|
||||
struct sshauthopt *auth_opts = NULL;
|
||||
struct sshbuf *loginmsg = NULL;
|
||||
|
||||
static int listen_stream_set_append(listen_stream_set set, const char *listen_stream) {
|
||||
size_t n;
|
||||
|
||||
if (!set)
|
||||
return -EINVAL;
|
||||
|
||||
n = strnlen(listen_stream, MAX_LISTEN_STREAM_LEN);
|
||||
if (n == MAX_LISTEN_STREAM_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
for (int i = 0; i < MAX_LISTEN_STREAMS; i++) {
|
||||
if (strcmp(set[i], listen_stream) == 0)
|
||||
return 0;
|
||||
|
||||
if (strnlen(set[i], MAX_LISTEN_STREAM_LEN) > 0)
|
||||
continue;
|
||||
|
||||
memcpy(set[i], listen_stream, n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
static int listen_stream_set_len(listen_stream_set set) {
|
||||
int r = 0;
|
||||
|
||||
if (!set)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < MAX_LISTEN_STREAMS; i++) {
|
||||
if (strnlen(set[i], MAX_LISTEN_STREAM_LEN) > 0)
|
||||
r++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *path_append(const char *base, const char *append) {
|
||||
bool add_slash;
|
||||
size_t n = 0, len_base, len_append;
|
||||
char *path = NULL;
|
||||
|
||||
len_base = strnlen(base, PATH_MAX);
|
||||
len_append = strnlen(append, PATH_MAX);
|
||||
add_slash = base[len_base - 1] != '/';
|
||||
|
||||
path = calloc(len_base + len_append + (add_slash ? 2 : 1), sizeof(char));
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
memcpy(path, base, len_base);
|
||||
n += len_base;
|
||||
|
||||
if (add_slash)
|
||||
path[n++] = '/';
|
||||
|
||||
memcpy(path + n, append, len_append);
|
||||
n += len_append;
|
||||
path[n] = '\0';
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static int fflush_and_check(FILE *f) {
|
||||
errno = 0;
|
||||
fflush(f);
|
||||
|
||||
if (ferror(f))
|
||||
return errno > 0 ? -errno : -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_systemd_socket_file(const char *destdir) {
|
||||
listen_stream_set listen_streams = {};
|
||||
int num_listen_streams;
|
||||
char *conf = NULL, *overridedir = NULL;
|
||||
FILE *f = NULL;
|
||||
int r;
|
||||
|
||||
overridedir = path_append(destdir, "ssh.socket.d");
|
||||
if (!overridedir) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mkdir(overridedir, 0755) < 0 && errno != EEXIST) {
|
||||
r = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
conf = path_append(overridedir, "addresses.conf");
|
||||
if (!conf) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
f = fopen(conf, "we");
|
||||
if (!f) {
|
||||
r = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"# Automatically generated by sshd-socket-generator\n"
|
||||
"\n[Socket]\n"
|
||||
"ListenStream=\n");
|
||||
|
||||
for (u_int i = 0; i < options.num_listen_addrs; i++) {
|
||||
for (struct addrinfo *ai = options.listen_addrs[i].addrs; ai; ai = ai->ai_next) {
|
||||
char addr[NI_MAXHOST] = {}, port[NI_MAXSERV] = {},
|
||||
listen_stream[MAX_LISTEN_STREAM_LEN] = {};
|
||||
|
||||
r = getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
addr, sizeof(addr),
|
||||
port, sizeof(port),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV);
|
||||
if (r != 0) {
|
||||
fprintf(stderr, "%s\n", gai_strerror(r));
|
||||
r = r == EAI_SYSTEM ? -errno : -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(addr, "0.0.0.0") == 0 || strcmp(addr, "::") == 0) {
|
||||
/* If ListenAddress is 0.0.0.0 or ::, only
|
||||
* write the port in ListenStream=. */
|
||||
snprintf(listen_stream,
|
||||
MAX_LISTEN_STREAM_LEN,
|
||||
"ListenStream=%s",
|
||||
port);
|
||||
} else
|
||||
snprintf(listen_stream,
|
||||
MAX_LISTEN_STREAM_LEN,
|
||||
"ListenStream=%s%s%s:%s",
|
||||
ai->ai_family == AF_INET6 ? "[" : "",
|
||||
addr,
|
||||
ai->ai_family == AF_INET6 ? "]" : "",
|
||||
port);
|
||||
|
||||
r = listen_stream_set_append(listen_streams, listen_stream);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
num_listen_streams = listen_stream_set_len(listen_streams);
|
||||
|
||||
if (num_listen_streams <= 0) {
|
||||
/* We didn't generate anything useful, so clean up and leave
|
||||
* ssh.socket as-is. */
|
||||
r = -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (num_listen_streams == 1 && strcmp(listen_streams[0], "ListenStream=22") == 0) {
|
||||
/* This is the default already specified in ssh.socket. No need
|
||||
* to write the override. */
|
||||
r = -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_listen_streams; i++)
|
||||
fprintf(f, "%s\n", listen_streams[i]);
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
||||
if (r < 0) {
|
||||
(void) remove(conf);
|
||||
(void) remove(overridedir);
|
||||
}
|
||||
|
||||
free(overridedir);
|
||||
free(conf);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int parse_sshd_config_options() {
|
||||
struct connection_info *connection_info;
|
||||
|
||||
cfg = sshbuf_new();
|
||||
if (!cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
initialize_server_options(&options);
|
||||
load_server_config(_PATH_SERVER_CONFIG_FILE, cfg);
|
||||
parse_server_config(&options, _PATH_SERVER_CONFIG_FILE, cfg, &includes, NULL, 0);
|
||||
fill_default_server_options(&options);
|
||||
|
||||
connection_info = get_connection_info(NULL, 0, 0);
|
||||
connection_info->test = 1;
|
||||
|
||||
parse_server_match_config(&options, &includes, connection_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *destdir = NULL;
|
||||
int r;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Expected at least one argument.\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
destdir = argv[1];
|
||||
|
||||
r = parse_sshd_config_options();
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Faild to parse sshd config: %s\n", strerror(-r));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (options.num_listen_addrs <= 0) {
|
||||
/* No listen addresses configured? Don't generate anything. */
|
||||
fprintf(stderr, "No listen addresses configured. Will not generate anything.\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
r = write_systemd_socket_file(destdir);
|
||||
if (r == -ENODATA) {
|
||||
fprintf(stderr, "No custom listen addresses configured. Will not generated anything.\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to generate ssh.socket: %s\n", strerror(-r));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue