786 lines
27 KiB
C++
786 lines
27 KiB
C++
//--------------------------------------------------------------------
|
|
// Copyright (C)1998 Microsoft Corporation, All Rights Reserved.
|
|
//
|
|
// scep.h
|
|
//
|
|
// Constants and Types for the Simple Command Execution Protocol
|
|
// (SCEP). This is the transport protocol for IrTran-P V1.0.
|
|
//
|
|
// NOTE: That IrTran-P is a big-endian protocol when on the net.
|
|
//
|
|
// NOTE: That the protocol data structures below assume that the
|
|
// compiler generates structures with natural alignment by
|
|
// field type.
|
|
//
|
|
// Author:
|
|
//
|
|
// Edward Reus (edwardr) 02-05-98 Initial coding.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
|
|
#ifndef _SCEP_H_
|
|
#define _SCEP_H_
|
|
|
|
#ifndef _BFTP_H_
|
|
#include "bftp.h"
|
|
#endif
|
|
|
|
//--------------------------------------------------------------------
|
|
// Constants:
|
|
//--------------------------------------------------------------------
|
|
|
|
#define LITTLE_ENDIAN
|
|
|
|
#define PROTOCOL_VERSION 0x01
|
|
#define NEGOTIATION_VERSION 0x11 // SCEP_NEGOTIATION revision.
|
|
#define INF_VERSION 0x10 // Information Struct version.
|
|
|
|
#define USE_LENGTH2 0xff
|
|
|
|
// These PDU sizes are the default and negotiated sizes:
|
|
#define PDU_SIZE_1 512
|
|
#define PDU_SIZE_2 1024
|
|
#define PDU_SIZE_3 2048
|
|
#define PDU_SIZE_4 4096
|
|
#define MAX_PDU_SIZE PDU_SIZE_4
|
|
|
|
#define DEFAULT_PDU_SIZE MAX_PDU_SIZE
|
|
|
|
// These sizes are used to check if we have a complete PDU:
|
|
#define MIN_PDU_SIZE_CONNECT 28
|
|
#define MAX_PDU_SIZE_CONNECT 256
|
|
#define MIN_PDU_SIZE_CONNECT_RESP 24
|
|
#define MAX_PDU_SIZE_CONNECT_RESP 255
|
|
|
|
#define MIN_PDU_SIZE_DATA 8
|
|
|
|
#define MIN_PDU_SIZE_DISCONNECT 6
|
|
|
|
// These are the sizes of the SCEP headers:
|
|
#define SCEP_HEADER_SIZE 2
|
|
#define SCEP_REQ_HEADER_SHORT_SIZE 34
|
|
#define COMMAND_HEADER_SIZE 28
|
|
|
|
#define FILE_NAME_SIZE 12 // 8.3
|
|
|
|
// These are the attribute strings that go in the negotiation part
|
|
// of connect request and response PDUs:
|
|
#define CONNECT_PDU_ATTRIBUTES "fr:3\r\nid:Microsoft IrTran-P v1.0\r\n"
|
|
#define RESPONSE_PDU_ATTRIBUTES "fr:4\r\nid:Microsoft IrTran-P v1.0\r\n"
|
|
|
|
// Message Types (field: MsgType):
|
|
#define MSG_TYPE_CONNECT_REQ 0x10 // Connection request.
|
|
#define MSG_TYPE_CONNECT_RESP 0x11 // Connection confirmation.
|
|
#define MSG_TYPE_DATA 0x20 // Data PDU.
|
|
#define MSG_TYPE_DISCONNECT 0x30 // Disconnection.
|
|
|
|
// Information Types (field: InfType):
|
|
#define INF_TYPE_VERSION 0x00 // Connection establishment.
|
|
#define INF_TYPE_NEGOTIATION 0x01 // Connection establish or accept.
|
|
#define INF_TYPE_USER_DATA 0x03 // Only if MsgType is MSG_TYPE_DATA.
|
|
#define INF_TYPE_EXTEND 0x10 // Connection establishment.
|
|
#define INF_TYPE_REASON 0x20 // Only for disconnect.
|
|
|
|
// Command Header: Pdu Types (top two bits in PduType):
|
|
#define PDU_TYPE_REQUEST 0x00 // b:00000000
|
|
#define PDU_TYPE_REPLY_ACK 0x40 // b:01000000
|
|
#define PDU_TYPE_REPLY_NACK 0x80 // b:10000000
|
|
#define PDU_TYPE_ABORT 0xc0 // b:11000000
|
|
|
|
#define PDU_TYPE_MASK 0xc0 // b:11000000
|
|
#define PDU_TYPE_RESERVED 0x3f // b:00111111
|
|
|
|
// The machine ID is in the Connect PDU (SCEP_NEGOTIATION), it
|
|
// is in EUI-64 format:
|
|
#define MACHINE_ID_SIZE 8
|
|
|
|
// Machine PIDs: In the command header, the default source and destination
|
|
// program Ids are unsigned shorts with value 8. Some machines will have
|
|
// a PID other than this (see the first command header sent to us):
|
|
#define DEFAULT_PID 8
|
|
|
|
// CFlag meanings:
|
|
//
|
|
// There are two cases, one where a device/machine can only issue commands,
|
|
// the other when a device can both issue and execute commands.
|
|
//
|
|
#define CFLAG_ISSUE_ONLY 0x00
|
|
#define CFLAG_ISSUE_OR_EXECUTE 0x04
|
|
|
|
// DFlag Meanings:
|
|
//
|
|
// DFlag give information about the data and fragmentation (why did they
|
|
// put the reject in here?).
|
|
//
|
|
#define DFLAG_SINGLE_PDU 0xc1
|
|
#define DFLAG_FIRST_FRAGMENT 0x41
|
|
#define DFLAG_FRAGMENT 0x01
|
|
#define DFLAG_LAST_FRAGMENT 0x81
|
|
#define DFLAG_INTERRUPT 0xc2
|
|
#define DFLAG_CONNECT_REJECT 0xc3
|
|
|
|
// Reason Codes:
|
|
//
|
|
// Currently for V1.0 all reason codes are 2-byte numbers:
|
|
#define REASON_CODE_UNSPECIFIED 0x0000
|
|
#define REASON_CODE_USER_DISCONNECT 0x0001
|
|
#define REASON_CODE_PROVIDER_DISCONNECT 0x0002
|
|
|
|
// Connection States:
|
|
#define STATE_CLOSED 0
|
|
#define STATE_CONNECTING 1
|
|
#define STATE_CONNECTED 2
|
|
|
|
// Put Response Protocol Error Codes (sent back to the camera):
|
|
#define ERROR_PUT_UNDEFINED_ERROR 0x0000
|
|
#define ERROR_PUT_ILLEGAL_DATA 0x0001
|
|
#define ERROR_PUT_UNSUPPORTED_PID 0x0002
|
|
#define ERROR_PUT_ILLEGAL_ATTRIBUTE 0x0010
|
|
#define ERROR_PUT_UNSUPPORTED_CMD 0x0011
|
|
#define ERROR_PUT_FILE_SYSTEM_FULL 0x0020
|
|
#define ERROR_PUT_NO_FILE_OR_DIR 0x0021
|
|
#define ERROR_PUT_LOW_BATTERY 0x0030
|
|
#define ERROR_PUT_ABORT_EXECUTION 0x0031
|
|
#define ERROR_PUT_NO_ERROR 0xffff
|
|
|
|
//--------------------------------------------------------------------
|
|
// SCEP Protocol Headers:
|
|
//--------------------------------------------------------------------
|
|
|
|
// Turn off warning for zero-sized array...
|
|
#pragma warning(disable:4200)
|
|
#pragma pack(1)
|
|
|
|
typedef struct _SCEP_HEADER
|
|
{
|
|
UCHAR Null; // Always zero.
|
|
UCHAR MsgType; // See MSG_TYPE_* above.
|
|
UCHAR Rest[]; // Dependent on the MsgType...
|
|
} SCEP_HEADER;
|
|
|
|
typedef struct _SCEP_VERSION
|
|
{
|
|
UCHAR InfType; // Always INF_TYPE_VERSION (0x00).
|
|
UCHAR Version; // Currently 0x01 (Version = 1).
|
|
} SCEP_VERSION;
|
|
|
|
typedef struct _SCEP_NEGOTIATION
|
|
{
|
|
UCHAR InfType; // Always INF_TYPE_NEGOTATION (0x01).
|
|
UCHAR Length; // Length (bytes) from InfVersion to
|
|
// the end of the Negotiation information.
|
|
// This will be from 0 to 228.
|
|
UCHAR InfVersion; // Version of InfType = INF_VERSION.
|
|
UCHAR CFlag; //
|
|
UCHAR SecondaryMachineId[8]; //
|
|
UCHAR PrimaryMachineId[8]; //
|
|
UCHAR Negotiation[]; //
|
|
} SCEP_NEGOTIATION;
|
|
|
|
typedef struct _SCEP_DISCONNECT
|
|
{
|
|
UCHAR InfType; // Always INF_TYPE_REASON (0x20).
|
|
UCHAR Length1; // For V1.0 this should be 2.
|
|
USHORT ReasonCode; // See the REASON_CODE_xxx
|
|
} SCEP_DISCONNECT;
|
|
|
|
typedef struct _SCEP_EXTEND
|
|
{
|
|
UCHAR InfType; // Always INF_TYPE_EXTEND (0x10).
|
|
UCHAR Length; // Always 2 (bytes).
|
|
UCHAR Parameter1;
|
|
UCHAR Parameter2;
|
|
} SCEP_EXTEND;
|
|
|
|
typedef struct _COMMAND_HEADER
|
|
{
|
|
UCHAR Marker58h; // Always 0x58 (See: 3.2.2.1.3 of Protocol).
|
|
UCHAR PduType; // One of: PDU_TYPE_xxxx.
|
|
ULONG Length4;
|
|
UCHAR DestMachineId[MACHINE_ID_SIZE];
|
|
UCHAR SrcMachineId[MACHINE_ID_SIZE];
|
|
USHORT DestPid;
|
|
USHORT SrcPid;
|
|
USHORT CommandId;
|
|
} COMMAND_HEADER;
|
|
|
|
typedef struct _SCEP_REQ_HEADER_SHORT
|
|
{
|
|
UCHAR InfType; // Always INF_TYPE_USER_DATA (0x03).
|
|
UCHAR Length1;
|
|
UCHAR InfVersion; // Version of InfType = INF_VERSION.
|
|
UCHAR DFlag;
|
|
USHORT Length3;
|
|
UCHAR CommandHeader[sizeof(COMMAND_HEADER)];
|
|
UCHAR UserData[];
|
|
} SCEP_REQ_HEADER_SHORT;
|
|
|
|
typedef struct _SCEP_REQ_HEADER_LONG
|
|
{
|
|
UCHAR InfType; // Always INF_TYPE_USER_DATA (0x03).
|
|
UCHAR Length1;
|
|
USHORT Length2; // Only present if Length1 == 0xff.
|
|
UCHAR InfVersion; // Version of InfType = INF_VERSION.
|
|
UCHAR DFlag;
|
|
USHORT Length3;
|
|
UCHAR CommandHeader[sizeof(COMMAND_HEADER)];
|
|
UCHAR UserData[];
|
|
} SCEP_REQ_HEADER_LONG;
|
|
|
|
typedef struct _SCEP_REQ_HEADER_SHORT_FRAG
|
|
{
|
|
UCHAR Inftype; // Always INF_TYPE_USER_DATA (0x03).
|
|
UCHAR Length1;
|
|
UCHAR InfVersion; // Version of InfType = INF_VERSION.
|
|
UCHAR DFlag;
|
|
USHORT Length3;
|
|
DWORD SequenceNo; // Fragment number.
|
|
DWORD RestNo; // Number of fragments left for this PDU.
|
|
UCHAR CommandHeader[sizeof(COMMAND_HEADER)];
|
|
UCHAR UserData[];
|
|
} SCEP_REQ_HEADER_SHORT_FRAG;
|
|
|
|
typedef struct _SCEP_REQ_HEADER_LONG_FRAG
|
|
{
|
|
UCHAR InfType; // Always INF_TYPE_USER_DATA (0x03).
|
|
UCHAR Length1;
|
|
USHORT Length2; // Only present if Length1 == 0xff.
|
|
UCHAR InfVersion; // Version of InfType = INF_VERSION.
|
|
UCHAR DFlag;
|
|
USHORT Length3;
|
|
DWORD SequenceNo; // Fragment number.
|
|
DWORD RestNo; // Number of fragments left for this PDU.
|
|
UCHAR CommandHeader[sizeof(COMMAND_HEADER)];
|
|
UCHAR UserData[];
|
|
} SCEP_REQ_HEADER_LONG_FRAG;
|
|
|
|
#pragma pack()
|
|
#pragma warning(default:4200)
|
|
|
|
//--------------------------------------------------------------------
|
|
// SCEP API Structures:
|
|
//--------------------------------------------------------------------
|
|
|
|
class CSCEP_CONNECTION
|
|
{
|
|
public:
|
|
CSCEP_CONNECTION();
|
|
~CSCEP_CONNECTION();
|
|
|
|
void *operator new( IN size_t Size );
|
|
|
|
void operator delete( IN void *pObj,
|
|
IN size_t Size );
|
|
|
|
// Assemble the next PDU as data comes in:
|
|
DWORD AssemblePdu( IN void *pInputData,
|
|
IN DWORD dwInputDataSize,
|
|
OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
// Parse the PDU returned from AssemblePdu():
|
|
DWORD ParsePdu( IN SCEP_HEADER *pPdu,
|
|
IN DWORD dwPduSize,
|
|
OUT COMMAND_HEADER **ppCommand,
|
|
OUT UCHAR **ppUserData,
|
|
OUT DWORD *pdwUserDataSize );
|
|
|
|
DWORD SetScepLength( IN SCEP_HEADER *pPdu,
|
|
IN DWORD dwTotalPduSize );
|
|
|
|
// Construct SCEP connection/control PDUs:
|
|
DWORD BuildConnectPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD BuildConnectRespPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD BuildConnectNackPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD BuildAbortPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD BuildStopPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD BuildDisconnectPdu( IN USHORT ReasonCode,
|
|
OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
// Build bFTP request (client-side) PDUs:
|
|
DWORD BuildBftpWht0RinfPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize,
|
|
OUT SCEP_REQ_HEADER_LONG **ppCommand,
|
|
OUT COMMAND_HEADER **ppCommandHeader );
|
|
|
|
DWORD BuildBftpPutPdu( IN DWORD dwUpfFileSize,
|
|
IN CHAR *pszUpfFile,
|
|
IN OUT DWORD *pdwFragNo,
|
|
OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize,
|
|
OUT SCEP_REQ_HEADER_LONG_FRAG **ppCommand );
|
|
|
|
// Build bFTP response PDUs:
|
|
DWORD BuildBftpRespPdu( IN DWORD dwPduSize,
|
|
OUT SCEP_HEADER **ppPdu,
|
|
OUT SCEP_REQ_HEADER_SHORT **ppCommand,
|
|
OUT COMMAND_HEADER **ppCommandHeader );
|
|
|
|
DWORD BuildWht0RespPdu( IN DWORD dwWht0Type,
|
|
OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD BuildPutRespPdu( IN DWORD dwPduAckOrNack,
|
|
IN USHORT usErrorCode,
|
|
OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
// Parse the bFTP in a SCEP command request PDU:
|
|
DWORD ParseBftp( IN UCHAR *pvBftpData,
|
|
IN DWORD dwDataSize,
|
|
IN BOOL fSaveAsUPF,
|
|
OUT DWORD *pdwBftpOp,
|
|
OUT UCHAR **ppPutData,
|
|
OUT DWORD *pdwPutDataSize );
|
|
|
|
// Parse and save the create date/time that was specified as a
|
|
// bFTP option:
|
|
DWORD SaveBftpCreateDate( IN UCHAR *pDate,
|
|
IN DWORD dwLength );
|
|
|
|
// Parse the UPF file header to find the image JPEG file:
|
|
DWORD ParseUpfHeaders( IN UCHAR *pPutData,
|
|
IN DWORD dwPutDataSize,
|
|
OUT DWORD *pdwJpegOffset,
|
|
OUT DWORD *pdwJpegSize );
|
|
|
|
// Used when a SCEP command PDU is received:
|
|
BOOL IsFragmented();
|
|
DWORD GetSequenceNo();
|
|
DWORD GetRestNo();
|
|
DWORD GetCommandId();
|
|
WCHAR *GetFileName();
|
|
UCHAR GetDFlag();
|
|
FILETIME *GetCreateTime();
|
|
|
|
protected:
|
|
|
|
DWORD CheckPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD CheckConnectPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD CheckAckPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD CheckNackPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD CheckConnectRespPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD CheckDataPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD CheckDisconnectPdu( OUT SCEP_HEADER **ppPdu,
|
|
OUT DWORD *pdwPduSize );
|
|
|
|
DWORD ParseConnectPdu( IN SCEP_HEADER *pPdu,
|
|
IN DWORD dwPduSize );
|
|
|
|
DWORD ParseConnectRespPdu( IN SCEP_HEADER *pPdu,
|
|
IN DWORD dwPduSize );
|
|
|
|
DWORD ParseDataPdu( IN SCEP_HEADER *pPdu,
|
|
IN DWORD dwPduSize,
|
|
OUT COMMAND_HEADER **ppCommand,
|
|
OUT UCHAR **ppUserData,
|
|
OUT DWORD *pdwUserDataSize );
|
|
|
|
DWORD ParseDisconnectPdu( IN SCEP_HEADER *pPdu,
|
|
IN DWORD dwPduSize );
|
|
|
|
DWORD ParseNegotiation( IN UCHAR *pNegotiation,
|
|
IN DWORD dwNegotiationSize );
|
|
|
|
UCHAR *ParseAttribute( IN UCHAR *pAttributes,
|
|
IN OUT DWORD *pdwAttributeSize,
|
|
OUT DWORD *pdwStatus );
|
|
|
|
DWORD ParseSingleLongPdu( IN SCEP_HEADER *pPdu,
|
|
IN DWORD dwPduSize );
|
|
|
|
BFTP_ATTRIBUTE *ParseBftpAttributeName(
|
|
IN BFTP_ATTRIBUTE *pAttr,
|
|
IN OUT DWORD *pdwSize,
|
|
OUT DWORD *pdwWhichAttr );
|
|
|
|
DWORD m_dwConnectionState;
|
|
DWORD m_dwPduSendSize;
|
|
DWORD m_dwPduReceiveSize;
|
|
UCHAR m_CFlag;
|
|
UCHAR *m_pPrimaryMachineId;
|
|
UCHAR *m_pSecondaryMachineId;
|
|
USHORT m_DestPid; // My PID (Camera point of view).
|
|
USHORT m_SrcPid; // Camera's PID (Camera point of view).
|
|
UCHAR *m_pszProductId;
|
|
UCHAR *m_pszUserName;
|
|
UCHAR *m_pszPassword;
|
|
|
|
// Used during PDU assembley process.
|
|
UCHAR *m_pAssembleBuffer;
|
|
DWORD m_dwAssembleBufferSize;
|
|
DWORD m_dwMaxAssembleBufferSize;
|
|
BOOL m_fDidByteSwap;
|
|
|
|
// Used to manage the current SCEP command PDU.
|
|
UCHAR m_Fragmented;
|
|
UCHAR m_DFlag;
|
|
DWORD m_dwSequenceNo;
|
|
DWORD m_dwRestNo;
|
|
DWORD m_dwCommandId;
|
|
COMMAND_HEADER *m_pCommandHeader;
|
|
|
|
// UPF Hear and bFTP information
|
|
// NOTE: The CHAR version of the file name is the one that camera
|
|
// sent us, the WCHAR version is the one we will actually
|
|
// create. Note that the WCHAR version usually has a different
|
|
// suffix.
|
|
CHAR *m_pszFileName;
|
|
CHAR *m_pszLongFileName;
|
|
WCHAR *m_pwszFileName;
|
|
FILETIME m_CreateTime;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// Inline Functions:
|
|
//--------------------------------------------------------------------
|
|
|
|
inline BOOL CSCEP_CONNECTION::IsFragmented()
|
|
{
|
|
return m_Fragmented;
|
|
}
|
|
|
|
inline DWORD CSCEP_CONNECTION::GetSequenceNo()
|
|
{
|
|
return m_dwSequenceNo;
|
|
}
|
|
|
|
inline DWORD CSCEP_CONNECTION::GetRestNo()
|
|
{
|
|
return m_dwRestNo;
|
|
}
|
|
|
|
inline DWORD CSCEP_CONNECTION::GetCommandId()
|
|
{
|
|
return m_dwCommandId;
|
|
}
|
|
|
|
inline WCHAR *CSCEP_CONNECTION::GetFileName()
|
|
{
|
|
return m_pwszFileName;
|
|
}
|
|
|
|
inline UCHAR CSCEP_CONNECTION::GetDFlag()
|
|
{
|
|
return m_DFlag;
|
|
}
|
|
|
|
inline FILETIME *CSCEP_CONNECTION::GetCreateTime()
|
|
{
|
|
if ( (m_CreateTime.dwLowDateTime)
|
|
|| (m_CreateTime.dwHighDateTime) )
|
|
{
|
|
return &m_CreateTime;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// Utility Functions/Macros:
|
|
//--------------------------------------------------------------------
|
|
|
|
#define ByteSwapShort(Value) \
|
|
( (((Value) & 0x00FF) << 8) \
|
|
| (((Value) & 0xFF00) >> 8))
|
|
|
|
#define ByteSwapLong(Value) \
|
|
( (((Value) & 0xFF000000) >> 24) \
|
|
| (((Value) & 0x00FF0000) >> 8) \
|
|
| (((Value) & 0x0000FF00) << 8) \
|
|
| (((Value) & 0x000000FF) << 24))
|
|
|
|
extern void ByteSwapReqHeaderShort( SCEP_REQ_HEADER_SHORT *pSingleShort );
|
|
|
|
extern void ByteSwapReqHeaderLong( SCEP_REQ_HEADER_LONG *pSingleLong );
|
|
|
|
extern void ByteSwapCommandHeader( COMMAND_HEADER *pCommandHeader );
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// Memory management functions:
|
|
//--------------------------------------------------------------------
|
|
|
|
DWORD InitializeMemory();
|
|
|
|
DWORD UninitializeMemory();
|
|
|
|
void *AllocateMemory( DWORD dwBytes );
|
|
|
|
DWORD FreeMemory( void *pvMemory );
|
|
|
|
SCEP_HEADER *NewPdu( DWORD dwPduSize = MAX_PDU_SIZE );
|
|
|
|
void DeletePdu( SCEP_HEADER *pPdu );
|
|
|
|
#if FALSE
|
|
//--------------------------------------------------------------------
|
|
|
|
SCEP Connect PDU
|
|
----------------
|
|
|
|
Connection request PDU. This is a SCEP_HEADER with Rest[] filled
|
|
with three Inf Records, a SCEP_VERSION followed by a SCEP_NEGOTIATION
|
|
followed by a SCEP_EXTEND. The Connect PDU must be less than or equal
|
|
to 256 bytes in length.
|
|
|
|
SCEP_HEADER 2 bytes.
|
|
Rest[]: SCEP_VERSION 2 bytes.
|
|
SCEP_NEGOTIATION 20 - 228 bytes.
|
|
SCEP_EXTEND 4 bytes.
|
|
--------
|
|
28 - 256 bytes.
|
|
|
|
- If either the SecondaryMachineId[] or PrimariyMachineId is unused,
|
|
then they are set to 00,00,00,00,00,00,00,00.
|
|
- If a machine gets a Connect PDU but can't execute commands
|
|
(CFlag = CFLAG_ISSUE_ONLY), then it needs to respond with a
|
|
NACK PDU.
|
|
- The negotiation information is a simple text based command
|
|
language.
|
|
|
|
|
|
SCEP Connection ACK PDU
|
|
-----------------------
|
|
|
|
Connection acceptance PDU. This is a SCEP_HEADER with Rest[] filled
|
|
with two Inf Records, a SCEP_VERSION followed by a SCEP_NEGOTIATION.
|
|
|
|
SCEP_HEADER 2 bytes.
|
|
SCEP_VERSION 2 bytes.
|
|
Rest[]: SCEP_NEGOTIATION 20-251 bytes.
|
|
------
|
|
24-255 bytes.
|
|
|
|
- Note that the size of the ACK PDU is limited by the fact that
|
|
the Length field is a single byte and that the ACK PDU can not
|
|
be fragmented. Normally these PDUs will never be this long.
|
|
|
|
|
|
SCEP Connection NACK PDU
|
|
------------------------
|
|
|
|
Connection rejected PDU. This one can have either of two different
|
|
formats.
|
|
|
|
SCEP_HEADER
|
|
Rest[]: SCEP_REQ_HEADER_SHORT
|
|
|
|
or
|
|
|
|
SCEP_HEADER
|
|
Rest[]: SCEP_REQ_HEADER_LONG
|
|
|
|
- In the first case, Length1 = 4, DFlag = DFLAG_CONNECT_REJECT,
|
|
and Length 3 = 0.
|
|
- In the second case, Length1 = 0xff, DFlag = DFLAG_CONNECT_REJECT,
|
|
and Length 3 = 0.
|
|
|
|
|
|
SCEP Disconnect PDU
|
|
-------------------
|
|
|
|
A disconnect can be generated by either side of the connection,
|
|
or by one of the transports at any time.
|
|
|
|
SCEP_HEADER
|
|
Rest[]: SCEP_DISCONNECT
|
|
|
|
- For V1.0, Length1 = 2, and ReasonCode is a USHORT.
|
|
|
|
|
|
SCEP Command Request and Response PDUs (Non-fragmented)
|
|
-------------------------------------------------------
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_SHORT 4 + 0-254 bytes
|
|
---------
|
|
6 - 260 bytes
|
|
or
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_LONG 4 + 0-4090 bytes (1)
|
|
----------
|
|
6 - 4096 bytes
|
|
|
|
- In either case, DFlag = DFLAG_SINGLE_PDU.
|
|
- PduType = PDU_TYPE_REQUEST.
|
|
- If Length1 = 0xff then the long version is used.
|
|
- The Length1(2) field specifies the byte size from InfVersion to the
|
|
end of the user data. If the total size will exceed the maximum PDU
|
|
size then the request must be fragmented.
|
|
- So the total PDU size is: 6 + Length1(2) bytes.
|
|
|
|
(1) Assuming the maximum PDU size is 4096 (fr:4).
|
|
|
|
|
|
SCEP Command Request and Response PDUs (Fragmented)
|
|
---------------------------------------------------
|
|
|
|
For requests these PDUs are generated when the PDU size is greater
|
|
than that of the responder that you are connected to. For responses,
|
|
the PDUs are fragmented when the returned data is greater than the
|
|
maximum that the requester specified during the connection establishment.
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_SHORT_FRAG 6 + 0-254 bytes
|
|
---------
|
|
8 - 260 bytes
|
|
or
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_LONG_FRAG 8 + 0-4088 bytes (1)
|
|
---------
|
|
10 - 4096 bytes
|
|
|
|
- For the first PDU fragment, DFlag = DFLAG_FIRST_FRAGMENT, for
|
|
intermediate fragments, DFlag = DFLAG_FRAGMENT, and for the
|
|
last fragment, DFlag = DFLAG_LAST_FRAGMENT.
|
|
- PduType = PDU_TYPE_REQUEST for the request.
|
|
- PduType = PDU_TYPE_REPLY_ACK or PDU_TYPE_REPLY_NACK in the
|
|
response.
|
|
- If Length1 = 0xff then the long version is used.
|
|
- Length1(2) can not exceed the maximum PDU size - 6 bytes.
|
|
- SequenceNo is 0 for the first PDU (NOTE: 4 bytes).
|
|
- RestNo is the remaining number of PDUs to get. It is 1 for
|
|
the last PDU (really, it says so in the spec!). So, a client
|
|
should start this as the total number of PDUs in the first
|
|
fragment (not really the number remaining). NOTE: 4 bytes.
|
|
|
|
(1) Assuming the maximum PDU size is 4096 (fr:4).
|
|
|
|
|
|
SCEP Abort PDU
|
|
--------------
|
|
|
|
Use the abort to stop execution of a command (specified by the
|
|
DestPid and CommandId) after ALL of the request PDUs have been
|
|
sent. An abort PDU also has two possible formats.
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_SHORT 34 bytes
|
|
--
|
|
36 bytes
|
|
or
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_LONG 36 bytes
|
|
--
|
|
38 bytes
|
|
|
|
- In either case, DFlag = DFLAG_SINGLE_PDU.
|
|
- In either case, PduType = PDU_TYPE_ABORT.
|
|
- For the short PDU, Length1 = 0x20 (32), and Length3 = 0x1c
|
|
(28).
|
|
- For the long PDU, Length1 = 0xff, Length2 = 0x20 (32),
|
|
and Length3 = 0x1c (28).
|
|
|
|
|
|
SCEP Stop (Interrupt) PDU
|
|
-------------------------
|
|
|
|
If an Abort PDU has been sent out to stop a command, and as the
|
|
command is halted some response data has already been sent, the
|
|
the responder will send this PDU. It appears that a Stop PDU should
|
|
not be sent if no response has yet been sent back.
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_SHORT 6 bytes
|
|
--
|
|
8 bytes
|
|
or
|
|
|
|
SCEP_HEADER 2 bytes
|
|
Rest[]: SCEP_REQ_HEADER_LONG 8 bytes
|
|
--
|
|
10 bytes
|
|
|
|
- In either case, DFlag = DFLAG_INTERRUPT.
|
|
- For the short PDU, Length1 = 4, and Length3 = 0.
|
|
- For the long PDU, Length1 = 0xff, Length2 = 4, and
|
|
Length3 = 0.
|
|
|
|
Negotiation Information
|
|
-----------------------
|
|
|
|
The negotiation information is used to convey the frame size,
|
|
authentication data, and product information, etc.
|
|
|
|
Its structure is a version code (currently 0x11) followed by
|
|
text in the following syntax:
|
|
|
|
NegInf -> Attribute ':' Spaces Value CrLf
|
|
|
|
Attribute -> AttribChar AttribChar
|
|
|
|
AttribChar-> 'a-zA-Z'
|
|
|
|
Value -> ValueChar Value
|
|
->
|
|
|
|
ValueChar -> 'ASCII string, bytes must be between 0x20 and 0x8e
|
|
inclusive'
|
|
|
|
Spaces -> ' ' Spaces
|
|
->
|
|
|
|
CrLf -> 0x0d 0x0a
|
|
|
|
Attribute Meaning
|
|
--------- -------
|
|
fr Frame (PDU) size. The sender requests the maximum
|
|
receivable PDU size, the receiver decides the
|
|
transmission PDU size in accordance with the senders
|
|
requested PDU size. The maximum PDU size of the sender
|
|
may be different than that of the receiver. The value
|
|
is one of:
|
|
|
|
1 - 512 bytes PDU size (default).
|
|
2 - 1024 bytes PDU size.
|
|
3 - 2048 bytes PDU size.
|
|
4 - 4096 bytes PDU size.
|
|
|
|
id Product Identification string.
|
|
|
|
nm User name. any byte string that doesn't include CR or
|
|
LF (note the conflict in by values with the syntax
|
|
specification above). The user name may be up to 32
|
|
characters long.
|
|
|
|
pw Password. This is a MD5 encoded password expressed
|
|
in a 16 byte "hex" string, no spaces are allowd.
|
|
It appears that this will always be 32 characters
|
|
long. For example: 0aff3728e4a62791337984282871a6bc
|
|
|
|
//--------------------------------------------------------------------
|
|
#endif
|
|
|
|
#endif //_SCEP_H_
|
|
|