📄 ext_copy.c
字号:
/****************************************************************************
* *
* Certificate Attribute Copy Routines *
* Copyright Peter Gutmann 1996-2004 *
* *
****************************************************************************/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL ) || defined( INC_CHILD )
#include "cert.h"
#include "certattr.h"
#else
#include "cert/cert.h"
#include "cert/certattr.h"
#endif /* Compiler-specific includes */
/* When replicating attributes from one type of cert object to another (for
example from an issuer cert to a subject cert when issuing a new cert)
we may have to adjust the attribute info based on the source and
destination object roles. The following values denote the different
copy types that we have to handle. Usually this is a direct copy,
however if we're copying from subject to issuer we have to adjust
attribute IDs such as the altName (subjectAltName -> issuerAltName), if
we're copying from issuer to subject we have to adjust path length-based
contraints since the new subject is one further down the chain */
typedef enum {
COPY_DIRECT, /* Direct attribute copy */
COPY_SUBJECT_TO_ISSUER, /* Copy of subject attributes to issuer cert */
COPY_ISSUER_TO_SUBJECT, /* Copy of issuer attributes to subject cert */
COPY_LAST /* Last valid copy type */
} COPY_TYPE;
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Copy an attribute field */
static int copyAttributeField( ATTRIBUTE_LIST **destAttributeField,
const ATTRIBUTE_LIST *srcAttributeField )
{
ATTRIBUTE_LIST *newElement;
int status = CRYPT_OK;
assert( isWritePtr( destAttributeField, sizeof( ATTRIBUTE_LIST * ) ) );
assert( isReadPtr( srcAttributeField, sizeof( ATTRIBUTE_LIST ) ) );
/* Allocate memory for the new element and copy the information across */
*destAttributeField = NULL;
if( ( newElement = ( ATTRIBUTE_LIST * ) \
clAlloc( "copyAttributeField", \
sizeofVarStruct( srcAttributeField, \
ATTRIBUTE_LIST ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
copyVarStruct( newElement, srcAttributeField, ATTRIBUTE_LIST );
if( srcAttributeField->fieldType == FIELDTYPE_DN )
{
/* If the field contains a DN, copy the DN across */
status = copyDN( ( void ** ) &newElement->value,
srcAttributeField->value );
if( cryptStatusError( status ) )
{
endVarStruct( newElement, ATTRIBUTE_LIST );
clFree( "copyAttributeField", newElement );
return( status );
}
}
newElement->next = newElement->prev = NULL;
*destAttributeField = newElement;
return( CRYPT_OK );
}
/* Copy an attribute from one attribute list to another. This is an all-or-
nothing copy in that it either copies a complete attribute or nothing at
all */
static int copyAttribute( ATTRIBUTE_LIST **destListHeadPtr,
const ATTRIBUTE_LIST *srcListPtr,
const COPY_TYPE copyType )
{
const CRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;
CRYPT_ATTRIBUTE_TYPE newAttributeID = attributeID;
ATTRIBUTE_LIST *newAttributeListHead = NULL, *newAttributeListTail;
ATTRIBUTE_LIST *insertPoint, *prevElement = NULL;
assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
assert( copyType >= COPY_DIRECT && copyType < COPY_LAST );
/* If we're re-mapping the destination attribute ID (see the comment
further down), we have to insert it at a point corresponding to the
re-mapped ID, not the original ID, to maintain the list's sorted
property */
if( copyType == COPY_SUBJECT_TO_ISSUER )
{
if( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )
newAttributeID = CRYPT_CERTINFO_ISSUERALTNAME;
if( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )
newAttributeID = CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;
}
/* Find the location at which to insert this attribute (this assumes
that the fieldIDs are defined in sorted order) */
for( insertPoint = *destListHeadPtr;
insertPoint != NULL && \
insertPoint->attributeID < newAttributeID && \
insertPoint->fieldID != CRYPT_ATTRIBUTE_NONE;
insertPoint = insertPoint->next )
prevElement = insertPoint;
insertPoint = prevElement;
/* Build a new attribute list containing the attribute fields */
while( srcListPtr != NULL && srcListPtr->attributeID == attributeID )
{
ATTRIBUTE_LIST *newAttributeField;
int status;
/* Copy the field across */
status = copyAttributeField( &newAttributeField, srcListPtr );
if( cryptStatusError( status ) )
{
deleteAttributes( &newAttributeListHead );
return( status );
}
/* If we're copying from an issuer to a subject attribute list and
the field is an altName or keyIdentifier, change the field type
from issuer.subjectAltName to subject.issuerAltName or
issuer.subjectKeyIdentifier to subject.authorityKeyIdentifier */
if( copyType == COPY_SUBJECT_TO_ISSUER )
{
if( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )
newAttributeField->attributeID = \
newAttributeField->fieldID = \
CRYPT_CERTINFO_ISSUERALTNAME;
if( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )
{
newAttributeField->attributeID = \
CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;
newAttributeField->fieldID = \
CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER;
}
}
/* If we're copying from a subject to an issuer attribute list and
it's a path length-based constraint, adjust the constraint value
by one since we're now one further down the chain */
if( copyType == COPY_ISSUER_TO_SUBJECT && \
( newAttributeField->fieldID == \
CRYPT_CERTINFO_PATHLENCONSTRAINT || \
newAttributeField->fieldID == \
CRYPT_CERTINFO_REQUIREEXPLICITPOLICY || \
newAttributeField->fieldID == \
CRYPT_CERTINFO_INHIBITPOLICYMAPPING ) )
{
/* If we're already at a path length of zero we can't reduce it
any further, the best that we can do is to not copy the
attribute */
if( newAttributeField->intValue <= 0 )
deleteAttributeField( &newAttributeField, NULL,
newAttributeField, NULL );
else
newAttributeField->intValue--;
}
/* Append the new field to the new attribute list. We can't use
insertDoubleListElement() for this because we're appending the
element to the list rather than inserting it at a given
position */
if( newAttributeListHead == NULL )
newAttributeListHead = newAttributeListTail = newAttributeField;
else
{
newAttributeListTail->next = newAttributeField;
newAttributeField->prev = newAttributeListTail;
newAttributeListTail = newAttributeField;
}
/* Move on to the next field */
srcListPtr = srcListPtr->next;
}
/* Link the new list into the existing list at the appropriate position */
insertDoubleListElements( destListHeadPtr, insertPoint,
newAttributeListHead, newAttributeListTail );
return( CRYPT_OK );
}
/* Copy a length constraint, adjusting the value by one */
static int copyLengthConstraint( ATTRIBUTE_LIST **destListHeadPtr,
const ATTRIBUTE_LIST *srcListPtr,
const CRYPT_ATTRIBUTE_TYPE fieldID )
{
ATTRIBUTE_LIST *destListPtr;
/* If there's nothing to copy, we're done */
srcListPtr = findAttributeField( srcListPtr, fieldID,
CRYPT_ATTRIBUTE_NONE );
if( srcListPtr == NULL )
return( CRYPT_OK );
/* There's something to copy, if it's not already present in the
destination, just copy it across */
destListPtr = findAttributeField( *destListHeadPtr, fieldID,
CRYPT_ATTRIBUTE_NONE );
if( destListPtr == NULL )
return( copyAttributeField( destListHeadPtr, srcListPtr ) );
/* The same constraint exists in source and destination, set the result
value to the lesser of the two */
if( srcListPtr->intValue < destListPtr->intValue )
destListPtr->intValue = srcListPtr->intValue;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Copy a Complete Attribute List *
* *
****************************************************************************/
/* Copy a complete attribute list */
int copyAttributes( ATTRIBUTE_LIST **destListHeadPtr,
ATTRIBUTE_LIST *srcListPtr,
CRYPT_ATTRIBUTE_TYPE *errorLocus,
CRYPT_ERRTYPE_TYPE *errorType )
{
assert( isWritePtr( destListHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );
assert( isReadPtr( srcListPtr, sizeof( ATTRIBUTE_LIST ) ) );
assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
/* If there are destination attributes present, make a first pass down
the list checking that the attribute to copy isn't already in the
destination attributes, first for recognised attributes and then for
unrecognised ones. We have to do this separately since once we begin
the copy process it's rather hard to undo it. Note that in theory
there are some attributes that can have multiple instances of a field
present, which means that we could allow them to appear in both the
source and destination lists, however if this occurs it's more likely
to be an error than a desire to merge two disparate collections of
attributes */
if( *destListHeadPtr != NULL )
{
ATTRIBUTE_LIST *attributeListCursor;
for( attributeListCursor = srcListPtr;
attributeListCursor != NULL && \
!isBlobAttribute( attributeListCursor );
attributeListCursor = attributeListCursor->next )
{
assert( !isValidAttributeField( attributeListCursor->next ) || \
attributeListCursor->attributeID <= \
attributeListCursor->next->attributeID );
if( findAttributeField( *destListHeadPtr,
attributeListCursor->fieldID, CRYPT_ATTRIBUTE_NONE ) != NULL )
{
*errorLocus = attributeListCursor->fieldID;
*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
return( CRYPT_ERROR_DUPLICATE );
}
}
while( attributeListCursor != NULL )
{
assert( isBlobAttribute( attributeListCursor ) );
if( findAttributeByOID( *destListHeadPtr,
attributeListCursor->oid ) != NULL )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -