Fix bug # 132040 - LDAP tools need a "no man in the middle" option.

New libssldap public function: ldapssl_set_strength().
	New command line tool option: -3 ("no third").
Fix bug # 134035 - LDAP command line tools don't report vendor mismatch.
Improved error checks and reporting for SSL errors in tools.


git-svn-id: svn://10.0.0.236/trunk@119280 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mcs%netscape.com 2002-04-18 18:53:19 +00:00
parent 489585d1a5
commit 0c1f40ad50
11 changed files with 159 additions and 97 deletions

View File

@ -18,42 +18,42 @@ The "avail" lists included options that are available for use.
common.c (supported by all of the tools):
raw: nvEMRHZ0d:D:f:h:I:j:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:
sorted: 0 DEHIKMNOPQRVWXYZ dfhikmnpvwy
avail: [2-9] J g (not used by any of the tools)
raw: nvEMRHZ0d:D:f:h:I:j:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:
sorted: 0 DEHIJKMNOPQRVWXYZ dfhikmnpvwy
avail: 2 [4-9] g (not used by any of the tools)
ldapcmp.c:
raw: Bb:l:s:z:
sorted: B blsz
all: 0 BDHIKMNOPQRVWXYZ bdfhiklmnpsvwyz
avail: [1-9] ACFGJLSTU acegjoqrtu
avail: [12] [4-9] ACFGLSTU acegjoqrtu
ldapcompare.c:
raw: cq
sorted: cq
all: 0 DEHIKMNOPQRVWXYZ cdfhikmnpqvwy
avail: [1-9] ABCFJLSTU abegjlorstuxz
avail: [12] [4-9] ABCFLSTU abegjlorstuxz
ldapdelete.c (deprecated)
raw: c
sorted: c
all: 0 DHIKMNOPQRVWXYZ cdfhikmnpvwy
avail: [1-9] ABCFGJLSTU abegjloqrstuxz
avail: [12] [4-9] ABCFGLSTU abegjloqrstuxz
ldapmodify.c
raw: aAbcFe:B:q
sorted: ABF abceq
all: 0 ABDFHIKMNOPQRVWXYZ abcdefhikmnpqvwy
avail: [1-9] CGJLSTU gjlorstuxz
avail: [12] [4-9] CGLSTU gjlorstuxz
ldapmodrdn.c (deprecated)
raw: cr
sorted: cr
all: 0 DHIKMNOPQRVWXYZ cdfhikmnprvwy
avail: [1-9] ABCFGJLSTU abegjloqstuxz
avail: [12] [4-9] ABCFGLSTU abegjloqstuxz
ldapsearch.c
raw: ABLTU1eotuxa:b:F:G:l:S:s:z:C:
sorted: 1 ABCFGLSTU abeostuxz
all: 01 ABCDFGHIKLMNOPQRSTUVWXYZ abdefhikmnopstuvwxyz
avail: [2-9] J cgjlqr
avail: 2 [4-9] cgjlqr

View File

@ -97,6 +97,7 @@ ldaptool_common_usage( int two_hosts )
fprintf( stderr, " -m pathname\tpath to security module database\n");
#endif /* LDAP_TOOL_PKCS11 */
fprintf( stderr, " -W\t\tSSL key password\n" );
fprintf( stderr, " -3\t\tcheck hostnames in SSL certificates\n" );
#ifdef LDAP_TOOL_PKCS11
fprintf( stderr, " -Q [token][:certificate name]\tPKCS 11\n" );
@ -181,6 +182,7 @@ static int isW = 0;
static int isw = 0;
static int isD = 0;
static int isj = 0;
static int ssl_strength = LDAPTOOL_DEFSSLSTRENGTH;
static char *ssl_certdbpath = LDAPTOOL_DEFCERTDBPATH;
static char *ssl_keydbpath = LDAPTOOL_DEFKEYDBPATH;
/*
@ -299,8 +301,18 @@ ldaptool_process_args( int argc, char **argv, char *extra_opts,
if ( lib_version_mismatch_is_fatal ) {
exit( LDAP_LOCAL_ERROR );
}
} else if ( strcmp( ldai.ldapai_vendor_name, LDAP_VENDOR_NAME ) == 0
&& ldai.ldapai_vendor_version < LDAP_VENDOR_VERSION ) {
} else if ( strcmp( ldai.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0 ) {
fprintf( stderr, "%s: this program requires %s's LDAP\n"
"\tlibrary version %2.2f or greater; running with\n"
"\t%s's version %2.2f.\n",
ldaptool_progname, LDAP_VENDOR_NAME,
(float)LDAP_VENDOR_VERSION / 100,
ldai.ldapai_vendor_name,
(float)ldai.ldapai_vendor_version / 100 );
if ( lib_version_mismatch_is_fatal ) {
exit( LDAP_LOCAL_ERROR );
}
} else if ( ldai.ldapai_vendor_version < LDAP_VENDOR_VERSION ) {
fprintf( stderr, "%s: this program requires %s's LDAP\n"
"\tlibrary version %2.2f or greater; running with"
" version %2.2f.\n",
@ -319,7 +331,7 @@ ldaptool_process_args( int argc, char **argv, char *extra_opts,
extra_opts = "";
}
common_opts = "nvEMRHZ0d:D:f:h:j:I:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:";
common_opts = "nvEMRHZ03d:D:f:h:j:I:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:";
/* note: optstring must include room for liblcache "C:" option */
if (( optstring = (char *) malloc( strlen( extra_opts ) + strlen( common_opts )
@ -441,6 +453,11 @@ ldaptool_process_args( int argc, char **argv, char *extra_opts,
}
isW = 1;
break;
case '3': /* check hostnames in SSL certificates ("no third") */
ssl_strength = LDAPSSL_AUTH_CNCHECK;
break;
#ifdef LDAP_TOOL_PKCS11
case 'm': /* SSL secmod path */
ssl_secmodpath = strdup( optarg);
@ -537,7 +554,8 @@ ldaptool_process_args( int argc, char **argv, char *extra_opts,
case '0': /* zero -- override LDAP library version check */
break; /* already handled above */
case 'J':
case 'J': /* send an arbitrary control */
if ( (ctrl_arg = strdup( optarg)) == NULL ) {
perror ("strdup");
exit (LDAP_NO_MEMORY);
@ -570,11 +588,17 @@ ldaptool_process_args( int argc, char **argv, char *extra_opts,
/* If '-Z' is specified, check if '-P' is specified too. */
if ( isN || isW ) {
if ( !isZ ) {
printf( "%s: with -N, -W options, please specify -Z\n\n", ldaptool_progname );
fprintf( stderr, "%s: with -N, -W options, please specify -Z\n\n", ldaptool_progname );
return (-1);
}
}
/* if '-N' is specified, -W is needed too */
if ( isN && NULL == ssl_passwd ) {
fprintf( stderr, "%s: with the -N option, please specify -W also\n\n", ldaptool_progname );
return (-1);
}
if ( isj && isw ) {
fprintf(stderr, "%s: -j and -w options cannot be specified simultaneously\n\n", ldaptool_progname );
return (-1);
@ -753,7 +777,7 @@ static int PinArgRegistration( void )
#ifndef _WIN32
if ( SVRCORE_CreateStdPinObj(&StdPinObj, filename, PR_TRUE) !=
SVRCORE_Success) {
printf("Security Initialization: Unable to create PinObj "
fprintf(stderr, "Security Initialization: Unable to create PinObj "
"(%d)", PR_GetError());
return -1;
}
@ -772,14 +796,14 @@ static int PinArgRegistration( void )
{
local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName);
if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
printf("Security Initialization: Unable to create NTUserPinObj "
fprintf(stderr, "Security Initialization: Unable to create NTUserPinObj "
"(%d)", PR_GetError());
exit( LDAP_LOCAL_ERROR );
}
if ((err = SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin,
(SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success)
{
printf("Security Initialization: Unable to create ArgPinObj "
fprintf(stderr, "Security Initialization: Unable to create ArgPinObj "
"(%d)", PR_GetError());
return -1;
@ -790,7 +814,7 @@ static int PinArgRegistration( void )
else
{
if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){
printf("Security Initialization: Unable to create NTUserPinObj "
fprintf( stderr, "Security Initialization: Unable to create NTUserPinObj "
"(%d)", PR_GetError());
return -1;
}
@ -798,14 +822,14 @@ static int PinArgRegistration( void )
{
if ((err = SVRCORE_CreateFilePinObj(&FilePinObj, filename)) !=
SVRCORE_Success) {
printf("Security Initialization: Unable to create FilePinObj "
fprintf( stderr, "Security Initialization: Unable to create FilePinObj "
"(%d)", PR_GetError());
return -1;
}
if ((err = SVRCORE_CreateAltPinObj(&AltPinObj, (SVRCOREPinObj *)FilePinObj,
(SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success) {
printf("Security Initialization: Unable to create AltPinObj "
fprintf( stderr, "Security Initialization: Unable to create AltPinObj "
"(%d)", PR_GetError());
return -1;
}
@ -890,6 +914,12 @@ ldaptool_ldap_init( int second_host )
}
#endif /* LDAP_TOOL_PKCS11 */
/* set the default SSL strength (used for all future ld's we create) */
if ( ldapssl_set_strength( NULL, ssl_strength ) < 0 ) {
perror( "ldapssl_set_strength" );
exit( LDAP_LOCAL_ERROR );
}
if (secure) {
if ( !user_port ) {
port = LDAPS_PORT;
@ -1555,7 +1585,7 @@ ldaptool_parse_ctrl_arg(char *ctrl_arg, char sep,
char **ctrl_oid, int *ctrl_criticality,
char **ctrl_value, int *vlen)
{
char *s, *p, *d;
char *s, *p;
int strict;
/* Initialize passed variables with default values */

View File

@ -103,6 +103,7 @@ extern "C" {
#define LDAPTOOL_DEFSEP "=" /* used by ldapcmp and ldapsearch */
#define LDAPTOOL_DEFHOST "localhost"
#define LDAPTOOL_DEFSSLSTRENGTH LDAPSSL_AUTH_CERT
#define LDAPTOOL_DEFCERTDBPATH "."
#define LDAPTOOL_DEFKEYDBPATH "."
#define LDAPTOOL_DEFREFHOPLIMIT 5

View File

@ -48,6 +48,7 @@ LDAP * LDAP_CALL ldapssl_init( const char *defhost, int defport,
/*
* Install I/O routines to make SSL over LDAP possible.
* Use this after ldap_init() or just use ldapssl_init() instead.
* Returns 0 if all goes well.
*/
int LDAP_CALL ldapssl_install_routines( LDAP *ld );
@ -86,6 +87,7 @@ int LDAP_CALL ldapssl_install_routines( LDAP *ld );
/*
* Initialize the secure parts (Security and SSL) of the runtime for use
* by a client application. This is only called once.
* Returns 0 if all goes well.
*/
int LDAP_CALL ldapssl_client_init(
@ -119,6 +121,8 @@ int LDAP_CALL ldapssl_client_init(
* Furthermore, the port number must be passed
* via the "defport" parameter, and cannot
* be passed via a host:port option.
*
* Returns 0 if all goes well.
*/
int LDAP_CALL ldapssl_serverauth_init(
@ -127,6 +131,7 @@ int LDAP_CALL ldapssl_serverauth_init(
/*
* Initialize the secure parts (Security and SSL) of the runtime for use
* by a client application that may want to do SSL client authentication.
* Returns 0 if all goes well.
*/
int LDAP_CALL ldapssl_clientauth_init(
@ -142,6 +147,8 @@ int LDAP_CALL ldapssl_clientauth_init(
* problems which can be caused by passing in wrong host & portname
* values. The same warning applies to the ldapssl_advclientauth_init()
* function.
*
* Returns 0 if all goes well.
*/
int LDAP_CALL ldapssl_advclientauth_init(
@ -162,16 +169,24 @@ const char * LDAP_CALL ldapssl_err2string( const int prerrno );
/*
* Enable SSL client authentication on the given ld.
* Returns 0 if all goes well.
*/
int LDAP_CALL ldapssl_enable_clientauth( LDAP *ld, char *keynickname,
char *keypasswd, char *certnickname );
/*
* Set the SSL strength for an existing SSL-enabled LDAP session handle.
*
* See the description of ldapssl_serverauth_init() above for valid
* sslstrength values. If ld is NULL, the default for new LDAP session
* handles is set.
*
* Returns 0 if all goes well.
*/
int LDAP_CALL ldapssl_set_strength( LDAP *ld, int sslstrength );
#ifdef __cplusplus
}
#endif
#endif /* !defined(LDAP_SSL_H) */

View File

@ -7,6 +7,7 @@
457 ldapssl_pkcs_init
458 ldapssl_err2string
459 ldapssl_serverauth_init
460 ldapssl_set_strength
# the last Windows ordinal number that has been reserved for SSL is 469.
# Windows ordinals 1100-1150 are reserved for privately/non-published

View File

@ -65,7 +65,6 @@ static PRStatus local_SSLPLCY_Install(void);
* This little tricky guy keeps us from initializing twice
*/
static int inited = 0;
static int ssl_strength = LDAPSSL_AUTH_CERT;
static char tokDes[34] = "Internal (Software) Database ";
static char ptokDes[34] = "Internal (Software) Token ";
@ -390,35 +389,6 @@ ldapssl_clientauth_init( const char *certdbpath, void *certdbhandle,
}
/*
* This is not the most elegant solution to SSL strength, but it
* works because ldapssl_advclientauth_init() is only called once.
*/
int get_ssl_strength( void )
{
return ssl_strength;
}
/*
* At some point we might want to consider protecting this
* with a mutex.. For now there is no need.
*/
int set_ssl_strength(int strength_val)
{
if (strength_val == LDAPSSL_AUTH_WEAK ||
strength_val == LDAPSSL_AUTH_CERT ||
strength_val == LDAPSSL_AUTH_CNCHECK ) {
ssl_strength = strength_val;
return LDAP_SUCCESS;
}
return LDAP_PARAM_ERROR;
}
/*
* Initialize ns/security so it can be used for SSL client authentication.
* It is safe to call this more than once.
@ -487,10 +457,7 @@ ldapssl_advclientauth_init(
inited = 1;
set_ssl_strength( sslstrength );
return( 0 );
return ( ldapssl_set_strength( NULL, sslstrength ));
}
@ -591,12 +558,7 @@ ldapssl_pkcs_init( const struct ldapssl_pkcs_fns *pfns )
ldapssl_free((void **) &certdbName );
}
/*
set_ssl_strength( sslstrength );
*/
set_ssl_strength( LDAPSSL_AUTH_CERT );
return( 0 );
return ( ldapssl_set_strength( NULL, LDAPSSL_AUTH_CERT ));
}
@ -637,10 +599,8 @@ ldapssl_serverauth_init(const char* certdbpath,
void *certdbhandle,
const int sslstrength )
{
int rc = LDAP_SUCCESS;
if ((rc = set_ssl_strength( sslstrength )) != LDAP_SUCCESS) {
return ( rc );
if ( ldapssl_set_strength( NULL, sslstrength ) != 0 ) {
return( -1 );
}
return( ldapssl_clientauth_init( certdbpath, certdbhandle,

View File

@ -75,9 +75,11 @@ typedef struct ldapssl_std_functions {
*/
typedef struct ldapssl_session_info {
int lssei_using_pcks_fns;
int lssei_ssl_strength;
char *lssei_certnickname;
char *lssei_keypasswd;
LDAPSSLStdFunctions lssei_std_functions;
CERTCertDBHandle *lssei_certdbh;
} LDAPSSLSessionInfo;
@ -103,12 +105,6 @@ void set_using_pkcs_functions( int val )
}
/*
* External functions... this function currently lives in clientinit.c
*/
int get_ssl_strength( void );
/*
* Utility functions:
*/
@ -120,7 +116,7 @@ static void ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp );
* SSL Stuff
*/
static int ldapssl_AuthCertificate(void *certdbarg, PRFileDesc *fd,
static int ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd,
PRBool checkSig, PRBool isServer);
/*
@ -137,6 +133,12 @@ static SECStatus check_clientauth_nicknames_and_passwd( LDAP *ld,
static char *get_keypassword( PK11SlotInfo *slot, PRBool retry,
void *sessionarg );
/*
* Static variables.
*/
static int default_ssl_strength = LDAPSSL_AUTH_CERT;
/*
* Like ldap_init(), except also install I/O routines from libsec so we
* can support SSL. If defsecure is non-zero, SSL is enabled for the
@ -290,7 +292,7 @@ do_ldapssl_connect(const char *hostlist, int defport, int timeout,
*/
SSL_AuthCertificateHook( soi.soinfo_prfd,
(SSLAuthCertificate)ldapssl_AuthCertificate,
(void *)CERT_GetDefaultCertDB());
(void *)sseip );
if ( SSL_GetClientAuthDataHook( soi.soinfo_prfd,
get_clientauth_data, clientauth ? sseip : NULL ) != 0 ) {
@ -382,7 +384,16 @@ ldapssl_install_routines( LDAP *ld )
ldap_set_lderrno( ld, LDAP_NO_MEMORY, NULL, NULL );
return( -1 );
}
/*
* Initialize session info.
* XXX: it would be nice to be able to set these on a per-session basis:
* lssei_using_pcks_fns
* lssei_certdbh
*/
ssip->lssei_ssl_strength = default_ssl_strength;
ssip->lssei_using_pcks_fns = using_pkcs_functions;
ssip->lssei_certdbh = CERT_GetDefaultCertDB();
/*
* override a few functions, saving a pointer to the standard function
@ -489,6 +500,47 @@ ldapssl_enable_clientauth( LDAP *ld, char *keynickname,
}
/*
* Set the SSL strength for an existing SSL-enabled LDAP session handle.
*
* See the description of ldapssl_serverauth_init() above for valid
* sslstrength values. If ld is NULL, the default for new LDAP session
* handles is set.
*
* Returns 0 if all goes well and -1 if an error occurs.
*/
int
LDAP_CALL
ldapssl_set_strength( LDAP *ld, int sslstrength )
{
int rc = 0; /* assume success */
if ( sslstrength != LDAPSSL_AUTH_WEAK &&
sslstrength != LDAPSSL_AUTH_CERT &&
sslstrength != LDAPSSL_AUTH_CNCHECK ) {
rc = -1;
} else {
if ( NULL == ld ) { /* set default strength */
default_ssl_strength = sslstrength;
} else { /* set session-specific strength */
PRLDAPSessionInfo sei;
LDAPSSLSessionInfo *sseip;
memset( &sei, 0, sizeof( sei ));
sei.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
if ( prldap_get_session_info( ld, NULL, &sei ) == LDAP_SUCCESS ) {
sseip = (LDAPSSLSessionInfo *)sei.seinfo_appdata;
sseip->lssei_ssl_strength = sslstrength;
} else {
rc = -1;
}
}
}
return( rc );
}
static void
ldapssl_free_session_info( LDAPSSLSessionInfo **ssipp )
{
@ -523,27 +575,25 @@ ldapssl_free_socket_info( LDAPSSLSocketInfo **soipp )
* the cn is checked against the host name, set with SSL_SetURL()
*/
/*
* XXXceb NOTE, this needs to be fixed to check for the MITM hack 980623
*/
static int
ldapssl_AuthCertificate(void *certdbarg, PRFileDesc *fd, PRBool checkSig,
ldapssl_AuthCertificate(void *sessionarg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer)
{
SECStatus rv = SECFailure;
CERTCertDBHandle * handle;
CERTCertificate * cert;
SECCertUsage certUsage;
char * hostname = (char *)0;
if (!certdbarg || !socket)
SECStatus rv = SECFailure;
LDAPSSLSessionInfo *sseip;
CERTCertificate *cert;
SECCertUsage certUsage;
char *hostname = (char *)0;
if (!sessionarg || !socket) {
return rv;
}
if (LDAPSSL_AUTH_WEAK == get_ssl_strength() )
return SECSuccess;
sseip = (LDAPSSLSessionInfo *)sessionarg;
handle = (CERTCertDBHandle *)certdbarg;
if (LDAPSSL_AUTH_WEAK == sseip->lssei_ssl_strength ) { /* no check */
return SECSuccess;
}
if ( isServer ) {
certUsage = certUsageSSLClient;
@ -552,13 +602,14 @@ ldapssl_AuthCertificate(void *certdbarg, PRFileDesc *fd, PRBool checkSig,
}
cert = SSL_PeerCertificate( fd );
rv = CERT_VerifyCertNow(handle, cert, checkSig, certUsage, NULL);
rv = CERT_VerifyCertNow(sseip->lssei_certdbh, cert, checkSig,
certUsage, NULL);
if ( rv != SECSuccess || isServer )
if ( rv != SECSuccess || isServer ) {
return rv;
}
if ( LDAPSSL_AUTH_CNCHECK == get_ssl_strength() )
{
if ( LDAPSSL_AUTH_CNCHECK == sseip->lssei_ssl_strength ) {
/* cert is OK. This is the client side of an SSL connection.
* Now check the name field in the cert against the desired hostname.
* NB: This is our only defense against Man-In-The-Middle (MITM)

View File

@ -10,6 +10,7 @@ ldapssl_advclientauth_init
ldapssl_pkcs_init
ldapssl_err2string
ldapssl_serverauth_init
ldapssl_set_strength
# the last Windows ordinal number that has been reserved for SSL is 469.
# Windows ordinals 1100-1150 are reserved for privately/non-published

View File

@ -12,6 +12,7 @@
ldapssl_pkcs_init @457
ldapssl_err2string @458
ldapssl_serverauth_init @459
ldapssl_set_strength @460
; the last Windows ordinal number that has been reserved for SSL is 469.
; Windows ordinals 1100-1150 are reserved for privately/non-published

View File

@ -18,6 +18,7 @@ EXPORTS
ldapssl_pkcs_init @457
ldapssl_err2string @458
ldapssl_serverauth_init @459
ldapssl_set_strength @460
; the last Windows ordinal number that has been reserved for SSL is 469.
; Windows ordinals 1100-1150 are reserved for privately/non-published

View File

@ -18,6 +18,7 @@ EXPORTS
ldapssl_pkcs_init @457
ldapssl_err2string @458
ldapssl_serverauth_init @459
ldapssl_set_strength @460
; the last Windows ordinal number that has been reserved for SSL is 469.
; Windows ordinals 1100-1150 are reserved for privately/non-published