📄 dbxldap.c
字号:
return( CRYPT_ERROR_NOTFOUND );
#ifndef NETSCAPE_CLIENT
case LDAP_NOT_SUPPORTED:
return( CRYPT_ERROR_NOTAVAIL );
#endif /* NETSCAPE_CLIENT */
case LDAP_RESULTS_TOO_LARGE:
return( CRYPT_ERROR_OVERFLOW );
}
return( defaultError );
}
/* Copy attribute information into an LDAPMod structure so it can be written to
the directory */
static LDAPMod *copyAttribute( const char *attributeName,
const void *attributeValue,
const int attributeLength )
{
LDAPMod *ldapModPtr;
/* Allocate room for the LDAPMod structure and the data pointers.
mod_values and mod_bvalues members have the same representation so we
can allocate them with the same malloc */
if( ( ldapModPtr = ( LDAPMod * ) malloc( sizeof( LDAPMod ) ) ) == NULL )
return( NULL );
if( ( ldapModPtr->mod_values = malloc( 2 * sizeof( void * ) ) ) == NULL )
{
free( ldapModPtr );
return( NULL );
}
/* Set up the pointers to the attribute information. This differs
slightly depending on whether we're adding text or binary data */
if( !attributeLength )
{
ldapModPtr->mod_op = LDAP_MOD_ADD;
ldapModPtr->mod_type = ( char * ) attributeName;
ldapModPtr->mod_values[ 0 ] = ( char * ) attributeValue;
ldapModPtr->mod_values[ 1 ] = NULL;
}
else
{
if( ( ldapModPtr->mod_bvalues[ 0 ] = \
malloc( sizeof( struct berval ) ) ) == NULL )
{
free( ldapModPtr->mod_values );
free( ldapModPtr );
return( NULL );
}
ldapModPtr->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
ldapModPtr->mod_type = ( char * ) attributeName;
ldapModPtr->mod_bvalues[ 0 ]->bv_len = attributeLength;
ldapModPtr->mod_bvalues[ 0 ]->bv_val = ( char * ) attributeValue;
ldapModPtr->mod_bvalues[ 1 ] = NULL;
}
return( ldapModPtr );
}
/* Encode DN information in the RFC 1779 reversed format. We don't have to
check for overflows because the cert.management code limits the size of
each component to a small fraction of the total buffer size */
static void copyComponent( char *dest, char *src )
{
while( *src )
{
const char ch = *src++;
if( ch == ',' )
*dest++ = '\\';
*dest++ = ch;
}
*dest++ = '\0';
}
static int encodeDN( char *dn, char *C, char *SP, char *L, char *O, char *OU,
char *CN )
{
char *bufPtr = dn;
strcpy( dn, "CN=" );
strcpy( dn + 3, CN );
bufPtr += strlen( bufPtr );
if( *OU )
{
strcpy( bufPtr, ",OU=" );
copyComponent( bufPtr + 4, OU );
bufPtr += strlen( bufPtr );
}
if( *O )
{
strcpy( bufPtr, ",O=" );
copyComponent( bufPtr + 3, O );
bufPtr += strlen( bufPtr );
}
if( *L )
{
strcpy( bufPtr, ",L=" );
copyComponent( bufPtr + 3, L );
bufPtr += strlen( bufPtr );
}
if( *SP )
{
strcpy( bufPtr, ",ST=" ); /* Not to be confused with ST=street */
copyComponent( bufPtr + 4, SP );
bufPtr += strlen( bufPtr );
}
strcpy( bufPtr, ",C=" );
copyComponent( bufPtr + 3, C );
return( CRYPT_OK );
}
/* Decompose an LDAP URL into a server name and optional port */
static int parseURL( char *ldapServer, const char *url )
{
int ldapPort = LDAP_PORT, len;
/* Skip a leading URL specifier if this is present */
if( !strnicmp( url, "ldap://", 7 ) )
url += 7;
else
if( !strnicmp( url, "ldaps://", 8 ) )
url += 8;
/* Decompose what's left into a FQDN and port */
for( len = 0; url[ len ]; len++ )
if( url[ len ] == ':' )
break;
strncpy( ldapServer, url, len );
ldapServer[ len ] = '\0';
if( url[ len ] )
ldapPort = atoi( url + len + 1 );
return( ldapPort );
}
/****************************************************************************
* *
* Directory Open/Close Routines *
* *
****************************************************************************/
/* Close a previously-opened LDAP connection. We have to have this before
the init function since it may be called by it if the open process fails.
This is necessary because the complex LDAP open may require a fairly
extensive cleanup afterwards */
static void shutdownFunction( KEYSET_INFO *keysetInfo )
{
ldap_unbind( keysetInfo->keysetLDAP.ld );
keysetInfo->keysetLDAP.ld = NULL;
}
/* Open a connection to an LDAP directory */
static int initFunction( KEYSET_INFO *keysetInfo, const char *server,
const char *user, const CRYPT_KEYOPT_TYPE options )
{
char ldapServer[ MAX_URL_SIZE ];
int maxEntries = 2, timeout, ldapPort, ldapStatus = LDAP_OTHER;
/* Check the URL. The Netscape API provides the function
ldap_is_ldap_url() for this, but this requires a complete LDAP URL
rather than just a server name and port */
if( strlen( server ) > MAX_URL_SIZE - 1 )
return( CRYPT_ARGERROR_STR1 );
ldapPort = parseURL( ldapServer, server );
/* Open the connection to the server */
if( ( keysetInfo->keysetLDAP.ld = \
ldap_init( ldapServer, ldapPort ) ) == NULL )
return( CRYPT_ERROR_OPEN );
if( ( ldapStatus = \
ldap_simple_bind_s( keysetInfo->keysetLDAP.ld,
( char * ) user, NULL ) ) != LDAP_SUCCESS )
{
getErrorInfo( keysetInfo, ldapStatus );
ldap_unbind( keysetInfo->keysetLDAP.ld );
keysetInfo->keysetLDAP.ld = NULL;
return( mapLDAPerror( ldapStatus, CRYPT_ERROR_OPEN ) );
}
/* Set the search timeout and limit the maximum number of returned
entries to 2 */
krnlSendMessage( keysetInfo->ownerHandle, RESOURCE_IMESSAGE_GETATTRIBUTE,
&timeout, CRYPT_OPTION_NET_CONNECTTIMEOUT );
ldap_set_option( keysetInfo->keysetLDAP.ld, LDAP_OPT_TIMELIMIT, &timeout );
ldap_set_option( keysetInfo->keysetLDAP.ld, LDAP_OPT_SIZELIMIT, &maxEntries );
/* Set up the names of the objects and attributes */
assignFieldName( keysetInfo->ownerHandle,
keysetInfo->keysetLDAP.nameObjectClass,
CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS );
assignFieldName( keysetInfo->ownerHandle,
keysetInfo->keysetLDAP.nameFilter,
CRYPT_OPTION_KEYS_LDAP_FILTER );
assignFieldName( keysetInfo->ownerHandle,
keysetInfo->keysetLDAP.nameCACert,
CRYPT_OPTION_KEYS_LDAP_CACERTNAME );
assignFieldName( keysetInfo->ownerHandle,
keysetInfo->keysetLDAP.nameCert,
CRYPT_OPTION_KEYS_LDAP_CERTNAME );
assignFieldName( keysetInfo->ownerHandle,
keysetInfo->keysetLDAP.nameCRL,
CRYPT_OPTION_KEYS_LDAP_CRLNAME );
assignFieldName( keysetInfo->ownerHandle,
keysetInfo->keysetLDAP.nameEmail,
CRYPT_OPTION_KEYS_LDAP_EMAILNAME );
krnlSendMessage( keysetInfo->ownerHandle, RESOURCE_IMESSAGE_GETATTRIBUTE,
&keysetInfo->keysetLDAP.objectType,
CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Directory Access Routines *
* *
****************************************************************************/
/* Retrieve a key attribute from an LDAP directory */
static int getItemFunction( KEYSET_INFO *keysetInfo,
CRYPT_HANDLE *iCryptHandle,
const KEYMGMT_ITEM_TYPE itemType,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
void *auxInfo, int *auxInfoLength,
const int flags )
{
LDAPMessage *result, *resultEntry;
BerElement *ber;
struct berval **valuePtrs;
char *attributePtr;
int status = CRYPT_OK;
assert( keyIDtype != CRYPT_KEYID_NONE || iCryptHandle != NULL );
assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
assert( auxInfo == NULL ); assert( *auxInfoLength == 0 );
/* If we're not in the middle of an ongoing fetch, send the query to the
server */
if( !keysetInfo->queryInProgress )
{
const CRYPT_CERTTYPE_TYPE objectType = keysetInfo->keysetLDAP.objectType;
const char *certAttributes[] = { keysetInfo->keysetLDAP.nameCert, NULL };
const char *caCertAttributes[] = { keysetInfo->keysetLDAP.nameCACert, NULL };
const char *crlAttributes[] = { keysetInfo->keysetLDAP.nameCRL, NULL };
char dn[ MAX_DN_STRINGSIZE ];
int ldapStatus = LDAP_OTHER;
assert( keyIDtype == CRYPT_KEYID_NAME || \
keyIDtype == CRYPT_KEYID_EMAIL );
/* Convert the DN into a null-terminated form */
if( keyIDlength > MAX_DN_STRINGSIZE - 1 )
return( CRYPT_ARGERROR_STR1 );
memcpy( dn, keyID, keyIDlength );
dn[ keyIDlength ] = '\0';
/* Try and retrieve the entry for this DN from the directory. We use
a base specified by the DN, a chop of 0 (to return only the
current entry), any object class (to get around the problem of
implementations which stash certs in whatever they feel like), and
look for a certificate attribute. If the search fails for this
attribute, we try again but this time go for a CA certificate
attribute which unfortunately slows down the search somewhat when
the cert isn't found but can't really be avoided since there's no
way to tell in advance whether a cert will be an end entity or a
CA cert. To complicate things even further, we may also need to
check for a CRL in case this is what the user is after */
if( objectType == CRYPT_CERTTYPE_NONE || \
objectType == CRYPT_CERTTYPE_CERTIFICATE )
ldapStatus = ldap_search_s( keysetInfo->keysetLDAP.ld, dn,
LDAP_SCOPE_BASE,
keysetInfo->keysetLDAP.nameFilter,
( char ** ) certAttributes, 0, &result );
if( ldapStatus != LDAP_SUCCESS && \
( objectType == CRYPT_CERTTYPE_NONE || \
objectType == CRYPT_CERTTYPE_CERTIFICATE ) )
ldapStatus = ldap_search_s( keysetInfo->keysetLDAP.ld, dn,
LDAP_SCOPE_BASE,
keysetInfo->keysetLDAP.nameFilter,
( char ** ) caCertAttributes, 0, &result );
if( ldapStatus != LDAP_SUCCESS && \
( objectType == CRYPT_CERTTYPE_NONE || \
objectType == CRYPT_CERTTYPE_CRL ) )
ldapStatus = ldap_search_s( keysetInfo->keysetLDAP.ld, dn,
LDAP_SCOPE_BASE,
keysetInfo->keysetLDAP.nameFilter,
( char ** ) crlAttributes, 0, &result );
if( ldapStatus != LDAP_SUCCESS )
{
getErrorInfo( keysetInfo, ldapStatus );
return( mapLDAPerror( ldapStatus, CRYPT_ERROR_READ ) );
}
/* We got something, start fetching the results */
if( ( resultEntry = ldap_first_entry( keysetInfo->keysetLDAP.ld, result ) ) == NULL )
{
ldap_msgfree( result );
return( CRYPT_ERROR_NOTFOUND );
}
/* If we've been passed a null crypt handle, this is the start of a
general-purpose query rather than a single cert fetch, save the
query state and record the fact that we're in the middle of a
query */
if( iCryptHandle == NULL )
{
keysetInfo->keysetLDAP.result = result;
keysetInfo->queryInProgress = TRUE;
}
}
else
{
/* We're in an ongoing query, try and fetch the next set of results */
if( ( resultEntry = ldap_next_entry( keysetInfo->keysetLDAP.ld,
keysetInfo->keysetLDAP.result ) ) == NULL )
{
/* No more results, wrap up the processing */
ldap_msgfree( keysetInfo->keysetLDAP.result );
keysetInfo->keysetLDAP.result = NULL;
return( CRYPT_ERROR_COMPLETE );
}
}
/* Copy out the certificate */
if( ( attributePtr = ldap_first_attribute( keysetInfo->keysetLDAP.ld,
resultEntry, &ber ) ) == NULL )
{
if( keysetInfo->queryInProgress )
ldap_msgfree( result );
return( CRYPT_ERROR_NOTFOUND );
}
valuePtrs = ldap_get_values_len( keysetInfo->keysetLDAP.ld, resultEntry,
attributePtr );
if( valuePtrs != NULL )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
/* Create a certificate object from the returned data */
setMessageCreateObjectIndirectInfo( &createInfo, valuePtrs[ 0 ]->bv_val,
valuePtrs[ 0 ]->bv_len );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -