443 lines
16 KiB
C
443 lines
16 KiB
C
/************************************************************************/
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
|
/************************************************************************/
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
|
/* 1986 - 2001, All Rights Reserved. */
|
|
/* */
|
|
/* PROPRIETARY AND CONFIDENTIAL */
|
|
/* */
|
|
/* MODULE NAME : ms_ext.c */
|
|
/* PRODUCT(S) : MMSEASE */
|
|
/* */
|
|
/* MODULE DESCRIPTION : */
|
|
/* */
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
|
/* */
|
|
/* MODIFICATION LOG : */
|
|
/* Date Who Rev Comments */
|
|
/* -------- --- ------ ------------------------------------------- */
|
|
/* 03/11/04 GLB 04 Cleaned up "thisFileName" */
|
|
/* 03/31/03 JRB 03 asn1r_get_bitstr: add max_bits arg. */
|
|
/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */
|
|
/* 09/13/99 MDE 01 Added SD_CONST modifiers */
|
|
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
|
|
/* history. */
|
|
/************************************************************************/
|
|
|
|
#include "glbtypes.h"
|
|
#include "sysincs.h"
|
|
#include "glbsem.h"
|
|
|
|
#include "mmsdefs.h"
|
|
#include "asn1defs.h"
|
|
|
|
/************************************************************************/
|
|
/* For debug version, use a static pointer to avoid duplication of */
|
|
/* __FILE__ strings. */
|
|
|
|
#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT)
|
|
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
|
|
ST_VOID ms_get_extern (ASN1_DEC_CTXT *aCtx, EXTERN_INFO *dest);
|
|
|
|
static EXTERN_INFO *ext_dest;
|
|
|
|
static ST_VOID ext_cstr (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID ext_cstr_done (ASN1_DEC_CTXT *aCtx);
|
|
|
|
static ST_INT save_method; /* storage for decode method */
|
|
|
|
/************************************************************************/
|
|
/* ms_decode_extern */
|
|
/************************************************************************/
|
|
|
|
ST_RET ms_decode_extern (ST_UCHAR *asn1ptr, ST_INT asn1len,
|
|
EXTERN_INFO *dest)
|
|
{
|
|
ST_RET ret;
|
|
ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_DEC_CTXT *aCtx = &localDecCtx;
|
|
|
|
memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean. */
|
|
S_LOCK_COMMON_RESOURCES ();
|
|
aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* select tag method */
|
|
aCtx->asn1r_decode_done_fun = asn1r_done_err;/* not legal to be done at this time */
|
|
aCtx->asn1r_err_fun = NULL;
|
|
|
|
ext_dest = dest;
|
|
|
|
ASN1R_TAG_ADD (aCtx, UNI|CONSTR, EXTERN_CODE, ext_cstr);
|
|
asn1r_decode_asn1 (aCtx, asn1ptr,asn1len);/* decode entire ASN.1 'Data' entity */
|
|
|
|
if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) /* check for sucess or return error */
|
|
ret = SD_SUCCESS;
|
|
else
|
|
ret = MVE_DATA_CONVERT;
|
|
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (ret);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ext_cstr */
|
|
/* This function is called when an 'EXTERNAL' data element has been */
|
|
/* found. It will put info into the selected structure. */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID ext_cstr (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
ms_get_extern (aCtx, ext_dest);
|
|
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ext_cstr_done;
|
|
}
|
|
|
|
|
|
static ST_VOID ext_cstr_done (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
aCtx->asn1r_decode_done = SD_TRUE;
|
|
aCtx->asn1r_decode_done_fun = NULL;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
|
|
static EXTERN_INFO *ext_info_ptr;
|
|
static ST_VOID get_dir_ref (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID get_indir_ref (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID get_objdesc (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID get_sngl_asn1 (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID sngl_parse_done (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID sngl_done (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID get_oct_alignd_cstr (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID get_oct_alignd_prim (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID oct_alignd_done (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID get_arb_cstr (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID get_arb_prim (ASN1_DEC_CTXT *aCtx);
|
|
static ST_VOID arb_done (ASN1_DEC_CTXT *aCtx);
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* ms_get_extern */
|
|
/* This function is called when an 'EXTERNAL' data element has been */
|
|
/* found. It will put info into the selected structure. */
|
|
/************************************************************************/
|
|
|
|
ST_VOID ms_get_extern (ASN1_DEC_CTXT *aCtx, EXTERN_INFO *dest)
|
|
{
|
|
save_method = aCtx->asn1r_decode_method; /* use class method */
|
|
aCtx->asn1r_decode_method = ASN1_TAG_METHOD;
|
|
|
|
ext_info_ptr = dest; /* save the destination */
|
|
ext_info_ptr -> dir_ref_pres = SD_FALSE; /* clear pres flag */
|
|
ext_info_ptr -> indir_ref_pres = SD_FALSE; /* clear pres flag */
|
|
ext_info_ptr -> dv_descr_pres = SD_FALSE; /* clear present flag */
|
|
|
|
ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,get_dir_ref); /* transfer syntax name */
|
|
ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_indir_ref); /* PCI */
|
|
ASN1R_TAG_ADD (aCtx, UNI,OBJDSCR_CODE,get_objdesc); /* object descripter */
|
|
/* Data Types */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* get_dir_ref */
|
|
/* This is the function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_dir_ref (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_dir_ref");
|
|
|
|
ext_info_ptr->dir_ref_pres = SD_TRUE; /* mark present */
|
|
|
|
if (asn1r_get_objid (aCtx, ext_info_ptr->dir_ref.comps,
|
|
&ext_info_ptr->dir_ref.num_comps))
|
|
{
|
|
asn1r_set_dec_err (aCtx, RESP_BAD_VALUE);
|
|
return;
|
|
}
|
|
|
|
ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_indir_ref); /* indir ref maybe */
|
|
ASN1R_TAG_ADD (aCtx, UNI,OBJDSCR_CODE,get_objdesc); /* object descripter */
|
|
/* Data Types */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* get_indir_ref */
|
|
/* This is the function called when the PCI element of a PDV is found */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_indir_ref (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_indir_ref");
|
|
|
|
if (asn1r_get_i32 (aCtx, &ext_info_ptr->indir_ref)) /* If out of range for us */
|
|
asn1r_set_dec_err (aCtx, RESP_BAD_VALUE);
|
|
else
|
|
{
|
|
ext_info_ptr->indir_ref_pres = SD_TRUE;
|
|
ASN1R_TAG_ADD (aCtx, UNI,OBJDSCR_CODE,get_objdesc); /* object descripter */
|
|
/* Data Types */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* get_objdesc */
|
|
/* This is the function called when the PCI element of a PDV is found */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_objdesc (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_objdesc");
|
|
|
|
ext_info_ptr->dv_descr_pres = SD_TRUE; /* mark present */
|
|
ext_info_ptr->dv_descr_len = aCtx->asn1r_elmnt_len; /* len of string */
|
|
ext_info_ptr->dv_descr = aCtx->asn1r_field_ptr; /* leave it lie */
|
|
aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* skip over */
|
|
|
|
/* set up to get presentation data values - choice of three */
|
|
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */
|
|
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */
|
|
ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* get_sngl_asn1 */
|
|
/* This is the function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_sngl_asn1 (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_sngl_asn1");
|
|
|
|
/* aCtx->asn1r_field_ptr points to 'any', elmnt is length of data */
|
|
ext_info_ptr->encoding_tag = 0; /* write tag */
|
|
ext_info_ptr->data_len = aCtx->asn1r_elmnt_len; /* len of ANY */
|
|
ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */
|
|
|
|
asn1r_parse_next (aCtx, sngl_parse_done);
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* sngl_parse_done */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID sngl_parse_done (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("sngl_parse_done");
|
|
|
|
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = sngl_done;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* sngl_done */
|
|
/* This is the cstr done function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID sngl_done (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("sngl_done");
|
|
|
|
aCtx->asn1r_decode_method = save_method; /* this extern is now done */
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* get_oct_alignd_prim */
|
|
/* This is the function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_oct_alignd_prim (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_oct_alignd_prim");
|
|
|
|
/* aCtx->asn1r_elmnt_len == # octects */
|
|
|
|
ext_info_ptr->encoding_tag = 1; /* write tag */
|
|
ext_info_ptr->data_len = aCtx->asn1r_elmnt_len; /* len of ANY */
|
|
ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */
|
|
|
|
aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* skip over data */
|
|
|
|
aCtx->asn1r_decode_method = save_method; /* this extern is now done */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* get_oct_alignd_cstr */
|
|
/* This is the function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_oct_alignd_cstr (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_oct_alignd_cstr");
|
|
|
|
ext_info_ptr->encoding_tag = 1; /* write tag */
|
|
ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */
|
|
asn1r_get_octstr_cstr (aCtx, ASN1_MAX_PDU, aCtx->asn1r_field_ptr);
|
|
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = oct_alignd_done;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* oct_alignd_done */
|
|
/* This is the cstr done function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID oct_alignd_done (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("oct_alignd_done");
|
|
|
|
ext_info_ptr->data_len = aCtx->asn1r_octetcount; /* len of octet string */
|
|
aCtx->asn1r_decode_method = save_method; /* this extern is now done */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* get_arb_prim */
|
|
/* This is the function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_arb_prim (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_arb_prim");
|
|
|
|
/* aCtx->asn1r_bitcount = bits */
|
|
|
|
ext_info_ptr->encoding_tag = 2; /* write tag */
|
|
ext_info_ptr->data_len = aCtx->asn1r_elmnt_len-1; /* len of ANY */
|
|
ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */
|
|
asn1r_get_bitstr (aCtx, aCtx->asn1r_field_ptr,0); /* max_bits=0 (no limit)*/
|
|
ext_info_ptr->num_bits = aCtx->asn1r_bitcount;
|
|
aCtx->asn1r_decode_method = save_method; /* this extern is now done */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* get_arb_cstr */
|
|
/* This is the function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID get_arb_cstr (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("get_arb_cstr");
|
|
|
|
ext_info_ptr->encoding_tag = 2; /* write tag */
|
|
ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */
|
|
|
|
asn1r_get_bitstr_cstr (aCtx, ASN1_MAX_PDU, aCtx->asn1r_field_ptr);
|
|
|
|
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arb_done;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* arb_done */
|
|
/* This is the cstr done function called when : */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID arb_done (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
MLOG_CDEC0 ("arb_done");
|
|
|
|
ext_info_ptr->num_bits = aCtx->asn1r_bitcount;
|
|
ext_info_ptr->data_len = CALC_BIT_LEN (aCtx->asn1r_bitcount);
|
|
aCtx->asn1r_decode_method = save_method; /* this extern is now done */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* ms_encode_extern */
|
|
/************************************************************************/
|
|
|
|
ST_RET ms_encode_extern (EXTERN_INFO *ext, ST_UCHAR *dest, ST_INT dest_len,
|
|
ST_INT *ext_len, ST_UCHAR **ext_ptr)
|
|
{
|
|
ST_RET ret;
|
|
ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_ENC_CTXT *aCtx = &localEncCtx;
|
|
|
|
S_LOCK_COMMON_RESOURCES ();
|
|
asn1r_strt_asn1_bld (aCtx, dest,dest_len); /* init the builder */
|
|
wr_external (aCtx, ext);
|
|
|
|
*ext_ptr = aCtx->asn1r_field_ptr + 1;
|
|
*ext_len = (dest+dest_len) - *ext_ptr;
|
|
|
|
if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */
|
|
ret = SD_SUCCESS;
|
|
else
|
|
ret = ME_ASN1_ENCODE_OVERRUN;
|
|
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (ret);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* wr_external */
|
|
/************************************************************************/
|
|
|
|
ST_VOID wr_external (ASN1_ENC_CTXT *aCtx, EXTERN_INFO *ext)
|
|
{
|
|
asn1r_strt_constr (aCtx); /* start EXTERNAL */
|
|
|
|
if (ext->encoding_tag == 0) /* ANY */
|
|
{
|
|
asn1r_wr_octstr (aCtx, ext->data_ptr,ext->data_len);
|
|
asn1r_fin_constr (aCtx, 0,CTX,DEF);
|
|
}
|
|
else if (ext->encoding_tag == 1) /* Octet Aligned */
|
|
{
|
|
asn1r_wr_octstr (aCtx, ext->data_ptr,ext->data_len);
|
|
asn1r_fin_prim (aCtx, 1,CTX); /* finish octet-aligned string */
|
|
}
|
|
else if (ext->encoding_tag == 2) /* Arbitrary */
|
|
{
|
|
asn1r_wr_bitstr (aCtx, ext->data_ptr,ext->num_bits);
|
|
asn1r_fin_prim (aCtx, 2,CTX);
|
|
}
|
|
|
|
if (ext->dv_descr_pres)
|
|
{
|
|
asn1r_wr_octstr (aCtx, ext->dv_descr,ext->dv_descr_len);
|
|
asn1r_fin_prim (aCtx, OBJDSCR_CODE,UNI); /* object descripter */
|
|
}
|
|
|
|
if (ext->indir_ref_pres)
|
|
{
|
|
asn1r_wr_i32 (aCtx, ext->indir_ref);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
}
|
|
|
|
if (ext->dir_ref_pres)
|
|
{
|
|
asn1r_wr_objid (aCtx, ext->dir_ref.comps,ext->dir_ref.num_comps);
|
|
asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI);
|
|
}
|
|
|
|
asn1r_fin_constr (aCtx, EXTERN_CODE,UNI,DEF); /* finish EXTERNAL */
|
|
}
|
|
|
|
|