1335 lines
48 KiB
C
1335 lines
48 KiB
C
/************************************************************************/
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
|
/************************************************************************/
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
|
/* 1995-2008, All Rights Reserved */
|
|
/* */
|
|
/* MODULE NAME : acse2enc.c */
|
|
/* PRODUCT(S) : */
|
|
/* */
|
|
/* MODULE DESCRIPTION : */
|
|
/* ACSE Encode Functions. */
|
|
/* */
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
|
/* */
|
|
/* MODIFICATION LOG : */
|
|
/* Date Who Rev Comments */
|
|
/* -------- --- ------ ------------------------------------------- */
|
|
/* 02/27/08 EJV 35 a_associate_rsp: do not free acse_conn. */
|
|
/* 11/07/06 EJV 34 MMSEASE_MOSI:elim HPUX warn when logging PSEL*/
|
|
/* 07/06/05 EJV 33 a_associate_req: log "IP ADDR: ip" same line,*/
|
|
/* MMSEASE_MOSI: log local PSEL,SSEL,TSEL. */
|
|
/* 05/06/05 EJV 32 Log PORT if configured. */
|
|
/* 01/24/05 JRB 31 Move acse_debug_sel & "*_logstr" to lean_var.c*/
|
|
/* 09/17/04 JRB 30 a_abort_req: don't access acse_conn after */
|
|
/* copp_u_abort_req (it may have been freed). */
|
|
/* 08/06/04 EJV 29 Added typecast (ST_UCHAR *) ...password. */
|
|
/* 03/04/04 JRB 28 Mov thisFil.. after incs, they may define DEBUG_..*/
|
|
/* Del logging of A-DATA.req (use MVL or COPP) */
|
|
/* 12/18/03 JRB 27 If MOSI, use cosp_buf, DON't use acse_buf. */
|
|
/* Use ASN1_ENC_PTR, ASN1_ENC_LEN macros. */
|
|
/* 10/21/03 JRB 26 Add a_get_event_handles_unix. */
|
|
/* 08/20/03 EJV 25 Chg cosp_msgsize to fit larger User Data */
|
|
/* ACSE_AUTH_ENABLED code wo/define. */
|
|
/* Added security functions. */
|
|
/* Added param to tp4_connect . */
|
|
/* Fix the ACSE Auth encode. */
|
|
/* 06/17/03 EJV 24 Added _acse_dib_logstr. */
|
|
/* 10/22/02 ASK 23 Wrap ifdef TP0_ENABLED around inet_ntoa calls*/
|
|
/* 10/14/02 ASK 22 Added encoding for abort diagnostic. */
|
|
/* 08/26/02 ASK 21 Added password mechanism encoding in */
|
|
/* a_associate_req and a_associate rsp. */
|
|
/* 07/16/02 JRB 20 Add tp0_sock.h for sockets/IP defs. */
|
|
/* 06/26/02 JRB 19 associate_req: Log calling/called address. */
|
|
/* 01/22/02 JRB 18 Add args to copp_initialize (same as MAP30..)*/
|
|
/* Del a_set_msgsize (no longer needed). */
|
|
/* 01/02/02 JRB 17 Converted to use ASN1R (re-entrant ASN1) */
|
|
/* 06/22/01 JRB 16 Fix a_release_rsp handling of STATE_RESP_COLL*/
|
|
/* state per ISO 8650 (was kluged before). */
|
|
/* 03/15/01 JRB 15 Use new SMEM allocation functions. */
|
|
/* 01/04/01 EJV 14 a_get_event_handles used only on _WIN32 */
|
|
/* 09/24/99 JRB 13 a_get_event_handles not used on */
|
|
/* DOS, QNX or VXWORKS */
|
|
/* 09/13/99 MDE 12 Added SD_CONST modifiers */
|
|
/* 08/05/99 JRB 11 Add "a_get_event_handles" function for MOSI. */
|
|
/* 10/08/98 MDE 10 Migrated to updated SLOG interface */
|
|
/* 08/13/98 JRB 09 Lint cleanup. */
|
|
/* 07/10/98 JRB 08 Del *_obj_id, use acse2var.c */
|
|
/* 03/23/98 NAV 07 Free buffers on termination */
|
|
/* 02/16/98 JRB 06 Del or "#if out" unused locals. */
|
|
/* 11/10/97 JRB 05 Chg cosp_buf to (ST_UCHAR *). */
|
|
/* 09/22/97 JRB 04 acse_msgsize MUST be set before copp_init. */
|
|
/* a_data_req (MOSI): check for buffer overflow */
|
|
/* 09/04/97 JRB 03 Pass SPDU msgsize arg to tp4_initialize. */
|
|
/* 07/31/97 JRB 02 copp_bind & a_associate_req set "tp_type" */
|
|
/* in tp4_addr. New TP4 needs it. */
|
|
/* 06/09/97 JRB 01 If !MOSI, on A-ASSOCIATE.rsp-, just set */
|
|
/* state=STATE_IDLE. Don't free as did on 3/7/97*/
|
|
/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */
|
|
/* 05/02/97 JRB 24 wr_* functs now ret void, so don't check. */
|
|
/* 04/09/97 JRB 23 a_associate_req return (0L) for any error. */
|
|
/* 03/19/97 JRB 22 Add MOSI "CALLING" support. */
|
|
/* 03/19/97 JRB 21 Encode AARQ in a_associate_req: need for MOSI*/
|
|
/* In a_release_req, chg handling if send fails.*/
|
|
/* Use acse_free_conn to free conn ctrl struct. */
|
|
/* Improve logging. */
|
|
/* Improve release collision handling. */
|
|
/* 03/07/97 JRB 20 Always send result-source-diag on AARE. */
|
|
/* Rechecked spec, and this is MANDATORY. */
|
|
/* 03/07/97 JRB 19 If !MOSI, free acse_conn on negative */
|
|
/* A-Associate.rsp (MOSI frees in COSP). */
|
|
/* 03/07/97 JRB 18 Use new "acse_free_con" to free acse_conn. */
|
|
/* 03/07/97 JRB 17 Added MOSI support. */
|
|
/* 02/11/97 JRB 16 In a_release_rsp, if send fails, don't free */
|
|
/* acse_conn and don't change state. */
|
|
/* 01/23/97 JRB 15 Init acse_debug_sel in copp_initialize. */
|
|
/* 11/18/96 JRB 14 Del acse_dummyfun call. Funct is gone now. */
|
|
/* 11/15/96 JRB 13 Don't initialize globals. */
|
|
/* Move acse_debug_sel global here. */
|
|
/* 08/19/96 MDE 12 Add dummy a_buffers_avail for Reduced Stack */
|
|
/* 08/14/96 JRB 11 Add a_buffers_avail function. */
|
|
/* 07/19/96 JRB 10 Change DEBUG_MMS to DEBUG_SISCO. */
|
|
/* 07/15/96 JRB 09 Only free acse_conn->aarq_apdu.user_info.ptr */
|
|
/* if len != 0 (wasn't alloc'd otherwise). */
|
|
/* 05/02/96 JRB 08 Add STATE_TP4CONN_WAIT. */
|
|
/* 04/23/96 MDE 07 Fixed minor warning */
|
|
/* 04/18/96 JRB 06 a_associate_req return acse_conn_id or NULL */
|
|
/* on error, instead of just SD_SUCCESS or error. */
|
|
/* if (acse_conn->state == STATE_AARE_WAIT) */
|
|
/* in a_abort_req, set to STATE_AARE_ABANDON. */
|
|
/* 03/26/96 MDE 05 Added REDUCED_STACK support */
|
|
/* 03/11/96 JRB 04 Move acse_msgsize here & use for acse_buf. */
|
|
/* 03/07/96 JRB 03 Handle aarq_apdu->user_info.len = 0. */
|
|
/* 01/19/96 JRB 02 Cast constant chars to ST_UCHAR. */
|
|
/* 10/30/95 JRB 01 Created */
|
|
/************************************************************************/
|
|
#include "glbtypes.h"
|
|
#include "sysincs.h"
|
|
#include "mem_chk.h"
|
|
#include "asn1defs.h"
|
|
#include "acse2.h"
|
|
#if defined (MOSI)
|
|
#include "cosp_usr.h"
|
|
#include "copp_usr.h"
|
|
#endif /* MOSI */
|
|
#if defined (MMSEASE_MOSI)
|
|
#include "cosp.h" /* for cosp_only_sel */
|
|
#include "copp.h" /* for only_loc_psel */
|
|
#include "tp4.h" /* for tp0_check_bind_id */
|
|
#endif
|
|
#include "tp4api.h"
|
|
#include "tp0_sock.h"
|
|
|
|
#ifdef DEBUG_SISCO
|
|
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
|
#endif
|
|
|
|
ST_UINT acse_msgsize;
|
|
|
|
|
|
/* Buffer for building init, release, and abort reqests. */
|
|
#if defined (MOSI)
|
|
ST_UINT cosp_msgsize;
|
|
ST_UCHAR *cosp_buf; /* Buffer containing "acse_buf" + COSP&COPP headers.*/
|
|
static ST_VOID acse_encode_user_info (ASN1_ENC_CTXT *aCtx, ACSE_CONN *acse_conn, BUFFER *user_info);
|
|
#else /* !MOSI */
|
|
static ST_UCHAR *acse_buf;
|
|
#endif /* !MOSI */
|
|
|
|
#define TP4_EOT 1 /* for tp4_data calls. */
|
|
|
|
/************************************************************************/
|
|
/* copp_initialize */
|
|
/* Save "msg_size". Pass "max_conns" to tp4_initialize. */
|
|
/************************************************************************/
|
|
ST_RET copp_initialize (ST_INT max_conns, ST_UINT msg_size)
|
|
{
|
|
ST_RET ret;
|
|
|
|
|
|
|
|
|
|
acse_msgsize = msg_size; /* Save msg size in global. */
|
|
|
|
/* Always enable error logging. */
|
|
#if defined(DEBUG_SISCO)
|
|
acse_debug_sel |= (ACSE_LOG_ERR | COPP_LOG_ERR | COSP_LOG_ERR);
|
|
#endif
|
|
|
|
if (acse_msgsize == 0)
|
|
{ /* ACSE user must call a_set_msgsize first. */
|
|
ACSELOG_ERR0 ("ACSE-ERROR: msg size not set");
|
|
return (E_ACSE_INVALID_PARAM); /* Invalid Parameter */
|
|
}
|
|
#if defined(MOSI)
|
|
cosp_msgsize = max(acse_msgsize, COSP_MAX_UDATA_CON) + MAX_COSP_COPP_HEADER;
|
|
cosp_buf = (ST_UCHAR *) M_MALLOC (MSMEM_STARTUP, cosp_msgsize);
|
|
|
|
ret = tp4_initialize (max_conns, cosp_msgsize);
|
|
#else /* !MOSI */
|
|
acse_buf = (ST_UCHAR *) M_MALLOC (MSMEM_STARTUP, acse_msgsize);
|
|
ret = tp4_initialize (max_conns, acse_msgsize);
|
|
#endif /* !MOSI */
|
|
return (ret);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* copp_terminate */
|
|
/************************************************************************/
|
|
ST_RET copp_terminate (ST_VOID)
|
|
{
|
|
|
|
#ifdef MOSI
|
|
if (cosp_buf)
|
|
M_FREE (MSMEM_STARTUP, cosp_buf);
|
|
#else
|
|
if(acse_buf)
|
|
M_FREE (MSMEM_STARTUP, acse_buf);
|
|
#endif
|
|
|
|
return (tp4_terminate ());
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* copp_event */
|
|
/************************************************************************/
|
|
ST_BOOLEAN copp_event (ST_VOID)
|
|
{
|
|
return (tp4_event ());
|
|
}
|
|
|
|
#if !defined (MOSI) /* see copp_enc.c for MOSI bind functs. */
|
|
/************************************************************************/
|
|
/* copp_bind */
|
|
/************************************************************************/
|
|
ST_RET copp_bind (ST_LONG user_bind_id, PRES_ADDR *pres_addr,
|
|
ST_INT sharable, ST_INT max_conns)
|
|
{
|
|
TP4_ADDR tp4_addr;
|
|
|
|
ACSELOG_ENC1 ("COPP-Bind Req. user_bind_id =%9ld", user_bind_id);
|
|
|
|
#if !defined(REDUCED_STACK)
|
|
/* Copy tsel and nsap from pres_addr to tp4_addr struct */
|
|
tp4_addr.tp_type = pres_addr->tp_type;
|
|
tp4_addr.tp4_sel_len = pres_addr->tsel_len;
|
|
memcpy (tp4_addr.tp4_sel, pres_addr->tsel, pres_addr->tsel_len);
|
|
tp4_addr.net_addr_len = pres_addr->nsap_len;
|
|
memcpy (tp4_addr.net_addr, pres_addr->nsap, pres_addr->nsap_len);
|
|
#else
|
|
tp4_addr.adlcAddr = pres_addr->adlcAddr;
|
|
#endif
|
|
|
|
/* Call tp4_bind. */
|
|
return (tp4_bind (user_bind_id, &tp4_addr, sharable, max_conns));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* copp_unbind */
|
|
/************************************************************************/
|
|
ST_RET copp_unbind (ST_LONG copp_bind_id)
|
|
{
|
|
ACSELOG_ENC1 ("COPP-Unbind Req. copp_bind_id =%9ld", copp_bind_id);
|
|
return (tp4_unbind (copp_bind_id));
|
|
}
|
|
#endif /* !MOSI */
|
|
|
|
/************************************************************************/
|
|
/* a_associate_req */
|
|
/************************************************************************/
|
|
ST_LONG a_associate_req (
|
|
ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/
|
|
ST_LONG user_conn_id, /* USER's connection ID */
|
|
AARQ_APDU *aarq_apdu) /* AARQ_APDU info */
|
|
{
|
|
#if !defined (MOSI)
|
|
TP4_ADDR tp4_addr;
|
|
#endif /* !MOSI */
|
|
ACSE_CONN *acse_conn;
|
|
AE_TITLE *ae_title;
|
|
ST_UCHAR version1_bit_str = BIT_VERSION1; /* Bit 0 of bitstr (high bit) set */
|
|
ST_UCHAR auth_bit_str = BIT_AUTHENTICATION;
|
|
|
|
ST_UCHAR *msg_ptr;
|
|
ST_UINT msg_len;
|
|
ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_ENC_CTXT *aCtx = &localEncCtx;
|
|
ST_INT j;
|
|
|
|
/* Allocate connection tracking structure "acse_conn". */
|
|
acse_conn = (ACSE_CONN *) M_CALLOC (MSMEM_ACSE_CONN, 1, sizeof (ACSE_CONN));
|
|
|
|
/* Save USER's connection ID. Use it in calls to user functions. */
|
|
acse_conn->user_conn_id = user_conn_id;
|
|
|
|
/* save the encryption info */
|
|
acse_conn->encrypt_ctrl = aarq_apdu->encrypt_ctrl;
|
|
|
|
ACSELOG_ENC2 ("A-ASSOCIATE.req: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|
acse_conn, acse_conn->user_conn_id);
|
|
ACSELOG_ENC0C ("DST (CALLED) ADDRESS:");
|
|
if (aarq_apdu->called_ae_title.AP_title_pres)
|
|
{
|
|
for (j = 0; j < aarq_apdu->called_ae_title.AP_title.num_comps; ++j)
|
|
{ /* Verbose but gets the job done. */
|
|
ACSELOG_ENC2C (" AP_title.comps[%d] = %d",
|
|
j, aarq_apdu->called_ae_title.AP_title.comps[j]);
|
|
}
|
|
}
|
|
if (aarq_apdu->called_ae_title.AE_qual_pres)
|
|
{
|
|
ACSELOG_ENC1C (" AE_qual = %ld", aarq_apdu->called_ae_title.AE_qual);
|
|
}
|
|
ACSELOG_ENC0C (" PSEL:");
|
|
ACSELOG_ENCH (aarq_apdu->called_paddr.psel_len, aarq_apdu->called_paddr.psel);
|
|
ACSELOG_ENC0C (" SSEL:");
|
|
ACSELOG_ENCH (aarq_apdu->called_paddr.ssel_len, aarq_apdu->called_paddr.ssel);
|
|
ACSELOG_ENC0C (" TSEL:");
|
|
ACSELOG_ENCH (aarq_apdu->called_paddr.tsel_len, aarq_apdu->called_paddr.tsel);
|
|
if (aarq_apdu->called_paddr.tp_type == TP_TYPE_TCP)
|
|
{
|
|
struct in_addr sin_addr; /* inet_ntoa needs this addr format*/
|
|
sin_addr.s_addr = aarq_apdu->called_paddr.netAddr.ip;
|
|
#if defined(TP0_ENABLED)
|
|
ACSELOG_ENC1C (" IP ADDR: %s", inet_ntoa (sin_addr));
|
|
if (!aarq_apdu->encrypt_ctrl.encryptMode == S_SEC_ENCRYPT_SSL &&
|
|
aarq_apdu->called_paddr.port)
|
|
ACSELOG_ENC1C (" PORT: %u", (ST_UINT) aarq_apdu->called_paddr.port);
|
|
#endif
|
|
if (aarq_apdu->encrypt_ctrl.encryptMode == S_SEC_ENCRYPT_SSL)
|
|
ACSELOG_ENC1C (" Encryption: SSL, port=%d", aarq_apdu->encrypt_ctrl.u.ssl.port);
|
|
else
|
|
ACSELOG_ENC0C (" Encryption: None");
|
|
if (aarq_apdu->auth_info.auth_pres)
|
|
{
|
|
if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT)
|
|
ACSELOG_ENC0C (" Authentication: MACE");
|
|
else if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD)
|
|
ACSELOG_ENC0C (" Authentication: password");
|
|
else
|
|
ACSELOG_ENC0C (" Authentication: other");
|
|
}
|
|
else
|
|
ACSELOG_ENC0C (" Authentication: None");
|
|
}
|
|
else
|
|
{
|
|
ACSELOG_ENC0C (" NSAP:");
|
|
ACSELOG_ENCH (aarq_apdu->called_paddr.nsap_len, aarq_apdu->called_paddr.netAddr.nsap);
|
|
}
|
|
|
|
ACSELOG_ENC0C ("SRC (CALLING) ADDRESS:");
|
|
if (aarq_apdu->calling_ae_title.AP_title_pres)
|
|
{
|
|
for (j = 0; j < aarq_apdu->calling_ae_title.AP_title.num_comps; ++j)
|
|
{ /* Verbose but gets the job done. */
|
|
ACSELOG_ENC2C (" AP_title.comps[%d] = %d",
|
|
j, aarq_apdu->calling_ae_title.AP_title.comps[j]);
|
|
}
|
|
}
|
|
if (aarq_apdu->calling_ae_title.AE_qual_pres)
|
|
{
|
|
ACSELOG_ENC1C (" AE_qual = %ld", aarq_apdu->calling_ae_title.AE_qual);
|
|
}
|
|
#if defined (MMSEASE_MOSI)
|
|
{
|
|
ST_UCHAR *tp0_loc_tsap;
|
|
ACSELOG_ENC0C (" PSEL:");
|
|
if (only_loc_psel[0])
|
|
ACSELOG_ENCH ((ST_UINT) only_loc_psel[0], &only_loc_psel[1]);
|
|
ACSELOG_ENC0C (" SSEL:");
|
|
if (cosp_only_ssel[0])
|
|
ACSELOG_ENCH ((ST_UINT) cosp_only_ssel[0], &cosp_only_ssel[1]);
|
|
ACSELOG_ENC0C (" TSEL:");
|
|
if (tp0_check_bind_id (copp_bind_id, &tp0_loc_tsap) == SD_SUCCESS)
|
|
ACSELOG_ENCH ((ST_UINT) tp0_loc_tsap[0], &tp0_loc_tsap[1]);
|
|
}
|
|
#else
|
|
/* NOTE: aarq_apdu->calling_paddr is NOT logged because caller may */
|
|
/* not set it, and even if they do, it is not used. The address */
|
|
/* passed to "copp_bind" is used as the calling_paddr. */
|
|
#endif
|
|
|
|
/* Begin encoding request. */
|
|
#if defined (MOSI)
|
|
asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize);
|
|
#else
|
|
asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize);
|
|
#endif
|
|
|
|
asn1r_strt_constr (aCtx); /* Start AARQ APDU constructor */
|
|
/* Write user_info. */
|
|
if (aarq_apdu->user_info.len)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
#if defined (MOSI)
|
|
/* PCI's must be set before any encoding. */
|
|
acse_conn->pciacse = 1;
|
|
acse_conn->pcimms = 3;
|
|
acse_encode_user_info (aCtx, acse_conn, &aarq_apdu->user_info);
|
|
#else /* !MOSI */
|
|
asn1r_wr_octstr (aCtx, aarq_apdu->user_info.ptr, aarq_apdu->user_info.len);
|
|
/* No P-Contexts in this implementation, so skip transfer-syntax */
|
|
/* and p-context-id. */
|
|
#endif /* !MOSI */
|
|
asn1r_fin_constr (aCtx, AARQ_user_info,CTX,DEF);
|
|
}
|
|
|
|
if(aarq_apdu->auth_info.auth_pres == SD_TRUE)
|
|
{
|
|
if(aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD)
|
|
{
|
|
ACSELOG_ENC0C (" Authentication: password");
|
|
/* Write the password value */
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_octstr (aCtx, (ST_UCHAR *) aarq_apdu->auth_info.u.pw_auth.password,
|
|
strlen(aarq_apdu->auth_info.u.pw_auth.password)); /* Strip off the NULL */
|
|
asn1r_fin_prim (aCtx, 0,CTX);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLING_auth_value,CTX,DEF);
|
|
|
|
/* Write the mechanism name (password in this case) */
|
|
asn1r_wr_objid (aCtx, a_auth_password_obj_id.comps, a_auth_password_obj_id.num_comps);
|
|
asn1r_fin_prim (aCtx, AARQ_mechanism_name, CTX);
|
|
}
|
|
else
|
|
{
|
|
if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT)
|
|
ACSELOG_ENC0C ("Authentication: MACE");
|
|
else
|
|
ACSELOG_ENC0C ("Authentication: other");
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_strt_constr (aCtx); /* Authentication-value */
|
|
asn1r_strt_constr (aCtx); /* Single ASN.1 Type */
|
|
asn1r_wr_octstr (aCtx, aarq_apdu->auth_info.u.other_auth.auth_value.ptr,
|
|
aarq_apdu->auth_info.u.other_auth.auth_value.len);
|
|
asn1r_fin_constr (aCtx, 0, CTX, SD_FALSE); /* Single ASN.1 Type */
|
|
asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); /* Authentication-value */
|
|
asn1r_fin_constr (aCtx, AARQ_CALLING_auth_value,CTX,DEF);
|
|
|
|
/* Write the mechanism name */
|
|
asn1r_wr_objid (aCtx, aarq_apdu->auth_info.u.other_auth.mech_id.comps, aarq_apdu->auth_info.u.other_auth.mech_id.num_comps);
|
|
asn1r_fin_prim (aCtx, AARQ_mechanism_name, CTX);
|
|
}
|
|
|
|
/* Let's encode the authentication present bit to enable security */
|
|
asn1r_wr_bitstr (aCtx, &auth_bit_str, 1);
|
|
asn1r_fin_prim (aCtx, AARQ_acse_requirements, CTX);
|
|
}
|
|
|
|
/* Write CALLING AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id).*/
|
|
ae_title = &aarq_apdu->calling_ae_title;
|
|
|
|
if (ae_title->AE_inv_id_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AE_inv_id);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLING_AE_inv_id,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AP_inv_id_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AP_inv_id);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLING_AP_inv_id,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AE_qual_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AE_qual);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLING_AE_qual,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AP_title_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps);
|
|
asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLING_AP_title,CTX,DEF);
|
|
}
|
|
|
|
|
|
/* Write CALLED AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id).*/
|
|
ae_title = &aarq_apdu->called_ae_title;
|
|
|
|
if (ae_title->AE_inv_id_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AE_inv_id);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLED_AE_inv_id,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AP_inv_id_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AP_inv_id);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLED_AP_inv_id,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AE_qual_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AE_qual);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLED_AE_qual,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AP_title_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps);
|
|
asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_CALLED_AP_title,CTX,DEF);
|
|
}
|
|
|
|
/* Write ASO Context Name. */
|
|
if (aarq_apdu->ASO_context_name_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_objid (aCtx, aarq_apdu->ASO_context_name.comps, aarq_apdu->ASO_context_name.num_comps);
|
|
asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARQ_ASO_context_name,CTX,DEF);
|
|
}
|
|
|
|
/* Write protocol_version. */
|
|
asn1r_wr_bitstr (aCtx, &version1_bit_str, 1);
|
|
asn1r_fin_prim (aCtx, AARQ_protocol_version, CTX);
|
|
|
|
asn1r_fin_constr (aCtx, TAG_AARQ,APP,DEF); /* Finish AARQ APDU */
|
|
|
|
msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */
|
|
msg_len = ASN1_ENC_LEN (aCtx);
|
|
|
|
#if ! (defined(REDUCED_STACK) || defined(MOSI) )
|
|
/* Fastbyte Presentation and Session (2 bytes). */
|
|
*(--msg_ptr) = 0x01; /* Short-CP mode = BER */
|
|
*(--msg_ptr) = (ST_UCHAR) 0xE8; /* Short-SCN, SI = 11101, 0 params */
|
|
msg_len+=2; /* adjust len */
|
|
#endif /* ! (defined(REDUCED_STACK) || defined(MOSI) ) */
|
|
if (msg_len > acse_msgsize)
|
|
return (0L);
|
|
|
|
#if defined (MOSI)
|
|
acse_conn->apdu_ptr = msg_ptr;
|
|
acse_conn->apdu_len = msg_len;
|
|
/* Send AARQ APDU via P-CONNECT.req */
|
|
if (copp_con_req (copp_bind_id, acse_conn, &aarq_apdu->called_paddr) != SD_SUCCESS)
|
|
{
|
|
acse_free_con (acse_conn); /* Dump conn tracking struct */
|
|
return (0L);
|
|
}
|
|
acse_conn->state = STATE_AARE_WAIT; /* Waiting for AARE-apdu */
|
|
#else /* !MOSI */
|
|
/* Save AARQ APDU (in save_buf) to send when tp4 connection */
|
|
/* established (see tp4_connect_cnf). */
|
|
acse_conn->save_buf.len = msg_len;
|
|
acse_conn->save_buf.ptr = (ST_UCHAR *) M_MALLOC (MSMEM_ACSE_DATA, msg_len);
|
|
memcpy (acse_conn->save_buf.ptr, msg_ptr, msg_len);
|
|
|
|
/* Send Transport connect request. */
|
|
/* The connection ID is just a pointer to "acse_conn" cast to a ST_LONG. */
|
|
/* Copy tsel and nsap from aarq_apdu->called_paddr to tp4_addr */
|
|
#if !defined(REDUCED_STACK)
|
|
tp4_addr.tp_type = aarq_apdu->called_paddr.tp_type;
|
|
tp4_addr.tp4_sel_len = aarq_apdu->called_paddr.tsel_len;
|
|
memcpy (tp4_addr.tp4_sel, aarq_apdu->called_paddr.tsel,
|
|
aarq_apdu->called_paddr.tsel_len);
|
|
tp4_addr.net_addr_len = aarq_apdu->called_paddr.nsap_len;
|
|
memcpy (tp4_addr.net_addr, aarq_apdu->called_paddr.nsap,
|
|
aarq_apdu->called_paddr.nsap_len);
|
|
#else
|
|
tp4_addr.adlcAddr = aarq_apdu->called_paddr.adlcAddr;
|
|
#endif
|
|
|
|
if (tp4_connect (copp_bind_id, (ST_LONG) acse_conn,
|
|
&tp4_addr, 0, NULL, NULL) != SD_SUCCESS)
|
|
{
|
|
acse_free_con (acse_conn); /* Dump conn tracking struct */
|
|
return (0L);
|
|
}
|
|
acse_conn->state = STATE_TP4CONN_WAIT; /* Waiting for TP4 connection*/
|
|
#endif /* !MOSI */
|
|
return ((ST_LONG)acse_conn);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* a_associate_rsp */
|
|
/************************************************************************/
|
|
ST_RET a_associate_rsp (
|
|
ST_LONG acse_conn_id, /* ACSE's connection ID */
|
|
ST_LONG user_conn_id, /* USER's connection ID */
|
|
AARE_APDU *info) /* AARE_APDU info */
|
|
{
|
|
AE_TITLE *ae_title;
|
|
ST_UCHAR version1_bit_str = BIT_VERSION1; /* Bit 0 of bitstr (high bit) set */
|
|
ST_UCHAR auth_bit_str = BIT_AUTHENTICATION;
|
|
|
|
ST_UCHAR *msg_ptr;
|
|
ST_UINT msg_len;
|
|
ACSE_CONN *acse_conn;
|
|
ST_RET retcode;
|
|
ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_ENC_CTXT *aCtx = &localEncCtx;
|
|
|
|
ACSELOG_ENC2 ("A-ASSOCIATE.rsp: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|
acse_conn_id, user_conn_id);
|
|
|
|
acse_conn = (ACSE_CONN *) acse_conn_id;
|
|
|
|
if (acse_conn == NULL)
|
|
return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */
|
|
|
|
if (acse_conn->state != STATE_AASCRSP_WAIT)
|
|
return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/
|
|
|
|
/* Save USER's connection ID. Use it in calls to user functions. */
|
|
acse_conn->user_conn_id = user_conn_id;
|
|
|
|
/* Everything looks OK. Go ahead and encode response and send it. */
|
|
#if defined (MOSI)
|
|
asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize);
|
|
#else
|
|
asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize);
|
|
#endif
|
|
|
|
asn1r_strt_constr (aCtx); /* Start AARE APDU constructor */
|
|
/* Write user_info. */
|
|
if (info->user_info.len)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
#if defined (MOSI)
|
|
acse_encode_user_info (aCtx, acse_conn, &info->user_info);
|
|
#else /* !MOSI */
|
|
asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len);
|
|
/* No P-Contexts in this implementation, so skip transfer-syntax */
|
|
/* and p-context-id. */
|
|
#endif /* !MOSI */
|
|
asn1r_fin_constr (aCtx, AARE_user_info,CTX,DEF);
|
|
}
|
|
|
|
if(info->auth_info.auth_pres == SD_TRUE)
|
|
{
|
|
if(info->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD)
|
|
{
|
|
/* Write the password value */
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_octstr (aCtx, (ST_UCHAR *) info->auth_info.u.pw_auth.password,
|
|
strlen(info->auth_info.u.pw_auth.password)); /* Strip off the NULL */
|
|
asn1r_fin_prim (aCtx, 0,CTX);
|
|
asn1r_fin_constr (aCtx, AARE_RESPONDING_auth_value,CTX,DEF);
|
|
|
|
/* Write the mechanism name (password in this case) */
|
|
asn1r_wr_objid (aCtx, a_auth_password_obj_id.comps, a_auth_password_obj_id.num_comps);
|
|
asn1r_fin_prim (aCtx, AARE_mechanism_name, CTX);
|
|
}
|
|
else
|
|
{
|
|
if (info->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT)
|
|
ACSELOG_ENC0C ("Authentication: MACE");
|
|
else
|
|
ACSELOG_ENC0C ("Authentication: other");
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_strt_constr (aCtx); /* Authentication-value */
|
|
asn1r_strt_constr (aCtx); /* Single ASN.1 Type */
|
|
asn1r_wr_octstr (aCtx, info->auth_info.u.other_auth.auth_value.ptr,
|
|
info->auth_info.u.other_auth.auth_value.len);
|
|
asn1r_fin_constr (aCtx, 0, CTX, SD_FALSE); /* Single ASN.1 Type */
|
|
asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); /* Authentication-value */
|
|
asn1r_fin_constr (aCtx, AARE_RESPONDING_auth_value,CTX,DEF);
|
|
|
|
/* Write the mechanism name */
|
|
asn1r_wr_objid (aCtx, info->auth_info.u.other_auth.mech_id.comps,
|
|
info->auth_info.u.other_auth.mech_id.num_comps);
|
|
asn1r_fin_prim (aCtx, AARE_mechanism_name, CTX);
|
|
}
|
|
|
|
/* Let's encode the authentication present bit to enable security */
|
|
asn1r_wr_bitstr (aCtx, &auth_bit_str, 1);
|
|
asn1r_fin_prim (aCtx, AARE_RESPONDER_acse_requirements, CTX);
|
|
}
|
|
|
|
/* Write RESP AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id) */
|
|
/* fields of AARE APDU. */
|
|
ae_title = &info->responding_ae_title;
|
|
|
|
if (ae_title->AE_inv_id_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AE_inv_id);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARE_RESPONDING_AE_inv_id,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AP_inv_id_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AP_inv_id);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARE_RESPONDING_AP_inv_id,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AE_qual_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i32 (aCtx, ae_title->AE_qual);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARE_RESPONDING_AE_qual,CTX,DEF);
|
|
}
|
|
|
|
if (ae_title->AP_title_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps);
|
|
asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARE_RESPONDING_AP_title,CTX,DEF);
|
|
}
|
|
|
|
/* Write result-source-diagnostic. */
|
|
/* DEBUG: If user required to set "result_source" and "result_diag", */
|
|
/* "result_source_diag_pres" would no longer be needed. */
|
|
if (info->result_source_diag_pres == 0)
|
|
{ /* User probably didn't set values, so set to default. */
|
|
info->result_source = 1; /* Source = acse-service-user. */
|
|
info->result_diag = 0; /* Diag = null. */
|
|
}
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i16 (aCtx, info->result_diag);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
if (info->result_source != 1 && info->result_source != 2)
|
|
return (E_ACSE_ENC_ERR); /* Make sure source legal. */
|
|
asn1r_fin_constr (aCtx, info->result_source,CTX,DEF);
|
|
asn1r_fin_constr (aCtx, AARE_result_source_diagnostic,CTX,DEF);
|
|
|
|
/* Write result */
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_i16 (aCtx, info->result);
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARE_result,CTX,DEF);
|
|
|
|
/* Write ASO Context Name. */
|
|
if (info->ASO_context_name_pres)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_objid (aCtx, info->ASO_context_name.comps, info->ASO_context_name.num_comps);
|
|
asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, AARE_ASO_context_name,CTX,DEF);
|
|
}
|
|
|
|
/* Write protocol_version. */
|
|
asn1r_wr_bitstr (aCtx, &version1_bit_str, 1);
|
|
asn1r_fin_prim (aCtx, AARE_protocol_version, CTX);
|
|
|
|
asn1r_fin_constr (aCtx, TAG_AARE,APP,DEF); /* Finish AARE APDU */
|
|
|
|
msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */
|
|
msg_len = ASN1_ENC_LEN (aCtx);
|
|
|
|
#if !(defined(REDUCED_STACK) || defined(MOSI))
|
|
/* Fastbyte Presentation and Session (2 bytes). */
|
|
*(--msg_ptr) = 0x01; /* Short-CP mode = BER */
|
|
switch (info->result)
|
|
{
|
|
case 0:
|
|
*(--msg_ptr)=(ST_UCHAR)0xF0; /* Short-SAC (SI=11110) 0 params */
|
|
break;
|
|
case 1:
|
|
*(--msg_ptr)=(ST_UCHAR)0xE3; /* Short-SRF (SI=11100) 0 params, */
|
|
/* transport conn released, permanent */
|
|
break;
|
|
case 2:
|
|
*(--msg_ptr)=(ST_UCHAR)0xE2; /* Short-SRF (SI=11100) 0 params, */
|
|
/* transport conn released, transient */
|
|
break;
|
|
default:
|
|
return (E_ACSE_INVALID_PARAM); /* Invalid Parameter */
|
|
}
|
|
msg_len+=2; /* adjust len */
|
|
#endif /* !(defined(REDUCED_STACK) || defined(MOSI)) */
|
|
|
|
if (msg_len > acse_msgsize)
|
|
return (E_ACSE_BUFFER_OVERFLOW);
|
|
|
|
#if defined(MOSI)
|
|
acse_conn->apdu_ptr = msg_ptr;
|
|
acse_conn->apdu_len = msg_len;
|
|
if (info->result)
|
|
/* NOTE: COSP will free "acse_conn" after T-disconnect. */
|
|
retcode = copp_con_rsp_neg (acse_conn, -1); /* -1 means "from user" */
|
|
else
|
|
{
|
|
retcode = copp_con_rsp_pos (acse_conn);
|
|
if (retcode == SD_SUCCESS)
|
|
acse_conn->state = STATE_ASSOCIATED;
|
|
}
|
|
if (retcode != SD_SUCCESS)
|
|
{
|
|
#if 0
|
|
/* EJV 2/27/2008: if copp_con_rsp_* fails then the most probable cause is */
|
|
/* that the socket was disconencted. In this case the */
|
|
/* the tp0_disconnect_ind will free the acse_conn. */
|
|
/* If it was other error the application will issue an abort */
|
|
/* to cleanup the connection. */
|
|
acse_free_con (acse_conn); /* Dump conn tracking struct */
|
|
#endif /* 0 */
|
|
ACSELOG_ENC0 ("ACSE-ERROR: failed to send A-ASSOCIATE.rsp (disconnected socket or other error).");
|
|
return (E_ACSE_SEND_ERR);
|
|
}
|
|
#else /* !MOSI */
|
|
/* Send via tp4_data. */
|
|
/* The "user_conn_id" is just a pointer to "acse_conn" cast to a ST_LONG.*/
|
|
retcode = tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr);
|
|
if (retcode != SD_SUCCESS)
|
|
{
|
|
acse_free_con (acse_conn); /* Dump conn tracking struct */
|
|
return (E_ACSE_SEND_ERR);
|
|
}
|
|
|
|
if (info->result == 0)
|
|
acse_conn->state = STATE_ASSOCIATED;
|
|
else
|
|
acse_conn->state = STATE_IDLE;
|
|
#endif /* !MOSI */
|
|
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* a_release_req */
|
|
/************************************************************************/
|
|
ST_RET a_release_req (
|
|
ST_LONG acse_conn_id, /* ACSE's connection ID */
|
|
RLRQ_APDU *info) /* RLRQ_APDU info */
|
|
{
|
|
ST_UCHAR *msg_ptr;
|
|
ST_UINT msg_len;
|
|
ACSE_CONN *acse_conn;
|
|
ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_ENC_CTXT *aCtx = &localEncCtx;
|
|
|
|
acse_conn = (ACSE_CONN *)acse_conn_id;
|
|
|
|
ACSELOG_ENC2 ("A-RELEASE.req: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|
acse_conn, acse_conn->user_conn_id);
|
|
|
|
if (acse_conn == NULL)
|
|
return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */
|
|
|
|
if (acse_conn->state != STATE_ASSOCIATED)
|
|
return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/
|
|
|
|
/* Everything looks OK. Go ahead and encode request and send it. */
|
|
#if defined (MOSI)
|
|
asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize);
|
|
#else
|
|
asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize);
|
|
#endif
|
|
|
|
asn1r_strt_constr (aCtx); /* Start RLRQ APDU constructor */
|
|
/* Write user_info. */
|
|
if (info->user_info.len)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
#if defined (MOSI)
|
|
acse_encode_user_info (aCtx, acse_conn, &info->user_info);
|
|
#else /* !MOSI */
|
|
asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len);
|
|
/* No P-Contexts in this implementation, so skip transfer-syntax */
|
|
/* and p-context-id. */
|
|
#endif /* !MOSI */
|
|
asn1r_fin_constr (aCtx, RLRQ_user_info,CTX,DEF);
|
|
}
|
|
|
|
/* Write Release Reason. */
|
|
if (info->reason_pres)
|
|
{
|
|
asn1r_wr_i16 (aCtx, info->reason);
|
|
asn1r_fin_prim (aCtx, RLRQ_reason,CTX);
|
|
}
|
|
|
|
asn1r_fin_constr (aCtx, TAG_RLRQ,APP,DEF); /* Finish RLRQ APDU */
|
|
msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */
|
|
msg_len = ASN1_ENC_LEN (aCtx);
|
|
if (msg_len > acse_msgsize)
|
|
return (E_ACSE_BUFFER_OVERFLOW);
|
|
|
|
#if defined(MOSI)
|
|
acse_conn->apdu_ptr = msg_ptr;
|
|
acse_conn->apdu_len = msg_len;
|
|
/* Send RLRQ APDU via P-RELEASE.req */
|
|
if (copp_rel_req (acse_conn) != SD_SUCCESS)
|
|
return (E_ACSE_SEND_ERR);
|
|
#else /* !MOSI */
|
|
/* Send RLRQ APDU via T-DATA.req */
|
|
if (tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr) != SD_SUCCESS)
|
|
return (E_ACSE_SEND_ERR);
|
|
#endif /* !MOSI */
|
|
acse_conn->state = STATE_RLRE_WAIT;
|
|
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* a_release_rsp */
|
|
/************************************************************************/
|
|
ST_RET a_release_rsp (
|
|
ST_LONG acse_conn_id, /* ACSE's connection ID */
|
|
RLRE_APDU *info) /* RLRE_APDU info */
|
|
{
|
|
ST_UCHAR *msg_ptr;
|
|
ST_UINT msg_len;
|
|
ACSE_CONN *acse_conn;
|
|
ST_RET retcode;
|
|
ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_ENC_CTXT *aCtx = &localEncCtx;
|
|
|
|
acse_conn = (ACSE_CONN *)acse_conn_id;
|
|
|
|
ACSELOG_ENC2 ("A-RELEASE.rsp: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|
acse_conn, acse_conn->user_conn_id);
|
|
|
|
if (acse_conn == 0)
|
|
return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */
|
|
|
|
/* This state may happen, but ACSE state machine says do nothing. */
|
|
if (acse_conn->state == STATE_RESP_COLL)
|
|
{
|
|
ACSELOG_ENC0C ("A-RELEASE.rsp not sent because this is Responder side of RELEASE collision");
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
if (acse_conn->state != STATE_ARLSRSP_WAIT &&
|
|
acse_conn->state != STATE_INIT_COLL)
|
|
return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/
|
|
|
|
/* Everything looks OK. Go ahead and encode response and send it. */
|
|
#if defined (MOSI)
|
|
asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize);
|
|
#else
|
|
asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize);
|
|
#endif
|
|
|
|
asn1r_strt_constr (aCtx); /* Start RLRE APDU constructor */
|
|
/* Write user_info. */
|
|
if (info->user_info.len)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
#if defined (MOSI)
|
|
acse_encode_user_info (aCtx, acse_conn, &info->user_info);
|
|
#else /* !MOSI */
|
|
asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len);
|
|
/* No P-Contexts in this implementation, so skip transfer-syntax */
|
|
/* and p-context-id. */
|
|
#endif /* !MOSI */
|
|
asn1r_fin_constr (aCtx, RLRE_user_info,CTX,DEF);
|
|
}
|
|
|
|
/* Write Release Reason. */
|
|
if (info->reason_pres)
|
|
{
|
|
asn1r_wr_i16 (aCtx, info->reason);
|
|
asn1r_fin_prim (aCtx, RLRE_reason,CTX);
|
|
}
|
|
|
|
asn1r_fin_constr (aCtx, TAG_RLRE,APP,DEF); /* Finish RLRE APDU */
|
|
msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */
|
|
msg_len = ASN1_ENC_LEN (aCtx);
|
|
if (msg_len > acse_msgsize)
|
|
return (E_ACSE_BUFFER_OVERFLOW);
|
|
|
|
#if defined(MOSI)
|
|
acse_conn->apdu_ptr = msg_ptr;
|
|
acse_conn->apdu_len = msg_len;
|
|
/* NOTE: Only "affirmative" allowed because "Negotiated Release" not */
|
|
/* supported by Session. */
|
|
retcode = copp_rel_rsp_pos (acse_conn);
|
|
#else /* !MOSI */
|
|
/* Send Transport Data request. */
|
|
retcode = tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr);
|
|
#endif /* !MOSI */
|
|
if (retcode != SD_SUCCESS)
|
|
return (E_ACSE_SEND_ERR);
|
|
|
|
if (acse_conn->state == STATE_ARLSRSP_WAIT)
|
|
acse_conn->state = STATE_IDLE;
|
|
else /* must be STATE_INIT_COLL */
|
|
acse_conn->state = STATE_RLRE_WAIT;
|
|
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* a_abort_req */
|
|
/************************************************************************/
|
|
ST_RET a_abort_req (
|
|
ST_LONG acse_conn_id, /* ACSE's connection ID */
|
|
ABRT_APDU *info) /* ABRT_APDU info */
|
|
{
|
|
ST_UCHAR *msg_ptr;
|
|
ST_UINT msg_len;
|
|
ACSE_CONN *acse_conn;
|
|
ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_ENC_CTXT *aCtx = &localEncCtx;
|
|
|
|
|
|
|
|
|
|
acse_conn = (ACSE_CONN *)acse_conn_id;
|
|
|
|
ACSELOG_ENC2 ("A-ABORT.req: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|
acse_conn, acse_conn->user_conn_id);
|
|
|
|
if (acse_conn == NULL)
|
|
return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */
|
|
|
|
if (acse_conn->state == STATE_IDLE) /* Waiting for T-DISCONNECT */
|
|
return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/
|
|
|
|
#ifndef MOSI
|
|
if (acse_conn->state == STATE_TP4CONN_WAIT)
|
|
{
|
|
/* Don't free struct now. When get response, don't pass up to user */
|
|
/* and free acse_conn then. */
|
|
acse_conn->state = STATE_AARE_ABANDON;
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
if (acse_conn->state == STATE_AARE_WAIT)
|
|
{
|
|
/* Don't free struct now. When get response, don't pass up to user */
|
|
/* and free acse_conn then. */
|
|
acse_conn->state = STATE_AARE_ABANDON;
|
|
return (SD_SUCCESS);
|
|
}
|
|
#endif /* !MOSI */
|
|
|
|
/* Everything looks OK. Go ahead and encode request and send it. */
|
|
#if defined (MOSI)
|
|
asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize);
|
|
#else
|
|
asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize);
|
|
#endif
|
|
|
|
asn1r_strt_constr (aCtx); /* Start ABRT APDU constructor */
|
|
/* Write user_info. */
|
|
if (info->user_info.len)
|
|
{
|
|
asn1r_strt_constr (aCtx);
|
|
#if defined (MOSI)
|
|
acse_encode_user_info (aCtx, acse_conn, &info->user_info);
|
|
#else /* !MOSI */
|
|
asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len);
|
|
/* No P-Contexts in this implementation, so skip transfer-syntax */
|
|
/* and p-context-id. */
|
|
#endif /* !MOSI */
|
|
asn1r_fin_constr (aCtx, ABRT_user_info,CTX,DEF);
|
|
}
|
|
|
|
/* Write Abort Diagnostic. */
|
|
if(info->diagnostic_pres == SD_TRUE)
|
|
{
|
|
asn1r_wr_i16 (aCtx, info->diagnostic);
|
|
asn1r_fin_prim (aCtx, ABRT_diagnostic,CTX);
|
|
}
|
|
|
|
/* Write Abort Source. */
|
|
asn1r_wr_i16 (aCtx, info->source);
|
|
asn1r_fin_prim (aCtx, ABRT_source,CTX);
|
|
|
|
asn1r_fin_constr (aCtx, TAG_ABRT,APP,DEF); /* Finish ABRT APDU */
|
|
msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */
|
|
msg_len = ASN1_ENC_LEN (aCtx);
|
|
if (msg_len > acse_msgsize)
|
|
return (E_ACSE_BUFFER_OVERFLOW);
|
|
|
|
|
|
|
|
|
|
#if defined(MOSI)
|
|
/* Send P-U-Abort Request. */
|
|
acse_conn->apdu_ptr = msg_ptr;
|
|
acse_conn->apdu_len = msg_len;
|
|
acse_conn->state = STATE_IDLE; /* COSP will free acse_conn. */
|
|
if (copp_u_abort_req (acse_conn) != SD_SUCCESS)
|
|
return (E_ACSE_SEND_ERR);
|
|
/* CRITICAL: DO NOT access acse_conn after abort. It may have been */
|
|
/* freed by cosp_u_abort_req (called from copp_u_abort_req). */
|
|
#else /* !MOSI */
|
|
/* Send Transport Disconnect request. */
|
|
tp4_disconnect (acse_conn->tp4_conn_id, msg_len, (ST_CHAR *) msg_ptr);
|
|
acse_free_con (acse_conn); /* Dump conn tracking struct */
|
|
#endif /* !MOSI */
|
|
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* a_data_req - Send A-Data req. */
|
|
/************************************************************************/
|
|
ST_RET a_data_req (
|
|
ST_LONG acse_conn_id, /* ACSE's ID for this connection */
|
|
ST_UINT data_len,
|
|
ST_UCHAR *data)
|
|
{
|
|
ACSE_CONN *acse_conn;
|
|
|
|
acse_conn = (ACSE_CONN *)acse_conn_id;
|
|
|
|
#if defined(MOSI)
|
|
if (data_len > acse_msgsize)
|
|
{ /* Should never happen if ACSE user code is correct. */
|
|
ACSELOG_ERR2 ("ACSE-ERROR: A-DATA.req: data len (%d) > max (%d)",
|
|
data_len, acse_msgsize);
|
|
return (E_ACSE_BUFFER_OVERFLOW);
|
|
}
|
|
/* Just copy data to end of "cosp_buf" & set apdu_ptr, apdu_len. */
|
|
/* copp_data_req will add COPP encoding in front of this data. */
|
|
acse_conn->apdu_ptr = cosp_buf + cosp_msgsize - data_len;
|
|
acse_conn->apdu_len = data_len;
|
|
memcpy (acse_conn->apdu_ptr, data, data_len);
|
|
|
|
return (copp_data_req (acse_conn));
|
|
#else /* !MOSI */
|
|
return (tp4_data (acse_conn->tp4_conn_id, TP4_EOT, data_len,(ST_CHAR *)data));
|
|
#endif /* !MOSI */
|
|
}
|
|
|
|
#if defined (MOSI)
|
|
/************************************************************************/
|
|
/* acse_encode_user_info */
|
|
/************************************************************************/
|
|
static ST_VOID acse_encode_user_info (ASN1_ENC_CTXT *aCtx, ACSE_CONN *acse_conn, BUFFER *user_info)
|
|
{
|
|
asn1r_strt_constr (aCtx); /* start EXTERNAL */
|
|
asn1r_strt_constr (aCtx); /* start single-ASN1-type */
|
|
asn1r_wr_octstr (aCtx, user_info->ptr, user_info->len);
|
|
asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */
|
|
asn1r_wr_i8 (aCtx, acse_conn->pcimms); /* PCI for MMS */
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
|
|
/* NOTE: Transfer-syntax-name (OPTIONAL) not sent. Saves few bytes. */
|
|
|
|
asn1r_fin_constr (aCtx, EXTERN_CODE,UNI,DEF); /* finish EXTERNAL */
|
|
return;
|
|
}
|
|
|
|
#endif /* MOSI */
|
|
|
|
#if !defined (MOSI)
|
|
/************************************************************************/
|
|
/* acse_free_con */
|
|
/*----------------------------------------------------------------------*/
|
|
/* This function will free the pointer to connection info. */
|
|
/* For MOSI, a slightly different "acse_free_con" function is */
|
|
/* defined in COSP????.c */
|
|
/************************************************************************/
|
|
ST_VOID acse_free_con (ACSE_CONN *acse_conn)
|
|
{
|
|
if (acse_conn->save_buf.len)
|
|
M_FREE (MSMEM_ACSE_DATA, acse_conn->save_buf.ptr);
|
|
M_FREE (MSMEM_ACSE_CONN, acse_conn);
|
|
}
|
|
#endif /* !MOSI */
|
|
|
|
/************************************************************************/
|
|
/* a_buffers_avail - Buffers available for sending A-Data req. */
|
|
/* This function returns the number of buffers available for sending */
|
|
/* A-Data. This may be used, for example, when sending Information */
|
|
/* Reports, to make sure there are always enough buffers for sending */
|
|
/* responses to incoming requests. */
|
|
/* */
|
|
/* Parameters: */
|
|
/* ST_LONG acse_conn_id ACSE Connection ID */
|
|
/* */
|
|
/* Return: */
|
|
/* ST_INT # of ACSE transmit buffers available */
|
|
/************************************************************************/
|
|
|
|
#if defined(LEAN_T) || defined(REDUCED_STACK)
|
|
|
|
ST_INT a_buffers_avail (
|
|
ST_LONG acse_conn_id) /* ACSE's ID for this connection */
|
|
{
|
|
#if defined(LEAN_T)
|
|
ACSE_CONN *acse_conn;
|
|
|
|
acse_conn = (ACSE_CONN *)acse_conn_id;
|
|
|
|
return (tp4_buffers_avail (acse_conn->tp4_conn_id));
|
|
#endif
|
|
|
|
#if defined(REDUCED_STACK)
|
|
return (2);
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined (MOSI) /* Only MOSI uses events. */
|
|
#if defined(_WIN32)
|
|
/* Not used for DOS, QNX, or VXWORKS */
|
|
/************************************************************************/
|
|
/* a_get_event_handles */
|
|
/* Returns a pointer to an array of (ST_EVENT_SEM) and sets */
|
|
/* (*pNumEntries) equal to the number of entries. */
|
|
/************************************************************************/
|
|
ST_EVENT_SEM a_get_event_handles (ST_INT *pNumEntries)
|
|
{
|
|
static ST_EVENT_SEM EventArray [2];
|
|
ST_INT NumEntries = 0;
|
|
|
|
#if defined (TP4_ENABLED)
|
|
/* If "hMainEvent" initialized, use it instead of default "hMMSEvent"*/
|
|
if (hMainEvent)
|
|
EventArray [NumEntries++] = hMainEvent; /* CLNP thread event. */
|
|
else
|
|
EventArray [NumEntries++] = hMMSEvent; /* driver event */
|
|
#endif
|
|
#if defined (TP0_ENABLED)
|
|
EventArray [NumEntries++] = hTcpEvent; /* TCP/IP sockets event */
|
|
#endif
|
|
|
|
*pNumEntries = NumEntries;
|
|
return (EventArray);
|
|
}
|
|
#else /* !defined(_WIN32) */
|
|
/************************************************************************/
|
|
/* a_get_event_handles_unix */
|
|
/* Returns a pointer to an array of handles and sets */
|
|
/* (*pNumEntries) equal to the number of entries. */
|
|
/* NOTE: The TP4_ENABLED option currently only works on "linux". */
|
|
/************************************************************************/
|
|
#if defined(TP4_ENABLED)
|
|
#if defined(linux)
|
|
extern int hPktSock;
|
|
#else
|
|
#error TP4 not supported on this platform
|
|
#endif
|
|
#endif
|
|
#if defined(TP0_ENABLED)
|
|
extern int pipe_to_main; /* DEBUG: move to include */
|
|
#endif
|
|
int *a_get_event_handles_unix (ST_INT *pNumEntries)
|
|
{
|
|
static int fd_array [2];
|
|
ST_INT NumEntries = 0;
|
|
|
|
#if defined(TP4_ENABLED)
|
|
fd_array[NumEntries++] = hPktSock;
|
|
#endif
|
|
#if defined(TP0_ENABLED)
|
|
fd_array[NumEntries++] = pipe_to_main;
|
|
#endif
|
|
*pNumEntries = NumEntries;
|
|
return (fd_array);
|
|
}
|
|
#endif /* !defined(_WIN32) */
|
|
#endif /* MOSI */
|
|
|
|
|
|
/*------------------------------------------------------*/
|
|
/* Security functions */
|
|
/*------------------------------------------------------*/
|
|
|
|
/********************************************************************************/
|
|
/* a_get_security_info */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Returns pointers to encryption control and partner's authentication info */
|
|
/* from the specified channel info. This functions should be called after */
|
|
/* connection indication was received to retrieve the security informations. */
|
|
/* After the connection terminates call the s_free_part_security_info() to free */
|
|
/* the allocated auth_value buf and cleanup the channel info. */
|
|
/* Parameters: */
|
|
/* ST_LONG acse_conn_id indirect ptr to access security info */
|
|
/* S_SEC_PARAMS *secParams pointer where to ret security info. */
|
|
/* Return: */
|
|
/* ST_RET SD_SUCCESS if get operation succeeded, otherwise */
|
|
/* SD_FAILURE or other error. */
|
|
/********************************************************************************/
|
|
ST_RET a_get_security_info (ST_LONG acse_conn_id, S_SEC_SPARAMS *secParams)
|
|
{
|
|
ST_RET ret = SD_SUCCESS;
|
|
ACSE_CONN *acse_conn;
|
|
|
|
secParams->authInfo = NULL; /* local auth info not stored */
|
|
secParams->partAuthInfo = NULL; /* partner auth info */
|
|
secParams->encryptCtrl = NULL; /* connection encryption info */
|
|
|
|
if (acse_conn_id)
|
|
{
|
|
acse_conn= (ACSE_CONN *) acse_conn_id;
|
|
if (acse_conn)
|
|
{
|
|
secParams->partAuthInfo = &acse_conn->part_auth_info;
|
|
secParams->encryptCtrl = &acse_conn->encrypt_ctrl;
|
|
}
|
|
}
|
|
else
|
|
ret = SD_FAILURE; /* cc should be valid in this call */
|
|
|
|
return (ret);
|
|
}
|
|
|
|
/********************************************************************************/
|
|
/* a_free_security_info */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Releases authentication info resources. */
|
|
/* Parameters: */
|
|
/* ACSE_AUTH_INFO *authInfo ptr to free the security resources */
|
|
/* Return: */
|
|
/* ST_RET SD_SUCCESS if free operation succeeded */
|
|
/* SD_FAILURE otherwise */
|
|
/********************************************************************************/
|
|
ST_RET a_free_security_info (ACSE_AUTH_INFO *authInfo)
|
|
{
|
|
ST_RET ret = SD_SUCCESS;
|
|
|
|
if (authInfo)
|
|
{
|
|
/* clear authentication info */
|
|
/* if there is an existing auth_value buf pointer then we have to free it */
|
|
if (authInfo->auth_pres && authInfo->mech_type != ACSE_AUTH_MECH_PASSWORD)
|
|
if (authInfo->u.other_auth.auth_value.buf)
|
|
{
|
|
chk_free (authInfo->u.other_auth.auth_value.buf);
|
|
authInfo->u.other_auth.auth_value.buf = NULL;
|
|
authInfo->u.other_auth.auth_value.ptr = NULL;
|
|
authInfo->u.other_auth.auth_value.len = 0;
|
|
}
|
|
authInfo->auth_pres = SD_FALSE;
|
|
}
|
|
|
|
return (ret);
|
|
}
|
|
|
|
|
|
/********************************************************************************/
|
|
/* a_free_part_security_info */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Releases partner authentication resources and resets the field in ACSE_CONN. */
|
|
/* Parameters: */
|
|
/* ST_LONG acse_conn_id indirect ptr to access security info */
|
|
/* Return: */
|
|
/* ST_RET SD_SUCCESS if free operation succeeded */
|
|
/* SD_FAILURE otherwise */
|
|
/********************************************************************************/
|
|
ST_RET a_free_part_security_info (ST_LONG acse_conn_id)
|
|
{
|
|
ST_RET ret = SD_SUCCESS;
|
|
ACSE_CONN *acse_conn;
|
|
|
|
if (acse_conn_id)
|
|
{
|
|
acse_conn= (ACSE_CONN *) acse_conn_id;
|
|
if (acse_conn)
|
|
ret = a_free_security_info (&acse_conn->part_auth_info);
|
|
}
|
|
return (ret);
|
|
}
|
|
|