/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1986 - 2004, All Rights Reserved. */ /* */ /* PROPRIETARY AND CONFIDENTIAL */ /* */ /* MODULE NAME : ard_vstr.c */ /* PRODUCT(S) : ASN1DE */ /* */ /* MODULE DESCRIPTION : */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 12/05/05 JRB 09 Add asn1r_get_vstr_maxlen. */ /* 03/22/05 JRB 08 Fix cast in log macro. */ /* 01/16/04 EJV 07 Added typecast to elim warning on AIX. */ /* 09/24/03 JRB 06 Fix to properly decode 0-length UTF8string. */ /* 04/22/03 JRB 05 Allow fixed len UTF8 only if local fmt=UTF16.*/ /* 04/02/03 JRB 04 Add UTF8string support (asn1r_get_utf8) */ /* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ /* 09/13/99 MDE 02 Added SD_CONST modifiers */ /* 07/26/99 MDE 01 New module, derived from ad_vstr.c */ /************************************************************************/ #include "glbtypes.h" #include "sysincs.h" #include #include "asn1r.h" #include "asn1log.h" /************************************************************************/ /* For debug version, use a static pointer to avoid duplication of */ /* __FILE__ strings. */ #ifdef DEBUG_SISCO SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; #endif /************************************************************************/ /* asn1r_get_vstr_maxlen */ /* Just like asn1r_get_vstr but checks the string length. */ /* NOTE: caller's buffer must be 1 byte bigger than max_len to allow */ /* room for NULL terminator. */ /************************************************************************/ ST_RET asn1r_get_vstr_maxlen (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT max_len) { if (aCtx->asn1r_elmnt_len > max_len) { ALOG_ERR0("ASN.1 decode: visible string too long"); return (SD_FAILURE); } else return (asn1r_get_vstr (aCtx, ptr)); } /************************************************************************/ /* get_vstr */ /* Reads visible character data from message into selected buffer. If */ /* character is encountered which is not valid for ASN.1 VisibleString */ /* type, error code will be returned as function return value. Other- */ /* wise, function return value will be zero. The calling function must */ /* verify that buffer is big enough. Conversion from ASCII to local */ /* character representation is not necessary for MS-DOS. */ /************************************************************************/ ST_RET asn1r_get_vstr (ASN1_DEC_CTXT *ac, ST_CHAR *ptr) { ST_INT i; #ifdef DEBUG_ASN1_DECODE if (!ptr) { slogCallStack (sLogCtrl, "get_vstr: attempt to reference through a NULL pointer"); return(SD_FAILURE); } #endif for (i = ac->asn1r_elmnt_len; i; --i) { *ptr = (ST_CHAR) *(ac->asn1r_field_ptr++); /* Move character to user buffer. */ if (*ptr < ' ') /* Check that character is not a control char. */ { ALOG_NERR1 ("ASN.1 decode: invalid character (0x%02x) in visible string", (ST_UINT)(ST_UCHAR) *ptr); /* 2 casts to avoid sign extension*/ return (SD_FAILURE); } ptr++; } *ptr = '\x00'; /* Null terminate the visible string. */ return(SD_SUCCESS); /* If no problelms, return success. */ } /************************************************************************/ /* asn1r_get_utf8 */ /* Reads Unicode UTF8 string data from message into selected buffer. If */ /* character is encountered which is not valid for ASN.1 UTF8string */ /* type, error code will be returned as function return value. Other- */ /* wise, function return value will be zero. The calling function must */ /* verify that buffer is big enough. */ /************************************************************************/ ST_RET asn1r_get_utf8 (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT el_len) { ST_INT dst_len, local_len; #ifdef DEBUG_ASN1_DECODE if (!ptr) { slogCallStack (sLogCtrl, "get_utf8: attempt to reference through a NULL pointer"); return(SD_FAILURE); } #endif /* Convert from UTF8 to local format. Input is NOT NULL terminated. * abs (el_len) = maximum number of Unicode "characters". * Multiply by the maximum size of each Unicode "character". */ #if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16) dst_len = abs(el_len)*2; #else /* default is UTF8 */ dst_len = abs(el_len)*4; #endif local_len = asn1r_utf8_to_local (ptr, dst_len, (ST_CHAR *) aCtx->asn1r_field_ptr, aCtx->asn1r_elmnt_len); if (local_len < 0) { ALOG_NERR0 ("ASN.1 decode: UTF8 to local conversion failed"); return(SD_FAILURE); } /* If this is "fixed length" (el_len>0), length must match. */ #if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16) if (el_len > 0 && el_len*2 != local_len) /* Fixed len string */ { ALOG_NERR2 ("ASN.1 decode: expected UTF8string%d, received UTF8string%d", el_len, local_len/2); return (SD_FAILURE); } *(ST_UINT16*)(ptr+local_len) = 0; /* add "2 byte" NULL */ #else /* default is UTF8 */ if (el_len > 0) /* Fixed len string */ { /* This error should never occur because no way to define fixed len UTF8.*/ ALOG_ERR0 ("ASN.1 decode: 'FIXED LENGTH' UTF8string not supported on this platform"); return (SD_FAILURE); } ptr[local_len] = '\0'; /* add NULL */ #endif aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* Update decode ptr*/ return(SD_SUCCESS); } #if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16) #if defined(_WIN32) #include /************************************************************************/ /* On Windows, the local format is UTF16, so this function converts */ /* from UTF8 string to UTF16 string. */ /* CRITICAL: "dst" is NOT automatically NULL terminated, so calling */ /* function must do so if necessary. */ /* dst_len = num bytes in dst "UTF16" string. */ /* src_len = num bytes in src "UTF8" string. */ /************************************************************************/ ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len) { int ret; ST_UINT16 *dst_utf16 = (ST_UINT16 *) dst; /* This function expects the max number of UTF16 chars (2 bytes per char) * in the last arg, so divide "dst_len" by 2. * It does NOT automatically NULL terminate, so neither does this function. * It returns the number of UTF16 chars converted, so we multiply the * return value by 2 to return the number of bytes. */ /*renxiaobao UTF8ÖÐÎıàÂëÐÞ¸Ä*/ #ifdef WIN32 memcpy(dst,src,src_len); return src_len; #else ret = MultiByteToWideChar (CP_UTF8, 0, src, src_len, dst_utf16, dst_len/2); if (ret >= 0) return (ret*2); /* success */ return (-1); /* error */ #endif } #else /* All other systems */ #error Unicode UTF16 currently only supported on Windows #endif #else /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */ /************************************************************************/ /* This function should work on any system where the local Unicode */ /* format is UTF8. The ASN.1 format is also UTF8, so this function */ /* basically just copies the string. */ /* CRITICAL: dst_len must be >= src_len */ /************************************************************************/ ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len) { if (dst_len >= src_len) /* make sure dst has room */ { if (src_len > 0) memcpy (dst, src, src_len); return (src_len); /* success */ } return (-1); /* error */ } #endif /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */