#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/ICE/ICElib.h>
#include "ICElibint.h"
#include <stdio.h>
#define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity, _return) \
if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
{ \
_IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
return (_return); \
}
#define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
{ \
_IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
return (0); \
}
#define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \
if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
!= _expected_len) \
{ \
_IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
IceDisposeCompleteMessage (iceConn, _pStart); \
return (0); \
}
#define BAIL_STRING(_iceConn, _opcode, _pStart) {\
_IceErrorBadLength (_iceConn, 0, _opcode, IceFatalToConnection);\
IceDisposeCompleteMessage (_iceConn, _pStart);\
return (0);\
}
IceProcessMessagesStatus
IceProcessMessages (
IceConn iceConn,
IceReplyWaitInfo *replyWait,
Bool *replyReadyRet
)
{
iceMsg *header;
Bool replyReady = False;
IceReplyWaitInfo *useThisReplyWait = NULL;
IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess;
if (replyWait)
*replyReadyRet = False;
iceConn->dispatch_level++;
if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf))
{
return (IceProcessMessagesConnectionClosed);
}
if (!iceConn->io_ok)
{
iceConn->dispatch_level--;
iceConn->connection_status = IceConnectIOError;
return (IceProcessMessagesIOError);
}
header = (iceMsg *) iceConn->inbuf;
iceConn->inbufptr = iceConn->inbuf + SIZEOF (iceMsg);
iceConn->receive_sequence++;
if (iceConn->waiting_for_byteorder)
{
if (header->majorOpcode == 0 &&
header->minorOpcode == ICE_ByteOrder)
{
char byteOrder = ((iceByteOrderMsg *) header)->byteOrder;
int endian = 1;
CHECK_SIZE_MATCH (iceConn, ICE_ByteOrder,
header->length, SIZEOF (iceByteOrderMsg),
IceFatalToConnection, IceProcessMessagesIOError);
if (byteOrder != IceMSBfirst && byteOrder != IceLSBfirst)
{
_IceErrorBadValue (iceConn, 0,
ICE_ByteOrder, 2, 1, &byteOrder);
iceConn->connection_status = IceConnectRejected;
}
else
{
iceConn->swap =
(((*(char *) &endian) && byteOrder == IceMSBfirst) ||
(!(*(char *) &endian) && byteOrder == IceLSBfirst));
iceConn->waiting_for_byteorder = 0;
}
}
else
{
if (header->majorOpcode != 0)
{
_IceErrorBadMajor (iceConn, header->majorOpcode,
header->minorOpcode, IceFatalToConnection);
}
else
{
_IceErrorBadState (iceConn, 0,
header->minorOpcode, IceFatalToConnection);
}
iceConn->connection_status = IceConnectRejected;
}
iceConn->dispatch_level--;
if (!iceConn->io_ok)
{
iceConn->connection_status = IceConnectIOError;
retStatus = IceProcessMessagesIOError;
}
return (retStatus);
}
if (iceConn->swap)
{
header->length = lswapl (header->length);
}
if (replyWait)
{
_IceAddReplyWait (iceConn, replyWait);
{
int op;
if (header->majorOpcode == 0)
{
op = 0;
}
else
{
int idx = header->majorOpcode - iceConn->his_min_opcode;
op = iceConn->process_msg_info[idx].my_opcode;
}
useThisReplyWait = _IceSearchReplyWaits (iceConn, op);
}
}
if (header->majorOpcode == 0)
{
Bool connectionClosed;
_IceProcessCoreMsgProc processIce =
_IceVersions[iceConn->my_ice_version_index].process_core_msg_proc;
(*processIce) (iceConn, header->minorOpcode,
header->length, iceConn->swap,
useThisReplyWait, &replyReady, &connectionClosed);
if (connectionClosed)
{
return (IceProcessMessagesConnectionClosed);
}
}
else
{
if ((int) header->majorOpcode < iceConn->his_min_opcode ||
(int) header->majorOpcode > iceConn->his_max_opcode ||
!(iceConn->process_msg_info[header->majorOpcode -
iceConn->his_min_opcode].in_use))
{
_IceErrorBadMajor (iceConn, header->majorOpcode,
header->minorOpcode, IceCanContinue);
_IceReadSkip (iceConn, header->length << 3);
}
else
{
_IceProcessMsgInfo *processMsgInfo = &iceConn->process_msg_info[
header->majorOpcode - iceConn->his_min_opcode];
if (processMsgInfo->accept_flag)
{
IcePaProcessMsgProc processProc =
processMsgInfo->process_msg_proc.accept_client;
(*processProc) (iceConn, processMsgInfo->client_data,
header->minorOpcode, header->length, iceConn->swap);
}
else
{
IcePoProcessMsgProc processProc =
processMsgInfo->process_msg_proc.orig_client;
(*processProc) (iceConn,
processMsgInfo->client_data, header->minorOpcode,
header->length, iceConn->swap,
useThisReplyWait, &replyReady);
}
}
}
if (replyReady)
{
_IceSetReplyReady (iceConn, useThisReplyWait);
}
if (replyWait)
*replyReadyRet = _IceCheckReplyReady (iceConn, replyWait);
iceConn->dispatch_level--;
if (iceConn->dispatch_level == 0 && iceConn->free_asap)
{
_IceFreeConnection (iceConn);
retStatus = IceProcessMessagesConnectionClosed;
}
else if (!iceConn->io_ok)
{
iceConn->connection_status = IceConnectIOError;
retStatus = IceProcessMessagesIOError;
}
return (retStatus);
}
static void
AuthRequired (
IceConn iceConn,
int authIndex,
int authDataLen,
IcePointer authData
)
{
iceAuthRequiredMsg *pMsg;
IceGetHeader (iceConn, 0, ICE_AuthRequired,
SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg);
pMsg->authIndex = authIndex;
pMsg->authDataLength = authDataLen;
pMsg->length += WORD64COUNT (authDataLen);
IceWriteData (iceConn, authDataLen, (char *) authData);
if (PAD64 (authDataLen))
IceWritePad (iceConn, PAD64 (authDataLen));
IceFlush (iceConn);
}
static void
AuthReply (
IceConn iceConn,
int authDataLen,
IcePointer authData
)
{
iceAuthReplyMsg *pMsg;
IceGetHeader (iceConn, 0, ICE_AuthReply,
SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg);
pMsg->authDataLength = authDataLen;
pMsg->length += WORD64COUNT (authDataLen);
IceWriteData (iceConn, authDataLen, (char *) authData);
if (PAD64 (authDataLen))
IceWritePad (iceConn, PAD64 (authDataLen));
IceFlush (iceConn);
}
static void
AuthNextPhase (
IceConn iceConn,
int authDataLen,
IcePointer authData
)
{
iceAuthNextPhaseMsg *pMsg;
IceGetHeader (iceConn, 0, ICE_AuthNextPhase,
SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg);
pMsg->authDataLength = authDataLen;
pMsg->length += WORD64COUNT (authDataLen);
IceWriteData (iceConn, authDataLen, (char *) authData);
if (PAD64 (authDataLen))
IceWritePad (iceConn, PAD64 (authDataLen));
IceFlush (iceConn);
}
static void
AcceptConnection (
IceConn iceConn,
int versionIndex
)
{
iceConnectionReplyMsg *pMsg;
char *pData;
int extra;
extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply,
SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra),
iceConnectionReplyMsg, pMsg, pData);
pMsg->versionIndex = versionIndex;
STORE_STRING (pData, IceVendorString);
STORE_STRING (pData, IceReleaseString);
IceFlush (iceConn);
iceConn->connection_status = IceConnectAccepted;
}
static void
AcceptProtocol (
IceConn iceConn,
int hisOpcode,
int myOpcode,
int versionIndex,
char *vendor,
char *release
)
{
iceProtocolReplyMsg *pMsg;
char *pData;
int extra;
extra = STRING_BYTES (vendor) + STRING_BYTES (release);
IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply,
SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra),
iceProtocolReplyMsg, pMsg, pData);
pMsg->protocolOpcode = myOpcode;
pMsg->versionIndex = versionIndex;
STORE_STRING (pData, vendor);
STORE_STRING (pData, release);
IceFlush (iceConn);
_IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
}
static void
PingReply (
IceConn iceConn
)
{
IceSimpleMessage (iceConn, 0, ICE_PingReply);
IceFlush (iceConn);
}
static Bool
ProcessError (
IceConn iceConn,
unsigned long length,
Bool swap,
IceReplyWaitInfo *replyWait
)
{
int invokeHandler = 0;
Bool errorReturned = False;
iceErrorMsg *message;
char *pData, *pStart;
char severity;
CHECK_AT_LEAST_SIZE (iceConn, ICE_Error,
length, SIZEOF (iceErrorMsg),
(iceConn->connect_to_you || iceConn->connect_to_me) ?
IceFatalToConnection : IceFatalToProtocol);
IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
iceErrorMsg, message, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
severity = message->severity;
if (severity != IceCanContinue && severity != IceFatalToProtocol &&
severity != IceFatalToConnection)
{
_IceErrorBadValue (iceConn, 0,
ICE_Error, 9, 1, &severity);
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
pData = pStart;
if (swap)
{
message->errorClass = lswaps (message->errorClass);
message->offendingSequenceNum = lswapl (message->offendingSequenceNum);
}
if (!replyWait ||
message->offendingSequenceNum != replyWait->sequence_of_request)
{
invokeHandler = 1;
}
else
{
if (iceConn->connect_to_you &&
((!iceConn->connect_to_you->auth_active &&
message->offendingMinorOpcode == ICE_ConnectionSetup) ||
(iceConn->connect_to_you->auth_active &&
message->offendingMinorOpcode == ICE_AuthReply)))
{
_IceConnectionError *errorReply =
&(((_IceReply *) (replyWait->reply))->connection_error);
char *errorStr = NULL;
const char *tempstr;
char *prefix, *temp;
invokeHandler = 0;
errorReturned = True;
switch (message->errorClass)
{
case IceNoVersion:
tempstr =
"None of the ICE versions specified are supported";
errorStr = strdup(tempstr);
break;
case IceNoAuth:
tempstr =
"None of the authentication protocols specified are supported";
errorStr = strdup(tempstr);
break;
case IceSetupFailed:
prefix = "Connection Setup Failed, reason : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
case IceAuthRejected:
prefix = "Authentication Rejected, reason : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
case IceAuthFailed:
prefix = "Authentication Failed, reason : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
default:
invokeHandler = 1;
}
errorReply->type = ICE_CONNECTION_ERROR;
errorReply->error_message = errorStr;
}
else if (iceConn->protosetup_to_you &&
((!iceConn->protosetup_to_you->auth_active &&
message->offendingMinorOpcode == ICE_ProtocolSetup) ||
(iceConn->protosetup_to_you->auth_active &&
message->offendingMinorOpcode == ICE_AuthReply)))
{
_IceProtocolError *errorReply =
&(((_IceReply *) (replyWait->reply))->protocol_error);
char *errorStr = "";
char *prefix, *temp;
invokeHandler = 0;
errorReturned = True;
switch (message->errorClass)
{
case IceNoVersion:
temp =
"None of the protocol versions specified are supported";
errorStr = strdup(temp);
break;
case IceNoAuth:
temp =
"None of the authentication protocols specified are supported";
errorStr = strdup(temp);
break;
case IceSetupFailed:
prefix = "Protocol Setup Failed, reason : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
case IceAuthRejected:
prefix = "Authentication Rejected, reason : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
case IceAuthFailed:
prefix = "Authentication Failed, reason : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
case IceProtocolDuplicate:
prefix = "Protocol was already registered : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
case IceMajorOpcodeDuplicate:
prefix = "The major opcode was already used : ";
errorStr = (char *) malloc (strlen (prefix) + 2);
sprintf (errorStr, "%s%d", prefix, (int) *pData);
break;
case IceUnknownProtocol:
prefix = "Unknown Protocol : ";
EXTRACT_STRING (pData, swap, temp);
errorStr = (char *) malloc (
strlen (prefix) + strlen (temp) + 1);
sprintf (errorStr, "%s%s", prefix, temp);
free (temp);
break;
default:
invokeHandler = 1;
}
errorReply->type = ICE_PROTOCOL_ERROR;
errorReply->error_message = errorStr;
}
if (errorReturned == True)
{
IcePoAuthProc authProc;
if (iceConn->connect_to_you &&
iceConn->connect_to_you->auth_active)
{
authProc = _IcePoAuthProcs[(int)
(iceConn->connect_to_you->my_auth_index)];
(*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
True , False ,
0, NULL, NULL, NULL, NULL);
}
else if (iceConn->protosetup_to_you &&
iceConn->protosetup_to_you->auth_active)
{
_IcePoProtocol *protocol = _IceProtocols[
iceConn->protosetup_to_you->my_opcode - 1].orig_client;
authProc = protocol->auth_procs[(int)(iceConn->
protosetup_to_you->my_auth_index)];
(*authProc) (iceConn,
&iceConn->protosetup_to_you->my_auth_state,
True , False ,
0, NULL, NULL, NULL, NULL);
}
}
}
if (invokeHandler)
{
(*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode,
message->offendingSequenceNum, message->errorClass,
message->severity, (IcePointer) pData);
}
IceDisposeCompleteMessage (iceConn, pStart);
return (errorReturned);
}
static int
ProcessConnectionSetup (
IceConn iceConn,
unsigned long length,
Bool swap
)
{
iceConnectionSetupMsg *message;
int myVersionCount, hisVersionCount;
int myVersionIndex, hisVersionIndex;
int hisMajorVersion, hisMinorVersion;
int myAuthCount, hisAuthCount;
int found, i, j;
char *myAuthName, **hisAuthNames = NULL;
char *pData, *pStart, *pEnd;
char *vendor = NULL;
char *release = NULL;
int myAuthIndex = 0;
int hisAuthIndex = 0;
int accept_setup_now = 0;
char mustAuthenticate;
int authUsableCount;
int authUsableFlags[MAX_ICE_AUTH_NAMES];
int authIndices[MAX_ICE_AUTH_NAMES];
CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup,
length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection);
IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg),
iceConnectionSetupMsg, message, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
pData = pStart;
pEnd = pStart + (length << 3);
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING(iceConn, ICE_ConnectionSetup,
pStart));
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING(iceConn, ICE_ConnectionSetup,
pStart));
SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
BAIL_STRING(iceConn, ICE_ConnectionSetup,
pStart));
pData += (message->versionCount * 4);
CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup,
length, pData - pStart + SIZEOF (iceConnectionSetupMsg),
pStart, IceFatalToConnection);
mustAuthenticate = message->mustAuthenticate;
if (mustAuthenticate != 0 && mustAuthenticate != 1)
{
_IceErrorBadValue (iceConn, 0,
ICE_ConnectionSetup, 8, 1, &mustAuthenticate);
iceConn->connection_status = IceConnectRejected;
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
pData = pStart;
EXTRACT_STRING (pData, swap, vendor);
EXTRACT_STRING (pData, swap, release);
if ((hisAuthCount = message->authCount) > 0)
{
hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
}
hisVersionCount = message->versionCount;
myVersionCount = _IceVersionCount;
hisVersionIndex = myVersionIndex = found = 0;
for (i = 0; i < hisVersionCount && !found; i++)
{
EXTRACT_CARD16 (pData, swap, hisMajorVersion);
EXTRACT_CARD16 (pData, swap, hisMinorVersion);
for (j = 0; j < myVersionCount && !found; j++)
{
if (_IceVersions[j].major_version == hisMajorVersion &&
_IceVersions[j].minor_version == hisMinorVersion)
{
hisVersionIndex = i;
myVersionIndex = j;
found = 1;
}
}
}
if (!found)
{
_IceErrorNoVersion (iceConn, ICE_ConnectionSetup);
iceConn->connection_status = IceConnectRejected;
free (vendor);
free (release);
if (hisAuthCount > 0)
{
for (i = 0; i < hisAuthCount; i++)
free (hisAuthNames[i]);
free ((char *) hisAuthNames);
}
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
_IceGetPaValidAuthIndices ("ICE", iceConn->connection_string,
_IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
for (i = 0; i < _IceAuthCount; i++)
{
authUsableFlags[i] = 0;
for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
authUsableFlags[i] = (authIndices[j] == i);
}
myAuthCount = _IceAuthCount;
for (i = found = 0; i < myAuthCount && !found; i++)
{
if (authUsableFlags[i])
{
myAuthName = _IceAuthNames[i];
for (j = 0; j < hisAuthCount && !found; j++)
if (strcmp (myAuthName, hisAuthNames[j]) == 0)
{
myAuthIndex = i;
hisAuthIndex = j;
found = 1;
}
}
}
if (!found)
{
if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc)
{
_IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup);
iceConn->connection_status = IceConnectRejected;
}
else
{
char *hostname = _IceGetPeerName (iceConn);
if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
{
accept_setup_now = 1;
}
else
{
_IceErrorAuthenticationRejected (iceConn,
ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
iceConn->connection_status = IceConnectRejected;
}
if (hostname)
free (hostname);
}
if (iceConn->connection_status == IceConnectRejected)
{
free (vendor);
free (release);
}
}
else
{
IcePaAuthStatus status;
int authDataLen;
IcePointer authData = NULL;
IcePointer authState;
char *errorString = NULL;
IcePaAuthProc authProc = _IcePaAuthProcs[myAuthIndex];
authState = NULL;
status = (*authProc) (iceConn, &authState,
swap, 0, NULL, &authDataLen, &authData, &errorString);
if (status == IcePaAuthContinue)
{
_IceConnectToMeInfo *setupInfo;
AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
iceConn->connect_to_me = setupInfo = (_IceConnectToMeInfo *)
malloc (sizeof (_IceConnectToMeInfo));
setupInfo->my_version_index = myVersionIndex;
setupInfo->his_version_index = hisVersionIndex;
setupInfo->his_vendor = vendor;
setupInfo->his_release = release;
setupInfo->my_auth_index = myAuthIndex;
setupInfo->my_auth_state = authState;
setupInfo->must_authenticate = mustAuthenticate;
}
else if (status == IcePaAuthAccepted)
{
accept_setup_now = 1;
}
if (authData && authDataLen > 0)
free ((char *) authData);
if (errorString)
free (errorString);
}
if (accept_setup_now)
{
AcceptConnection (iceConn, hisVersionIndex);
iceConn->vendor = vendor;
iceConn->release = release;
iceConn->my_ice_version_index = myVersionIndex;
}
if (hisAuthCount > 0)
{
for (i = 0; i < hisAuthCount; i++)
free (hisAuthNames[i]);
free ((char *) hisAuthNames);
}
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
static Bool
ProcessAuthRequired (
IceConn iceConn,
unsigned long length,
Bool swap,
IceReplyWaitInfo *replyWait
)
{
iceAuthRequiredMsg *message;
int authDataLen;
IcePointer authData;
int replyDataLen;
IcePointer replyData = NULL;
char *errorString = NULL;
IcePoAuthProc authProc;
IcePoAuthStatus status;
IcePointer authState;
int realAuthIndex = 0;
CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired,
length, SIZEOF (iceAuthRequiredMsg),
iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg),
iceAuthRequiredMsg, message, authData);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, authData);
return (0);
}
if (swap)
{
message->authDataLength = lswaps (message->authDataLength);
}
CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length,
message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData,
iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
if (iceConn->connect_to_you)
{
if ((int) message->authIndex >= _IceAuthCount)
{
_IceConnectionError *errorReply =
&(((_IceReply *) (replyWait->reply))->connection_error);
const char *tempstr
= "Received bad authIndex in the AuthRequired message";
char errIndex = (int) message->authIndex;
errorString = strdup(tempstr);
errorReply->type = ICE_CONNECTION_ERROR;
errorReply->error_message = errorString;
_IceErrorBadValue (iceConn, 0,
ICE_AuthRequired, 2, 1, &errIndex);
IceDisposeCompleteMessage (iceConn, authData);
return (1);
}
else
{
authProc = _IcePoAuthProcs[message->authIndex];
iceConn->connect_to_you->auth_active = 1;
}
}
else if (iceConn->protosetup_to_you)
{
if ((int) message->authIndex >=
iceConn->protosetup_to_you->my_auth_count)
{
_IceProtocolError *errorReply =
&(((_IceReply *) (replyWait->reply))->protocol_error);
const char *tempstr
= "Received bad authIndex in the AuthRequired message";
char errIndex = (int) message->authIndex;
errorString = strdup(tempstr);
errorReply->type = ICE_PROTOCOL_ERROR;
errorReply->error_message = errorString;
_IceErrorBadValue (iceConn, 0,
ICE_AuthRequired, 2, 1, &errIndex);
IceDisposeCompleteMessage (iceConn, authData);
return (1);
}
else
{
_IcePoProtocol *myProtocol = _IceProtocols[
iceConn->protosetup_to_you->my_opcode - 1].orig_client;
realAuthIndex = iceConn->protosetup_to_you->
my_auth_indices[message->authIndex];
authProc = myProtocol->auth_procs[realAuthIndex];
iceConn->protosetup_to_you->auth_active = 1;
}
}
else
{
_IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue);
IceDisposeCompleteMessage (iceConn, authData);
return (0);
}
authState = NULL;
authDataLen = message->authDataLength;
status = (*authProc) (iceConn, &authState, False ,
swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
if (status == IcePoAuthHaveReply)
{
AuthReply (iceConn, replyDataLen, replyData);
replyWait->sequence_of_request = iceConn->send_sequence;
replyWait->minor_opcode_of_request = ICE_AuthReply;
if (iceConn->connect_to_you)
{
iceConn->connect_to_you->my_auth_state = authState;
iceConn->connect_to_you->my_auth_index = message->authIndex;
}
else if (iceConn->protosetup_to_you)
{
iceConn->protosetup_to_you->my_auth_state = authState;
iceConn->protosetup_to_you->my_auth_index = realAuthIndex;
}
}
else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
{
char *prefix, *returnErrorString;
if (status == IcePoAuthRejected)
{
_IceErrorAuthenticationRejected (iceConn,
ICE_AuthRequired, errorString);
prefix = "Authentication Rejected, reason : ";
}
else
{
_IceErrorAuthenticationFailed (iceConn,
ICE_AuthRequired, errorString);
prefix = "Authentication Failed, reason : ";
}
returnErrorString = (char *) malloc (strlen (prefix) +
strlen (errorString) + 1);
sprintf (returnErrorString, "%s%s", prefix, errorString);
free (errorString);
if (iceConn->connect_to_you)
{
_IceConnectionError *errorReply =
&(((_IceReply *) (replyWait->reply))->connection_error);
errorReply->type = ICE_CONNECTION_ERROR;
errorReply->error_message = returnErrorString;
}
else
{
_IceProtocolError *errorReply =
&(((_IceReply *) (replyWait->reply))->protocol_error);
errorReply->type = ICE_PROTOCOL_ERROR;
errorReply->error_message = returnErrorString;
}
}
if (replyData && replyDataLen > 0)
free ((char *) replyData);
IceDisposeCompleteMessage (iceConn, authData);
return (status != IcePoAuthHaveReply);
}
static int
ProcessAuthReply (
IceConn iceConn,
unsigned long length,
Bool swap
)
{
iceAuthReplyMsg *message;
int replyDataLen;
IcePointer replyData;
int authDataLen;
IcePointer authData = NULL;
char *errorString = NULL;
CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply,
length, SIZEOF (iceAuthReplyMsg),
iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg),
iceAuthReplyMsg, message, replyData);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, replyData);
return (0);
}
if (swap)
{
message->authDataLength = lswaps (message->authDataLength);
}
CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length,
message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData,
iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
replyDataLen = message->authDataLength;
if (iceConn->connect_to_me)
{
IcePaAuthProc authProc = _IcePaAuthProcs[(int)
(iceConn->connect_to_me->my_auth_index)];
IcePaAuthStatus status =
(*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap,
replyDataLen, replyData, &authDataLen, &authData, &errorString);
if (status == IcePaAuthContinue)
{
AuthNextPhase (iceConn, authDataLen, authData);
}
else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
{
if (!iceConn->connect_to_me->must_authenticate &&
iceConn->listen_obj->host_based_auth_proc)
{
char *hostname = _IceGetPeerName (iceConn);
if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
{
status = IcePaAuthAccepted;
}
if (hostname)
free (hostname);
}
if (status != IcePaAuthAccepted)
{
free (iceConn->connect_to_me->his_vendor);
free (iceConn->connect_to_me->his_release);
free ((char *) iceConn->connect_to_me);
iceConn->connect_to_me = NULL;
iceConn->connection_status = IceConnectRejected;
if (status == IcePaAuthRejected)
{
_IceErrorAuthenticationRejected (iceConn,
ICE_AuthReply, errorString);
}
else
{
_IceErrorAuthenticationFailed (iceConn,
ICE_AuthReply, errorString);
}
}
}
if (status == IcePaAuthAccepted)
{
AcceptConnection (iceConn,
iceConn->connect_to_me->his_version_index);
iceConn->vendor = iceConn->connect_to_me->his_vendor;
iceConn->release = iceConn->connect_to_me->his_release;
iceConn->my_ice_version_index =
iceConn->connect_to_me->my_version_index;
free ((char *) iceConn->connect_to_me);
iceConn->connect_to_me = NULL;
}
}
else if (iceConn->protosetup_to_me)
{
_IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me->
my_opcode - 1].accept_client;
IcePaAuthProc authProc = myProtocol->auth_procs[(int)
(iceConn->protosetup_to_me->my_auth_index)];
IcePaAuthStatus status =
(*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state,
swap, replyDataLen, replyData,
&authDataLen, &authData, &errorString);
int free_setup_info = 1;
if (status == IcePaAuthContinue)
{
AuthNextPhase (iceConn, authDataLen, authData);
free_setup_info = 0;
}
else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
{
if (!iceConn->protosetup_to_me->must_authenticate &&
myProtocol->host_based_auth_proc)
{
char *hostname = _IceGetPeerName (iceConn);
if ((*myProtocol->host_based_auth_proc) (hostname))
{
status = IcePaAuthAccepted;
}
if (hostname)
free (hostname);
}
if (status == IcePaAuthRejected)
{
_IceErrorAuthenticationRejected (iceConn,
ICE_AuthReply, errorString);
}
else
{
_IceErrorAuthenticationFailed (iceConn,
ICE_AuthReply, errorString);
}
}
if (status == IcePaAuthAccepted)
{
IcePaProcessMsgProc processMsgProc;
IceProtocolSetupProc protocolSetupProc;
IceProtocolActivateProc protocolActivateProc;
_IceProcessMsgInfo *process_msg_info;
IcePointer clientData = NULL;
char *failureReason = NULL;
Status status = 1;
protocolSetupProc = myProtocol->protocol_setup_proc;
protocolActivateProc = myProtocol->protocol_activate_proc;
if (protocolSetupProc)
{
status = (*protocolSetupProc) (iceConn,
myProtocol->version_recs[iceConn->protosetup_to_me->
my_version_index].major_version,
myProtocol->version_recs[iceConn->protosetup_to_me->
my_version_index].minor_version,
iceConn->protosetup_to_me->his_vendor,
iceConn->protosetup_to_me->his_release,
&clientData, &failureReason);
iceConn->protosetup_to_me->his_vendor = NULL;
iceConn->protosetup_to_me->his_release = NULL;
}
if (status != 0)
{
AcceptProtocol (iceConn,
iceConn->protosetup_to_me->his_opcode,
iceConn->protosetup_to_me->my_opcode,
iceConn->protosetup_to_me->his_version_index,
myProtocol->vendor, myProtocol->release);
processMsgProc = myProtocol->version_recs[
iceConn->protosetup_to_me->
my_version_index].process_msg_proc;
process_msg_info = &iceConn->process_msg_info[
iceConn->protosetup_to_me->
his_opcode -iceConn->his_min_opcode];
process_msg_info->client_data = clientData;
process_msg_info->accept_flag = 1;
process_msg_info->process_msg_proc.
accept_client = processMsgProc;
iceConn->proto_ref_count++;
if (protocolActivateProc)
{
(*protocolActivateProc) (iceConn,
process_msg_info->client_data);
}
}
else
{
_IceErrorSetupFailed (iceConn, ICE_ProtocolSetup,
failureReason);
if (failureReason)
free (failureReason);
}
}
if (free_setup_info)
{
if (iceConn->protosetup_to_me->his_vendor)
free (iceConn->protosetup_to_me->his_vendor);
if (iceConn->protosetup_to_me->his_release)
free (iceConn->protosetup_to_me->his_release);
free ((char *) iceConn->protosetup_to_me);
iceConn->protosetup_to_me = NULL;
}
}
else
{
_IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue);
}
if (authData && authDataLen > 0)
free ((char *) authData);
if (errorString)
free (errorString);
IceDisposeCompleteMessage (iceConn, replyData);
return (0);
}
static Bool
ProcessAuthNextPhase (
IceConn iceConn,
unsigned long length,
Bool swap,
IceReplyWaitInfo *replyWait
)
{
iceAuthNextPhaseMsg *message;
int authDataLen;
IcePointer authData;
int replyDataLen;
IcePointer replyData = NULL;
char *errorString = NULL;
IcePoAuthProc authProc;
IcePoAuthStatus status;
IcePointer *authState;
CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase,
length, SIZEOF (iceAuthNextPhaseMsg),
iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg),
iceAuthNextPhaseMsg, message, authData);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, authData);
return (0);
}
if (swap)
{
message->authDataLength = lswaps (message->authDataLength);
}
CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length,
message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData,
iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
if (iceConn->connect_to_you)
{
authProc = _IcePoAuthProcs[(int)
(iceConn->connect_to_you->my_auth_index)];
authState = &iceConn->connect_to_you->my_auth_state;
}
else if (iceConn->protosetup_to_you)
{
_IcePoProtocol *myProtocol =
_IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client;
authProc = myProtocol->auth_procs[(int)
(iceConn->protosetup_to_you->my_auth_index)];
authState = &iceConn->protosetup_to_you->my_auth_state;
}
else
{
_IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue);
IceDisposeCompleteMessage (iceConn, authData);
return (0);
}
authDataLen = message->authDataLength;
status = (*authProc) (iceConn, authState, False ,
swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
if (status == IcePoAuthHaveReply)
{
AuthReply (iceConn, replyDataLen, replyData);
replyWait->sequence_of_request = iceConn->send_sequence;
}
else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
{
char *prefix = NULL, *returnErrorString;
if (status == IcePoAuthRejected)
{
_IceErrorAuthenticationRejected (iceConn,
ICE_AuthNextPhase, errorString);
prefix = "Authentication Rejected, reason : ";
}
else if (status == IcePoAuthFailed)
{
_IceErrorAuthenticationFailed (iceConn,
ICE_AuthNextPhase, errorString);
prefix = "Authentication Failed, reason : ";
}
returnErrorString = (char *) malloc (strlen (prefix) +
strlen (errorString) + 1);
sprintf (returnErrorString, "%s%s", prefix, errorString);
free (errorString);
if (iceConn->connect_to_you)
{
_IceConnectionError *errorReply =
&(((_IceReply *) (replyWait->reply))->connection_error);
errorReply->type = ICE_CONNECTION_ERROR;
errorReply->error_message = returnErrorString;
}
else
{
_IceProtocolError *errorReply =
&(((_IceReply *) (replyWait->reply))->protocol_error);
errorReply->type = ICE_PROTOCOL_ERROR;
errorReply->error_message = returnErrorString;
}
}
if (replyData && replyDataLen > 0)
free ((char *) replyData);
IceDisposeCompleteMessage (iceConn, authData);
return (status != IcePoAuthHaveReply);
}
static Bool
ProcessConnectionReply (
IceConn iceConn,
unsigned long length,
Bool swap,
IceReplyWaitInfo *replyWait
)
{
iceConnectionReplyMsg *message;
char *pData, *pStart, *pEnd;
Bool replyReady;
#if 0
CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply,
length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection);
#endif
IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg),
iceConnectionReplyMsg, message, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
pData = pStart;
pEnd = pStart + (length << 3);
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING (iceConn, ICE_ConnectionReply,
pStart));
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING (iceConn, ICE_ConnectionReply,
pStart));
CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply,
length, pData - pStart + SIZEOF (iceConnectionReplyMsg),
pStart, IceFatalToConnection);
pData = pStart;
if (iceConn->connect_to_you)
{
if (iceConn->connect_to_you->auth_active)
{
IcePoAuthProc authProc = _IcePoAuthProcs[(int)
(iceConn->connect_to_you->my_auth_index)];
(*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
True , False ,
0, NULL, NULL, NULL, NULL);
}
if ((int) message->versionIndex >= _IceVersionCount)
{
_IceConnectionError *errorReply =
&(((_IceReply *) (replyWait->reply))->connection_error);
char errIndex = message->versionIndex;
_IceErrorBadValue (iceConn, 0,
ICE_ConnectionReply, 2, 1, &errIndex);
errorReply->type = ICE_CONNECTION_ERROR;
errorReply->error_message =
"Received bad version index in Connection Reply";
}
else
{
_IceReply *reply = (_IceReply *) (replyWait->reply);
reply->type = ICE_CONNECTION_REPLY;
reply->connection_reply.version_index = message->versionIndex;
EXTRACT_STRING (pData, swap, reply->connection_reply.vendor);
EXTRACT_STRING (pData, swap, reply->connection_reply.release);
}
replyReady = True;
}
else
{
_IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue);
replyReady = False;
}
IceDisposeCompleteMessage (iceConn, pStart);
return (replyReady);
}
static int
ProcessProtocolSetup (
IceConn iceConn,
unsigned long length,
Bool swap
)
{
iceProtocolSetupMsg *message;
_IcePaProtocol *myProtocol;
int myVersionCount, hisVersionCount;
int myVersionIndex, hisVersionIndex;
int hisMajorVersion, hisMinorVersion;
int myAuthCount, hisAuthCount;
int myOpcode, hisOpcode;
int found, i, j;
char *myAuthName, **hisAuthNames = NULL;
char *protocolName;
char *pData, *pStart, *pEnd;
char *vendor = NULL;
char *release = NULL;
int accept_setup_now = 0;
int myAuthIndex = 0;
int hisAuthIndex = 0;
char mustAuthenticate;
int authUsableCount;
int authUsableFlags[MAX_ICE_AUTH_NAMES];
int authIndices[MAX_ICE_AUTH_NAMES];
CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,
length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);
if (iceConn->want_to_close)
{
iceConn->want_to_close = 0;
}
IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),
iceProtocolSetupMsg, message, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
pData = pStart;
pEnd = pStart + (length << 3);
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING(iceConn, ICE_ProtocolSetup,
pStart));
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING(iceConn, ICE_ProtocolSetup,
pStart));
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING(iceConn, ICE_ProtocolSetup,
pStart));
SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
BAIL_STRING(iceConn, ICE_ProtocolSetup,
pStart));
pData += (message->versionCount * 4);
CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,
length, pData - pStart + SIZEOF (iceProtocolSetupMsg),
pStart, IceFatalToProtocol);
mustAuthenticate = message->mustAuthenticate;
if (mustAuthenticate != 0 && mustAuthenticate != 1)
{
_IceErrorBadValue (iceConn, 0,
ICE_ProtocolSetup, 4, 1, &mustAuthenticate);
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
pData = pStart;
if (iceConn->process_msg_info &&
(int) message->protocolOpcode >= iceConn->his_min_opcode &&
(int) message->protocolOpcode <= iceConn->his_max_opcode &&
iceConn->process_msg_info[
message->protocolOpcode - iceConn->his_min_opcode].in_use)
{
_IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
EXTRACT_STRING (pData, swap, protocolName);
if (iceConn->process_msg_info)
{
for (i = 0;
i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)
{
if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,
iceConn->process_msg_info[i].protocol->protocol_name) == 0)
{
_IceErrorProtocolDuplicate (iceConn, protocolName);
free (protocolName);
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
}
}
for (i = 0; i < _IceLastMajorOpcode; i++)
if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)
break;
if (i < _IceLastMajorOpcode &&
(myProtocol = _IceProtocols[i].accept_client) != NULL)
{
hisOpcode = message->protocolOpcode;
myOpcode = i + 1;
free (protocolName);
}
else
{
_IceErrorUnknownProtocol (iceConn, protocolName);
free (protocolName);
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
EXTRACT_STRING (pData, swap, vendor);
EXTRACT_STRING (pData, swap, release);
if ((hisAuthCount = message->authCount) > 0)
{
hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
}
hisVersionCount = message->versionCount;
myVersionCount = myProtocol->version_count;
hisVersionIndex = myVersionIndex = found = 0;
for (i = 0; i < hisVersionCount && !found; i++)
{
EXTRACT_CARD16 (pData, swap, hisMajorVersion);
EXTRACT_CARD16 (pData, swap, hisMinorVersion);
for (j = 0; j < myVersionCount && !found; j++)
{
if (myProtocol->version_recs[j].major_version == hisMajorVersion &&
myProtocol->version_recs[j].minor_version == hisMinorVersion)
{
hisVersionIndex = i;
myVersionIndex = j;
found = 1;
}
}
}
if (!found)
{
_IceErrorNoVersion (iceConn, ICE_ProtocolSetup);
free (vendor);
free (release);
if (hisAuthCount > 0)
{
for (i = 0; i < hisAuthCount; i++)
free (hisAuthNames[i]);
free ((char *) hisAuthNames);
}
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
myAuthCount = myProtocol->auth_count;
_IceGetPaValidAuthIndices (
_IceProtocols[myOpcode - 1].protocol_name,
iceConn->connection_string, myAuthCount, myProtocol->auth_names,
&authUsableCount, authIndices);
for (i = 0; i < myAuthCount; i++)
{
authUsableFlags[i] = 0;
for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
authUsableFlags[i] = (authIndices[j] == i);
}
for (i = found = 0; i < myAuthCount && !found; i++)
{
if (authUsableFlags[i])
{
myAuthName = myProtocol->auth_names[i];
for (j = 0; j < hisAuthCount && !found; j++)
if (strcmp (myAuthName, hisAuthNames[j]) == 0)
{
myAuthIndex = i;
hisAuthIndex = j;
found = 1;
}
}
}
if (!found)
{
if (mustAuthenticate || !myProtocol->host_based_auth_proc)
{
_IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);
}
else
{
char *hostname = _IceGetPeerName (iceConn);
if ((*myProtocol->host_based_auth_proc) (hostname))
{
accept_setup_now = 1;
}
else
{
_IceErrorAuthenticationRejected (iceConn,
ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
}
if (hostname)
free (hostname);
}
}
else
{
IcePaAuthStatus status;
int authDataLen;
IcePointer authData = NULL;
IcePointer authState;
char *errorString = NULL;
IcePaAuthProc authProc =
myProtocol->auth_procs[myAuthIndex];
authState = NULL;
status = (*authProc) (iceConn, &authState, swap, 0, NULL,
&authDataLen, &authData, &errorString);
if (status == IcePaAuthContinue)
{
_IceProtoSetupToMeInfo *setupInfo;
AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
iceConn->protosetup_to_me = setupInfo =
(_IceProtoSetupToMeInfo *) malloc (
sizeof (_IceProtoSetupToMeInfo));
setupInfo->his_opcode = hisOpcode;
setupInfo->my_opcode = myOpcode;
setupInfo->my_version_index = myVersionIndex;
setupInfo->his_version_index = hisVersionIndex;
setupInfo->his_vendor = vendor;
setupInfo->his_release = release;
vendor = release = NULL;
setupInfo->my_auth_index = myAuthIndex;
setupInfo->my_auth_state = authState;
setupInfo->must_authenticate = mustAuthenticate;
}
else if (status == IcePaAuthAccepted)
{
accept_setup_now = 1;
}
if (authData && authDataLen > 0)
free ((char *) authData);
if (errorString)
free (errorString);
}
if (accept_setup_now)
{
IcePaProcessMsgProc processMsgProc;
IceProtocolSetupProc protocolSetupProc;
IceProtocolActivateProc protocolActivateProc;
_IceProcessMsgInfo *process_msg_info;
IcePointer clientData = NULL;
char *failureReason = NULL;
Status status = 1;
protocolSetupProc = myProtocol->protocol_setup_proc;
protocolActivateProc = myProtocol->protocol_activate_proc;
if (protocolSetupProc)
{
status = (*protocolSetupProc) (iceConn,
myProtocol->version_recs[myVersionIndex].major_version,
myProtocol->version_recs[myVersionIndex].minor_version,
vendor, release, &clientData, &failureReason);
vendor = release = NULL;
}
if (status != 0)
{
AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,
myProtocol->vendor, myProtocol->release);
processMsgProc = myProtocol->version_recs[
myVersionIndex].process_msg_proc;
process_msg_info = &iceConn->process_msg_info[hisOpcode -
iceConn->his_min_opcode];
process_msg_info->client_data = clientData;
process_msg_info->accept_flag = 1;
process_msg_info->process_msg_proc.accept_client = processMsgProc;
iceConn->proto_ref_count++;
if (protocolActivateProc)
{
(*protocolActivateProc) (iceConn,
process_msg_info->client_data);
}
}
else
{
_IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);
if (failureReason)
free (failureReason);
}
}
if (vendor)
free (vendor);
if (release)
free (release);
if (hisAuthCount > 0)
{
for (i = 0; i < hisAuthCount; i++)
free (hisAuthNames[i]);
free ((char *) hisAuthNames);
}
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
static Bool
ProcessProtocolReply (
IceConn iceConn,
unsigned long length,
Bool swap,
IceReplyWaitInfo *replyWait
)
{
iceProtocolReplyMsg *message;
char *pData, *pStart, *pEnd;
Bool replyReady;
#if 0
CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply,
length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol);
#endif
IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg),
iceProtocolReplyMsg, message, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return (0);
}
pData = pStart;
pEnd = pStart + (length << 3);
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING(iceConn, ICE_ProtocolReply,
pStart));
SKIP_STRING (pData, swap, pEnd,
BAIL_STRING(iceConn, ICE_ProtocolReply,
pStart));
CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply,
length, pData - pStart + SIZEOF (iceProtocolReplyMsg),
pStart, IceFatalToProtocol);
pData = pStart;
if (iceConn->protosetup_to_you)
{
if (iceConn->protosetup_to_you->auth_active)
{
_IcePoProtocol *myProtocol = _IceProtocols[
iceConn->protosetup_to_you->my_opcode - 1].orig_client;
IcePoAuthProc authProc = myProtocol->auth_procs[(int)
(iceConn->protosetup_to_you->my_auth_index)];
#ifdef SVR4
if (authProc)
#endif
(*authProc) (iceConn,
&iceConn->protosetup_to_you->my_auth_state,
True , False ,
0, NULL, NULL, NULL, NULL);
}
if ((int) message->versionIndex >= _IceVersionCount)
{
_IceProtocolError *errorReply =
&(((_IceReply *) (replyWait->reply))->protocol_error);
char errIndex = message->versionIndex;
_IceErrorBadValue (iceConn, 0,
ICE_ProtocolReply, 2, 1, &errIndex);
errorReply->type = ICE_PROTOCOL_ERROR;
errorReply->error_message =
"Received bad version index in Protocol Reply";
}
else
{
_IceProtocolReply *reply =
&(((_IceReply *) (replyWait->reply))->protocol_reply);
reply->type = ICE_PROTOCOL_REPLY;
reply->major_opcode = message->protocolOpcode;
reply->version_index = message->versionIndex;
EXTRACT_STRING (pData, swap, reply->vendor);
EXTRACT_STRING (pData, swap, reply->release);
}
replyReady = True;
}
else
{
_IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue);
replyReady = False;
}
IceDisposeCompleteMessage (iceConn, pStart);
return (replyReady);
}
static int
ProcessPing (
IceConn iceConn,
unsigned long length
)
{
CHECK_SIZE_MATCH (iceConn, ICE_Ping,
length, SIZEOF (icePingMsg), IceFatalToConnection, 0);
PingReply (iceConn);
return (0);
}
static int
ProcessPingReply (
IceConn iceConn,
unsigned long length
)
{
CHECK_SIZE_MATCH (iceConn, ICE_PingReply,
length, SIZEOF (icePingReplyMsg), IceFatalToConnection, 0);
if (iceConn->ping_waits)
{
_IcePingWait *next = iceConn->ping_waits->next;
(*iceConn->ping_waits->ping_reply_proc) (iceConn,
iceConn->ping_waits->client_data);
free ((char *) iceConn->ping_waits);
iceConn->ping_waits = next;
}
else
{
_IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue);
}
return (0);
}
static int
ProcessWantToClose (
IceConn iceConn,
unsigned long length,
Bool *connectionClosedRet
)
{
*connectionClosedRet = False;
CHECK_SIZE_MATCH (iceConn, ICE_WantToClose,
length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection, 0);
if (iceConn->want_to_close || iceConn->open_ref_count == 0)
{
_IceConnectionClosed (iceConn);
_IceFreeConnection (iceConn);
*connectionClosedRet = True;
}
else if (iceConn->proto_ref_count > 0)
{
IceSimpleMessage (iceConn, 0, ICE_NoClose);
IceFlush (iceConn);
}
else
{
if (!iceConn->protosetup_to_you)
{
IceSimpleMessage (iceConn, 0, ICE_NoClose);
IceFlush (iceConn);
}
}
return (0);
}
static int
ProcessNoClose (
IceConn iceConn,
unsigned long length
)
{
CHECK_SIZE_MATCH (iceConn, ICE_NoClose,
length, SIZEOF (iceNoCloseMsg), IceFatalToConnection, 0);
if (iceConn->want_to_close)
{
iceConn->want_to_close = 0;
}
else
{
_IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue);
}
return (0);
}
static void
_IceProcessCoreMessage (
IceConn iceConn,
int opcode,
unsigned long length,
Bool swap,
IceReplyWaitInfo *replyWait,
Bool *replyReadyRet,
Bool *connectionClosedRet
)
{
Bool replyReady = False;
*connectionClosedRet = False;
switch (opcode)
{
case ICE_Error:
replyReady = ProcessError (iceConn, length, swap, replyWait);
break;
case ICE_ConnectionSetup:
ProcessConnectionSetup (iceConn, length, swap);
break;
case ICE_AuthRequired:
replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait);
break;
case ICE_AuthReply:
ProcessAuthReply (iceConn, length, swap);
break;
case ICE_AuthNextPhase:
replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait);
break;
case ICE_ConnectionReply:
replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait);
break;
case ICE_ProtocolSetup:
ProcessProtocolSetup (iceConn, length, swap);
break;
case ICE_ProtocolReply:
replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait);
break;
case ICE_Ping:
ProcessPing (iceConn, length);
break;
case ICE_PingReply:
ProcessPingReply (iceConn, length);
break;
case ICE_WantToClose:
ProcessWantToClose (iceConn, length, connectionClosedRet);
break;
case ICE_NoClose:
ProcessNoClose (iceConn, length);
break;
default:
_IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue);
_IceReadSkip (iceConn, length << 3);
break;
}
if (replyWait)
*replyReadyRet = replyReady;
}
int _IceVersionCount = 1;
_IceVersion _IceVersions[] = {
{IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};