1 /******************************************************************************
4 Copyright 1993, 1998 The Open Group
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
26 Author: Ralph Mor, X Consortium
27 ******************************************************************************/
32 #include <X11/ICE/ICElib.h>
33 #include "ICElibint.h"
35 #include <stdio.h> /* sprintf */
38 * Check for bad length
41 #define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity, _return) \
42 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
44 _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
48 #define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
49 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
51 _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
55 #define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \
56 if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
59 _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
60 IceDisposeCompleteMessage (iceConn, _pStart); \
64 #define BAIL_STRING(_iceConn, _opcode, _pStart) {\
65 _IceErrorBadLength (_iceConn, 0, _opcode, IceFatalToConnection);\
66 IceDisposeCompleteMessage (_iceConn, _pStart);\
73 /* sprintf variant found in newer libc's which allocates string to print to */
74 static int _X_ATTRIBUTE_PRINTF(2,3)
75 asprintf(char ** ret, const char *format, ...)
82 len = vsnprintf(buf, sizeof(buf), format, ap);
88 if (len < sizeof(buf))
94 *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */
98 len = vsnprintf(*ret, len + 1, format, ap);
116 * IceProcessMessages:
118 * If replyWait == NULL, the client is not waiting for a reply.
120 * If replyWait != NULL, the client is waiting for a reply...
122 * - replyWait->sequence_of_request is the sequence number of the
123 * message for which the client is waiting a reply. This is needed
124 * to determine if an error matches a replyWait.
126 * - replyWait->major_opcode_of_request is the major opcode of the
127 * message for which we are waiting a reply.
129 * - replyWait->minor_opcode_of_request is the minor opcode of the
130 * message for which we are waiting a reply.
132 * - replyWait->reply is a pointer to the reply message which will be
133 * filled in when the reply is ready (the protocol library should
134 * cast this IcePointer to the appropriate reply type). In most cases,
135 * the reply will have some fixed-size part, and the sender function
136 * will have provided a pointer to a structure (e.g.) to hold this
137 * fixed-size data. If there is variable-length data, it would be
138 * expected that the reply function will have to allocate additional
139 * memory and store pointer(s) to that memory in the fixed-size
140 * structure. If the entire data is variable length (e.g., a single
141 * variable-length string), then the sender function would probably
142 * just pass a pointer to fixed-size space to hold a pointer, and the
143 * reply function would allocate the storage and store the pointer.
144 * It is the responsibility of the client receiving the reply to
145 * free up any memory allocated on it's behalf.
147 * We might be waiting for several different replies (a function can wait
148 * for a reply, and while calling IceProcessMessages, a callback can be
149 * invoked which will wait for another reply). We take advantage of the
150 * fact that for a given protocol, we are guaranteed that messages are
151 * processed in the order we sent them. So, everytime we have a new
152 * replyWait, we add it to the END of the 'saved_reply_waits' list. When
153 * we read a message and want to see if it matches a replyWait, we use the
154 * FIRST replyWait in the list with the major opcode of the message. If the
155 * reply is ready, we remove that replyWait from the list.
157 * If the reply/error is ready for the replyWait passed in to
158 * IceProcessMessages, *replyReadyRet is set to True.
160 * The return value of IceProcessMessages is one of the following:
162 * IceProcessMessagesSuccess - the message was processed successfully.
163 * IceProcessMessagesIOError - an IO error occured. The caller should
164 * invoked IceCloseConnection.
165 * IceProcessMessagesConnectionClosed - the connection was closed as a
166 * result of shutdown negotiation.
169 IceProcessMessagesStatus
172 IceReplyWaitInfo *replyWait,
177 Bool replyReady = False;
178 IceReplyWaitInfo *useThisReplyWait = NULL;
179 IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess;
182 *replyReadyRet = False;
185 * Each time IceProcessMessages is entered, we increment the dispatch
186 * level. Each time we leave it, we decrement the dispatch level.
189 iceConn->dispatch_level++;
193 * Read the ICE message header.
196 if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf))
199 * If we previously sent a WantToClose and now we detected
200 * that the connection was closed, _IceRead returns status 0.
201 * Since the connection was closed, we just want to return here.
204 return (IceProcessMessagesConnectionClosed);
210 * An unexpected IO error occured. The caller of IceProcessMessages
211 * should call IceCloseConnection which will cause the watch procedures
212 * to be invoked and the ICE connection to be freed.
215 iceConn->dispatch_level--;
216 iceConn->connection_status = IceConnectIOError;
217 return (IceProcessMessagesIOError);
220 header = (iceMsg *) iceConn->inbuf;
221 iceConn->inbufptr = iceConn->inbuf + SIZEOF (iceMsg);
223 iceConn->receive_sequence++;
225 if (iceConn->waiting_for_byteorder)
227 if (header->majorOpcode == 0 &&
228 header->minorOpcode == ICE_ByteOrder)
230 char byteOrder = ((iceByteOrderMsg *) header)->byteOrder;
233 CHECK_SIZE_MATCH (iceConn, ICE_ByteOrder,
234 header->length, SIZEOF (iceByteOrderMsg),
235 IceFatalToConnection, IceProcessMessagesIOError);
237 if (byteOrder != IceMSBfirst && byteOrder != IceLSBfirst)
239 _IceErrorBadValue (iceConn, 0,
240 ICE_ByteOrder, 2, 1, &byteOrder);
242 iceConn->connection_status = IceConnectRejected;
247 (((*(char *) &endian) && byteOrder == IceMSBfirst) ||
248 (!(*(char *) &endian) && byteOrder == IceLSBfirst));
250 iceConn->waiting_for_byteorder = 0;
255 if (header->majorOpcode != 0)
257 _IceErrorBadMajor (iceConn, header->majorOpcode,
258 header->minorOpcode, IceFatalToConnection);
262 _IceErrorBadState (iceConn, 0,
263 header->minorOpcode, IceFatalToConnection);
266 iceConn->connection_status = IceConnectRejected;
269 iceConn->dispatch_level--;
272 iceConn->connection_status = IceConnectIOError;
273 retStatus = IceProcessMessagesIOError;
281 /* swap the length field */
283 header->length = lswapl (header->length);
289 * Add to the list of replyWaits (only if it doesn't exist
290 * in the list already.
293 _IceAddReplyWait (iceConn, replyWait);
296 * Note that there are two different replyWaits. The first is
297 * the one passed into IceProcessMessages, and is the replyWait
298 * for the message the client is blocking on. The second is
299 * the replyWait for the message currently being processed
300 * by IceProcessMessages. We call it "useThisReplyWait".
302 * Also, when two hosts communicate over an ICE connection and use
303 * different major opcodes for a subprotocol, it is impossible
304 * to use message replies unless we translate opcodes before
311 if (header->majorOpcode == 0)
317 int idx = header->majorOpcode - iceConn->his_min_opcode;
318 op = iceConn->process_msg_info[idx].my_opcode;
320 useThisReplyWait = _IceSearchReplyWaits (iceConn, op);
324 if (header->majorOpcode == 0)
330 Bool connectionClosed;
332 _IceProcessCoreMsgProc processIce =
333 _IceVersions[iceConn->my_ice_version_index].process_core_msg_proc;
335 (*processIce) (iceConn, header->minorOpcode,
336 header->length, iceConn->swap,
337 useThisReplyWait, &replyReady, &connectionClosed);
339 if (connectionClosed)
342 * As a result of shutdown negotiation, the connection was closed.
345 return (IceProcessMessagesConnectionClosed);
354 if ((int) header->majorOpcode < iceConn->his_min_opcode ||
355 (int) header->majorOpcode > iceConn->his_max_opcode ||
356 !(iceConn->process_msg_info[header->majorOpcode -
357 iceConn->his_min_opcode].in_use))
360 * The protocol of the message we just read is not supported.
363 _IceErrorBadMajor (iceConn, header->majorOpcode,
364 header->minorOpcode, IceCanContinue);
366 _IceReadSkip (iceConn, header->length << 3);
370 _IceProcessMsgInfo *processMsgInfo = &iceConn->process_msg_info[
371 header->majorOpcode - iceConn->his_min_opcode];
373 if (processMsgInfo->accept_flag)
375 IcePaProcessMsgProc processProc =
376 processMsgInfo->process_msg_proc.accept_client;
378 (*processProc) (iceConn, processMsgInfo->client_data,
379 header->minorOpcode, header->length, iceConn->swap);
383 IcePoProcessMsgProc processProc =
384 processMsgInfo->process_msg_proc.orig_client;
386 (*processProc) (iceConn,
387 processMsgInfo->client_data, header->minorOpcode,
388 header->length, iceConn->swap,
389 useThisReplyWait, &replyReady);
396 _IceSetReplyReady (iceConn, useThisReplyWait);
401 * Now we check if the reply is ready for the replyWait passed
402 * into IceProcessMessages. The replyWait is removed from the
403 * replyWait list if it is ready.
407 *replyReadyRet = _IceCheckReplyReady (iceConn, replyWait);
411 * Decrement the dispatch level. If we reach level 0, and the
412 * free_asap bit is set, free the connection now. Also check for
413 * possible bad IO status.
416 iceConn->dispatch_level--;
418 if (iceConn->dispatch_level == 0 && iceConn->free_asap)
420 _IceFreeConnection (iceConn);
421 retStatus = IceProcessMessagesConnectionClosed;
423 else if (!iceConn->io_ok)
425 iceConn->connection_status = IceConnectIOError;
426 retStatus = IceProcessMessagesIOError;
442 iceAuthRequiredMsg *pMsg;
444 IceGetHeader (iceConn, 0, ICE_AuthRequired,
445 SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg);
447 pMsg->authIndex = authIndex;
448 pMsg->authDataLength = authDataLen;
449 pMsg->length += WORD64COUNT (authDataLen);
451 IceWriteData (iceConn, authDataLen, (char *) authData);
453 if (PAD64 (authDataLen))
454 IceWritePad (iceConn, PAD64 (authDataLen));
468 iceAuthReplyMsg *pMsg;
470 IceGetHeader (iceConn, 0, ICE_AuthReply,
471 SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg);
473 pMsg->authDataLength = authDataLen;
474 pMsg->length += WORD64COUNT (authDataLen);
476 IceWriteData (iceConn, authDataLen, (char *) authData);
478 if (PAD64 (authDataLen))
479 IceWritePad (iceConn, PAD64 (authDataLen));
493 iceAuthNextPhaseMsg *pMsg;
495 IceGetHeader (iceConn, 0, ICE_AuthNextPhase,
496 SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg);
498 pMsg->authDataLength = authDataLen;
499 pMsg->length += WORD64COUNT (authDataLen);
501 IceWriteData (iceConn, authDataLen, (char *) authData);
503 if (PAD64 (authDataLen))
504 IceWritePad (iceConn, PAD64 (authDataLen));
517 iceConnectionReplyMsg *pMsg;
521 extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
523 IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply,
524 SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra),
525 iceConnectionReplyMsg, pMsg, pData);
527 pMsg->versionIndex = versionIndex;
529 STORE_STRING (pData, IceVendorString);
530 STORE_STRING (pData, IceReleaseString);
534 iceConn->connection_status = IceConnectAccepted;
549 iceProtocolReplyMsg *pMsg;
553 extra = STRING_BYTES (vendor) + STRING_BYTES (release);
555 IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply,
556 SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra),
557 iceProtocolReplyMsg, pMsg, pData);
559 pMsg->protocolOpcode = myOpcode;
560 pMsg->versionIndex = versionIndex;
562 STORE_STRING (pData, vendor);
563 STORE_STRING (pData, release);
569 * We may be using a different major opcode for this protocol
570 * than the other client. Whenever we get a message, we must
571 * map to our own major opcode.
574 _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
584 IceSimpleMessage (iceConn, 0, ICE_PingReply);
593 unsigned long length,
595 IceReplyWaitInfo *replyWait
598 int invokeHandler = 0;
599 Bool errorReturned = False;
600 iceErrorMsg *message;
601 char *pData, *pStart;
604 CHECK_AT_LEAST_SIZE (iceConn, ICE_Error,
605 length, SIZEOF (iceErrorMsg),
606 (iceConn->connect_to_you || iceConn->connect_to_me) ?
607 IceFatalToConnection : IceFatalToProtocol);
609 IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
610 iceErrorMsg, message, pStart);
612 if (!IceValidIO (iceConn))
614 IceDisposeCompleteMessage (iceConn, pStart);
618 severity = message->severity;
620 if (severity != IceCanContinue && severity != IceFatalToProtocol &&
621 severity != IceFatalToConnection)
623 _IceErrorBadValue (iceConn, 0,
624 ICE_Error, 9, 1, &severity);
625 IceDisposeCompleteMessage (iceConn, pStart);
633 message->errorClass = lswaps (message->errorClass);
634 message->offendingSequenceNum = lswapl (message->offendingSequenceNum);
638 message->offendingSequenceNum != replyWait->sequence_of_request)
644 if (iceConn->connect_to_you &&
645 ((!iceConn->connect_to_you->auth_active &&
646 message->offendingMinorOpcode == ICE_ConnectionSetup) ||
647 (iceConn->connect_to_you->auth_active &&
648 message->offendingMinorOpcode == ICE_AuthReply)))
650 _IceConnectionError *errorReply =
651 &(((_IceReply *) (replyWait->reply))->connection_error);
652 char *errorStr = NULL;
653 const char *tempstr, *prefix;
657 errorReturned = True;
659 switch (message->errorClass)
664 "None of the ICE versions specified are supported";
665 errorStr = strdup(tempstr);
671 "None of the authentication protocols specified are supported";
672 errorStr = strdup(tempstr);
677 prefix = "Connection Setup Failed, reason : ";
679 EXTRACT_STRING (pData, swap, temp);
680 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
685 case IceAuthRejected:
687 prefix = "Authentication Rejected, reason : ";
688 EXTRACT_STRING (pData, swap, temp);
689 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
696 prefix = "Authentication Failed, reason : ";
697 EXTRACT_STRING (pData, swap, temp);
698 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
707 errorReply->type = ICE_CONNECTION_ERROR;
708 errorReply->error_message = errorStr;
710 else if (iceConn->protosetup_to_you &&
711 ((!iceConn->protosetup_to_you->auth_active &&
712 message->offendingMinorOpcode == ICE_ProtocolSetup) ||
713 (iceConn->protosetup_to_you->auth_active &&
714 message->offendingMinorOpcode == ICE_AuthReply)))
716 _IceProtocolError *errorReply =
717 &(((_IceReply *) (replyWait->reply))->protocol_error);
723 errorReturned = True;
725 switch (message->errorClass)
730 "None of the protocol versions specified are supported");
736 "None of the authentication protocols specified are supported");
742 prefix = "Protocol Setup Failed, reason : ";
744 EXTRACT_STRING (pData, swap, temp);
745 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
750 case IceAuthRejected:
752 prefix = "Authentication Rejected, reason : ";
753 EXTRACT_STRING (pData, swap, temp);
754 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
761 prefix = "Authentication Failed, reason : ";
762 EXTRACT_STRING (pData, swap, temp);
763 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
768 case IceProtocolDuplicate:
770 prefix = "Protocol was already registered : ";
771 EXTRACT_STRING (pData, swap, temp);
772 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
777 case IceMajorOpcodeDuplicate:
779 prefix = "The major opcode was already used : ";
780 if (asprintf (&errorStr, "%s%d", prefix, (int) *pData) == -1)
784 case IceUnknownProtocol:
786 prefix = "Unknown Protocol : ";
787 EXTRACT_STRING (pData, swap, temp);
788 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
797 errorReply->type = ICE_PROTOCOL_ERROR;
798 errorReply->error_message = errorStr;
801 if (errorReturned == True)
804 * If we tried to authenticate, tell the authentication
805 * procedure to clean up.
808 IcePoAuthProc authProc;
810 if (iceConn->connect_to_you &&
811 iceConn->connect_to_you->auth_active)
813 authProc = _IcePoAuthProcs[(int)
814 (iceConn->connect_to_you->my_auth_index)];
816 (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
817 True /* clean up */, False /* swap */,
818 0, NULL, NULL, NULL, NULL);
820 else if (iceConn->protosetup_to_you &&
821 iceConn->protosetup_to_you->auth_active)
823 _IcePoProtocol *protocol = _IceProtocols[
824 iceConn->protosetup_to_you->my_opcode - 1].orig_client;
826 authProc = protocol->auth_procs[(int)(iceConn->
827 protosetup_to_you->my_auth_index)];
829 (*authProc) (iceConn,
830 &iceConn->protosetup_to_you->my_auth_state,
831 True /* clean up */, False /* swap */,
832 0, NULL, NULL, NULL, NULL);
839 (*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode,
840 message->offendingSequenceNum, message->errorClass,
841 message->severity, (IcePointer) pData);
844 IceDisposeCompleteMessage (iceConn, pStart);
846 return (errorReturned);
852 ProcessConnectionSetup (
854 unsigned long length,
858 iceConnectionSetupMsg *message;
859 int myVersionCount, hisVersionCount;
860 int myVersionIndex, hisVersionIndex;
861 int hisMajorVersion, hisMinorVersion;
862 int myAuthCount, hisAuthCount;
864 char **hisAuthNames = NULL;
865 char *pData, *pStart, *pEnd;
867 char *release = NULL;
869 int hisAuthIndex = 0;
870 int accept_setup_now = 0;
871 char mustAuthenticate;
873 int authUsableFlags[MAX_ICE_AUTH_NAMES];
874 int authIndices[MAX_ICE_AUTH_NAMES];
876 CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup,
877 length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection);
879 IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg),
880 iceConnectionSetupMsg, message, pStart);
882 if (!IceValidIO (iceConn))
884 IceDisposeCompleteMessage (iceConn, pStart);
889 pEnd = pStart + (length << 3);
891 SKIP_STRING (pData, swap, pEnd,
892 BAIL_STRING(iceConn, ICE_ConnectionSetup,
893 pStart)); /* vendor */
894 SKIP_STRING (pData, swap, pEnd,
895 BAIL_STRING(iceConn, ICE_ConnectionSetup,
896 pStart)); /* release */
897 SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
898 BAIL_STRING(iceConn, ICE_ConnectionSetup,
899 pStart)); /* auth names */
901 pData += (message->versionCount * 4); /* versions */
903 CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup,
904 length, pData - pStart + SIZEOF (iceConnectionSetupMsg),
905 pStart, IceFatalToConnection);
907 mustAuthenticate = message->mustAuthenticate;
908 if (mustAuthenticate != 0 && mustAuthenticate != 1)
910 _IceErrorBadValue (iceConn, 0,
911 ICE_ConnectionSetup, 8, 1, &mustAuthenticate);
912 iceConn->connection_status = IceConnectRejected;
913 IceDisposeCompleteMessage (iceConn, pStart);
919 EXTRACT_STRING (pData, swap, vendor);
920 EXTRACT_STRING (pData, swap, release);
922 if ((hisAuthCount = message->authCount) > 0)
924 hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
925 EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
928 hisVersionCount = message->versionCount;
929 myVersionCount = _IceVersionCount;
931 hisVersionIndex = myVersionIndex = found = 0;
933 for (i = 0; i < hisVersionCount && !found; i++)
935 EXTRACT_CARD16 (pData, swap, hisMajorVersion);
936 EXTRACT_CARD16 (pData, swap, hisMinorVersion);
938 for (j = 0; j < myVersionCount && !found; j++)
940 if (_IceVersions[j].major_version == hisMajorVersion &&
941 _IceVersions[j].minor_version == hisMinorVersion)
952 _IceErrorNoVersion (iceConn, ICE_ConnectionSetup);
953 iceConn->connection_status = IceConnectRejected;
958 if (hisAuthCount > 0)
960 for (i = 0; i < hisAuthCount; i++)
961 free (hisAuthNames[i]);
963 free ((char *) hisAuthNames);
966 IceDisposeCompleteMessage (iceConn, pStart);
970 _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string,
971 _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
973 for (i = 0; i < _IceAuthCount; i++)
975 authUsableFlags[i] = 0;
976 for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
977 authUsableFlags[i] = (authIndices[j] == i);
980 myAuthCount = _IceAuthCount;
982 for (i = found = 0; i < myAuthCount && !found; i++)
984 if (authUsableFlags[i])
986 const char *myAuthName = _IceAuthNames[i];
988 for (j = 0; j < hisAuthCount && !found; j++)
989 if (strcmp (myAuthName, hisAuthNames[j]) == 0)
1001 * None of the authentication methods specified by the
1002 * other client is supported. If the other client requires
1003 * authentication, we must reject the connection now.
1004 * Otherwise, we can invoke the host-based authentication callback
1005 * to see if we can accept this connection.
1008 if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc)
1010 _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup);
1011 iceConn->connection_status = IceConnectRejected;
1015 char *hostname = _IceGetPeerName (iceConn);
1017 if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1019 accept_setup_now = 1;
1023 _IceErrorAuthenticationRejected (iceConn,
1024 ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
1026 iceConn->connection_status = IceConnectRejected;
1033 if (iceConn->connection_status == IceConnectRejected)
1041 IcePaAuthStatus status;
1043 IcePointer authData = NULL;
1044 IcePointer authState;
1045 char *errorString = NULL;
1046 IcePaAuthProc authProc = _IcePaAuthProcs[myAuthIndex];
1050 status = (*authProc) (iceConn, &authState,
1051 swap, 0, NULL, &authDataLen, &authData, &errorString);
1053 if (status == IcePaAuthContinue)
1055 _IceConnectToMeInfo *setupInfo;
1057 AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
1059 iceConn->connect_to_me = setupInfo = (_IceConnectToMeInfo *)
1060 malloc (sizeof (_IceConnectToMeInfo));
1062 setupInfo->my_version_index = myVersionIndex;
1063 setupInfo->his_version_index = hisVersionIndex;
1064 setupInfo->his_vendor = vendor;
1065 setupInfo->his_release = release;
1066 setupInfo->my_auth_index = myAuthIndex;
1067 setupInfo->my_auth_state = authState;
1068 setupInfo->must_authenticate = mustAuthenticate;
1070 else if (status == IcePaAuthAccepted)
1072 accept_setup_now = 1;
1080 if (authData && authDataLen > 0)
1081 free ((char *) authData);
1087 if (accept_setup_now)
1089 AcceptConnection (iceConn, hisVersionIndex);
1091 iceConn->vendor = vendor;
1092 iceConn->release = release;
1093 iceConn->my_ice_version_index = myVersionIndex;
1096 if (hisAuthCount > 0)
1098 for (i = 0; i < hisAuthCount; i++)
1099 free (hisAuthNames[i]);
1101 free ((char *) hisAuthNames);
1104 IceDisposeCompleteMessage (iceConn, pStart);
1111 ProcessAuthRequired (
1113 unsigned long length,
1115 IceReplyWaitInfo *replyWait
1118 iceAuthRequiredMsg *message;
1120 IcePointer authData;
1122 IcePointer replyData = NULL;
1123 char *errorString = NULL;
1124 IcePoAuthProc authProc;
1125 IcePoAuthStatus status;
1126 IcePointer authState;
1127 int realAuthIndex = 0;
1129 CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired,
1130 length, SIZEOF (iceAuthRequiredMsg),
1131 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1133 IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg),
1134 iceAuthRequiredMsg, message, authData);
1136 if (!IceValidIO (iceConn))
1138 IceDisposeCompleteMessage (iceConn, authData);
1144 message->authDataLength = lswaps (message->authDataLength);
1147 CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length,
1148 message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData,
1149 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1151 if (iceConn->connect_to_you)
1153 if ((int) message->authIndex >= _IceAuthCount)
1155 _IceConnectionError *errorReply =
1156 &(((_IceReply *) (replyWait->reply))->connection_error);
1159 = "Received bad authIndex in the AuthRequired message";
1160 char errIndex = (int) message->authIndex;
1162 errorString = strdup(tempstr);
1164 errorReply->type = ICE_CONNECTION_ERROR;
1165 errorReply->error_message = errorString;
1167 _IceErrorBadValue (iceConn, 0,
1168 ICE_AuthRequired, 2, 1, &errIndex);
1170 IceDisposeCompleteMessage (iceConn, authData);
1175 authProc = _IcePoAuthProcs[message->authIndex];
1177 iceConn->connect_to_you->auth_active = 1;
1180 else if (iceConn->protosetup_to_you)
1182 if ((int) message->authIndex >=
1183 iceConn->protosetup_to_you->my_auth_count)
1185 _IceProtocolError *errorReply =
1186 &(((_IceReply *) (replyWait->reply))->protocol_error);
1189 = "Received bad authIndex in the AuthRequired message";
1190 char errIndex = (int) message->authIndex;
1192 errorString = strdup(tempstr);
1194 errorReply->type = ICE_PROTOCOL_ERROR;
1195 errorReply->error_message = errorString;
1197 _IceErrorBadValue (iceConn, 0,
1198 ICE_AuthRequired, 2, 1, &errIndex);
1200 IceDisposeCompleteMessage (iceConn, authData);
1205 _IcePoProtocol *myProtocol = _IceProtocols[
1206 iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1208 realAuthIndex = iceConn->protosetup_to_you->
1209 my_auth_indices[message->authIndex];
1211 authProc = myProtocol->auth_procs[realAuthIndex];
1213 iceConn->protosetup_to_you->auth_active = 1;
1219 * Unexpected message
1222 _IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue);
1224 IceDisposeCompleteMessage (iceConn, authData);
1229 authDataLen = message->authDataLength;
1231 status = (*authProc) (iceConn, &authState, False /* don't clean up */,
1232 swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1234 if (status == IcePoAuthHaveReply)
1236 AuthReply (iceConn, replyDataLen, replyData);
1238 replyWait->sequence_of_request = iceConn->send_sequence;
1239 replyWait->minor_opcode_of_request = ICE_AuthReply;
1241 if (iceConn->connect_to_you)
1243 iceConn->connect_to_you->my_auth_state = authState;
1244 iceConn->connect_to_you->my_auth_index = message->authIndex;
1246 else if (iceConn->protosetup_to_you)
1248 iceConn->protosetup_to_you->my_auth_state = authState;
1249 iceConn->protosetup_to_you->my_auth_index = realAuthIndex;
1252 else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1255 char *returnErrorString;
1257 if (status == IcePoAuthRejected)
1259 _IceErrorAuthenticationRejected (iceConn,
1260 ICE_AuthRequired, errorString);
1262 prefix = "Authentication Rejected, reason : ";
1266 _IceErrorAuthenticationFailed (iceConn,
1267 ICE_AuthRequired, errorString);
1269 prefix = "Authentication Failed, reason : ";
1272 if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1273 returnErrorString = NULL;
1276 if (iceConn->connect_to_you)
1278 _IceConnectionError *errorReply =
1279 &(((_IceReply *) (replyWait->reply))->connection_error);
1281 errorReply->type = ICE_CONNECTION_ERROR;
1282 errorReply->error_message = returnErrorString;
1286 _IceProtocolError *errorReply =
1287 &(((_IceReply *) (replyWait->reply))->protocol_error);
1289 errorReply->type = ICE_PROTOCOL_ERROR;
1290 errorReply->error_message = returnErrorString;
1294 if (replyData && replyDataLen > 0)
1295 free ((char *) replyData);
1297 IceDisposeCompleteMessage (iceConn, authData);
1299 return (status != IcePoAuthHaveReply);
1307 unsigned long length,
1311 iceAuthReplyMsg *message;
1313 IcePointer replyData;
1315 IcePointer authData = NULL;
1316 char *errorString = NULL;
1318 CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply,
1319 length, SIZEOF (iceAuthReplyMsg),
1320 iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1322 IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg),
1323 iceAuthReplyMsg, message, replyData);
1325 if (!IceValidIO (iceConn))
1327 IceDisposeCompleteMessage (iceConn, replyData);
1333 message->authDataLength = lswaps (message->authDataLength);
1336 CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length,
1337 message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData,
1338 iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1340 replyDataLen = message->authDataLength;
1342 if (iceConn->connect_to_me)
1344 IcePaAuthProc authProc = _IcePaAuthProcs[(int)
1345 (iceConn->connect_to_me->my_auth_index)];
1346 IcePaAuthStatus status =
1347 (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap,
1348 replyDataLen, replyData, &authDataLen, &authData, &errorString);
1350 if (status == IcePaAuthContinue)
1352 AuthNextPhase (iceConn, authDataLen, authData);
1354 else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1357 * Before we reject, invoke host-based authentication callback
1358 * and give it a chance to accept the connection (only if the
1359 * other client doesn't require authentication).
1362 if (!iceConn->connect_to_me->must_authenticate &&
1363 iceConn->listen_obj->host_based_auth_proc)
1365 char *hostname = _IceGetPeerName (iceConn);
1367 if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1369 status = IcePaAuthAccepted;
1376 if (status != IcePaAuthAccepted)
1378 free (iceConn->connect_to_me->his_vendor);
1379 free (iceConn->connect_to_me->his_release);
1380 free ((char *) iceConn->connect_to_me);
1381 iceConn->connect_to_me = NULL;
1383 iceConn->connection_status = IceConnectRejected;
1385 if (status == IcePaAuthRejected)
1387 _IceErrorAuthenticationRejected (iceConn,
1388 ICE_AuthReply, errorString);
1392 _IceErrorAuthenticationFailed (iceConn,
1393 ICE_AuthReply, errorString);
1398 if (status == IcePaAuthAccepted)
1400 AcceptConnection (iceConn,
1401 iceConn->connect_to_me->his_version_index);
1403 iceConn->vendor = iceConn->connect_to_me->his_vendor;
1404 iceConn->release = iceConn->connect_to_me->his_release;
1405 iceConn->my_ice_version_index =
1406 iceConn->connect_to_me->my_version_index;
1408 free ((char *) iceConn->connect_to_me);
1409 iceConn->connect_to_me = NULL;
1412 else if (iceConn->protosetup_to_me)
1414 _IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me->
1415 my_opcode - 1].accept_client;
1416 IcePaAuthProc authProc = myProtocol->auth_procs[(int)
1417 (iceConn->protosetup_to_me->my_auth_index)];
1418 IcePaAuthStatus status =
1419 (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state,
1420 swap, replyDataLen, replyData,
1421 &authDataLen, &authData, &errorString);
1422 int free_setup_info = 1;
1424 if (status == IcePaAuthContinue)
1426 AuthNextPhase (iceConn, authDataLen, authData);
1427 free_setup_info = 0;
1429 else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1432 * Before we reject, invoke host-based authentication callback
1433 * and give it a chance to accept the Protocol Setup (only if the
1434 * other client doesn't require authentication).
1437 if (!iceConn->protosetup_to_me->must_authenticate &&
1438 myProtocol->host_based_auth_proc)
1440 char *hostname = _IceGetPeerName (iceConn);
1442 if ((*myProtocol->host_based_auth_proc) (hostname))
1444 status = IcePaAuthAccepted;
1451 if (status == IcePaAuthRejected)
1453 _IceErrorAuthenticationRejected (iceConn,
1454 ICE_AuthReply, errorString);
1458 _IceErrorAuthenticationFailed (iceConn,
1459 ICE_AuthReply, errorString);
1463 if (status == IcePaAuthAccepted)
1465 IcePaProcessMsgProc processMsgProc;
1466 IceProtocolSetupProc protocolSetupProc;
1467 IceProtocolActivateProc protocolActivateProc;
1468 _IceProcessMsgInfo *process_msg_info;
1469 IcePointer clientData = NULL;
1470 char *failureReason = NULL;
1473 protocolSetupProc = myProtocol->protocol_setup_proc;
1474 protocolActivateProc = myProtocol->protocol_activate_proc;
1476 if (protocolSetupProc)
1479 * Notify the client of the Protocol Setup.
1482 status = (*protocolSetupProc) (iceConn,
1483 myProtocol->version_recs[iceConn->protosetup_to_me->
1484 my_version_index].major_version,
1485 myProtocol->version_recs[iceConn->protosetup_to_me->
1486 my_version_index].minor_version,
1487 iceConn->protosetup_to_me->his_vendor,
1488 iceConn->protosetup_to_me->his_release,
1489 &clientData, &failureReason);
1492 * Set vendor and release pointers to NULL, so it won't
1493 * get freed below. The ProtocolSetupProc should
1497 iceConn->protosetup_to_me->his_vendor = NULL;
1498 iceConn->protosetup_to_me->his_release = NULL;
1504 * Send the Protocol Reply
1507 AcceptProtocol (iceConn,
1508 iceConn->protosetup_to_me->his_opcode,
1509 iceConn->protosetup_to_me->my_opcode,
1510 iceConn->protosetup_to_me->his_version_index,
1511 myProtocol->vendor, myProtocol->release);
1515 * Set info for this protocol.
1518 processMsgProc = myProtocol->version_recs[
1519 iceConn->protosetup_to_me->
1520 my_version_index].process_msg_proc;
1522 process_msg_info = &iceConn->process_msg_info[
1523 iceConn->protosetup_to_me->
1524 his_opcode -iceConn->his_min_opcode];
1526 process_msg_info->client_data = clientData;
1527 process_msg_info->accept_flag = 1;
1528 process_msg_info->process_msg_proc.
1529 accept_client = processMsgProc;
1533 * Increase the reference count for the number
1534 * of active protocols.
1537 iceConn->proto_ref_count++;
1541 * Notify the client that the protocol is active. The reason
1542 * we have this 2nd callback invoked is because the client
1543 * may wish to immediately generate a message for this
1544 * protocol, but it must wait until we send the Protocol Reply.
1547 if (protocolActivateProc)
1549 (*protocolActivateProc) (iceConn,
1550 process_msg_info->client_data);
1556 * An error was encountered.
1559 _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup,
1563 free (failureReason);
1568 if (free_setup_info)
1570 if (iceConn->protosetup_to_me->his_vendor)
1571 free (iceConn->protosetup_to_me->his_vendor);
1572 if (iceConn->protosetup_to_me->his_release)
1573 free (iceConn->protosetup_to_me->his_release);
1574 free ((char *) iceConn->protosetup_to_me);
1575 iceConn->protosetup_to_me = NULL;
1581 * Unexpected message
1584 _IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue);
1587 if (authData && authDataLen > 0)
1588 free ((char *) authData);
1593 IceDisposeCompleteMessage (iceConn, replyData);
1600 ProcessAuthNextPhase (
1602 unsigned long length,
1604 IceReplyWaitInfo *replyWait
1607 iceAuthNextPhaseMsg *message;
1609 IcePointer authData;
1611 IcePointer replyData = NULL;
1612 char *errorString = NULL;
1613 IcePoAuthProc authProc;
1614 IcePoAuthStatus status;
1615 IcePointer *authState;
1617 CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase,
1618 length, SIZEOF (iceAuthNextPhaseMsg),
1619 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1621 IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg),
1622 iceAuthNextPhaseMsg, message, authData);
1624 if (!IceValidIO (iceConn))
1626 IceDisposeCompleteMessage (iceConn, authData);
1632 message->authDataLength = lswaps (message->authDataLength);
1635 CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length,
1636 message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData,
1637 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1639 if (iceConn->connect_to_you)
1641 authProc = _IcePoAuthProcs[(int)
1642 (iceConn->connect_to_you->my_auth_index)];
1644 authState = &iceConn->connect_to_you->my_auth_state;
1646 else if (iceConn->protosetup_to_you)
1648 _IcePoProtocol *myProtocol =
1649 _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1651 authProc = myProtocol->auth_procs[(int)
1652 (iceConn->protosetup_to_you->my_auth_index)];
1654 authState = &iceConn->protosetup_to_you->my_auth_state;
1659 * Unexpected message
1662 _IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue);
1664 IceDisposeCompleteMessage (iceConn, authData);
1668 authDataLen = message->authDataLength;
1670 status = (*authProc) (iceConn, authState, False /* don't clean up */,
1671 swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1673 if (status == IcePoAuthHaveReply)
1675 AuthReply (iceConn, replyDataLen, replyData);
1677 replyWait->sequence_of_request = iceConn->send_sequence;
1679 else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1681 const char *prefix = NULL;
1682 char *returnErrorString;
1684 if (status == IcePoAuthRejected)
1686 _IceErrorAuthenticationRejected (iceConn,
1687 ICE_AuthNextPhase, errorString);
1689 prefix = "Authentication Rejected, reason : ";
1691 else if (status == IcePoAuthFailed)
1693 _IceErrorAuthenticationFailed (iceConn,
1694 ICE_AuthNextPhase, errorString);
1696 prefix = "Authentication Failed, reason : ";
1699 if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1700 returnErrorString = NULL;
1703 if (iceConn->connect_to_you)
1705 _IceConnectionError *errorReply =
1706 &(((_IceReply *) (replyWait->reply))->connection_error);
1708 errorReply->type = ICE_CONNECTION_ERROR;
1709 errorReply->error_message = returnErrorString;
1713 _IceProtocolError *errorReply =
1714 &(((_IceReply *) (replyWait->reply))->protocol_error);
1716 errorReply->type = ICE_PROTOCOL_ERROR;
1717 errorReply->error_message = returnErrorString;
1721 if (replyData && replyDataLen > 0)
1722 free ((char *) replyData);
1724 IceDisposeCompleteMessage (iceConn, authData);
1726 return (status != IcePoAuthHaveReply);
1732 ProcessConnectionReply (
1734 unsigned long length,
1736 IceReplyWaitInfo *replyWait
1739 iceConnectionReplyMsg *message;
1740 char *pData, *pStart, *pEnd;
1744 CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply,
1745 length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection);
1748 IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg),
1749 iceConnectionReplyMsg, message, pStart);
1751 if (!IceValidIO (iceConn))
1753 IceDisposeCompleteMessage (iceConn, pStart);
1758 pEnd = pStart + (length << 3);
1760 SKIP_STRING (pData, swap, pEnd,
1761 BAIL_STRING (iceConn, ICE_ConnectionReply,
1762 pStart)); /* vendor */
1763 SKIP_STRING (pData, swap, pEnd,
1764 BAIL_STRING (iceConn, ICE_ConnectionReply,
1765 pStart)); /* release */
1767 CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply,
1768 length, pData - pStart + SIZEOF (iceConnectionReplyMsg),
1769 pStart, IceFatalToConnection);
1773 if (iceConn->connect_to_you)
1775 if (iceConn->connect_to_you->auth_active)
1778 * Tell the authentication procedure to clean up.
1781 IcePoAuthProc authProc = _IcePoAuthProcs[(int)
1782 (iceConn->connect_to_you->my_auth_index)];
1784 (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
1785 True /* clean up */, False /* swap */,
1786 0, NULL, NULL, NULL, NULL);
1789 if ((int) message->versionIndex >= _IceVersionCount)
1791 _IceConnectionError *errorReply =
1792 &(((_IceReply *) (replyWait->reply))->connection_error);
1793 char errIndex = message->versionIndex;
1795 _IceErrorBadValue (iceConn, 0,
1796 ICE_ConnectionReply, 2, 1, &errIndex);
1798 errorReply->type = ICE_CONNECTION_ERROR;
1799 errorReply->error_message =
1800 "Received bad version index in Connection Reply";
1804 _IceReply *reply = (_IceReply *) (replyWait->reply);
1806 reply->type = ICE_CONNECTION_REPLY;
1807 reply->connection_reply.version_index = message->versionIndex;
1809 EXTRACT_STRING (pData, swap, reply->connection_reply.vendor);
1810 EXTRACT_STRING (pData, swap, reply->connection_reply.release);
1818 * Unexpected message
1821 _IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue);
1826 IceDisposeCompleteMessage (iceConn, pStart);
1828 return (replyReady);
1834 ProcessProtocolSetup (
1836 unsigned long length,
1840 iceProtocolSetupMsg *message;
1841 _IcePaProtocol *myProtocol;
1842 int myVersionCount, hisVersionCount;
1843 int myVersionIndex, hisVersionIndex;
1844 int hisMajorVersion, hisMinorVersion;
1845 int myAuthCount, hisAuthCount;
1846 int myOpcode, hisOpcode;
1848 char **hisAuthNames = NULL;
1850 char *pData, *pStart, *pEnd;
1851 char *vendor = NULL;
1852 char *release = NULL;
1853 int accept_setup_now = 0;
1854 int myAuthIndex = 0;
1855 int hisAuthIndex = 0;
1856 char mustAuthenticate;
1857 int authUsableCount;
1858 int authUsableFlags[MAX_ICE_AUTH_NAMES];
1859 int authIndices[MAX_ICE_AUTH_NAMES];
1861 CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,
1862 length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);
1864 if (iceConn->want_to_close)
1867 * If we sent a WantToClose message, but just got a ProtocolSetup,
1868 * we must cancel our WantToClose. It is the responsiblity of the
1869 * other client to send a WantToClose later on.
1872 iceConn->want_to_close = 0;
1875 IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),
1876 iceProtocolSetupMsg, message, pStart);
1878 if (!IceValidIO (iceConn))
1880 IceDisposeCompleteMessage (iceConn, pStart);
1885 pEnd = pStart + (length << 3);
1887 SKIP_STRING (pData, swap, pEnd,
1888 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1889 pStart)); /* proto name */
1890 SKIP_STRING (pData, swap, pEnd,
1891 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1892 pStart)); /* vendor */
1893 SKIP_STRING (pData, swap, pEnd,
1894 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1895 pStart)); /* release */
1896 SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
1897 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1898 pStart)); /* auth names */
1899 pData += (message->versionCount * 4); /* versions */
1901 CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,
1902 length, pData - pStart + SIZEOF (iceProtocolSetupMsg),
1903 pStart, IceFatalToProtocol);
1905 mustAuthenticate = message->mustAuthenticate;
1907 if (mustAuthenticate != 0 && mustAuthenticate != 1)
1909 _IceErrorBadValue (iceConn, 0,
1910 ICE_ProtocolSetup, 4, 1, &mustAuthenticate);
1911 IceDisposeCompleteMessage (iceConn, pStart);
1917 if (iceConn->process_msg_info &&
1918 (int) message->protocolOpcode >= iceConn->his_min_opcode &&
1919 (int) message->protocolOpcode <= iceConn->his_max_opcode &&
1920 iceConn->process_msg_info[
1921 message->protocolOpcode - iceConn->his_min_opcode].in_use)
1923 _IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);
1924 IceDisposeCompleteMessage (iceConn, pStart);
1928 EXTRACT_STRING (pData, swap, protocolName);
1930 if (iceConn->process_msg_info)
1933 i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)
1935 if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,
1936 iceConn->process_msg_info[i].protocol->protocol_name) == 0)
1938 _IceErrorProtocolDuplicate (iceConn, protocolName);
1939 free (protocolName);
1940 IceDisposeCompleteMessage (iceConn, pStart);
1946 for (i = 0; i < _IceLastMajorOpcode; i++)
1947 if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)
1950 if (i < _IceLastMajorOpcode &&
1951 (myProtocol = _IceProtocols[i].accept_client) != NULL)
1953 hisOpcode = message->protocolOpcode;
1955 free (protocolName);
1959 _IceErrorUnknownProtocol (iceConn, protocolName);
1960 free (protocolName);
1961 IceDisposeCompleteMessage (iceConn, pStart);
1965 EXTRACT_STRING (pData, swap, vendor);
1966 EXTRACT_STRING (pData, swap, release);
1968 if ((hisAuthCount = message->authCount) > 0)
1970 hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
1971 EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
1974 hisVersionCount = message->versionCount;
1975 myVersionCount = myProtocol->version_count;
1977 hisVersionIndex = myVersionIndex = found = 0;
1979 for (i = 0; i < hisVersionCount && !found; i++)
1981 EXTRACT_CARD16 (pData, swap, hisMajorVersion);
1982 EXTRACT_CARD16 (pData, swap, hisMinorVersion);
1984 for (j = 0; j < myVersionCount && !found; j++)
1986 if (myProtocol->version_recs[j].major_version == hisMajorVersion &&
1987 myProtocol->version_recs[j].minor_version == hisMinorVersion)
1989 hisVersionIndex = i;
1998 _IceErrorNoVersion (iceConn, ICE_ProtocolSetup);
2003 if (hisAuthCount > 0)
2005 for (i = 0; i < hisAuthCount; i++)
2006 free (hisAuthNames[i]);
2008 free ((char *) hisAuthNames);
2011 IceDisposeCompleteMessage (iceConn, pStart);
2015 myAuthCount = myProtocol->auth_count;
2017 _IceGetPaValidAuthIndices (
2018 _IceProtocols[myOpcode - 1].protocol_name,
2019 iceConn->connection_string, myAuthCount,
2020 (const char **) myProtocol->auth_names,
2021 &authUsableCount, authIndices);
2023 for (i = 0; i < myAuthCount; i++)
2025 authUsableFlags[i] = 0;
2026 for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
2027 authUsableFlags[i] = (authIndices[j] == i);
2030 for (i = found = 0; i < myAuthCount && !found; i++)
2032 if (authUsableFlags[i])
2034 const char *myAuthName = myProtocol->auth_names[i];
2036 for (j = 0; j < hisAuthCount && !found; j++)
2037 if (strcmp (myAuthName, hisAuthNames[j]) == 0)
2049 * None of the authentication methods specified by the
2050 * other client is supported. If the other client requires
2051 * authentication, we must reject the Protocol Setup now.
2052 * Otherwise, we can invoke the host-based authentication callback
2053 * to see if we can accept this Protocol Setup.
2056 if (mustAuthenticate || !myProtocol->host_based_auth_proc)
2058 _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);
2062 char *hostname = _IceGetPeerName (iceConn);
2064 if ((*myProtocol->host_based_auth_proc) (hostname))
2066 accept_setup_now = 1;
2070 _IceErrorAuthenticationRejected (iceConn,
2071 ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
2080 IcePaAuthStatus status;
2082 IcePointer authData = NULL;
2083 IcePointer authState;
2084 char *errorString = NULL;
2085 IcePaAuthProc authProc =
2086 myProtocol->auth_procs[myAuthIndex];
2090 status = (*authProc) (iceConn, &authState, swap, 0, NULL,
2091 &authDataLen, &authData, &errorString);
2093 if (status == IcePaAuthContinue)
2095 _IceProtoSetupToMeInfo *setupInfo;
2097 AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
2099 iceConn->protosetup_to_me = setupInfo =
2100 (_IceProtoSetupToMeInfo *) malloc (
2101 sizeof (_IceProtoSetupToMeInfo));
2103 setupInfo->his_opcode = hisOpcode;
2104 setupInfo->my_opcode = myOpcode;
2105 setupInfo->my_version_index = myVersionIndex;
2106 setupInfo->his_version_index = hisVersionIndex;
2107 setupInfo->his_vendor = vendor;
2108 setupInfo->his_release = release;
2109 vendor = release = NULL; /* so we don't free it */
2110 setupInfo->my_auth_index = myAuthIndex;
2111 setupInfo->my_auth_state = authState;
2112 setupInfo->must_authenticate = mustAuthenticate;
2114 else if (status == IcePaAuthAccepted)
2116 accept_setup_now = 1;
2119 if (authData && authDataLen > 0)
2120 free ((char *) authData);
2126 if (accept_setup_now)
2128 IcePaProcessMsgProc processMsgProc;
2129 IceProtocolSetupProc protocolSetupProc;
2130 IceProtocolActivateProc protocolActivateProc;
2131 _IceProcessMsgInfo *process_msg_info;
2132 IcePointer clientData = NULL;
2133 char *failureReason = NULL;
2136 protocolSetupProc = myProtocol->protocol_setup_proc;
2137 protocolActivateProc = myProtocol->protocol_activate_proc;
2139 if (protocolSetupProc)
2142 * Notify the client of the Protocol Setup.
2145 status = (*protocolSetupProc) (iceConn,
2146 myProtocol->version_recs[myVersionIndex].major_version,
2147 myProtocol->version_recs[myVersionIndex].minor_version,
2148 vendor, release, &clientData, &failureReason);
2150 vendor = release = NULL; /* so we don't free it */
2156 * Send the Protocol Reply
2159 AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,
2160 myProtocol->vendor, myProtocol->release);
2164 * Set info for this protocol.
2167 processMsgProc = myProtocol->version_recs[
2168 myVersionIndex].process_msg_proc;
2170 process_msg_info = &iceConn->process_msg_info[hisOpcode -
2171 iceConn->his_min_opcode];
2173 process_msg_info->client_data = clientData;
2174 process_msg_info->accept_flag = 1;
2175 process_msg_info->process_msg_proc.accept_client = processMsgProc;
2179 * Increase the reference count for the number of active protocols.
2182 iceConn->proto_ref_count++;
2186 * Notify the client that the protocol is active. The reason
2187 * we have this 2nd callback invoked is because the client
2188 * may wish to immediately generate a message for this
2189 * protocol, but it must wait until we send the Protocol Reply.
2192 if (protocolActivateProc)
2194 (*protocolActivateProc) (iceConn,
2195 process_msg_info->client_data);
2201 * An error was encountered.
2204 _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);
2207 free (failureReason);
2217 if (hisAuthCount > 0)
2219 for (i = 0; i < hisAuthCount; i++)
2220 free (hisAuthNames[i]);
2222 free ((char *) hisAuthNames);
2225 IceDisposeCompleteMessage (iceConn, pStart);
2232 ProcessProtocolReply (
2234 unsigned long length,
2236 IceReplyWaitInfo *replyWait
2239 iceProtocolReplyMsg *message;
2240 char *pData, *pStart, *pEnd;
2244 CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply,
2245 length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol);
2248 IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg),
2249 iceProtocolReplyMsg, message, pStart);
2251 if (!IceValidIO (iceConn))
2253 IceDisposeCompleteMessage (iceConn, pStart);
2258 pEnd = pStart + (length << 3);
2260 SKIP_STRING (pData, swap, pEnd,
2261 BAIL_STRING(iceConn, ICE_ProtocolReply,
2262 pStart)); /* vendor */
2263 SKIP_STRING (pData, swap, pEnd,
2264 BAIL_STRING(iceConn, ICE_ProtocolReply,
2265 pStart)); /* release */
2267 CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply,
2268 length, pData - pStart + SIZEOF (iceProtocolReplyMsg),
2269 pStart, IceFatalToProtocol);
2273 if (iceConn->protosetup_to_you)
2275 if (iceConn->protosetup_to_you->auth_active)
2278 * Tell the authentication procedure to clean up.
2281 _IcePoProtocol *myProtocol = _IceProtocols[
2282 iceConn->protosetup_to_you->my_opcode - 1].orig_client;
2284 IcePoAuthProc authProc = myProtocol->auth_procs[(int)
2285 (iceConn->protosetup_to_you->my_auth_index)];
2287 (*authProc) (iceConn,
2288 &iceConn->protosetup_to_you->my_auth_state,
2289 True /* clean up */, False /* swap */,
2290 0, NULL, NULL, NULL, NULL);
2293 if ((int) message->versionIndex >= _IceVersionCount)
2295 _IceProtocolError *errorReply =
2296 &(((_IceReply *) (replyWait->reply))->protocol_error);
2297 char errIndex = message->versionIndex;
2299 _IceErrorBadValue (iceConn, 0,
2300 ICE_ProtocolReply, 2, 1, &errIndex);
2302 errorReply->type = ICE_PROTOCOL_ERROR;
2303 errorReply->error_message =
2304 "Received bad version index in Protocol Reply";
2308 _IceProtocolReply *reply =
2309 &(((_IceReply *) (replyWait->reply))->protocol_reply);
2311 reply->type = ICE_PROTOCOL_REPLY;
2312 reply->major_opcode = message->protocolOpcode;
2313 reply->version_index = message->versionIndex;
2315 EXTRACT_STRING (pData, swap, reply->vendor);
2316 EXTRACT_STRING (pData, swap, reply->release);
2323 _IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue);
2328 IceDisposeCompleteMessage (iceConn, pStart);
2330 return (replyReady);
2338 unsigned long length
2341 CHECK_SIZE_MATCH (iceConn, ICE_Ping,
2342 length, SIZEOF (icePingMsg), IceFatalToConnection, 0);
2344 PingReply (iceConn);
2354 unsigned long length
2357 CHECK_SIZE_MATCH (iceConn, ICE_PingReply,
2358 length, SIZEOF (icePingReplyMsg), IceFatalToConnection, 0);
2360 if (iceConn->ping_waits)
2362 _IcePingWait *next = iceConn->ping_waits->next;
2364 (*iceConn->ping_waits->ping_reply_proc) (iceConn,
2365 iceConn->ping_waits->client_data);
2367 free ((char *) iceConn->ping_waits);
2368 iceConn->ping_waits = next;
2372 _IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue);
2381 ProcessWantToClose (
2383 unsigned long length,
2384 Bool *connectionClosedRet
2387 *connectionClosedRet = False;
2389 CHECK_SIZE_MATCH (iceConn, ICE_WantToClose,
2390 length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection, 0);
2392 if (iceConn->want_to_close || iceConn->open_ref_count == 0)
2395 * We just received a WantToClose. Either we also sent a
2396 * WantToClose, so we close the connection, or the iceConn
2397 * is not being used, so we close the connection. This
2398 * second case is possible if we sent a WantToClose because
2399 * the iceConn->open_ref_count reached zero, but then we
2400 * received a NoClose.
2403 _IceConnectionClosed (iceConn); /* invoke watch procs */
2404 _IceFreeConnection (iceConn);
2405 *connectionClosedRet = True;
2407 else if (iceConn->proto_ref_count > 0)
2410 * We haven't shut down all of our protocols yet. We send a NoClose,
2411 * and it's up to us to generate a WantToClose later on.
2414 IceSimpleMessage (iceConn, 0, ICE_NoClose);
2420 * The reference count on this iceConn is zero. This means that
2421 * there are no active protocols, but the client didn't explicitly
2422 * close the connection yet. If we didn't just send a Protocol Setup,
2423 * we send a NoClose, and it's up to us to generate a WantToClose
2427 if (!iceConn->protosetup_to_you)
2429 IceSimpleMessage (iceConn, 0, ICE_NoClose);
2442 unsigned long length
2445 CHECK_SIZE_MATCH (iceConn, ICE_NoClose,
2446 length, SIZEOF (iceNoCloseMsg), IceFatalToConnection, 0);
2448 if (iceConn->want_to_close)
2451 * The other side can't close now. We cancel our WantToClose,
2452 * and we can expect a WantToClose from the other side.
2455 iceConn->want_to_close = 0;
2459 _IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue);
2468 _IceProcessCoreMessage (
2471 unsigned long length,
2473 IceReplyWaitInfo *replyWait,
2474 Bool *replyReadyRet,
2475 Bool *connectionClosedRet
2478 Bool replyReady = False;
2480 *connectionClosedRet = False;
2486 replyReady = ProcessError (iceConn, length, swap, replyWait);
2489 case ICE_ConnectionSetup:
2491 ProcessConnectionSetup (iceConn, length, swap);
2494 case ICE_AuthRequired:
2496 replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait);
2501 ProcessAuthReply (iceConn, length, swap);
2504 case ICE_AuthNextPhase:
2506 replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait);
2509 case ICE_ConnectionReply:
2511 replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait);
2514 case ICE_ProtocolSetup:
2516 ProcessProtocolSetup (iceConn, length, swap);
2519 case ICE_ProtocolReply:
2521 replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait);
2526 ProcessPing (iceConn, length);
2531 ProcessPingReply (iceConn, length);
2534 case ICE_WantToClose:
2536 ProcessWantToClose (iceConn, length, connectionClosedRet);
2541 ProcessNoClose (iceConn, length);
2546 _IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue);
2547 _IceReadSkip (iceConn, length << 3);
2552 *replyReadyRet = replyReady;
2555 int _IceVersionCount = 1;
2556 _IceVersion _IceVersions[] = {
2557 {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};