Author: rmeggins
Update of /cvs/dirsec/ldapserver/ldap/servers/slapd In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv2319/ldap/servers/slapd
Modified Files: detach.c main.c proto-slap.h Log Message: Resolves: bug 439829 Bug Description: simple password auth fails using NSS 3.11.99 or later Reviewed by: nkinder (Thanks!) Fix Description: The new softokn in NSS 3.11.99 and later requires that the server calls NSS_Init() after forking, but before detaching from the controlling terminal. In fact, this was always a requirement, but the softokn in older NSS allow it. However, it's possible that some hardware crypto devices do not allow this and may not work with older directory servers. The fix is to move the nss/ssl initialization so that it can be called at the right point, or from other points in cases where the server does not fork (e.g. db2ldif). Platforms tested: Fedora 9 i386, RHEL5 x86_64 Flag Day: no Doc impact: no
Index: detach.c =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/detach.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- detach.c 10 Nov 2006 23:45:40 -0000 1.6 +++ detach.c 3 Apr 2008 21:07:55 -0000 1.7 @@ -76,7 +76,8 @@ #endif /* USE_SYSCONF */
void -detach() +detach( int slapd_exemode, int importexport_encrypt, + int s_port, daemon_ports_t *ports_info ) { #ifndef _WIN32 int i, sd; @@ -108,6 +109,12 @@ break; }
+ /* call this right after the fork, but before closing stdin */ + if (slapd_do_all_nss_ssl_init(slapd_exemode, importexport_encrypt, + s_port, ports_info)) { + exit(1); + } + workingdir = config_get_workingdir(); if ( NULL == workingdir ) { errorlog = config_get_errorlog(); @@ -150,7 +157,12 @@ #endif /* USE_SETSID */
g_set_detached(1); - } + } else { /* not detaching - call nss/ssl init */ + if (slapd_do_all_nss_ssl_init(slapd_exemode, importexport_encrypt, + s_port, ports_info)) { + exit(1); + } + }
(void) SIGNAL( SIGPIPE, SIG_IGN ); #endif /* _WIN32 */
Index: main.c =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/main.c,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24 --- main.c 3 Apr 2008 16:52:46 -0000 1.23 +++ main.c 3 Apr 2008 21:07:55 -0000 1.24 @@ -901,48 +901,14 @@ } #endif
- /* - * Initialise NSS once for the whole slapd process, whether SSL - * is enabled or not. We use NSS for random number generation and - * other things even if we are not going to accept SSL connections. - * We also need NSS for attribute encryption/decryption on import and export. - */ - init_ssl = ( (slapd_exemode == SLAPD_EXEMODE_SLAPD) || importexport_encrypt) - && config_get_security() - && (0 != s_port) && (s_port <= LDAP_PORT_MAX); - /* As of DS 6.1, always do a full initialization so that other - * modules can assume NSS is available - */ - if ( slapd_nss_init((slapd_exemode == SLAPD_EXEMODE_SLAPD), - (slapd_exemode != SLAPD_EXEMODE_REFERRAL) /* have config? */ )) { - LDAPDebug(LDAP_DEBUG_ANY, - "ERROR: NSS Initialization Failed.\n", 0, 0, 0); - exit (1); - } - - if (slapd_exemode == SLAPD_EXEMODE_SLAPD) { - client_auth_init(); - } - - if ( init_ssl && ( 0 != slapd_ssl_init())) { - LDAPDebug(LDAP_DEBUG_ANY, - "ERROR: SSL Initialization Failed.\n", 0, 0, 0 ); - exit( 1 ); - } - - if ((slapd_exemode == SLAPD_EXEMODE_SLAPD) || - (slapd_exemode == SLAPD_EXEMODE_REFERRAL)) { - if ( init_ssl ) { - PRFileDesc **sock; - for (sock = ports_info.s_socket; sock && *sock; sock++) { - if ( 0 != slapd_ssl_init2(sock, 0) ) { - LDAPDebug(LDAP_DEBUG_ANY, - "ERROR: SSL Initialization phase 2 Failed.\n", 0, 0, 0 ); - exit( 1 ); - } - } - } - } + /* Do NSS and/or SSL init for those modes other than listening modes */ + if ((slapd_exemode != SLAPD_EXEMODE_REFERRAL) && + (slapd_exemode != SLAPD_EXEMODE_SLAPD)) { + if (slapd_do_all_nss_ssl_init(slapd_exemode, importexport_encrypt, + s_port, &ports_info)) { + return 1; + } + }
/* * if we were called upon to do special database stuff, do it and be @@ -1002,7 +968,8 @@ * Have to detach after ssl_init - the user may be prompted for the PIN * on the terminal, so it must be open. */ - detach(); + detach(slapd_exemode, importexport_encrypt, + s_port, &ports_info);
/* * Now write our PID to the startup PID file. @@ -2885,3 +2852,67 @@ } #endif /* LDAP_DEBUG */
+/* + This function does all NSS and SSL related initialization + required during startup. We use this function rather + than just call this code from main because we must perform + all of this initialization after the fork() but before + we detach from the controlling terminal. This is because + the NSS softokn requires that NSS_Init is called after the + fork - this was always the case, but it is a hard error in + NSS 3.11.99 and later. We also have to call NSS_Init before + doing the detach because NSS may prompt the user for the + token (h/w or softokn) password on stdin. So we use this + function that we can call from detach() if running in + regular slapd exemode or from main() if running in other + modes (or just not detaching). +*/ +int +slapd_do_all_nss_ssl_init(int slapd_exemode, int importexport_encrypt, + int s_port, daemon_ports_t *ports_info) +{ + /* + * Initialise NSS once for the whole slapd process, whether SSL + * is enabled or not. We use NSS for random number generation and + * other things even if we are not going to accept SSL connections. + * We also need NSS for attribute encryption/decryption on import and export. + */ + int init_ssl = ( (slapd_exemode == SLAPD_EXEMODE_SLAPD) || importexport_encrypt) + && config_get_security() + && (0 != s_port) && (s_port <= LDAP_PORT_MAX); + /* As of DS 6.1, always do a full initialization so that other + * modules can assume NSS is available + */ + if ( slapd_nss_init((slapd_exemode == SLAPD_EXEMODE_SLAPD), + (slapd_exemode != SLAPD_EXEMODE_REFERRAL) /* have config? */ )) { + LDAPDebug(LDAP_DEBUG_ANY, + "ERROR: NSS Initialization Failed.\n", 0, 0, 0); + exit (1); + } + + if (slapd_exemode == SLAPD_EXEMODE_SLAPD) { + client_auth_init(); + } + + if ( init_ssl && ( 0 != slapd_ssl_init())) { + LDAPDebug(LDAP_DEBUG_ANY, + "ERROR: SSL Initialization Failed.\n", 0, 0, 0 ); + exit( 1 ); + } + + if ((slapd_exemode == SLAPD_EXEMODE_SLAPD) || + (slapd_exemode == SLAPD_EXEMODE_REFERRAL)) { + if ( init_ssl ) { + PRFileDesc **sock; + for (sock = ports_info->s_socket; sock && *sock; sock++) { + if ( 0 != slapd_ssl_init2(sock, 0) ) { + LDAPDebug(LDAP_DEBUG_ANY, + "ERROR: SSL Initialization phase 2 Failed.\n", 0, 0, 0 ); + exit( 1 ); + } + } + } + } + + return 0; +}
Index: proto-slap.h =================================================================== RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/proto-slap.h,v retrieving revision 1.31 retrieving revision 1.32 diff -u -r1.31 -r1.32 --- proto-slap.h 18 Oct 2007 01:22:29 -0000 1.31 +++ proto-slap.h 3 Apr 2008 21:07:55 -0000 1.32 @@ -483,7 +483,8 @@ /* * detach.c */ -void detach( void ); +void detach( int slapd_exemode, int importexport_encrypt, + int s_port, daemon_ports_t *ports_info ); #ifndef _WIN32 void close_all_files( void ); #endif @@ -879,7 +880,6 @@ int slapd_ssl_listener_is_initialized(); int sasl_io_cleanup(Connection *c);
- /* * security_wrappers.c */ @@ -1277,4 +1277,7 @@ #if ( defined( hpux ) || defined( irix )) void signal2sigaction( int s, void *a ); #endif +int slapd_do_all_nss_ssl_init(int slapd_exemode, int importexport_encrypt, + int s_port, daemon_ports_t *ports_info); + #endif /* _PROTO_SLAP */
389-commits@lists.fedoraproject.org