Skip to content

Commit 9100fc4

Browse files
committed
Support dynamic TLS configuration reload via SIGHUP (fixes #81)
Store TLS settings in config structure and add cfg_reload_tls() to reapply them when SIGHUP is received, enabling certificate rotation without service restart.
1 parent 8ddb983 commit 9100fc4

File tree

3 files changed

+165
-1
lines changed

3 files changed

+165
-1
lines changed

nslcd/cfg.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,8 @@ static void handle_tls_reqcert(const char *filename, int lnr,
896896
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,%s)",
897897
print_tls_reqcert(value));
898898
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &value);
899+
if (nslcd_cfg != NULL)
900+
nslcd_cfg->tls_reqcert = value;
899901
}
900902

901903
#ifdef LDAP_OPT_X_TLS_REQUIRE_SAN
@@ -908,6 +910,8 @@ static void handle_tls_reqsan(const char *filename, int lnr,
908910
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_SAN,%s)",
909911
print_tls_reqcert(value));
910912
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_SAN, &value);
913+
if (nslcd_cfg != NULL)
914+
nslcd_cfg->tls_reqsan = value;
911915
}
912916
#endif /* LDAP_OPT_X_TLS_REQUIRE_SAN */
913917

@@ -936,6 +940,8 @@ static void handle_tls_crlcheck(const char *filename, int lnr,
936940
}
937941
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CRLCHECK,%s)", token);
938942
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CRLCHECK, &value);
943+
if (nslcd_cfg != NULL)
944+
nslcd_cfg->tls_crlcheck = value;
939945
}
940946

941947
static const char *print_tls_crlcheck(int value)
@@ -1299,6 +1305,20 @@ static void cfg_defaults(struct ldap_config *cfg)
12991305
cfg->reconnect_retrytime = 10;
13001306
#ifdef LDAP_OPT_X_TLS
13011307
cfg->ssl = SSL_OFF;
1308+
cfg->tls_cacertdir = NULL;
1309+
cfg->tls_cacertfile = NULL;
1310+
cfg->tls_randfile = NULL;
1311+
cfg->tls_ciphers = NULL;
1312+
cfg->tls_certfile = NULL;
1313+
cfg->tls_keyfile = NULL;
1314+
cfg->tls_crlfile = NULL;
1315+
cfg->tls_reqcert = LDAP_OPT_X_TLS_DEMAND;
1316+
#ifdef LDAP_OPT_X_TLS_REQUIRE_SAN
1317+
cfg->tls_reqsan = LDAP_OPT_X_TLS_ALLOW;
1318+
#endif /* LDAP_OPT_X_TLS_REQUIRE_SAN */
1319+
#ifdef LDAP_OPT_X_TLS_CRLCHECK
1320+
cfg->tls_crlcheck = LDAP_OPT_X_TLS_CRL_NONE;
1321+
#endif /* LDAP_OPT_X_TLS_CRLCHECK */
13021322
#endif /* LDAP_OPT_X_TLS */
13031323
cfg->pagesize = 0;
13041324
cfg->nss_initgroups_ignoreusers = NULL;
@@ -1592,6 +1612,9 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
15921612
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR,\"%s\")",
15931613
value);
15941614
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CACERTDIR, value);
1615+
if (cfg->tls_cacertdir != NULL)
1616+
free(cfg->tls_cacertdir);
1617+
cfg->tls_cacertdir = strdup(value);
15951618
free(value);
15961619
}
15971620
else if ((strcasecmp(keyword, "tls_cacertfile") == 0) ||
@@ -1603,6 +1626,9 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
16031626
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CACERTFILE,\"%s\")",
16041627
value);
16051628
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CACERTFILE, value);
1629+
if (cfg->tls_cacertfile != NULL)
1630+
free(cfg->tls_cacertfile);
1631+
cfg->tls_cacertfile = strdup(value);
16061632
free(value);
16071633
}
16081634
else if (strcasecmp(keyword, "tls_randfile") == 0)
@@ -1613,6 +1639,9 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
16131639
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_RANDOM_FILE,\"%s\")",
16141640
value);
16151641
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_RANDOM_FILE, value);
1642+
if (cfg->tls_randfile != NULL)
1643+
free(cfg->tls_randfile);
1644+
cfg->tls_randfile = strdup(value);
16161645
free(value);
16171646
}
16181647
else if (strcasecmp(keyword, "tls_ciphers") == 0)
@@ -1621,6 +1650,9 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
16211650
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CIPHER_SUITE,\"%s\")",
16221651
value);
16231652
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, value);
1653+
if (cfg->tls_ciphers != NULL)
1654+
free(cfg->tls_ciphers);
1655+
cfg->tls_ciphers = strdup(value);
16241656
free(value);
16251657
}
16261658
else if (strcasecmp(keyword, "tls_cert") == 0)
@@ -1631,6 +1663,9 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
16311663
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CERTFILE,\"%s\")",
16321664
value);
16331665
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CERTFILE, value);
1666+
if (cfg->tls_certfile != NULL)
1667+
free(cfg->tls_certfile);
1668+
cfg->tls_certfile = strdup(value);
16341669
free(value);
16351670
}
16361671
else if (strcasecmp(keyword, "tls_key") == 0)
@@ -1641,6 +1676,9 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
16411676
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_KEYFILE,\"%s\")",
16421677
value);
16431678
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_KEYFILE, value);
1679+
if (cfg->tls_keyfile != NULL)
1680+
free(cfg->tls_keyfile);
1681+
cfg->tls_keyfile = strdup(value);
16441682
free(value);
16451683
}
16461684
else if (strcasecmp(keyword, "tls_reqsan") == 0)
@@ -1672,6 +1710,9 @@ static void cfg_read(const char *filename, struct ldap_config *cfg)
16721710
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CRLFILE,\"%s\")",
16731711
value);
16741712
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CRLFILE, value);
1713+
if (cfg->tls_crlfile != NULL)
1714+
free(cfg->tls_crlfile);
1715+
cfg->tls_crlfile = strdup(value);
16751716
free(value);
16761717
#else /* not LDAP_OPT_X_TLS_CRLFILE */
16771718
log_log(LOG_ERR, "%s:%d: option %s not supported on platform",
@@ -2101,3 +2142,99 @@ void cfg_init(const char *fname)
21012142
service_init();
21022143
shadow_init();
21032144
}
2145+
2146+
#ifdef LDAP_OPT_X_TLS
2147+
/* Reload TLS configuration dynamically */
2148+
void cfg_reload_tls(void)
2149+
{
2150+
int rc;
2151+
2152+
/* Check if configuration is initialized */
2153+
if (nslcd_cfg == NULL)
2154+
{
2155+
log_log(LOG_ERR, "cfg_reload_tls() called before cfg_init()");
2156+
return;
2157+
}
2158+
2159+
log_log(LOG_INFO, "Reloading TLS configuration");
2160+
2161+
/* Reload TLS CA certificate directory */
2162+
if (nslcd_cfg->tls_cacertdir != NULL)
2163+
{
2164+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR,\"%s\")",
2165+
nslcd_cfg->tls_cacertdir);
2166+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CACERTDIR, nslcd_cfg->tls_cacertdir);
2167+
}
2168+
2169+
/* Reload TLS CA certificate file */
2170+
if (nslcd_cfg->tls_cacertfile != NULL)
2171+
{
2172+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CACERTFILE,\"%s\")",
2173+
nslcd_cfg->tls_cacertfile);
2174+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CACERTFILE, nslcd_cfg->tls_cacertfile);
2175+
}
2176+
2177+
/* Reload TLS random file */
2178+
if (nslcd_cfg->tls_randfile != NULL)
2179+
{
2180+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_RANDOM_FILE,\"%s\")",
2181+
nslcd_cfg->tls_randfile);
2182+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_RANDOM_FILE, nslcd_cfg->tls_randfile);
2183+
}
2184+
2185+
/* Reload TLS cipher suite */
2186+
if (nslcd_cfg->tls_ciphers != NULL)
2187+
{
2188+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CIPHER_SUITE,\"%s\")",
2189+
nslcd_cfg->tls_ciphers);
2190+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, nslcd_cfg->tls_ciphers);
2191+
}
2192+
2193+
/* Reload TLS client certificate file */
2194+
if (nslcd_cfg->tls_certfile != NULL)
2195+
{
2196+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CERTFILE,\"%s\")",
2197+
nslcd_cfg->tls_certfile);
2198+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CERTFILE, nslcd_cfg->tls_certfile);
2199+
}
2200+
2201+
/* Reload TLS client key file */
2202+
if (nslcd_cfg->tls_keyfile != NULL)
2203+
{
2204+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_KEYFILE,\"%s\")",
2205+
nslcd_cfg->tls_keyfile);
2206+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_KEYFILE, nslcd_cfg->tls_keyfile);
2207+
}
2208+
2209+
/* Reload TLS certificate requirement */
2210+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,%s)",
2211+
print_tls_reqcert(nslcd_cfg->tls_reqcert));
2212+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &nslcd_cfg->tls_reqcert);
2213+
2214+
#ifdef LDAP_OPT_X_TLS_REQUIRE_SAN
2215+
/* Reload TLS SAN requirement */
2216+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_SAN,%s)",
2217+
print_tls_reqcert(nslcd_cfg->tls_reqsan));
2218+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_SAN, &nslcd_cfg->tls_reqsan);
2219+
#endif /* LDAP_OPT_X_TLS_REQUIRE_SAN */
2220+
2221+
#ifdef LDAP_OPT_X_TLS_CRLCHECK
2222+
/* Reload TLS CRL check mode */
2223+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CRLCHECK,%s)",
2224+
print_tls_crlcheck(nslcd_cfg->tls_crlcheck));
2225+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CRLCHECK, &nslcd_cfg->tls_crlcheck);
2226+
#endif /* LDAP_OPT_X_TLS_CRLCHECK */
2227+
2228+
#ifdef LDAP_OPT_X_TLS_CRLFILE
2229+
/* Reload TLS CRL file */
2230+
if (nslcd_cfg->tls_crlfile != NULL)
2231+
{
2232+
log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_CRLFILE,\"%s\")",
2233+
nslcd_cfg->tls_crlfile);
2234+
LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CRLFILE, nslcd_cfg->tls_crlfile);
2235+
}
2236+
#endif /* LDAP_OPT_X_TLS_CRLFILE */
2237+
2238+
log_log(LOG_INFO, "TLS configuration reloaded successfully");
2239+
}
2240+
#endif /* LDAP_OPT_X_TLS */

nslcd/cfg.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,21 @@ struct ldap_config {
119119
#ifdef LDAP_OPT_X_TLS
120120
/* SSL enabled */
121121
enum ldap_ssl_options ssl;
122+
/* TLS configuration options for dynamic reload */
123+
char *tls_cacertdir; /* CA certificate directory */
124+
char *tls_cacertfile; /* CA certificate file */
125+
char *tls_randfile; /* random file for TLS */
126+
char *tls_ciphers; /* cipher suite */
127+
char *tls_certfile; /* client certificate file */
128+
char *tls_keyfile; /* client key file */
129+
char *tls_crlfile; /* CRL file */
130+
int tls_reqcert; /* certificate verification requirement */
131+
#ifdef LDAP_OPT_X_TLS_REQUIRE_SAN
132+
int tls_reqsan; /* SAN verification requirement */
133+
#endif /* LDAP_OPT_X_TLS_REQUIRE_SAN */
134+
#ifdef LDAP_OPT_X_TLS_CRLCHECK
135+
int tls_crlcheck; /* CRL check mode */
136+
#endif /* LDAP_OPT_X_TLS_CRLCHECK */
122137
#endif /* LDAP_OPT_X_TLS */
123138

124139
int pagesize; /* set to a greater than 0 to enable handling of paged results with the specified size */
@@ -149,4 +164,7 @@ extern struct ldap_config *nslcd_cfg;
149164
default configuration file and call exit() if an error occurs. */
150165
void cfg_init(const char *fname);
151166

167+
/* Reload TLS configuration dynamically from the same configuration file. */
168+
void cfg_reload_tls(void);
169+
152170
#endif /* NSLCD__CFG_H */

nslcd/nslcd.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ int main(int argc, char *argv[])
890890
/* enable receiving of signals */
891891
pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
892892
/* wait until we received a signal */
893-
while ((nslcd_receivedsignal == 0) || (nslcd_receivedsignal == SIGUSR1))
893+
while ((nslcd_receivedsignal == 0) || (nslcd_receivedsignal == SIGUSR1) || (nslcd_receivedsignal == SIGHUP))
894894
{
895895
sleep(INT_MAX); /* sleep as long as we can or until we receive a signal */
896896
if (nslcd_receivedsignal == SIGUSR1)
@@ -900,6 +900,15 @@ int main(int argc, char *argv[])
900900
myldap_immediate_reconnect();
901901
nslcd_receivedsignal = 0;
902902
}
903+
else if (nslcd_receivedsignal == SIGHUP)
904+
{
905+
log_log(LOG_INFO, "caught signal %s (%d), reloading TLS configuration",
906+
signame(nslcd_receivedsignal), nslcd_receivedsignal);
907+
#ifdef LDAP_OPT_X_TLS
908+
cfg_reload_tls();
909+
#endif /* LDAP_OPT_X_TLS */
910+
nslcd_receivedsignal = 0;
911+
}
903912
}
904913
/* print something about received signal */
905914
log_log(LOG_INFO, "caught signal %s (%d), shutting down",

0 commit comments

Comments
 (0)