From 3a17ecb3e5ec6f15d8200456e3bfc23df74ec66e Mon Sep 17 00:00:00 2001 From: h7x4 Date: Sun, 8 Feb 2026 16:07:33 +0900 Subject: [PATCH] WIP --- configure.ac | 15 +++++++++++++++ kadmin/kadm_conn.c | 7 +++++++ kdc/Makefile.am | 4 ++-- kdc/connect.c | 9 +++++++++ kdc/hpropd.c | 8 ++++++++ kpasswd/kpasswdd.c | 8 ++++++++ lib/roken/Makefile.am | 4 ++-- lib/roken/detach.c | 29 +++++++++++++++++++++++++++++ lib/roken/roken.h.in | 1 + nix/heimdal/default.nix | 11 +++++++++-- nix/module/heimdal.nix | 3 +++ 11 files changed, 93 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index be9f02e91..b7411433f 100644 --- a/configure.ac +++ b/configure.ac @@ -230,6 +230,21 @@ AM_CONDITIONAL([HAVE_MICROHTTPD], [test "$with_microhttpd" != "no"]) AC_SUBST([MICROHTTPD_CFLAGS]) AC_SUBST([MICROHTTPD_LIBS]) +dnl systemd sd_notify support +AC_ARG_WITH([systemd], + AC_HELP_STRING([--with-systemd], [use systemd sd_notify for readiness @<:@default=check@:>@]), + [], + [with_systemd=check]) +if test "$with_systemd" != "no"; then + PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [with_systemd=yes],[with_systemd=no]) +fi +if test "$with_systemd" = "yes"; then + AC_DEFINE_UNQUOTED([HAVE_SYSTEMD], 1, [Define if libsystemd sd_notify is available]) +fi +AM_CONDITIONAL([HAVE_SYSTEMD], [test "$with_systemd" != "no"]) +AC_SUBST([SYSTEMD_CFLAGS]) +AC_SUBST([SYSTEMD_LIBS]) + dnl mitkrb5 AC_ARG_WITH([mitkrb5], AC_HELP_STRING([--with-mitkrb5=PATH], [Path to MIT Kerberos for interop testing]), diff --git a/kadmin/kadm_conn.c b/kadmin/kadm_conn.c index ccd89211d..b6cb93d42 100644 --- a/kadmin/kadm_conn.c +++ b/kadmin/kadm_conn.c @@ -35,6 +35,9 @@ #ifdef HAVE_SYS_WAIT_H #include #endif +#ifdef HAVE_SYSTEMD +#include +#endif extern int daemon_child; @@ -304,6 +307,10 @@ start_server(krb5_context contextp, const char *port_str) krb5_errx(contextp, 1, "no sockets to listen to - exiting"); roken_detach_finish(NULL, daemon_child); +#ifdef HAVE_SYSTEMD + if (getenv("NOTIFY_SOCKET") != NULL) + sd_notify(0, "READY=1"); +#endif wait_for_connection(contextp, socks, num_socks); free(socks); diff --git a/kdc/Makefile.am b/kdc/Makefile.am index 267084092..c9e82422c 100644 --- a/kdc/Makefile.am +++ b/kdc/Makefile.am @@ -4,7 +4,7 @@ include $(top_srcdir)/Makefile.am.common WFLAGS += $(WFLAGS_ENUM_CONV) -AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) -I$(srcdir)/../lib/krb5 +AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) -I$(srcdir)/../lib/krb5 $(SYSTEMD_CFLAGS) lib_LTLIBRARIES = ipc_csr_authorizer.la \ libkdc.la @@ -174,7 +174,7 @@ hpropd_LDADD = \ $(LIB_kdb) \ $(top_builddir)/lib/asn1/libasn1.la \ $(LIB_roken) \ - $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB) + $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB) $(SYSTEMD_LIBS) if PKINIT LIB_pkinit = $(top_builddir)/lib/hx509/libhx509.la diff --git a/kdc/connect.c b/kdc/connect.c index ba8c8ad7b..6173ed42e 100644 --- a/kdc/connect.c +++ b/kdc/connect.c @@ -32,6 +32,9 @@ */ #include "kdc_locl.h" +#ifdef HAVE_SYSTEMD +#include +#endif /* * a tuple describing on what to listen @@ -1208,6 +1211,12 @@ start_kdc(krb5_context context, #endif roken_detach_finish(NULL, daemon_child); +#ifdef HAVE_SYSTEMD + /* If built with systemd support and running under systemd, notify readiness. + We check NOTIFY_SOCKET to avoid unnecessary calls when not under systemd. */ + if (getenv("NOTIFY_SOCKET") != NULL) + sd_notify(0, "READY=1"); +#endif #ifdef HAVE_FORK if (!testing_flag) { diff --git a/kdc/hpropd.c b/kdc/hpropd.c index 5d0ca5237..46d14b5f5 100644 --- a/kdc/hpropd.c +++ b/kdc/hpropd.c @@ -32,6 +32,9 @@ */ #include "hprop.h" +#ifdef HAVE_SYSTEMD +#include +#endif static int inetd_flag = -1; static int help_flag; @@ -156,6 +159,11 @@ main(int argc, char **argv) mini_inetd (krb5_getportbyname (context, "hprop", "tcp", HPROP_PORT), &sock); } +#ifdef HAVE_SYSTEMD + /* Notify systemd that the service is ready when running standalone */ + if (getenv("NOTIFY_SOCKET") != NULL) + sd_notify(0, "READY=1"); +#endif socket_set_keepalive(sock, 1); sin_len = sizeof(ss); if (getpeername(sock, sa, &sin_len) < 0) diff --git a/kpasswd/kpasswdd.c b/kpasswd/kpasswdd.c index 43a733589..9b8d66159 100644 --- a/kpasswd/kpasswdd.c +++ b/kpasswd/kpasswdd.c @@ -744,6 +744,14 @@ doit(krb5_keytab keytab, int port) krb5_errx(context, 1, "No sockets!"); roken_detach_finish(NULL, daemon_child); +#ifdef HAVE_SYSTEMD + /* If built with systemd support and running under systemd, notify readiness. + We check NOTIFY_SOCKET to avoid unnecessary calls when not under systemd. */ + if (getenv("NOTIFY_SOCKET") != NULL) { + extern int sd_notify(int, const char *); + (void) sd_notify(0, "READY=1"); + } +#endif while (exit_flag == 0) { krb5_ssize_t retx; diff --git a/lib/roken/Makefile.am b/lib/roken/Makefile.am index 115e759e8..a038096bf 100644 --- a/lib/roken/Makefile.am +++ b/lib/roken/Makefile.am @@ -9,7 +9,7 @@ CLEANFILES = roken.h make-roken.c $(XHEADERS) lib_LTLIBRARIES = libroken.la libroken_la_LDFLAGS = -version-info 20:0:1 -libroken_la_CPPFLAGS = -DBUILD_ROKEN_LIB +libroken_la_CPPFLAGS = -DBUILD_ROKEN_LIB $(SYSTEMD_CFLAGS) if versionscript libroken_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map @@ -199,7 +199,7 @@ EXTRA_libroken_la_SOURCES = \ search.hin \ vis.hin -libroken_la_LIBADD = @LTLIBOBJS@ $(LIB_crypt) $(LIB_pidfile) +libroken_la_LIBADD = @LTLIBOBJS@ $(LIB_crypt) $(LIB_pidfile) $(SYSTEMD_LIBS) if SUNOS libroken_la_LIBADD += -lnsl -lsocket endif diff --git a/lib/roken/detach.c b/lib/roken/detach.c index a9e5116c9..d69e285a8 100644 --- a/lib/roken/detach.c +++ b/lib/roken/detach.c @@ -38,6 +38,10 @@ #endif #include "roken.h" +#ifdef HAVE_SYSTEMD +#include +#endif + #ifdef WIN32 #define dup2 _dup2 #endif @@ -171,6 +175,24 @@ roken_detach_prep(int argc, char **argv, const char *special_arg) #define dup2 _dup2 #endif +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +roken_sd_notify(const char *state) +{ +#ifdef HAVE_SYSTEMD + int r; + + if (state == NULL) + return -1; + r = sd_notify(0, state); + if (r > 0) + return 0; + return -1; +#else + (void)state; + return -1; +#endif +} + ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL roken_detach_finish(const char *dir, int daemon_child_fd) { @@ -203,6 +225,13 @@ roken_detach_finish(const char *dir, int daemon_child_fd) err(1, "failed to chdir to /"); #endif + /* + * Notify systemd that we are ready (if built with systemd support). + * Do this after setsid/chdir and after pidfiles are written so that + * systemd sees the process in its final state. + */ + (void) roken_sd_notify("READY=1"); + do { bytes = write(pipefds[1], buf, sizeof(buf)); } while (bytes == -1 && errno == EINTR); diff --git a/lib/roken/roken.h.in b/lib/roken/roken.h.in index 868e9595b..730b0d496 100644 --- a/lib/roken/roken.h.in +++ b/lib/roken/roken.h.in @@ -939,6 +939,7 @@ ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL roken_detach_prep(int, char **, const char *); ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL roken_detach_finish(const char *, int); +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL roken_sd_notify(const char *); ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL net_write (rk_socket_t, const void *, size_t); diff --git a/nix/heimdal/default.nix b/nix/heimdal/default.nix index 8922f6320..167cd32ad 100644 --- a/nix/heimdal/default.nix +++ b/nix/heimdal/default.nix @@ -22,6 +22,7 @@ pam, libmicrohttpd, cjson, + systemdLibs, CoreFoundation, Security, @@ -43,6 +44,7 @@ withOpenLDAPAsHDBModule ? false, withOpenSSL ? true, withSQLite3 ? true, + withSystemd ? true, }: assert lib.assertMsg (withOpenLDAPAsHDBModule -> withOpenLDAP) '' @@ -89,9 +91,14 @@ stdenv.mkDerivation { ++ lib.optionals (withMicroHTTPD) [ libmicrohttpd ] ++ lib.optionals (withOpenLDAP) [ openldap ] ++ lib.optionals (withOpenSSL) [ openssl ] - ++ lib.optionals (withSQLite3) [ sqlite ]; + ++ lib.optionals (withSQLite3) [ sqlite ] + ++ lib.optionals (withSystemd) [ systemdLibs ]; - doCheck = true; + # env = { + # CHECK_LOCAL = "no-check-local"; + # }; + + # doCheck = true; nativeCheckInputs = [ curl jdk_headless diff --git a/nix/module/heimdal.nix b/nix/module/heimdal.nix index 0bc9a96d1..a5ec49574 100644 --- a/nix/module/heimdal.nix +++ b/nix/module/heimdal.nix @@ -71,6 +71,7 @@ in partOf = [ "kerberos-server.target" ]; wantedBy = [ "kerberos-server.target" ]; serviceConfig = { + Type = "notify"; ExecStart = "${package}/libexec/kadmind --config-file=/etc/heimdal-kdc/kdc.conf"; Slice = "system-kerberos-server.slice"; StateDirectory = "heimdal"; @@ -83,6 +84,7 @@ in partOf = [ "kerberos-server.target" ]; wantedBy = [ "kerberos-server.target" ]; serviceConfig = { + Type = "notify"; ExecStart = "${package}/libexec/kdc --config-file=/etc/heimdal-kdc/kdc.conf"; Slice = "system-kerberos-server.slice"; StateDirectory = "heimdal"; @@ -95,6 +97,7 @@ in partOf = [ "kerberos-server.target" ]; wantedBy = [ "kerberos-server.target" ]; serviceConfig = { + Type = "notify"; ExecStart = "${package}/libexec/kpasswdd"; Slice = "system-kerberos-server.slice"; StateDirectory = "heimdal";