📄 ext_add.c
字号:
/* Add an attribute field to a list of attributes at the appropriate
location */
int addAttributeField( ATTRIBUTE_LIST **attributeListPtr,
const CRYPT_ATTRIBUTE_TYPE fieldID,
const CRYPT_ATTRIBUTE_TYPE subFieldID,
const void *data, const int dataLength,
const int flags, CRYPT_ATTRIBUTE_TYPE *errorLocus,
CRYPT_ERRTYPE_TYPE *errorType )
{
const ATTRIBUTE_TYPE attributeType = \
( fieldID >= CRYPT_CERTINFO_FIRST_CMS ) ? \
ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;
CRYPT_ATTRIBUTE_TYPE attributeID;
const ATTRIBUTE_INFO *attributeInfoPtr = fieldIDToAttribute( attributeType,
fieldID, subFieldID, &attributeID );
ATTRIBUTE_LIST *newElement, *insertPoint, *prevElement = NULL;
BOOLEAN isNumeric = FALSE;
int storageSize, status;
assert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST * ) ) );
assert( fieldID >= CRYPT_CERTINFO_FIRST_EXTENSION && \
fieldID <= CRYPT_CERTINFO_LAST );
assert( dataLength == CRYPT_UNUSED || \
( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE ) );
assert( dataLength == CRYPT_UNUSED || isReadPtr( data, dataLength ) );
assert( !( flags & ATTR_FLAG_INVALID ) );
assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
/* Check the field's validity */
status = checkAttributeField( *attributeListPtr, attributeInfoPtr,
fieldID, subFieldID, data, dataLength,
flags, errorType );
if( cryptStatusError( status ) )
{
if( status == OK_SPECIAL )
/* Special indicator to tell us that the value is non-string
numeric data */
isNumeric = TRUE;
else
{
if( errorType != NULL && *errorType != CRYPT_ERRTYPE_NONE )
/* If we encountered an error that sets the error type,
record the locus */
*errorLocus = fieldID;
return( status );
}
}
assert( isNumeric || \
( ( attributeInfoPtr->fieldType == FIELDTYPE_DN || \
attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER ) && \
dataLength == CRYPT_UNUSED ) || \
dataLength > 0 );
/* Find the location at which to insert this attribute field (this
assumes that the fieldIDs are defined in sorted order) */
insertPoint = *attributeListPtr;
while( insertPoint != NULL && \
insertPoint->fieldID != CRYPT_ATTRIBUTE_NONE && \
insertPoint->fieldID <= fieldID )
{
assert( !isValidAttributeField( insertPoint->next ) || \
insertPoint->attributeID <= insertPoint->next->attributeID );
/* If it's a composite field that can have multiple fields with the
same field ID (e.g. a GeneralName), exit if the overall field ID
is greater (the component belongs to a different field entirely)
or if the field ID is the same and the subfield ID is greater (if
the component belongs to the same field) */
if( subFieldID != CRYPT_ATTRIBUTE_NONE && \
insertPoint->fieldID == fieldID && \
insertPoint->subFieldID > subFieldID )
break;
prevElement = insertPoint;
insertPoint = insertPoint->next;
}
insertPoint = prevElement;
/* Allocate memory for the new element and copy the information across.
If it's a simple type we can assign it to the simple value in the
element itself, otherwise we copy it into the storage in the element.
Something that encodes to NULL isn't really a numeric type, but we
class it as such so that any attempt to read it returns CRYPT_UNUSED
as the value */
storageSize = ( isNumeric || \
attributeInfoPtr->fieldType == FIELDTYPE_DN || \
attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER ) ? \
0 : dataLength;
if( ( newElement = ( ATTRIBUTE_LIST * ) \
clAlloc( "addAttributeField", sizeof( ATTRIBUTE_LIST ) + \
storageSize ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
initVarStruct( newElement, ATTRIBUTE_LIST, storageSize );
newElement->attributeID = attributeID;
newElement->fieldID = fieldID;
newElement->subFieldID = subFieldID;
newElement->flags = flags;
newElement->fieldType = attributeInfoPtr->fieldType;
switch( attributeInfoPtr->fieldType )
{
case BER_INTEGER:
case BER_ENUMERATED:
case BER_BITSTRING:
case BER_BOOLEAN:
case BER_NULL:
case FIELDTYPE_CHOICE:
newElement->intValue = *( ( int * ) data );
if( attributeInfoPtr->fieldType == BER_BOOLEAN )
/* Force it to the correct type if it's a boolean */
newElement->intValue = ( newElement->intValue ) ? TRUE : FALSE;
if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
/* For encoding purposes the subfield ID is set to the ID of
the CHOICE selection */
newElement->subFieldID = newElement->intValue;
break;
case BER_OBJECT_IDENTIFIER:
/* If it's a BER/DER-encoded OID copy it in as is, otherwise
convert it from the text form */
if( ( ( BYTE * ) data )[ 0 ] == BER_OBJECT_IDENTIFIER )
{
memcpy( newElement->value, data, dataLength );
newElement->valueLength = dataLength;
}
else
newElement->valueLength = textToOID( data, dataLength,
newElement->value );
break;
case FIELDTYPE_DN:
/* When creating a new cert, this is a placeholder to indicate
that a DN structure is being instantiated. When reading an
encoded cert, this is the decoded DN structure */
newElement->value = ( *( ( int * ) data ) == CRYPT_UNUSED ) ? \
NULL : ( void * ) data;
break;
case FIELDTYPE_IDENTIFIER:
/* This is a placeholder entry with no explicit value */
newElement->intValue = CRYPT_UNUSED;
break;
default:
assert( dataLength > 0 );
memcpy( newElement->value, data, dataLength );
newElement->valueLength = dataLength;
break;
}
insertDoubleListElement( attributeListPtr, insertPoint, newElement );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Delete Attribute Data *
* *
****************************************************************************/
/* Delete an attribute/attribute field from a list of attributes, updating
the list cursor at the same time. This is a somewhat ugly kludge, it's
not really possible to do this cleanly since deleting attributes affects
the attribute cursor */
int deleteAttributeField( ATTRIBUTE_LIST **attributeListPtr,
ATTRIBUTE_LIST **listCursorPtr,
ATTRIBUTE_LIST *listItem,
const void *dnCursor )
{
ATTRIBUTE_LIST *listPrevPtr = listItem->prev;
ATTRIBUTE_LIST *listNextPtr = listItem->next;
BOOLEAN deletedDN = FALSE;
assert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST * ) ) );
assert( isWritePtr( *attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );
assert( listCursorPtr == NULL || \
isWritePtr( listCursorPtr, sizeof( ATTRIBUTE_LIST * ) ) );
assert( isWritePtr( listItem, sizeof( ATTRIBUTE_LIST ) ) );
/* If we're about to delete the field that's pointed to by the attribute
cursor, advance the cursor to the next field. If there's no next
field, move it to the previous field. This behaviour is the most
logically consistent, it means that we can do things like deleting an
entire attribute list by repeatedly deleting a field */
if( listCursorPtr != NULL && *listCursorPtr == listItem )
*listCursorPtr = ( listNextPtr != NULL ) ? listNextPtr : listPrevPtr;
/* Remove the item from the list */
deleteDoubleListElement( attributeListPtr, listItem );
/* Clear all data in the item and free the memory */
if( listItem->fieldType == FIELDTYPE_DN )
{
/* If we've deleted the DN at the current cursor position, remember
this so that we can warn the caller */
if( dnCursor != NULL && dnCursor == &listItem->value )
deletedDN = TRUE;
deleteDN( ( void ** ) &listItem->value );
}
endVarStruct( listItem, ATTRIBUTE_LIST );
clFree( "deleteAttributeField", listItem );
/* If we deleted the DN at the current cursor position, return a
special-case code to let the caller know */
return( deletedDN ? OK_SPECIAL : CRYPT_OK );
}
int deleteAttribute( ATTRIBUTE_LIST **attributeListPtr,
ATTRIBUTE_LIST **listCursorPtr,
ATTRIBUTE_LIST *listItem,
const void *dnCursor )
{
CRYPT_ATTRIBUTE_TYPE attributeID;
ATTRIBUTE_LIST *attributeListCursor;
int status = CRYPT_OK;
assert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST * ) ) );
assert( isWritePtr( *attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );
assert( isWritePtr( listItem, sizeof( ATTRIBUTE_LIST ) ) );
/* If it's a blob-type attribute, everything is contained in this one
list item so we only need to destroy that */
if( isBlobAttribute( listItem ) )
return( deleteAttributeField( attributeListPtr, listCursorPtr,
listItem, NULL ) );
/* If it's a field that denotes an entire (constructed) attribute, it
won't have an entry in the list, so we find the first field of the
constructed attribute that's present in the list and start deleting
from that point */
if( isCompleteAttribute( listItem ) )
{
for( attributeListCursor = *attributeListPtr;
attributeListCursor != NULL && \
attributeListCursor->attributeID != listItem->intValue;
attributeListCursor = attributeListCursor->next );
}
else
/* The list item is a field in the attribute, find the start of the
fields in this attribute */
attributeListCursor = findAttributeStart( listItem );
assert( isWritePtr( attributeListCursor, sizeof( ATTRIBUTE_LIST ) ) );
attributeID = attributeListCursor->attributeID;
/* It's an item with multiple fields, destroy each field separately */
while( attributeListCursor != NULL && \
attributeListCursor->attributeID == attributeID )
{
ATTRIBUTE_LIST *itemToFree = attributeListCursor;
int localStatus;
attributeListCursor = attributeListCursor->next;
localStatus = deleteAttributeField( attributeListPtr, listCursorPtr,
itemToFree, dnCursor );
if( cryptStatusError( localStatus ) && status != OK_SPECIAL )
/* Remember the error code, giving priority to DN cursor-
modification notifications */
status = localStatus;
}
return( status );
}
/* Delete a complete set of attributes */
void deleteAttributes( ATTRIBUTE_LIST **attributeListPtr )
{
ATTRIBUTE_LIST *attributeListCursor = *attributeListPtr;
assert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST * ) ) );
/* If the list was empty, return now */
if( attributeListCursor == NULL )
return;
/* Destroy any remaining list items */
while( attributeListCursor != NULL )
{
ATTRIBUTE_LIST *itemToFree = attributeListCursor;
attributeListCursor = attributeListCursor->next;
deleteAttributeField( attributeListPtr, NULL, itemToFree, NULL );
}
assert( *attributeListPtr == NULL );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -