7
0
forked from pool/util-linux

Accepting request 1303156 from Base:System

- Implement escape code for printing of ssh host keys in agetty
  issue file (util-linux-agetty-ssh-host-keys.patch.
- Include fixes from
  https://github.com/util-linux/util-linux/pull/3649 (jsc#PED-8734,
  util-linux-lib-netlink.patch, util-linux-agetty-netlink.patch).

OBS-URL: https://build.opensuse.org/request/show/1303156
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/util-linux?expand=0&rev=301
This commit is contained in:
2025-09-10 15:30:10 +00:00
committed by Git OBS Bridge
5 changed files with 194 additions and 70 deletions

View File

@@ -1,8 +1,7 @@
From 1ddc84875c150ca7c142adba9bfcd4bf4323a3c4 Mon Sep 17 00:00:00 2001
From bf7c46ef9158f3baae6b637ebb73a24d8460d394 Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <sbrabec@suse.cz>
Date: Wed, 9 Jul 2025 14:35:28 +0200
Subject: [PATCH 2/2] agetty: Implement netlink based IP processing
References: https://github.com/util-linux/util-linux/pull/3649
The current \4 and \6 issue file escapes implementation is inferior. It
uses get getifaddrs() to get a list of IP addresses. This function does not
@@ -48,8 +47,8 @@ so bad, as \a automatically skips interfaces without reliable addresses
Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
---
term-utils/agetty.8.adoc | 6 +
term-utils/agetty.c | 414 ++++++++++++++++++++++-----------------
2 files changed, 244 insertions(+), 176 deletions(-)
term-utils/agetty.c | 417 ++++++++++++++++++++++-----------------
2 files changed, 246 insertions(+), 177 deletions(-)
diff --git a/term-utils/agetty.8.adoc b/term-utils/agetty.8.adoc
index a33f12a3f..6670498f5 100644
@@ -69,7 +68,7 @@ index a33f12a3f..6670498f5 100644
Insert the baudrate of the current line.
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index f65e511ca..1f5d937e4 100644
index 5e564c4f0..c37417e1e 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -32,10 +32,7 @@
@@ -109,7 +108,15 @@ index f65e511ca..1f5d937e4 100644
char *mem_old;
#endif
unsigned int do_tcsetattr : 1,
@@ -1603,81 +1603,7 @@ done:
@@ -364,6 +364,7 @@ int main(int argc, char **argv)
};
struct issue issue = {
.mem = NULL,
+ .nl.fd = -1
};
char *login_argv[LOGIN_ARGV_MAX + 1];
int login_argc = 0;
@@ -1603,81 +1604,7 @@ done:
}
#ifdef AGETTY_RELOAD
@@ -192,7 +199,7 @@ index f65e511ca..1f5d937e4 100644
{
char buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
fd_set rfds;
@@ -1711,9 +1637,9 @@ static int wait_for_term_input(int fd)
@@ -1711,9 +1638,9 @@ static int wait_for_term_input(int fd)
FD_SET(inotify_fd, &rfds);
nfds = max(nfds, inotify_fd);
}
@@ -205,7 +212,7 @@ index f65e511ca..1f5d937e4 100644
}
/* If waiting fails, just fall through, presumably reading input will fail */
@@ -1725,9 +1651,10 @@ static int wait_for_term_input(int fd)
@@ -1725,9 +1652,10 @@ static int wait_for_term_input(int fd)
}
@@ -219,7 +226,7 @@ index f65e511ca..1f5d937e4 100644
/* Just drain the inotify buffer */
} else if (inotify_fd >= 0 && FD_ISSET(inotify_fd, &rfds)) {
@@ -1937,11 +1864,44 @@ static void eval_issue_file(struct issue *ie,
@@ -1937,11 +1865,44 @@ static void eval_issue_file(struct issue *ie,
struct options *op,
struct termios *tp)
{
@@ -241,7 +248,7 @@ index f65e511ca..1f5d937e4 100644
+ netlink_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
+
+ /* Already initialized? */
+ if (ie->nl.fd)
+ if (ie->nl.fd >= 0)
+ goto skip;
+ /* Prepare netlink. */
+ ul_nl_init(&(ie->nl));
@@ -261,13 +268,13 @@ index f65e511ca..1f5d937e4 100644
+ /* In case of any error, the addrq list is just empty, and we can use
+ * the code without any error checking. */
+ ul_nl_close(&(ie->nl));
+ ie->nl.fd = 0;
+ ie->nl.fd = -1;
+skip:
+#endif
/*
* The custom issue file or directory list specified by:
* agetty --issue-file <path[:path]...>
@@ -1986,11 +1946,6 @@ static void eval_issue_file(struct issue *ie,
@@ -1986,11 +1947,6 @@ static void eval_issue_file(struct issue *ie,
issuedir_read(ie, _PATH_SYSCONFSTATICDIR "/" _PATH_ISSUE_DIRNAME, op, tp);
done:
@@ -279,7 +286,16 @@ index f65e511ca..1f5d937e4 100644
if (ie->output) {
fclose(ie->output);
ie->output = NULL;
@@ -2032,13 +1987,19 @@ again:
@@ -2002,7 +1958,7 @@ done:
*/
static void show_issue(struct options *op)
{
- struct issue ie = { .output = NULL };
+ struct issue ie = { .output = NULL, .nl.fd = -1 };
struct termios tp;
memset(&tp, 0, sizeof(struct termios));
@@ -2032,13 +1988,19 @@ again:
puts(_("[press ENTER to login]"));
#ifdef AGETTY_RELOAD
/* reload issue */
@@ -293,15 +309,15 @@ index f65e511ca..1f5d937e4 100644
- goto again;
+ {
+ /* TODO: Close to set netlink_groups again using pass 1 */
+ /* if (ie->nl.fd) ul_nl_close(&(ie->nl));
+ * ie->nl.fd = NULL; */
+ /* if (ie->nl.fd >= 0) ul_nl_close(&(ie->nl));
+ * ie->nl.fd = -1; */
+
+ goto again;
+ }
}
}
#endif
@@ -2168,7 +2129,7 @@ static char *get_logname(struct issue *ie, struct options *op, struct termios *t
@@ -2168,7 +2130,7 @@ static char *get_logname(struct issue *ie, struct options *op, struct termios *t
no_reload:
#ifdef AGETTY_RELOAD
@@ -310,16 +326,16 @@ index f65e511ca..1f5d937e4 100644
/* refresh prompt -- discard input data, clear terminal
* and call do_prompt() again
*/
@@ -2177,6 +2138,8 @@ static char *get_logname(struct issue *ie, struct options *op, struct termios *t
@@ -2177,6 +2139,8 @@ static char *get_logname(struct issue *ie, struct options *op, struct termios *t
eval_issue_file(ie, op, tp);
if (!issue_is_changed(ie))
goto no_reload;
+ /* if (ie->nl.fd) ul_nl_close(&(ie->nl));
+ * ie->nl.fd = NULL; */
+ /* if (ie->nl.fd >= 0) ul_nl_close(&(ie->nl));
+ * ie->nl.fd = -1; */
tcflush(STDIN_FILENO, TCIFLUSH);
if ((op->flags & F_VCONSOLE)
&& (op->flags & F_NOCLEAR) == 0)
@@ -2576,92 +2539,170 @@ static void log_warn(const char *fmt, ...)
@@ -2576,92 +2540,170 @@ static void log_warn(const char *fmt, ...)
va_end(ap);
}
@@ -560,7 +576,7 @@ index f65e511ca..1f5d937e4 100644
}
/*
@@ -2860,26 +2901,47 @@ static void output_special_char(struct issue *ie,
@@ -2860,26 +2902,47 @@ static void output_special_char(struct issue *ie,
case '4':
case '6':
{

View File

@@ -0,0 +1,111 @@
From 275a215e3ee02d8240d22b2bc61abcdd6b24c35f Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <sbrabec@suse.cz>
Date: Fri, 8 Aug 2025 02:39:28 +0200
Subject: [PATCH] agetty: Implement \k: print ssh host keys
Implement new keyword \k that will print all ssh host keys.
Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
---
term-utils/agetty.8.adoc | 3 +++
term-utils/agetty.c | 56 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+)
diff --git a/term-utils/agetty.8.adoc b/term-utils/agetty.8.adoc
index 6670498f5..f84ec2e1e 100644
--- a/term-utils/agetty.8.adoc
+++ b/term-utils/agetty.8.adoc
@@ -304,6 +304,9 @@ Insert the string "1 user" or "<n> users" where <n> is the number of current use
v::
Insert the version of the OS, that is, the build-date and such.
+k::
+Print host ssh keys.
+
An example. On my system, the following _/etc/issue_ file:
....
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index c37417e1e..d53882ef7 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -33,6 +33,7 @@
#include <grp.h>
#include <pwd.h>
#include <netdb.h>
+#include <glob.h>
#include <sys/utsname.h>
#include "strutils.h"
@@ -2706,6 +2707,58 @@ static void dump_iface_all(struct issue *ie,
fputs("\n", ie->output);
}
+#define SSH_KEYGEN_BUFFER_SIZE 512
+void print_ssh_keys(FILE *fd) {
+ glob_t glob_result;
+ int rc;
+
+ rc = glob("/etc/ssh/ssh_host_*_key.pub", 0, NULL, &glob_result);
+ if (rc != 0) {
+ if (rc == GLOB_NOMATCH) {
+ fprintf(fd, _("No SSH host keys found.\n"));
+ }
+ globfree(&glob_result);
+ return;
+ }
+
+ for (size_t i = 0; i < glob_result.gl_pathc; i++) {
+ int pipefd[2];
+ pid_t pid;
+
+ if (pipe(pipefd) == -1) {
+ continue;
+ }
+ pid = fork();
+ if (pid == -1) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ continue;
+ }
+ if (pid == 0) {
+ char *argv[] = {"ssh-keygen", "-l", "-f", glob_result.gl_pathv[i], NULL};
+
+ close(pipefd[0]);
+ dup2(pipefd[1], STDOUT_FILENO);
+ close(pipefd[1]);
+ execvp("ssh-keygen", argv);
+ return;
+ } else {
+ char buffer[SSH_KEYGEN_BUFFER_SIZE];
+
+ close(pipefd[1]);
+ wait(NULL);
+ if (fgets(buffer, sizeof(buffer), fdopen(pipefd[0], "r")) != NULL) {
+ char field2[SSH_KEYGEN_BUFFER_SIZE], field4[SSH_KEYGEN_BUFFER_SIZE];
+ if (sscanf(buffer, "%*s %s %*s %s", field2, field4) == 2) {
+ fprintf(fd, _("SSH host key: %s %s\n"), field2, field4);
+ }
+ }
+ close(pipefd[0]);
+ }
+ }
+ globfree(&glob_result);
+ return;
+}
/*
* parses \x{argument}, if not argument specified then returns NULL, the @fd
* has to point to one char after the sequence (it means '{').
@@ -2944,6 +2997,9 @@ static void output_special_char(struct issue *ie,
}
break;
#endif
+ case 'k':
+ print_ssh_keys(ie->output);
+ break;
default:
putc(c, ie->output);
break;
--
2.48.1

View File

@@ -1,8 +1,7 @@
From 7d11ab55ce140cb03ffebb55856c0a766853d83e Mon Sep 17 00:00:00 2001
From 02b917ba6fa43908a39f15c9496de04910044c0e Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <sbrabec@suse.cz>
Date: Wed, 9 Jul 2025 14:29:10 +0200
Subject: [PATCH 1/2] New netlink library
References: https://github.com/util-linux/util-linux/pull/3649
To support netlink and IP address processing, two new library files were
added:
@@ -18,13 +17,13 @@ etc.
Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
---
include/Makemodule.am | 2 +
include/netaddrq.h | 124 +++++++
include/netaddrq.h | 124 ++++++++
include/netlink.h | 171 ++++++++++
lib/Makemodule.am | 11 +
lib/meson.build | 2 +
lib/netaddrq.c | 729 ++++++++++++++++++++++++++++++++++++++++++
lib/netaddrq.c | 716 ++++++++++++++++++++++++++++++++++++++++++
lib/netlink.c | 465 +++++++++++++++++++++++++++
7 files changed, 1504 insertions(+)
7 files changed, 1491 insertions(+)
create mode 100644 include/netaddrq.h
create mode 100644 include/netlink.h
create mode 100644 lib/netaddrq.c
@@ -406,10 +405,10 @@ index 25febbc19..8734108a3 100644
randutils.c
diff --git a/lib/netaddrq.c b/lib/netaddrq.c
new file mode 100644
index 000000000..11730cf07
index 000000000..67a43cb85
--- /dev/null
+++ b/lib/netaddrq.c
@@ -0,0 +1,729 @@
@@ -0,0 +1,716 @@
+/*
+ * Netlink address quality rating list builder
+ *
@@ -503,7 +502,7 @@ index 000000000..11730cf07
+
+#define DBG_CASE(x) case x: str = #x; break
+#define DBG_CASE_DEF8(x) default: snprintf(strx+2, 3, "%02hhx", x); str = strx; break
+static char *ip_rating(enum ul_netaddrq_ip_rating q)
+static char *ip_rating_as_string(enum ul_netaddrq_ip_rating q)
+{
+ char *str;
+ static char strx[5] = "0x";
@@ -565,11 +564,7 @@ index 000000000..11730cf07
+ DBG(LIST, ul_debugobj(addrq,
+ "new ifa_index in addrq"));
+ if (!(ifaceq = malloc(sizeof(struct ul_netaddrq_iface))))
+ {
+ DBG(LIST, ul_debugobj(addrq,
+ "malloc() 1 failed"));
+ return -1;
+ }
+ return -ENOMEM;
+ INIT_LIST_HEAD(&(ifaceq->ip_quality_list_4));
+ INIT_LIST_HEAD(&(ifaceq->ip_quality_list_6));
+ ifaceq->ifa_index = nl->addr.ifa_index;
@@ -602,7 +597,7 @@ index 000000000..11730cf07
+ list_for_each(li, ipq_list) {
+ ipq = list_entry(li, struct ul_netaddrq_ip, entry);
+ if (ipq->addr->address_len == nl->addr.address_len)
+ if (memcmp(ipq->addr->address, nl->addr.address,
+ if (!memcmp(ipq->addr->address, nl->addr.address,
+ nl->addr.address_len))
+ break;
+ }
@@ -618,17 +613,13 @@ index 000000000..11730cf07
+
+ addr = ul_nl_addr_dup(&(nl->addr));
+ if (!addr) {
+ DBG(LIST, ul_debugobj(addrq,
+ "ul_nl_addr_dup() failed"));
+ rc = -1;
+ rc = -ENOMEM;
+ goto error;
+ }
+ if (ipq == NULL) {
+ if (!(ipq = malloc(sizeof(struct ul_netaddrq_ip))))
+ {
+ DBG(LIST, ul_debugobj(addrq,
+ "malloc() 3 failed"));
+ rc = -1;
+ rc = -ENOMEM;
+ ul_nl_addr_free(addr);
+ goto error;
+ }
@@ -645,7 +636,7 @@ index 000000000..11730cf07
+ DBG(ADDRQ,
+ ul_debugobj(addrq, "%s rating: %s",
+ ul_nl_addr_ntop_address(&(nl->addr)),
+ ip_rating(ipq->quality)));
+ ip_rating_as_string(ipq->quality)));
+ } else {
+ /* UL_NL_RTM_DEL */
+ if (ipq == NULL)
@@ -689,18 +680,14 @@ index 000000000..11730cf07
+ struct ul_netaddrq_data *addrq;
+
+ netaddrq_init_debug();
+ if (!(nl->data_addr = malloc(sizeof(struct ul_netaddrq_data))))
+ return -1;
+ if (!(nl->data_addr = calloc(1, sizeof(struct ul_netaddrq_data))))
+ return -ENOMEM;
+ nl->callback_addr = callback_addrq;
+ addrq = UL_NETADDRQ_DATA(nl);
+ addrq->callback_pre = callback_pre;
+ addrq->callback_post = callback_post;
+ addrq->callback_data = data;
+ addrq->nifaces = 0;
+ addrq->overflow = false;
+ INIT_LIST_HEAD(&(addrq->ifaces));
+ addrq->ifaces_change_4 = false;
+ addrq->ifaces_change_6 = false;
+ DBG(LIST, ul_debugobj(addrq, "callback initialized"));
+ return 0;
+}
@@ -725,7 +712,7 @@ index 000000000..11730cf07
+ DBG(BEST,
+ ul_debugobj((*best), "%s -> best[%s]",
+ ul_nl_addr_ntop_address(ipq->addr),
+ ip_rating(ipq->quality)));
+ ip_rating_as_string(ipq->quality)));
+ (*best)[ipq->quality] = ipq;
+ }
+
@@ -733,7 +720,7 @@ index 000000000..11730cf07
+ {
+ threshold = ipq->quality;
+ DBG(BEST,
+ ul_debug("threshold %s", ip_rating(threshold)));
+ ul_debug("threshold %s", ip_rating_as_string(threshold)));
+
+ }
+ }
@@ -793,8 +780,7 @@ index 000000000..11730cf07
+ *threshold = ul_netaddrq_bestaddr(nl, best_ifaceq, &best, ifa_family);
+ if (best[*threshold])
+ return ul_nl_addr_ntop_address(best[*threshold]->addr);
+ else
+ return NULL;
+ return NULL;
+}
+
+struct ul_netaddrq_iface *ul_netaddrq_iface_by_name(const struct ul_nl_data *nl,
@@ -1141,7 +1127,7 @@ index 000000000..11730cf07
+#endif /* TEST_PROGRAM_NETADDRQ */
diff --git a/lib/netlink.c b/lib/netlink.c
new file mode 100644
index 000000000..c57be4ce0
index 000000000..fbe04dd4c
--- /dev/null
+++ b/lib/netlink.c
@@ -0,0 +1,465 @@
@@ -1373,7 +1359,7 @@ index 000000000..c57be4ce0
+
+int ul_nl_process(struct ul_nl_data *nl, bool async, bool loop)
+{
+ char buf[4096];
+ char buf[BUFSIZ];
+ struct sockaddr_nl snl;
+ struct nlmsghdr *nh;
+ int rc;
@@ -1476,20 +1462,21 @@ index 000000000..c57be4ce0
+
+struct ul_nl_addr *ul_nl_addr_dup (struct ul_nl_addr *addr) {
+ struct ul_nl_addr *newaddr;
+ newaddr = malloc(sizeof(struct ul_nl_addr));
+ if (!newaddr) goto error1;
+ newaddr = calloc(1, sizeof(struct ul_nl_addr));
+ if (!newaddr)
+ goto error;
+ memcpy(newaddr, addr, sizeof(struct ul_nl_addr));
+ if (addr->ifa_address_len) {
+ newaddr->ifa_address = malloc(addr->ifa_address_len);
+ if (!newaddr->ifa_address)
+ goto error2;
+ goto error;
+ memcpy(newaddr->ifa_address, addr->ifa_address,
+ addr->ifa_address_len);
+ }
+ if (addr->ifa_local_len) {
+ newaddr->ifa_local = malloc(addr->ifa_local_len);
+ if (!newaddr->ifa_local)
+ goto error3;
+ goto error;
+ memcpy(newaddr->ifa_local, addr->ifa_local,
+ addr->ifa_local_len);
+ }
@@ -1497,22 +1484,21 @@ index 000000000..c57be4ce0
+ newaddr->address = newaddr->ifa_local;
+ else
+ newaddr->address = newaddr->ifa_address;
+ if ((newaddr->ifname = strdup(addr->ifname)))
+ return newaddr;
+ free(newaddr->ifa_local);
+error3:
+ free(newaddr->ifa_address);
+error2:
+ free(newaddr);
+error1:
+ if (!(newaddr->ifname = strdup(addr->ifname)))
+ goto error;
+ return newaddr;
+error:
+ ul_nl_addr_free(newaddr);
+ return NULL;
+}
+
+void ul_nl_addr_free (struct ul_nl_addr *addr) {
+ free(addr->ifa_address);
+ free(addr->ifa_local);
+ free(addr->ifname);
+ free(addr);
+ if (addr) {
+ free(addr->ifa_address);
+ free(addr->ifa_local);
+ free(addr->ifname);
+ free(addr);
+ }
+}
+
+const char *ul_nl_addr_ntop (const struct ul_nl_addr *addr, int addrid) {

View File

@@ -1,3 +1,12 @@
-------------------------------------------------------------------
Mon Aug 11 23:54:47 UTC 2025 - Stanislav Brabec <sbrabec@suse.com>
- Implement escape code for printing of ssh host keys in agetty
issue file (util-linux-agetty-ssh-host-keys.patch.
- Include fixes from
https://github.com/util-linux/util-linux/pull/3649 (jsc#PED-8734,
util-linux-lib-netlink.patch, util-linux-agetty-netlink.patch).
-------------------------------------------------------------------
Thu Jul 24 10:35:23 UTC 2025 - Dr. Werner Fink <werner@suse.de>

View File

@@ -114,6 +114,8 @@ Patch5: static_lib.patch
Patch6: util-linux-lib-netlink.patch
# PATCH-FEATURE-UPSTREAM util-linux-agetty-netlink.patch boo1139983 jsc#PED-8734 sbrabec@suse.com -- Implement netlink based IP address detection and issue reload.
Patch7: util-linux-agetty-netlink.patch
# PATCH-FEATURE-OPENSUSE util-linux-agetty-ssh-host-keys.patch sbrabec@suse.com -- Implement escape code for printing of ssh host keys in agetty issue file.
Patch8: util-linux-agetty-ssh-host-keys.patch
BuildRequires: audit-devel
BuildRequires: bc
BuildRequires: binutils-devel