1/******************************************************************************
2
3
4Copyright 1993, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25
26Author: Ralph Mor, X Consortium
27******************************************************************************/
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include <X11/ICE/ICElib.h>
33#include "ICElibint.h"
34
35#include <stdio.h> /* sprintf */
36
37/*
38 * Check for bad length
39 */
40
41#define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity, _return) \
42    if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
43    { \
44       _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
45       return (_return); \
46    }
47
48#define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
49    if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
50    { \
51       _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
52       return (0); \
53    }
54
55#define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \
56    if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
57        != _expected_len) \
58    { \
59       _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
60       IceDisposeCompleteMessage (iceConn, _pStart); \
61       return (0); \
62    }
63
64#define BAIL_STRING(_iceConn, _opcode, _pStart) {\
65    _IceErrorBadLength (_iceConn, 0, _opcode, IceFatalToConnection);\
66    IceDisposeCompleteMessage (_iceConn, _pStart);\
67    return (0);\
68}
69
70#ifndef HAVE_ASPRINTF
71# include <stdarg.h>
72
73/* sprintf variant found in newer libc's which allocates string to print to */
74static int _X_ATTRIBUTE_PRINTF(2,3)
75asprintf(char ** ret, const char *format, ...)
76{
77    char buf[256];
78    int len;
79    va_list ap;
80
81    va_start(ap, format);
82    len = vsnprintf(buf, sizeof(buf), format, ap);
83    va_end(ap);
84
85    if (len < 0)
86	return -1;
87
88    if (len < sizeof(buf))
89    {
90	*ret = strdup(buf);
91    }
92    else
93    {
94	*ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */
95	if (*ret != NULL)
96	{
97	    va_start(ap, format);
98	    len = vsnprintf(*ret, len + 1, format, ap);
99	    va_end(ap);
100	    if (len < 0) {
101		free(*ret);
102		*ret = NULL;
103	    }
104	}
105    }
106
107    if (*ret == NULL)
108	return -1;
109
110    return len;
111}
112#endif
113
114
115/*
116 * IceProcessMessages:
117 *
118 * If replyWait == NULL, the client is not waiting for a reply.
119 *
120 * If replyWait != NULL, the client is waiting for a reply...
121 *
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.
125 *
126 *    - replyWait->major_opcode_of_request is the major opcode of the
127 *      message for which we are waiting a reply.
128 *
129 *    - replyWait->minor_opcode_of_request is the minor opcode of the
130 *      message for which we are waiting a reply.
131 *
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.
146 *
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, every time 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.
156 *
157 * If the reply/error is ready for the replyWait passed in to
158 * IceProcessMessages, *replyReadyRet is set to True.
159 *
160 * The return value of IceProcessMessages is one of the following:
161 *
162 * IceProcessMessagesSuccess - the message was processed successfully.
163 * IceProcessMessagesIOError - an IO error occurred.  The caller should
164 *			       invoked IceCloseConnection.
165 * IceProcessMessagesConnectionClosed - the connection was closed as a
166 *					result of shutdown negotiation.
167 */
168
169IceProcessMessagesStatus
170IceProcessMessages (
171	IceConn		 iceConn,
172	IceReplyWaitInfo *replyWait,
173	Bool		 *replyReadyRet
174)
175{
176    iceMsg		*header;
177    Bool		replyReady = False;
178    IceReplyWaitInfo	*useThisReplyWait = NULL;
179    IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess;
180
181    if (replyWait)
182	*replyReadyRet = False;
183
184    /*
185     * Each time IceProcessMessages is entered, we increment the dispatch
186     * level.  Each time we leave it, we decrement the dispatch level.
187     */
188
189    iceConn->dispatch_level++;
190
191
192    /*
193     * Read the ICE message header.
194     */
195
196    if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf))
197    {
198	/*
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.
202	 */
203
204	return (IceProcessMessagesConnectionClosed);
205    }
206
207    if (!iceConn->io_ok)
208    {
209	/*
210	 * An unexpected IO error occurred.  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.
213	 */
214
215	iceConn->dispatch_level--;
216	iceConn->connection_status = IceConnectIOError;
217	return (IceProcessMessagesIOError);
218    }
219
220    header = (iceMsg *) iceConn->inbuf;
221    iceConn->inbufptr = iceConn->inbuf + SIZEOF (iceMsg);
222
223    iceConn->receive_sequence++;
224
225    if (iceConn->waiting_for_byteorder)
226    {
227	if (header->majorOpcode == 0 &&
228	    header->minorOpcode == ICE_ByteOrder)
229	{
230	    char byteOrder = ((iceByteOrderMsg *) header)->byteOrder;
231	    int endian = 1;
232
233	    CHECK_SIZE_MATCH (iceConn, ICE_ByteOrder,
234	        header->length, SIZEOF (iceByteOrderMsg),
235		IceFatalToConnection, IceProcessMessagesIOError);
236
237	    if (byteOrder != IceMSBfirst && byteOrder != IceLSBfirst)
238	    {
239		_IceErrorBadValue (iceConn, 0,
240	            ICE_ByteOrder, 2, 1, &byteOrder);
241
242		iceConn->connection_status = IceConnectRejected;
243	    }
244	    else
245	    {
246		iceConn->swap =
247	            (((*(char *) &endian) && byteOrder == IceMSBfirst) ||
248	             (!(*(char *) &endian) && byteOrder == IceLSBfirst));
249
250		iceConn->waiting_for_byteorder = 0;
251	    }
252	}
253	else
254	{
255	    if (header->majorOpcode != 0)
256	    {
257		_IceErrorBadMajor (iceConn, header->majorOpcode,
258		    header->minorOpcode, IceFatalToConnection);
259	    }
260	    else
261	    {
262		_IceErrorBadState (iceConn, 0,
263		    header->minorOpcode, IceFatalToConnection);
264	    }
265
266	    iceConn->connection_status = IceConnectRejected;
267	}
268
269	iceConn->dispatch_level--;
270	if (!iceConn->io_ok)
271	{
272	    iceConn->connection_status = IceConnectIOError;
273	    retStatus = IceProcessMessagesIOError;
274	}
275
276	return (retStatus);
277    }
278
279    if (iceConn->swap)
280    {
281	/* swap the length field */
282
283	header->length = lswapl (header->length);
284    }
285
286    if (replyWait)
287    {
288	/*
289	 * Add to the list of replyWaits (only if it doesn't exist
290	 * in the list already.
291	 */
292
293	_IceAddReplyWait (iceConn, replyWait);
294
295	/*
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".
301	 *
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
305	 * comparing them.
306	 */
307
308	{
309	    int op;
310
311	    if (header->majorOpcode == 0)
312	    {
313		op = 0;
314	    }
315	    else
316	    {
317		int idx = header->majorOpcode - iceConn->his_min_opcode;
318		op = iceConn->process_msg_info[idx].my_opcode;
319	    }
320	    useThisReplyWait = _IceSearchReplyWaits (iceConn, op);
321	}
322    }
323
324    if (header->majorOpcode == 0)
325    {
326	/*
327	 * ICE protocol
328	 */
329
330	Bool connectionClosed;
331
332	_IceProcessCoreMsgProc processIce =
333	    _IceVersions[iceConn->my_ice_version_index].process_core_msg_proc;
334
335	(*processIce) (iceConn, header->minorOpcode,
336	    header->length, iceConn->swap,
337	    useThisReplyWait, &replyReady, &connectionClosed);
338
339	if (connectionClosed)
340	{
341	    /*
342	     * As a result of shutdown negotiation, the connection was closed.
343	     */
344
345	    return (IceProcessMessagesConnectionClosed);
346	}
347    }
348    else
349    {
350	/*
351	 * Sub protocol
352	 */
353
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))
358	{
359	    /*
360	     * The protocol of the message we just read is not supported.
361	     */
362
363	    _IceErrorBadMajor (iceConn, header->majorOpcode,
364		header->minorOpcode, IceCanContinue);
365
366	    _IceReadSkip (iceConn, header->length << 3);
367	}
368	else
369	{
370	    _IceProcessMsgInfo *processMsgInfo = &iceConn->process_msg_info[
371		header->majorOpcode - iceConn->his_min_opcode];
372
373	    if (processMsgInfo->accept_flag)
374	    {
375		IcePaProcessMsgProc processProc =
376		    processMsgInfo->process_msg_proc.accept_client;
377
378		(*processProc) (iceConn, processMsgInfo->client_data,
379		    header->minorOpcode, header->length, iceConn->swap);
380	    }
381	    else
382	    {
383		IcePoProcessMsgProc processProc =
384		    processMsgInfo->process_msg_proc.orig_client;
385
386		(*processProc) (iceConn,
387		    processMsgInfo->client_data, header->minorOpcode,
388		    header->length, iceConn->swap,
389		    useThisReplyWait, &replyReady);
390	    }
391	}
392    }
393
394    if (replyReady)
395    {
396	_IceSetReplyReady (iceConn, useThisReplyWait);
397    }
398
399
400    /*
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.
404     */
405
406    if (replyWait)
407	*replyReadyRet = _IceCheckReplyReady (iceConn, replyWait);
408
409
410    /*
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.
414     */
415
416    iceConn->dispatch_level--;
417
418    if (iceConn->dispatch_level == 0 && iceConn->free_asap)
419    {
420	_IceFreeConnection (iceConn);
421	retStatus = IceProcessMessagesConnectionClosed;
422    }
423    else if (!iceConn->io_ok)
424    {
425	iceConn->connection_status = IceConnectIOError;
426	retStatus = IceProcessMessagesIOError;
427    }
428
429    return (retStatus);
430}
431
432
433
434static void
435AuthRequired (
436	IceConn		iceConn,
437	int  		authIndex,
438	int  		authDataLen,
439	IcePointer	authData
440)
441{
442    iceAuthRequiredMsg *pMsg;
443
444    IceGetHeader (iceConn, 0, ICE_AuthRequired,
445	SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg);
446
447    pMsg->authIndex = authIndex;
448    pMsg->authDataLength = authDataLen;
449
450    if (authDataLen) {
451	pMsg->length += WORD64COUNT (authDataLen);
452
453	IceWriteData (iceConn, authDataLen, (char *) authData);
454
455	if (PAD64 (authDataLen))
456	    IceWritePad (iceConn, PAD64 (authDataLen));
457    }
458
459    IceFlush (iceConn);
460}
461
462
463
464static void
465AuthReply (
466	IceConn		iceConn,
467	int 		authDataLen,
468	IcePointer	authData
469)
470{
471    iceAuthReplyMsg *pMsg;
472
473    IceGetHeader (iceConn, 0, ICE_AuthReply,
474	SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg);
475
476    pMsg->authDataLength = authDataLen;
477    pMsg->length +=  WORD64COUNT (authDataLen);
478
479    IceWriteData (iceConn, authDataLen, (char *) authData);
480
481    if (PAD64 (authDataLen))
482	IceWritePad (iceConn, PAD64 (authDataLen));
483
484    IceFlush (iceConn);
485}
486
487
488
489static void
490AuthNextPhase (
491	IceConn		iceConn,
492	int  		authDataLen,
493	IcePointer	authData
494)
495{
496    iceAuthNextPhaseMsg *pMsg;
497
498    IceGetHeader (iceConn, 0, ICE_AuthNextPhase,
499	SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg);
500
501    pMsg->authDataLength = authDataLen;
502    pMsg->length += WORD64COUNT (authDataLen);
503
504    IceWriteData (iceConn, authDataLen, (char *) authData);
505
506    if (PAD64 (authDataLen))
507	IceWritePad (iceConn, PAD64 (authDataLen));
508
509    IceFlush (iceConn);
510}
511
512
513
514static void
515AcceptConnection (
516	IceConn iceConn,
517	int 	versionIndex
518)
519{
520    iceConnectionReplyMsg	*pMsg;
521    char			*pData;
522    int				extra;
523
524    extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
525
526    IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply,
527	SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra),
528	iceConnectionReplyMsg, pMsg, pData);
529
530    pMsg->versionIndex = versionIndex;
531
532    if (pData != NULL) {
533	STORE_STRING (pData, IceVendorString);
534	STORE_STRING (pData, IceReleaseString);
535
536	IceFlush (iceConn);
537    } else {
538	SEND_STRING (iceConn, IceVendorString);
539	SEND_STRING (iceConn, IceReleaseString);
540    }
541
542    iceConn->connection_status = IceConnectAccepted;
543}
544
545
546
547static void
548AcceptProtocol (
549	IceConn iceConn,
550	int  	hisOpcode,
551	int  	myOpcode,
552	int  	versionIndex,
553	char 	*vendor,
554	char 	*release
555)
556{
557    iceProtocolReplyMsg	*pMsg;
558    char		*pData;
559    int			extra;
560
561    extra = STRING_BYTES (vendor) + STRING_BYTES (release);
562
563    IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply,
564	SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra),
565	iceProtocolReplyMsg, pMsg, pData);
566
567    pMsg->protocolOpcode = myOpcode;
568    pMsg->versionIndex = versionIndex;
569
570    if (pData != NULL) {
571	STORE_STRING (pData, vendor);
572	STORE_STRING (pData, release);
573
574	IceFlush (iceConn);
575    } else {
576	SEND_STRING (iceConn, vendor);
577	SEND_STRING (iceConn, release);
578    }
579
580
581    /*
582     * We may be using a different major opcode for this protocol
583     * than the other client.  Whenever we get a message, we must
584     * map to our own major opcode.
585     */
586
587    _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
588}
589
590
591
592static void
593PingReply (
594	IceConn iceConn
595)
596{
597    IceSimpleMessage (iceConn, 0, ICE_PingReply);
598    IceFlush (iceConn);
599}
600
601
602
603static Bool
604ProcessError (
605	IceConn		 iceConn,
606	unsigned long	 length,
607	Bool		 swap,
608	IceReplyWaitInfo *replyWait
609)
610{
611    int		invokeHandler = 0;
612    Bool	errorReturned = False;
613    iceErrorMsg *message;
614    char 	*pData, *pStart;
615    char	severity;
616
617    CHECK_AT_LEAST_SIZE (iceConn, ICE_Error,
618	length, SIZEOF (iceErrorMsg),
619	(iceConn->connect_to_you || iceConn->connect_to_me) ?
620	IceFatalToConnection : IceFatalToProtocol);
621
622    IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
623	iceErrorMsg, message, pStart);
624
625    if (!IceValidIO (iceConn) || pStart == NULL)
626    {
627	IceDisposeCompleteMessage (iceConn, pStart);
628	return (0);
629    }
630
631    severity = message->severity;
632
633    if (severity != IceCanContinue && severity != IceFatalToProtocol &&
634	severity != IceFatalToConnection)
635    {
636	_IceErrorBadValue (iceConn, 0,
637	    ICE_Error, 9, 1, &severity);
638	IceDisposeCompleteMessage (iceConn, pStart);
639	return (0);
640    }
641
642    pData = pStart;
643
644    if (swap)
645    {
646	message->errorClass = lswaps (message->errorClass);
647	message->offendingSequenceNum = lswapl (message->offendingSequenceNum);
648    }
649
650    if (!replyWait ||
651	message->offendingSequenceNum != replyWait->sequence_of_request)
652    {
653	invokeHandler = 1;
654    }
655    else
656    {
657	if (iceConn->connect_to_you &&
658	    ((!iceConn->connect_to_you->auth_active &&
659            message->offendingMinorOpcode == ICE_ConnectionSetup) ||
660            (iceConn->connect_to_you->auth_active &&
661	    message->offendingMinorOpcode == ICE_AuthReply)))
662	{
663	    _IceConnectionError *errorReply =
664	        &(((_IceReply *) (replyWait->reply))->connection_error);
665	    char *errorStr = NULL;
666	    const char *tempstr, *prefix;
667	    char *temp;
668
669	    invokeHandler = 0;
670	    errorReturned = True;
671
672	    switch (message->errorClass)
673	    {
674	    case IceNoVersion:
675
676		tempstr =
677		    "None of the ICE versions specified are supported";
678		errorStr = strdup(tempstr);
679		break;
680
681	    case IceNoAuth:
682
683		tempstr =
684		    "None of the authentication protocols specified are supported";
685		errorStr = strdup(tempstr);
686		break;
687
688	    case IceSetupFailed:
689
690		prefix = "Connection Setup Failed, reason : ";
691
692		EXTRACT_STRING (pData, swap, temp);
693		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
694		    errorStr = NULL;
695		free (temp);
696		break;
697
698	    case IceAuthRejected:
699
700		prefix = "Authentication Rejected, reason : ";
701		EXTRACT_STRING (pData, swap, temp);
702		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
703		    errorStr = NULL;
704		free (temp);
705		break;
706
707	    case IceAuthFailed:
708
709		prefix = "Authentication Failed, reason : ";
710		EXTRACT_STRING (pData, swap, temp);
711		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
712		    errorStr = NULL;
713		free (temp);
714		break;
715
716	    default:
717		invokeHandler = 1;
718	    }
719
720			if (!errorStr)
721			{
722				errorStr = strdup("");
723			}
724
725	    errorReply->type = ICE_CONNECTION_ERROR;
726	    errorReply->error_message = errorStr;
727	}
728	else if (iceConn->protosetup_to_you &&
729	    ((!iceConn->protosetup_to_you->auth_active &&
730            message->offendingMinorOpcode == ICE_ProtocolSetup) ||
731            (iceConn->protosetup_to_you->auth_active &&
732	    message->offendingMinorOpcode == ICE_AuthReply)))
733	{
734	    _IceProtocolError *errorReply =
735	        &(((_IceReply *) (replyWait->reply))->protocol_error);
736	    char *errorStr = NULL;
737	    const char *prefix;
738	    char *temp;
739
740	    invokeHandler = 0;
741	    errorReturned = True;
742
743	    switch (message->errorClass)
744	    {
745	    case IceNoVersion:
746
747		errorStr = strdup(
748		    "None of the protocol versions specified are supported");
749		break;
750
751	    case IceNoAuth:
752
753		errorStr = strdup(
754		    "None of the authentication protocols specified are supported");
755
756		break;
757
758	    case IceSetupFailed:
759
760		prefix = "Protocol Setup Failed, reason : ";
761
762		EXTRACT_STRING (pData, swap, temp);
763		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
764		    errorStr = NULL;
765		free (temp);
766		break;
767
768	    case IceAuthRejected:
769
770		prefix = "Authentication Rejected, reason : ";
771		EXTRACT_STRING (pData, swap, temp);
772		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
773		    errorStr = NULL;
774		free (temp);
775		break;
776
777	    case IceAuthFailed:
778
779		prefix = "Authentication Failed, reason : ";
780		EXTRACT_STRING (pData, swap, temp);
781		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
782		    errorStr = NULL;
783		free (temp);
784		break;
785
786	    case IceProtocolDuplicate:
787
788		prefix = "Protocol was already registered : ";
789		EXTRACT_STRING (pData, swap, temp);
790		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
791		    errorStr = NULL;
792		free (temp);
793		break;
794
795	    case IceMajorOpcodeDuplicate:
796
797		prefix = "The major opcode was already used : ";
798		if (asprintf (&errorStr, "%s%d", prefix, (int) *pData) == -1)
799		    errorStr = NULL;
800		break;
801
802	    case IceUnknownProtocol:
803
804		prefix = "Unknown Protocol : ";
805		EXTRACT_STRING (pData, swap, temp);
806		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
807		    errorStr = NULL;
808		free (temp);
809		break;
810
811	    default:
812		invokeHandler = 1;
813	    }
814
815			if (!errorStr)
816			{
817				errorStr = strdup("");
818			}
819
820	    errorReply->type = ICE_PROTOCOL_ERROR;
821	    errorReply->error_message = errorStr;
822	}
823
824	if (errorReturned == True)
825	{
826	    /*
827	     * If we tried to authenticate, tell the authentication
828	     * procedure to clean up.
829	     */
830
831	    IcePoAuthProc authProc;
832
833	    if (iceConn->connect_to_you &&
834		iceConn->connect_to_you->auth_active)
835	    {
836		authProc = _IcePoAuthProcs[(int)
837		    (iceConn->connect_to_you->my_auth_index)];
838
839		(*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
840		    True /* clean up */, False /* swap */,
841		    0, NULL, NULL, NULL, NULL);
842	    }
843	    else if (iceConn->protosetup_to_you &&
844		iceConn->protosetup_to_you->auth_active)
845	    {
846		_IcePoProtocol *protocol = _IceProtocols[
847		    iceConn->protosetup_to_you->my_opcode - 1].orig_client;
848
849		authProc = protocol->auth_procs[(int)(iceConn->
850		    protosetup_to_you->my_auth_index)];
851
852		(*authProc) (iceConn,
853		    &iceConn->protosetup_to_you->my_auth_state,
854		    True /* clean up */, False /* swap */,
855		    0, NULL, NULL, NULL, NULL);
856	    }
857	}
858    }
859
860    if (invokeHandler)
861    {
862	(*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode,
863	    message->offendingSequenceNum, message->errorClass,
864	    message->severity, (IcePointer) pData);
865    }
866
867    IceDisposeCompleteMessage (iceConn, pStart);
868
869    return (errorReturned);
870}
871
872
873
874static int
875ProcessConnectionSetup (
876	IceConn		iceConn,
877	unsigned long	length,
878	Bool		swap
879)
880{
881    iceConnectionSetupMsg *message;
882    const int myVersionCount = _IceVersionCount;
883    int  hisVersionCount;
884    int	 myVersionIndex, hisVersionIndex;
885    int  hisMajorVersion, hisMinorVersion;
886    int	 myAuthCount, hisAuthCount;
887    int	 found, i, j;
888    char **hisAuthNames = NULL;
889    char *pData, *pStart, *pEnd;
890    char *vendor = NULL;
891    char *release = NULL;
892    int myAuthIndex = 0;
893    int hisAuthIndex = 0;
894    int accept_setup_now = 0;
895    char mustAuthenticate;
896    int	authUsableCount;
897    int	authUsableFlags[MAX_ICE_AUTH_NAMES];
898    int	authIndices[MAX_ICE_AUTH_NAMES];
899
900    CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup,
901	length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection);
902
903    IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg),
904	iceConnectionSetupMsg, message, pStart);
905
906    if (!IceValidIO (iceConn) || pStart == NULL)
907    {
908	IceDisposeCompleteMessage (iceConn, pStart);
909	return (0);
910    }
911
912    pData = pStart;
913    pEnd = pStart + (length << 3);
914
915    SKIP_STRING (pData, swap, pEnd,
916		 BAIL_STRING(iceConn, ICE_ConnectionSetup,
917			     pStart));			       /* vendor */
918    SKIP_STRING (pData, swap, pEnd,
919		 BAIL_STRING(iceConn, ICE_ConnectionSetup,
920			    pStart));	        	       /* release */
921    SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
922			BAIL_STRING(iceConn, ICE_ConnectionSetup,
923				   pStart));		       /* auth names */
924
925    pData += (message->versionCount * 4);		       /* versions */
926
927    CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup,
928	length, pData - pStart + SIZEOF (iceConnectionSetupMsg),
929	pStart, IceFatalToConnection);
930
931    mustAuthenticate = message->mustAuthenticate;
932    if (mustAuthenticate != 0 && mustAuthenticate != 1)
933    {
934	_IceErrorBadValue (iceConn, 0,
935	    ICE_ConnectionSetup, 8, 1, &mustAuthenticate);
936	iceConn->connection_status = IceConnectRejected;
937	IceDisposeCompleteMessage (iceConn, pStart);
938	return (0);
939    }
940
941    pData = pStart;
942
943    EXTRACT_STRING (pData, swap, vendor);
944    EXTRACT_STRING (pData, swap, release);
945
946    hisAuthCount = message->authCount;
947    if (hisAuthCount > 0)
948    {
949	hisAuthNames = malloc (hisAuthCount * sizeof (char *));
950	if (hisAuthNames != NULL)
951	{
952	    EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
953	}
954	else
955	{
956	    SKIP_LISTOF_STRING (pData, swap, hisAuthCount, pEnd, break);
957	    hisAuthCount = 0;
958	}
959    }
960
961    hisVersionCount = message->versionCount;
962
963    hisVersionIndex = myVersionIndex = found = 0;
964
965    for (i = 0; i < hisVersionCount && !found; i++)
966    {
967	EXTRACT_CARD16 (pData, swap, hisMajorVersion);
968	EXTRACT_CARD16 (pData, swap, hisMinorVersion);
969
970	for (j = 0; j < myVersionCount && !found; j++)
971	{
972	    if (_IceVersions[j].major_version == hisMajorVersion &&
973		_IceVersions[j].minor_version == hisMinorVersion)
974	    {
975		hisVersionIndex = i;
976		myVersionIndex = j;
977		found = 1;
978	    }
979	}
980    }
981
982    if (!found)
983    {
984	_IceErrorNoVersion (iceConn, ICE_ConnectionSetup);
985	iceConn->connection_status = IceConnectRejected;
986
987	free (vendor);
988	free (release);
989
990	if (hisAuthCount > 0)
991	{
992	    for (i = 0; i < hisAuthCount; i++)
993		free (hisAuthNames[i]);
994
995	    free (hisAuthNames);
996	}
997
998	IceDisposeCompleteMessage (iceConn, pStart);
999	return (0);
1000    }
1001
1002    _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string,
1003	_IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
1004
1005    for (i = 0; i < _IceAuthCount; i++)
1006    {
1007	authUsableFlags[i] = 0;
1008	for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
1009	    authUsableFlags[i] = (authIndices[j] == i);
1010    }
1011
1012    myAuthCount = _IceAuthCount;
1013
1014    for (i = found = 0; i < myAuthCount && !found; i++)
1015    {
1016	if (authUsableFlags[i])
1017	{
1018	    const char *myAuthName = _IceAuthNames[i];
1019
1020	    for (j = 0; j < hisAuthCount && !found; j++)
1021		if (strcmp (myAuthName, hisAuthNames[j]) == 0)
1022		{
1023		    myAuthIndex = i;
1024		    hisAuthIndex = j;
1025		    found = 1;
1026		}
1027	}
1028    }
1029
1030    if (!found)
1031    {
1032	/*
1033	 * None of the authentication methods specified by the
1034	 * other client is supported.  If the other client requires
1035	 * authentication, we must reject the connection now.
1036	 * Otherwise, we can invoke the host-based authentication callback
1037	 * to see if we can accept this connection.
1038	 */
1039
1040	if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc)
1041	{
1042	    _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup);
1043	    iceConn->connection_status = IceConnectRejected;
1044	}
1045	else
1046	{
1047	    char *hostname = _IceGetPeerName (iceConn);
1048
1049	    if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1050	    {
1051		accept_setup_now = 1;
1052	    }
1053	    else
1054	    {
1055		_IceErrorAuthenticationRejected (iceConn,
1056	            ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
1057
1058		iceConn->connection_status = IceConnectRejected;
1059	    }
1060
1061	    free (hostname);
1062	}
1063
1064	if (iceConn->connection_status == IceConnectRejected)
1065	{
1066	    free (vendor);
1067	    free (release);
1068	}
1069    }
1070    else
1071    {
1072	IcePaAuthStatus	status;
1073	int		authDataLen;
1074	IcePointer	authData = NULL;
1075	IcePointer	authState;
1076	char		*errorString = NULL;
1077	IcePaAuthProc	authProc = _IcePaAuthProcs[myAuthIndex];
1078
1079	authState = NULL;
1080
1081	status = (*authProc) (iceConn, &authState,
1082	    swap, 0, NULL, &authDataLen, &authData, &errorString);
1083
1084	if (status == IcePaAuthContinue)
1085	{
1086	    _IceConnectToMeInfo *setupInfo;
1087
1088	    AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
1089
1090	    iceConn->connect_to_me = setupInfo =
1091		malloc (sizeof (_IceConnectToMeInfo));
1092
1093	    setupInfo->my_version_index = myVersionIndex;
1094	    setupInfo->his_version_index = hisVersionIndex;
1095	    setupInfo->his_vendor = vendor;
1096	    setupInfo->his_release = release;
1097	    setupInfo->my_auth_index = myAuthIndex;
1098	    setupInfo->my_auth_state = authState;
1099	    setupInfo->must_authenticate = mustAuthenticate;
1100	}
1101	else if (status == IcePaAuthAccepted)
1102	{
1103	    accept_setup_now = 1;
1104	}
1105	else
1106	{
1107	    free (vendor);
1108	    free (release);
1109	}
1110
1111	if (authData && authDataLen > 0)
1112	    free (authData);
1113
1114	free (errorString);
1115    }
1116
1117    if (accept_setup_now)
1118    {
1119	AcceptConnection (iceConn, hisVersionIndex);
1120
1121	iceConn->vendor = vendor;
1122	iceConn->release = release;
1123	iceConn->my_ice_version_index = myVersionIndex;
1124    }
1125
1126    if (hisAuthCount > 0)
1127    {
1128	for (i = 0; i < hisAuthCount; i++)
1129	    free (hisAuthNames[i]);
1130
1131	free (hisAuthNames);
1132    }
1133
1134    IceDisposeCompleteMessage (iceConn, pStart);
1135    return (0);
1136}
1137
1138
1139
1140static Bool
1141ProcessAuthRequired (
1142	IceConn			iceConn,
1143	unsigned long	 	length,
1144	Bool			swap,
1145	IceReplyWaitInfo	*replyWait
1146)
1147{
1148    iceAuthRequiredMsg  *message;
1149    int			authDataLen;
1150    IcePointer 		authData;
1151    int 		replyDataLen;
1152    IcePointer 		replyData = NULL;
1153    char		*errorString = NULL;
1154    IcePoAuthProc	authProc;
1155    IcePoAuthStatus	status;
1156    IcePointer 		authState;
1157    int			realAuthIndex = 0;
1158
1159    CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired,
1160	length, SIZEOF (iceAuthRequiredMsg),
1161	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1162
1163    IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg),
1164	iceAuthRequiredMsg, message, authData);
1165
1166    if (!IceValidIO (iceConn) || authData == NULL)
1167    {
1168	IceDisposeCompleteMessage (iceConn, authData);
1169	return (0);
1170    }
1171
1172    if (swap)
1173    {
1174	message->authDataLength = lswaps (message->authDataLength);
1175    }
1176
1177    CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length,
1178	message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData,
1179	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1180
1181    if (iceConn->connect_to_you)
1182    {
1183	if ((int) message->authIndex >= _IceAuthCount)
1184	{
1185	    _IceConnectionError *errorReply =
1186	        &(((_IceReply *) (replyWait->reply))->connection_error);
1187
1188	    const char *tempstr
1189		= "Received bad authIndex in the AuthRequired message";
1190	    char errIndex = (int) message->authIndex;
1191
1192	    errorString = strdup(tempstr);
1193
1194	    errorReply->type = ICE_CONNECTION_ERROR;
1195	    errorReply->error_message = errorString;
1196
1197	    _IceErrorBadValue (iceConn, 0,
1198		ICE_AuthRequired, 2, 1, &errIndex);
1199
1200	    IceDisposeCompleteMessage (iceConn, authData);
1201	    return (1);
1202	}
1203	else
1204	{
1205	    authProc = _IcePoAuthProcs[message->authIndex];
1206
1207	    iceConn->connect_to_you->auth_active = 1;
1208	}
1209    }
1210    else if (iceConn->protosetup_to_you)
1211    {
1212	if ((int) message->authIndex >=
1213	    iceConn->protosetup_to_you->my_auth_count)
1214	{
1215	    _IceProtocolError *errorReply =
1216	        &(((_IceReply *) (replyWait->reply))->protocol_error);
1217
1218	    const char *tempstr
1219		= "Received bad authIndex in the AuthRequired message";
1220	    char errIndex = (int) message->authIndex;
1221
1222	    errorString = strdup(tempstr);
1223
1224	    errorReply->type = ICE_PROTOCOL_ERROR;
1225	    errorReply->error_message = errorString;
1226
1227	    _IceErrorBadValue (iceConn, 0,
1228		ICE_AuthRequired, 2, 1, &errIndex);
1229
1230	    IceDisposeCompleteMessage (iceConn, authData);
1231	    return (1);
1232	}
1233	else
1234	{
1235	    _IcePoProtocol *myProtocol = _IceProtocols[
1236	        iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1237
1238	    realAuthIndex = iceConn->protosetup_to_you->
1239		my_auth_indices[message->authIndex];
1240
1241	    authProc = myProtocol->auth_procs[realAuthIndex];
1242
1243	    iceConn->protosetup_to_you->auth_active = 1;
1244	}
1245    }
1246    else
1247    {
1248	/*
1249	 * Unexpected message
1250	 */
1251
1252	_IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue);
1253
1254	IceDisposeCompleteMessage (iceConn, authData);
1255	return (0);
1256    }
1257
1258    authState = NULL;
1259    authDataLen = message->authDataLength;
1260
1261    status = (*authProc) (iceConn, &authState, False /* don't clean up */,
1262	swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1263
1264    if (status == IcePoAuthHaveReply)
1265    {
1266	AuthReply (iceConn, replyDataLen, replyData);
1267
1268	replyWait->sequence_of_request = iceConn->send_sequence;
1269	replyWait->minor_opcode_of_request = ICE_AuthReply;
1270
1271	if (iceConn->connect_to_you)
1272	{
1273	    iceConn->connect_to_you->my_auth_state = authState;
1274	    iceConn->connect_to_you->my_auth_index = message->authIndex;
1275	}
1276	else if (iceConn->protosetup_to_you)
1277	{
1278	    iceConn->protosetup_to_you->my_auth_state = authState;
1279	    iceConn->protosetup_to_you->my_auth_index = realAuthIndex;
1280	}
1281    }
1282    else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1283    {
1284	const char *prefix;
1285	char *returnErrorString;
1286
1287	if (status == IcePoAuthRejected)
1288	{
1289	    _IceErrorAuthenticationRejected (iceConn,
1290	        ICE_AuthRequired, errorString);
1291
1292	    prefix = "Authentication Rejected, reason : ";
1293	}
1294	else
1295	{
1296	    _IceErrorAuthenticationFailed (iceConn,
1297	       ICE_AuthRequired, errorString);
1298
1299	    prefix = "Authentication Failed, reason : ";
1300	}
1301
1302	if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1303	    returnErrorString = strdup("");
1304	free (errorString);
1305
1306	if (iceConn->connect_to_you)
1307	{
1308	    _IceConnectionError *errorReply =
1309	        &(((_IceReply *) (replyWait->reply))->connection_error);
1310
1311	    errorReply->type = ICE_CONNECTION_ERROR;
1312	    errorReply->error_message = returnErrorString;
1313	}
1314	else
1315	{
1316	    _IceProtocolError *errorReply =
1317	        &(((_IceReply *) (replyWait->reply))->protocol_error);
1318
1319	    errorReply->type = ICE_PROTOCOL_ERROR;
1320	    errorReply->error_message = returnErrorString;
1321	}
1322    }
1323
1324    if (replyData && replyDataLen > 0)
1325	free (replyData);
1326
1327    IceDisposeCompleteMessage (iceConn, authData);
1328
1329    return (status != IcePoAuthHaveReply);
1330}
1331
1332
1333
1334static int
1335ProcessAuthReply (
1336	IceConn		iceConn,
1337	unsigned long	length,
1338	Bool		swap
1339)
1340{
1341    iceAuthReplyMsg 	*message;
1342    int			replyDataLen;
1343    IcePointer		replyData;
1344    int 		authDataLen = 0;
1345    IcePointer 		authData = NULL;
1346    char		*errorString = NULL;
1347
1348    CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply,
1349	length, SIZEOF (iceAuthReplyMsg),
1350	iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1351
1352    IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg),
1353	iceAuthReplyMsg, message, replyData);
1354
1355    if (!IceValidIO (iceConn) || replyData == NULL)
1356    {
1357	IceDisposeCompleteMessage (iceConn, replyData);
1358	return (0);
1359    }
1360
1361    if (swap)
1362    {
1363	message->authDataLength = lswaps (message->authDataLength);
1364    }
1365
1366    CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length,
1367	message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData,
1368	iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1369
1370    replyDataLen = message->authDataLength;
1371
1372    if (iceConn->connect_to_me)
1373    {
1374	IcePaAuthProc authProc = _IcePaAuthProcs[(int)
1375	    (iceConn->connect_to_me->my_auth_index)];
1376	IcePaAuthStatus status =
1377	    (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap,
1378	    replyDataLen, replyData, &authDataLen, &authData, &errorString);
1379
1380	if (status == IcePaAuthContinue)
1381	{
1382	    AuthNextPhase (iceConn, authDataLen, authData);
1383	}
1384	else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1385	{
1386	    /*
1387	     * Before we reject, invoke host-based authentication callback
1388	     * and give it a chance to accept the connection (only if the
1389	     * other client doesn't require authentication).
1390	     */
1391
1392	    if (!iceConn->connect_to_me->must_authenticate &&
1393		iceConn->listen_obj->host_based_auth_proc)
1394	    {
1395		char *hostname = _IceGetPeerName (iceConn);
1396
1397		if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1398		{
1399		    status = IcePaAuthAccepted;
1400		}
1401
1402		free (hostname);
1403	    }
1404
1405	    if (status != IcePaAuthAccepted)
1406	    {
1407		free (iceConn->connect_to_me->his_vendor);
1408		free (iceConn->connect_to_me->his_release);
1409		free (iceConn->connect_to_me);
1410		iceConn->connect_to_me = NULL;
1411
1412		iceConn->connection_status = IceConnectRejected;
1413
1414		if (status == IcePaAuthRejected)
1415		{
1416		    _IceErrorAuthenticationRejected (iceConn,
1417	                ICE_AuthReply, errorString);
1418		}
1419		else
1420		{
1421		    _IceErrorAuthenticationFailed (iceConn,
1422	                ICE_AuthReply, errorString);
1423		}
1424	    }
1425	}
1426
1427	if (status == IcePaAuthAccepted)
1428	{
1429	    AcceptConnection (iceConn,
1430		iceConn->connect_to_me->his_version_index);
1431
1432	    iceConn->vendor = iceConn->connect_to_me->his_vendor;
1433	    iceConn->release = iceConn->connect_to_me->his_release;
1434	    iceConn->my_ice_version_index =
1435		iceConn->connect_to_me->my_version_index;
1436
1437	    free (iceConn->connect_to_me);
1438	    iceConn->connect_to_me = NULL;
1439	}
1440    }
1441    else if (iceConn->protosetup_to_me)
1442    {
1443	_IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me->
1444	    my_opcode - 1].accept_client;
1445	IcePaAuthProc authProc = myProtocol->auth_procs[(int)
1446	    (iceConn->protosetup_to_me->my_auth_index)];
1447	IcePaAuthStatus status =
1448	    (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state,
1449	    swap, replyDataLen, replyData,
1450	    &authDataLen, &authData, &errorString);
1451	int free_setup_info = 1;
1452
1453	if (status == IcePaAuthContinue)
1454	{
1455	    AuthNextPhase (iceConn, authDataLen, authData);
1456	    free_setup_info = 0;
1457	}
1458	else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1459	{
1460	    /*
1461	     * Before we reject, invoke host-based authentication callback
1462	     * and give it a chance to accept the Protocol Setup (only if the
1463	     * other client doesn't require authentication).
1464	     */
1465
1466	    if (!iceConn->protosetup_to_me->must_authenticate &&
1467		myProtocol->host_based_auth_proc)
1468	    {
1469		char *hostname = _IceGetPeerName (iceConn);
1470
1471		if ((*myProtocol->host_based_auth_proc) (hostname))
1472		{
1473		    status = IcePaAuthAccepted;
1474		}
1475
1476		free (hostname);
1477	    }
1478
1479	    if (status == IcePaAuthRejected)
1480	    {
1481		_IceErrorAuthenticationRejected (iceConn,
1482	            ICE_AuthReply, errorString);
1483	    }
1484	    else
1485	    {
1486	        _IceErrorAuthenticationFailed (iceConn,
1487	            ICE_AuthReply, errorString);
1488	    }
1489	}
1490
1491	if (status == IcePaAuthAccepted)
1492	{
1493	    IcePaProcessMsgProc	processMsgProc;
1494	    IceProtocolSetupProc protocolSetupProc;
1495	    IceProtocolActivateProc protocolActivateProc;
1496	    _IceProcessMsgInfo *process_msg_info;
1497	    IcePointer clientData = NULL;
1498	    char *failureReason = NULL;
1499	    Status setupStatus = 1;
1500
1501	    protocolSetupProc = myProtocol->protocol_setup_proc;
1502	    protocolActivateProc = myProtocol->protocol_activate_proc;
1503
1504	    if (protocolSetupProc)
1505	    {
1506		/*
1507		 * Notify the client of the Protocol Setup.
1508		 */
1509
1510		setupStatus = (*protocolSetupProc) (iceConn,
1511		    myProtocol->version_recs[iceConn->protosetup_to_me->
1512		        my_version_index].major_version,
1513		    myProtocol->version_recs[iceConn->protosetup_to_me->
1514		        my_version_index].minor_version,
1515		    iceConn->protosetup_to_me->his_vendor,
1516		    iceConn->protosetup_to_me->his_release,
1517		    &clientData, &failureReason);
1518
1519		/*
1520		 * Set vendor and release pointers to NULL, so it won't
1521		 * get freed below.  The ProtocolSetupProc should
1522		 * free it.
1523		 */
1524
1525		iceConn->protosetup_to_me->his_vendor = NULL;
1526		iceConn->protosetup_to_me->his_release = NULL;
1527	    }
1528
1529	    if (setupStatus != 0)
1530	    {
1531		/*
1532		 * Send the Protocol Reply
1533		 */
1534
1535		AcceptProtocol (iceConn,
1536	            iceConn->protosetup_to_me->his_opcode,
1537	            iceConn->protosetup_to_me->my_opcode,
1538	            iceConn->protosetup_to_me->his_version_index,
1539		    myProtocol->vendor, myProtocol->release);
1540
1541
1542		/*
1543		 * Set info for this protocol.
1544		 */
1545
1546		processMsgProc = myProtocol->version_recs[
1547	            iceConn->protosetup_to_me->
1548	            my_version_index].process_msg_proc;
1549
1550		process_msg_info = &iceConn->process_msg_info[
1551	            iceConn->protosetup_to_me->
1552		    his_opcode -iceConn->his_min_opcode];
1553
1554		process_msg_info->client_data = clientData;
1555		process_msg_info->accept_flag = 1;
1556		process_msg_info->process_msg_proc.
1557		    accept_client = processMsgProc;
1558
1559
1560		/*
1561		 * Increase the reference count for the number
1562		 * of active protocols.
1563		 */
1564
1565		iceConn->proto_ref_count++;
1566
1567
1568		/*
1569		 * Notify the client that the protocol is active.  The reason
1570		 * we have this 2nd callback invoked is because the client
1571		 * may wish to immediately generate a message for this
1572		 * protocol, but it must wait until we send the Protocol Reply.
1573		 */
1574
1575		if (protocolActivateProc)
1576		{
1577		    (*protocolActivateProc) (iceConn,
1578		        process_msg_info->client_data);
1579		}
1580	    }
1581	    else
1582	    {
1583		/*
1584		 * An error was encountered.
1585		 */
1586
1587		_IceErrorSetupFailed (iceConn, ICE_ProtocolSetup,
1588		    failureReason);
1589
1590		free (failureReason);
1591	    }
1592	}
1593
1594
1595	if (free_setup_info)
1596	{
1597	    free (iceConn->protosetup_to_me->his_vendor);
1598	    free (iceConn->protosetup_to_me->his_release);
1599	    free (iceConn->protosetup_to_me);
1600	    iceConn->protosetup_to_me = NULL;
1601	}
1602    }
1603    else
1604    {
1605	/*
1606	 * Unexpected message
1607	 */
1608
1609	_IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue);
1610    }
1611
1612    if (authData && authDataLen > 0)
1613	free (authData);
1614
1615
1616    free (errorString);
1617
1618    IceDisposeCompleteMessage (iceConn, replyData);
1619    return (0);
1620}
1621
1622
1623
1624static Bool
1625ProcessAuthNextPhase (
1626	IceConn		  	iceConn,
1627	unsigned long	 	length,
1628	Bool			swap,
1629	IceReplyWaitInfo	*replyWait
1630)
1631{
1632    iceAuthNextPhaseMsg *message;
1633    int 		authDataLen;
1634    IcePointer		authData;
1635    int 		replyDataLen;
1636    IcePointer		replyData = NULL;
1637    char		*errorString = NULL;
1638    IcePoAuthProc 	authProc;
1639    IcePoAuthStatus	status;
1640    IcePointer 		*authState;
1641
1642    CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase,
1643	length, SIZEOF (iceAuthNextPhaseMsg),
1644	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1645
1646    IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg),
1647	iceAuthNextPhaseMsg, message, authData);
1648
1649    if (!IceValidIO (iceConn) || authData == NULL)
1650    {
1651	IceDisposeCompleteMessage (iceConn, authData);
1652	return (0);
1653    }
1654
1655    if (swap)
1656    {
1657	message->authDataLength = lswaps (message->authDataLength);
1658    }
1659
1660    CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length,
1661	message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData,
1662	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1663
1664    if (iceConn->connect_to_you)
1665    {
1666	authProc = _IcePoAuthProcs[(int)
1667	    (iceConn->connect_to_you->my_auth_index)];
1668
1669	authState = &iceConn->connect_to_you->my_auth_state;
1670    }
1671    else if (iceConn->protosetup_to_you)
1672    {
1673	_IcePoProtocol *myProtocol =
1674	  _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1675
1676	authProc = myProtocol->auth_procs[(int)
1677	    (iceConn->protosetup_to_you->my_auth_index)];
1678
1679	authState = &iceConn->protosetup_to_you->my_auth_state;
1680    }
1681    else
1682    {
1683	/*
1684	 * Unexpected message
1685	 */
1686
1687	_IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue);
1688
1689	IceDisposeCompleteMessage (iceConn, authData);
1690	return (0);
1691    }
1692
1693    authDataLen = message->authDataLength;
1694
1695    status = (*authProc) (iceConn, authState, False /* don't clean up */,
1696	swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1697
1698    if (status == IcePoAuthHaveReply)
1699    {
1700	AuthReply (iceConn, replyDataLen, replyData);
1701
1702	replyWait->sequence_of_request = iceConn->send_sequence;
1703    }
1704    else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1705    {
1706	const char *prefix = NULL;
1707	char *returnErrorString;
1708
1709	if (status == IcePoAuthRejected)
1710	{
1711	    _IceErrorAuthenticationRejected (iceConn,
1712	       ICE_AuthNextPhase, errorString);
1713
1714	    prefix = "Authentication Rejected, reason : ";
1715	}
1716	else if (status == IcePoAuthFailed)
1717	{
1718	    _IceErrorAuthenticationFailed (iceConn,
1719	       ICE_AuthNextPhase, errorString);
1720
1721	    prefix = "Authentication Failed, reason : ";
1722	}
1723
1724	if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1725	    returnErrorString = strdup("");
1726	free (errorString);
1727
1728	if (iceConn->connect_to_you)
1729	{
1730	    _IceConnectionError *errorReply =
1731	        &(((_IceReply *) (replyWait->reply))->connection_error);
1732
1733	    errorReply->type = ICE_CONNECTION_ERROR;
1734	    errorReply->error_message = returnErrorString;
1735	}
1736	else
1737	{
1738	    _IceProtocolError *errorReply =
1739	        &(((_IceReply *) (replyWait->reply))->protocol_error);
1740
1741	    errorReply->type = ICE_PROTOCOL_ERROR;
1742	    errorReply->error_message = returnErrorString;
1743	}
1744    }
1745
1746    if (replyData && replyDataLen > 0)
1747	free (replyData);
1748
1749    IceDisposeCompleteMessage (iceConn, authData);
1750
1751    return (status != IcePoAuthHaveReply);
1752}
1753
1754
1755
1756static Bool
1757ProcessConnectionReply (
1758	IceConn			iceConn,
1759	unsigned long	 	length,
1760	Bool			swap,
1761	IceReplyWaitInfo 	*replyWait
1762)
1763{
1764    iceConnectionReplyMsg 	*message;
1765    char 			*pData, *pStart, *pEnd;
1766    Bool			replyReady;
1767
1768#if 0 /* No-op */
1769    CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply,
1770	length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection);
1771#endif
1772
1773    IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg),
1774	iceConnectionReplyMsg, message, pStart);
1775
1776    if (!IceValidIO (iceConn) || pStart == NULL)
1777    {
1778	IceDisposeCompleteMessage (iceConn, pStart);
1779	return (0);
1780    }
1781
1782    pData = pStart;
1783    pEnd = pStart + (length << 3);
1784
1785    SKIP_STRING (pData, swap, pEnd,
1786		 BAIL_STRING (iceConn, ICE_ConnectionReply,
1787			      pStart));		    	     /* vendor */
1788    SKIP_STRING (pData, swap, pEnd,
1789		 BAIL_STRING (iceConn, ICE_ConnectionReply,
1790			      pStart));			     /* release */
1791
1792    CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply,
1793	length, pData - pStart + SIZEOF (iceConnectionReplyMsg),
1794	pStart, IceFatalToConnection);
1795
1796    pData = pStart;
1797
1798    if (iceConn->connect_to_you)
1799    {
1800	if (iceConn->connect_to_you->auth_active)
1801	{
1802	    /*
1803	     * Tell the authentication procedure to clean up.
1804	     */
1805
1806	    IcePoAuthProc authProc = _IcePoAuthProcs[(int)
1807		(iceConn->connect_to_you->my_auth_index)];
1808
1809	    (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
1810		True /* clean up */, False /* swap */,
1811	        0, NULL, NULL, NULL, NULL);
1812	}
1813
1814	if ((int) message->versionIndex >= _IceVersionCount)
1815	{
1816	    _IceConnectionError *errorReply =
1817	        &(((_IceReply *) (replyWait->reply))->connection_error);
1818	    char errIndex = message->versionIndex;
1819
1820	    _IceErrorBadValue (iceConn, 0,
1821		ICE_ConnectionReply, 2, 1, &errIndex);
1822
1823	    errorReply->type = ICE_CONNECTION_ERROR;
1824	    errorReply->error_message =
1825		strdup("Received bad version index in Connection Reply");
1826	}
1827	else
1828	{
1829	    _IceReply *reply = (_IceReply *) (replyWait->reply);
1830
1831	    reply->type = ICE_CONNECTION_REPLY;
1832	    reply->connection_reply.version_index = message->versionIndex;
1833
1834	    EXTRACT_STRING (pData, swap, reply->connection_reply.vendor);
1835	    EXTRACT_STRING (pData, swap, reply->connection_reply.release);
1836	}
1837
1838	replyReady = True;
1839    }
1840    else
1841    {
1842	/*
1843	 * Unexpected message
1844	 */
1845
1846	_IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue);
1847
1848	replyReady = False;
1849    }
1850
1851    IceDisposeCompleteMessage (iceConn, pStart);
1852
1853    return (replyReady);
1854}
1855
1856
1857
1858static int
1859ProcessProtocolSetup (
1860	IceConn		iceConn,
1861	unsigned long	length,
1862	Bool		swap
1863)
1864{
1865    iceProtocolSetupMsg	*message;
1866    _IcePaProtocol 	*myProtocol;
1867    int  	      	myVersionCount, hisVersionCount;
1868    int	 	      	myVersionIndex, hisVersionIndex;
1869    int  	      	hisMajorVersion, hisMinorVersion;
1870    int	 	      	myAuthCount, hisAuthCount;
1871    int  	      	myOpcode, hisOpcode;
1872    int	 	      	found, i, j;
1873    char	      	**hisAuthNames = NULL;
1874    char 	      	*protocolName;
1875    char 		*pData, *pStart, *pEnd;
1876    char 	      	*vendor = NULL;
1877    char 	      	*release = NULL;
1878    int  	      	accept_setup_now = 0;
1879    int			myAuthIndex = 0;
1880    int			hisAuthIndex = 0;
1881    char		mustAuthenticate;
1882    int			authUsableCount;
1883    int			authUsableFlags[MAX_ICE_AUTH_NAMES];
1884    int			authIndices[MAX_ICE_AUTH_NAMES];
1885
1886    CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,
1887	length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);
1888
1889    if (iceConn->want_to_close)
1890    {
1891	/*
1892	 * If we sent a WantToClose message, but just got a ProtocolSetup,
1893	 * we must cancel our WantToClose.  It is the responsibility of the
1894	 * other client to send a WantToClose later on.
1895	 */
1896
1897	iceConn->want_to_close = 0;
1898    }
1899
1900    IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),
1901	iceProtocolSetupMsg, message, pStart);
1902
1903    if (!IceValidIO (iceConn) || pStart == NULL)
1904    {
1905	IceDisposeCompleteMessage (iceConn, pStart);
1906	return (0);
1907    }
1908
1909    pData = pStart;
1910    pEnd = pStart + (length << 3);
1911
1912    SKIP_STRING (pData, swap, pEnd,
1913		 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1914			     pStart));			       /* proto name */
1915    SKIP_STRING (pData, swap, pEnd,
1916		 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1917			     pStart));			       /* vendor */
1918    SKIP_STRING (pData, swap, pEnd,
1919		 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1920			     pStart));			       /* release */
1921    SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
1922			BAIL_STRING(iceConn, ICE_ProtocolSetup,
1923				    pStart));		       /* auth names */
1924    pData += (message->versionCount * 4);		       /* versions */
1925
1926    CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,
1927	length, pData - pStart + SIZEOF (iceProtocolSetupMsg),
1928	pStart, IceFatalToProtocol);
1929
1930    mustAuthenticate = message->mustAuthenticate;
1931
1932    if (mustAuthenticate != 0 && mustAuthenticate != 1)
1933    {
1934	_IceErrorBadValue (iceConn, 0,
1935	    ICE_ProtocolSetup, 4, 1, &mustAuthenticate);
1936	IceDisposeCompleteMessage (iceConn, pStart);
1937	return (0);
1938    }
1939
1940    pData = pStart;
1941
1942    if (iceConn->process_msg_info &&
1943	(int) message->protocolOpcode >= iceConn->his_min_opcode &&
1944        (int) message->protocolOpcode <= iceConn->his_max_opcode &&
1945	iceConn->process_msg_info[
1946	message->protocolOpcode - iceConn->his_min_opcode].in_use)
1947    {
1948	_IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);
1949	IceDisposeCompleteMessage (iceConn, pStart);
1950	return (0);
1951    }
1952
1953    EXTRACT_STRING (pData, swap, protocolName);
1954    if (protocolName == NULL)
1955    {
1956	_IceErrorSetupFailed (iceConn, message->protocolOpcode,
1957	    "protocolName allocation failed");
1958	IceDisposeCompleteMessage (iceConn, pStart);
1959	return (0);
1960    }
1961
1962    if (iceConn->process_msg_info)
1963    {
1964	for (i = 0;
1965	    i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)
1966	{
1967	    if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,
1968	        iceConn->process_msg_info[i].protocol->protocol_name) == 0)
1969	    {
1970		_IceErrorProtocolDuplicate (iceConn, protocolName);
1971		free (protocolName);
1972		IceDisposeCompleteMessage (iceConn, pStart);
1973		return (0);
1974	    }
1975	}
1976    }
1977
1978    for (i = 0; i < _IceLastMajorOpcode; i++)
1979	if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)
1980	    break;
1981
1982    if (i < _IceLastMajorOpcode &&
1983        (myProtocol = _IceProtocols[i].accept_client) != NULL)
1984    {
1985	hisOpcode = message->protocolOpcode;
1986	myOpcode = i + 1;
1987	free (protocolName);
1988    }
1989    else
1990    {
1991	_IceErrorUnknownProtocol (iceConn, protocolName);
1992	free (protocolName);
1993	IceDisposeCompleteMessage (iceConn, pStart);
1994	return (0);
1995    }
1996
1997    EXTRACT_STRING (pData, swap, vendor);
1998    EXTRACT_STRING (pData, swap, release);
1999
2000    hisAuthCount = message->authCount;
2001    if (hisAuthCount > 0)
2002    {
2003	hisAuthNames = malloc (hisAuthCount * sizeof (char *));
2004	EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
2005    }
2006
2007    hisVersionCount = message->versionCount;
2008    myVersionCount = myProtocol->version_count;
2009
2010    hisVersionIndex = myVersionIndex = found = 0;
2011
2012    for (i = 0; i < hisVersionCount && !found; i++)
2013    {
2014	EXTRACT_CARD16 (pData, swap, hisMajorVersion);
2015	EXTRACT_CARD16 (pData, swap, hisMinorVersion);
2016
2017	for (j = 0; j < myVersionCount && !found; j++)
2018	{
2019	    if (myProtocol->version_recs[j].major_version == hisMajorVersion &&
2020		myProtocol->version_recs[j].minor_version == hisMinorVersion)
2021	    {
2022		hisVersionIndex = i;
2023		myVersionIndex = j;
2024		found = 1;
2025	    }
2026	}
2027    }
2028
2029    if (!found)
2030    {
2031	_IceErrorNoVersion (iceConn, ICE_ProtocolSetup);
2032
2033	free (vendor);
2034	free (release);
2035
2036	if (hisAuthCount > 0)
2037	{
2038	    for (i = 0; i < hisAuthCount; i++)
2039		free (hisAuthNames[i]);
2040
2041	    free (hisAuthNames);
2042	}
2043
2044	IceDisposeCompleteMessage (iceConn, pStart);
2045	return (0);
2046    }
2047
2048    myAuthCount = myProtocol->auth_count;
2049
2050    _IceGetPaValidAuthIndices (
2051	_IceProtocols[myOpcode - 1].protocol_name,
2052	iceConn->connection_string, myAuthCount,
2053	(const char **) myProtocol->auth_names,
2054        &authUsableCount, authIndices);
2055
2056    for (i = 0; i < myAuthCount; i++)
2057    {
2058	authUsableFlags[i] = 0;
2059	for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
2060	    authUsableFlags[i] = (authIndices[j] == i);
2061    }
2062
2063    for (i = found = 0; i < myAuthCount && !found; i++)
2064    {
2065	if (authUsableFlags[i])
2066	{
2067	    const char *myAuthName = myProtocol->auth_names[i];
2068
2069	    for (j = 0; j < hisAuthCount && !found; j++)
2070		if (strcmp (myAuthName, hisAuthNames[j]) == 0)
2071		{
2072		    myAuthIndex = i;
2073		    hisAuthIndex = j;
2074		    found = 1;
2075		}
2076	}
2077    }
2078
2079    if (!found)
2080    {
2081	/*
2082	 * None of the authentication methods specified by the
2083	 * other client is supported.  If the other client requires
2084	 * authentication, we must reject the Protocol Setup now.
2085	 * Otherwise, we can invoke the host-based authentication callback
2086	 * to see if we can accept this Protocol Setup.
2087	 */
2088
2089	if (mustAuthenticate || !myProtocol->host_based_auth_proc)
2090	{
2091	    _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);
2092	}
2093	else
2094	{
2095	    char *hostname = _IceGetPeerName (iceConn);
2096
2097	    if ((*myProtocol->host_based_auth_proc) (hostname))
2098	    {
2099		accept_setup_now = 1;
2100	    }
2101	    else
2102	    {
2103		_IceErrorAuthenticationRejected (iceConn,
2104	            ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
2105	    }
2106
2107	    free (hostname);
2108	}
2109    }
2110    else
2111    {
2112	IcePaAuthStatus	status;
2113	int 		authDataLen;
2114	IcePointer 	authData = NULL;
2115	IcePointer 	authState;
2116	char		*errorString = NULL;
2117	IcePaAuthProc	authProc =
2118		myProtocol->auth_procs[myAuthIndex];
2119
2120	authState = NULL;
2121
2122	status = (*authProc) (iceConn, &authState, swap, 0, NULL,
2123	    &authDataLen, &authData, &errorString);
2124
2125	if (status == IcePaAuthContinue)
2126	{
2127	    _IceProtoSetupToMeInfo *setupInfo;
2128
2129	    AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
2130
2131	    iceConn->protosetup_to_me = setupInfo =
2132		malloc (sizeof (_IceProtoSetupToMeInfo));
2133
2134	    setupInfo->his_opcode = hisOpcode;
2135	    setupInfo->my_opcode = myOpcode;
2136	    setupInfo->my_version_index = myVersionIndex;
2137	    setupInfo->his_version_index = hisVersionIndex;
2138	    setupInfo->his_vendor = vendor;
2139	    setupInfo->his_release = release;
2140	    vendor = release = NULL;   /* so we don't free it */
2141	    setupInfo->my_auth_index = myAuthIndex;
2142	    setupInfo->my_auth_state = authState;
2143	    setupInfo->must_authenticate = mustAuthenticate;
2144	}
2145	else if (status == IcePaAuthAccepted)
2146	{
2147	    accept_setup_now = 1;
2148	}
2149
2150	if (authData && authDataLen > 0)
2151	    free (authData);
2152
2153
2154	free (errorString);
2155    }
2156
2157    if (accept_setup_now)
2158    {
2159	IcePaProcessMsgProc		processMsgProc;
2160	IceProtocolSetupProc		protocolSetupProc;
2161	IceProtocolActivateProc		protocolActivateProc;
2162	_IceProcessMsgInfo		*process_msg_info;
2163	IcePointer			clientData = NULL;
2164	char 				*failureReason = NULL;
2165	Status				status = 1;
2166
2167	protocolSetupProc = myProtocol->protocol_setup_proc;
2168	protocolActivateProc = myProtocol->protocol_activate_proc;
2169
2170	if (protocolSetupProc)
2171	{
2172	    /*
2173	     * Notify the client of the Protocol Setup.
2174	     */
2175
2176	    status = (*protocolSetupProc) (iceConn,
2177		myProtocol->version_recs[myVersionIndex].major_version,
2178		myProtocol->version_recs[myVersionIndex].minor_version,
2179	        vendor, release, &clientData, &failureReason);
2180
2181	    vendor = release = NULL;   /* so we don't free it */
2182	}
2183
2184	if (status != 0)
2185	{
2186	    /*
2187	     * Send the Protocol Reply
2188	     */
2189
2190	    AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,
2191	        myProtocol->vendor, myProtocol->release);
2192
2193
2194	    /*
2195	     * Set info for this protocol.
2196	     */
2197
2198	    processMsgProc = myProtocol->version_recs[
2199	        myVersionIndex].process_msg_proc;
2200
2201	    process_msg_info = &iceConn->process_msg_info[hisOpcode -
2202	        iceConn->his_min_opcode];
2203
2204	    process_msg_info->client_data = clientData;
2205	    process_msg_info->accept_flag = 1;
2206	    process_msg_info->process_msg_proc.accept_client = processMsgProc;
2207
2208
2209	    /*
2210	     * Increase the reference count for the number of active protocols.
2211	     */
2212
2213	    iceConn->proto_ref_count++;
2214
2215
2216	    /*
2217	     * Notify the client that the protocol is active.  The reason
2218	     * we have this 2nd callback invoked is because the client
2219	     * may wish to immediately generate a message for this
2220	     * protocol, but it must wait until we send the Protocol Reply.
2221	     */
2222
2223	    if (protocolActivateProc)
2224	    {
2225		(*protocolActivateProc) (iceConn,
2226		    process_msg_info->client_data);
2227	    }
2228	}
2229	else
2230	{
2231	    /*
2232	     * An error was encountered.
2233	     */
2234
2235	    _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);
2236
2237	    free (failureReason);
2238	}
2239    }
2240
2241
2242    free (vendor);
2243    free (release);
2244
2245    if (hisAuthCount > 0)
2246    {
2247	for (i = 0; i < hisAuthCount; i++)
2248	    free (hisAuthNames[i]);
2249
2250	free (hisAuthNames);
2251    }
2252
2253    IceDisposeCompleteMessage (iceConn, pStart);
2254    return (0);
2255}
2256
2257
2258
2259static Bool
2260ProcessProtocolReply (
2261	IceConn		  	iceConn,
2262	unsigned long	 	length,
2263	Bool			swap,
2264	IceReplyWaitInfo 	*replyWait
2265)
2266{
2267    iceProtocolReplyMsg *message;
2268    char		*pData, *pStart, *pEnd;
2269    Bool		replyReady;
2270
2271#if 0 /* No-op */
2272    CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply,
2273	length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol);
2274#endif
2275
2276    IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg),
2277	iceProtocolReplyMsg, message, pStart);
2278
2279    if (!IceValidIO (iceConn))
2280    {
2281	IceDisposeCompleteMessage (iceConn, pStart);
2282	return (0);
2283    }
2284
2285    pData = pStart;
2286    pEnd = pStart + (length << 3);
2287
2288    SKIP_STRING (pData, swap, pEnd,
2289		 BAIL_STRING(iceConn, ICE_ProtocolReply,
2290			     pStart));			     /* vendor */
2291    SKIP_STRING (pData, swap, pEnd,
2292		 BAIL_STRING(iceConn, ICE_ProtocolReply,
2293			     pStart));			     /* release */
2294
2295    CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply,
2296	length, pData - pStart + SIZEOF (iceProtocolReplyMsg),
2297	pStart, IceFatalToProtocol);
2298
2299    pData = pStart;
2300
2301    if (iceConn->protosetup_to_you)
2302    {
2303	if (iceConn->protosetup_to_you->auth_active)
2304	{
2305	    /*
2306	     * Tell the authentication procedure to clean up.
2307	     */
2308
2309	    _IcePoProtocol *myProtocol = _IceProtocols[
2310		iceConn->protosetup_to_you->my_opcode - 1].orig_client;
2311
2312	    IcePoAuthProc authProc = myProtocol->auth_procs[(int)
2313		(iceConn->protosetup_to_you->my_auth_index)];
2314
2315	    (*authProc) (iceConn,
2316		&iceConn->protosetup_to_you->my_auth_state,
2317		True /* clean up */, False /* swap */,
2318	        0, NULL, NULL, NULL, NULL);
2319	}
2320
2321	if ((int) message->versionIndex >= _IceVersionCount)
2322	{
2323	    _IceProtocolError *errorReply =
2324	        &(((_IceReply *) (replyWait->reply))->protocol_error);
2325	    char errIndex = message->versionIndex;
2326
2327	    _IceErrorBadValue (iceConn, 0,
2328		ICE_ProtocolReply, 2, 1, &errIndex);
2329
2330	    errorReply->type = ICE_PROTOCOL_ERROR;
2331	    errorReply->error_message =
2332		strdup("Received bad version index in Protocol Reply");
2333	}
2334	else
2335	{
2336	    _IceProtocolReply *reply =
2337	        &(((_IceReply *) (replyWait->reply))->protocol_reply);
2338
2339	    reply->type = ICE_PROTOCOL_REPLY;
2340	    reply->major_opcode = message->protocolOpcode;
2341	    reply->version_index = message->versionIndex;
2342
2343	    EXTRACT_STRING (pData, swap, reply->vendor);
2344	    EXTRACT_STRING (pData, swap, reply->release);
2345	}
2346
2347	replyReady = True;
2348    }
2349    else
2350    {
2351	_IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue);
2352
2353	replyReady = False;
2354    }
2355
2356    IceDisposeCompleteMessage (iceConn, pStart);
2357
2358    return (replyReady);
2359}
2360
2361
2362
2363static int
2364ProcessPing (
2365	IceConn 	iceConn,
2366	unsigned long	length
2367)
2368{
2369    CHECK_SIZE_MATCH (iceConn, ICE_Ping,
2370	length, SIZEOF (icePingMsg), IceFatalToConnection, 0);
2371
2372    PingReply (iceConn);
2373
2374    return (0);
2375}
2376
2377
2378
2379static int
2380ProcessPingReply (
2381	IceConn 	iceConn,
2382	unsigned long	length
2383)
2384{
2385    CHECK_SIZE_MATCH (iceConn, ICE_PingReply,
2386	length, SIZEOF (icePingReplyMsg), IceFatalToConnection, 0);
2387
2388    if (iceConn->ping_waits)
2389    {
2390	_IcePingWait *next = iceConn->ping_waits->next;
2391
2392	(*iceConn->ping_waits->ping_reply_proc) (iceConn,
2393	    iceConn->ping_waits->client_data);
2394
2395	free (iceConn->ping_waits);
2396	iceConn->ping_waits = next;
2397    }
2398    else
2399    {
2400	_IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue);
2401    }
2402
2403    return (0);
2404}
2405
2406
2407
2408static int
2409ProcessWantToClose (
2410	IceConn 	iceConn,
2411	unsigned long	length,
2412	Bool		*connectionClosedRet
2413)
2414{
2415    *connectionClosedRet = False;
2416
2417    CHECK_SIZE_MATCH (iceConn, ICE_WantToClose,
2418	length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection, 0);
2419
2420    if (iceConn->want_to_close || iceConn->open_ref_count == 0)
2421    {
2422	/*
2423	 * We just received a WantToClose.  Either we also sent a
2424	 * WantToClose, so we close the connection, or the iceConn
2425	 * is not being used, so we close the connection.  This
2426	 * second case is possible if we sent a WantToClose because
2427	 * the iceConn->open_ref_count reached zero, but then we
2428	 * received a NoClose.
2429	 */
2430
2431	_IceConnectionClosed (iceConn);		/* invoke watch procs */
2432	_IceFreeConnection (iceConn);
2433	*connectionClosedRet = True;
2434    }
2435    else if (iceConn->proto_ref_count > 0)
2436    {
2437	/*
2438	 * We haven't shut down all of our protocols yet.  We send a NoClose,
2439	 * and it's up to us to generate a WantToClose later on.
2440	 */
2441
2442	IceSimpleMessage (iceConn, 0, ICE_NoClose);
2443	IceFlush (iceConn);
2444    }
2445    else
2446    {
2447	/*
2448	 * The reference count on this iceConn is zero.  This means that
2449	 * there are no active protocols, but the client didn't explicitly
2450	 * close the connection yet.  If we didn't just send a Protocol Setup,
2451	 * we send a NoClose, and it's up to us to generate a WantToClose
2452	 * later on.
2453	 */
2454
2455	if (!iceConn->protosetup_to_you)
2456	{
2457	    IceSimpleMessage (iceConn, 0, ICE_NoClose);
2458	    IceFlush (iceConn);
2459	}
2460    }
2461
2462    return (0);
2463}
2464
2465
2466
2467static int
2468ProcessNoClose (
2469	IceConn 	iceConn,
2470	unsigned long	length
2471)
2472{
2473    CHECK_SIZE_MATCH (iceConn, ICE_NoClose,
2474	length, SIZEOF (iceNoCloseMsg), IceFatalToConnection, 0);
2475
2476    if (iceConn->want_to_close)
2477    {
2478	/*
2479	 * The other side can't close now.  We cancel our WantToClose,
2480	 * and we can expect a WantToClose from the other side.
2481	 */
2482
2483	iceConn->want_to_close = 0;
2484    }
2485    else
2486    {
2487	_IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue);
2488    }
2489
2490    return (0);
2491}
2492
2493
2494
2495static void
2496_IceProcessCoreMessage (
2497	IceConn 	 iceConn,
2498	int     	 opcode,
2499	unsigned long	 length,
2500	Bool    	 swap,
2501	IceReplyWaitInfo *replyWait,
2502	Bool		 *replyReadyRet,
2503	Bool		 *connectionClosedRet
2504)
2505{
2506    Bool replyReady = False;
2507
2508    *connectionClosedRet = False;
2509
2510    switch (opcode)
2511    {
2512    case ICE_Error:
2513
2514	replyReady = ProcessError (iceConn, length, swap, replyWait);
2515	break;
2516
2517    case ICE_ConnectionSetup:
2518
2519	ProcessConnectionSetup (iceConn, length, swap);
2520	break;
2521
2522    case ICE_AuthRequired:
2523
2524	replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait);
2525        break;
2526
2527    case ICE_AuthReply:
2528
2529	ProcessAuthReply (iceConn, length, swap);
2530	break;
2531
2532    case ICE_AuthNextPhase:
2533
2534	replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait);
2535	break;
2536
2537    case ICE_ConnectionReply:
2538
2539	replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait);
2540	break;
2541
2542    case ICE_ProtocolSetup:
2543
2544	ProcessProtocolSetup (iceConn, length, swap);
2545	break;
2546
2547    case ICE_ProtocolReply:
2548
2549	replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait);
2550	break;
2551
2552    case ICE_Ping:
2553
2554	ProcessPing (iceConn, length);
2555	break;
2556
2557    case ICE_PingReply:
2558
2559	ProcessPingReply (iceConn, length);
2560	break;
2561
2562    case ICE_WantToClose:
2563
2564	ProcessWantToClose (iceConn, length, connectionClosedRet);
2565	break;
2566
2567    case ICE_NoClose:
2568
2569	ProcessNoClose (iceConn, length);
2570	break;
2571
2572    default:
2573
2574	_IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue);
2575	_IceReadSkip (iceConn, length << 3);
2576	break;
2577    }
2578
2579    if (replyWait)
2580	*replyReadyRet = replyReady;
2581}
2582
2583const int		_IceVersionCount = 1;
2584const _IceVersion	_IceVersions[] = {
2585			    {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};
2586