process.c revision a3129944
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, 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.
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 occured.  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 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.
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    pMsg->length += WORD64COUNT (authDataLen);
450
451    IceWriteData (iceConn, authDataLen, (char *) authData);
452
453    if (PAD64 (authDataLen))
454	IceWritePad (iceConn, PAD64 (authDataLen));
455
456    IceFlush (iceConn);
457}
458
459
460
461static void
462AuthReply (
463	IceConn		iceConn,
464	int 		authDataLen,
465	IcePointer	authData
466)
467{
468    iceAuthReplyMsg *pMsg;
469
470    IceGetHeader (iceConn, 0, ICE_AuthReply,
471	SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg);
472
473    pMsg->authDataLength = authDataLen;
474    pMsg->length +=  WORD64COUNT (authDataLen);
475
476    IceWriteData (iceConn, authDataLen, (char *) authData);
477
478    if (PAD64 (authDataLen))
479	IceWritePad (iceConn, PAD64 (authDataLen));
480
481    IceFlush (iceConn);
482}
483
484
485
486static void
487AuthNextPhase (
488	IceConn		iceConn,
489	int  		authDataLen,
490	IcePointer	authData
491)
492{
493    iceAuthNextPhaseMsg *pMsg;
494
495    IceGetHeader (iceConn, 0, ICE_AuthNextPhase,
496	SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg);
497
498    pMsg->authDataLength = authDataLen;
499    pMsg->length += WORD64COUNT (authDataLen);
500
501    IceWriteData (iceConn, authDataLen, (char *) authData);
502
503    if (PAD64 (authDataLen))
504	IceWritePad (iceConn, PAD64 (authDataLen));
505
506    IceFlush (iceConn);
507}
508
509
510
511static void
512AcceptConnection (
513	IceConn iceConn,
514	int 	versionIndex
515)
516{
517    iceConnectionReplyMsg	*pMsg;
518    char			*pData;
519    int				extra;
520
521    extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
522
523    IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply,
524	SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra),
525	iceConnectionReplyMsg, pMsg, pData);
526
527    pMsg->versionIndex = versionIndex;
528
529    STORE_STRING (pData, IceVendorString);
530    STORE_STRING (pData, IceReleaseString);
531
532    IceFlush (iceConn);
533
534    iceConn->connection_status = IceConnectAccepted;
535}
536
537
538
539static void
540AcceptProtocol (
541	IceConn iceConn,
542	int  	hisOpcode,
543	int  	myOpcode,
544	int  	versionIndex,
545	char 	*vendor,
546	char 	*release
547)
548{
549    iceProtocolReplyMsg	*pMsg;
550    char		*pData;
551    int			extra;
552
553    extra = STRING_BYTES (vendor) + STRING_BYTES (release);
554
555    IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply,
556	SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra),
557	iceProtocolReplyMsg, pMsg, pData);
558
559    pMsg->protocolOpcode = myOpcode;
560    pMsg->versionIndex = versionIndex;
561
562    STORE_STRING (pData, vendor);
563    STORE_STRING (pData, release);
564
565    IceFlush (iceConn);
566
567
568    /*
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.
572     */
573
574    _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
575}
576
577
578
579static void
580PingReply (
581	IceConn iceConn
582)
583{
584    IceSimpleMessage (iceConn, 0, ICE_PingReply);
585    IceFlush (iceConn);
586}
587
588
589
590static Bool
591ProcessError (
592	IceConn		 iceConn,
593	unsigned long	 length,
594	Bool		 swap,
595	IceReplyWaitInfo *replyWait
596)
597{
598    int		invokeHandler = 0;
599    Bool	errorReturned = False;
600    iceErrorMsg *message;
601    char 	*pData, *pStart;
602    char	severity;
603
604    CHECK_AT_LEAST_SIZE (iceConn, ICE_Error,
605	length, SIZEOF (iceErrorMsg),
606	(iceConn->connect_to_you || iceConn->connect_to_me) ?
607	IceFatalToConnection : IceFatalToProtocol);
608
609    IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
610	iceErrorMsg, message, pStart);
611
612    if (!IceValidIO (iceConn))
613    {
614	IceDisposeCompleteMessage (iceConn, pStart);
615	return (0);
616    }
617
618    severity = message->severity;
619
620    if (severity != IceCanContinue && severity != IceFatalToProtocol &&
621	severity != IceFatalToConnection)
622    {
623	_IceErrorBadValue (iceConn, 0,
624	    ICE_Error, 9, 1, &severity);
625	IceDisposeCompleteMessage (iceConn, pStart);
626	return (0);
627    }
628
629    pData = pStart;
630
631    if (swap)
632    {
633	message->errorClass = lswaps (message->errorClass);
634	message->offendingSequenceNum = lswapl (message->offendingSequenceNum);
635    }
636
637    if (!replyWait ||
638	message->offendingSequenceNum != replyWait->sequence_of_request)
639    {
640	invokeHandler = 1;
641    }
642    else
643    {
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)))
649	{
650	    _IceConnectionError *errorReply =
651	        &(((_IceReply *) (replyWait->reply))->connection_error);
652	    char *errorStr = NULL;
653	    const char *tempstr, *prefix;
654	    char *temp;
655
656	    invokeHandler = 0;
657	    errorReturned = True;
658
659	    switch (message->errorClass)
660	    {
661	    case IceNoVersion:
662
663		tempstr =
664		    "None of the ICE versions specified are supported";
665		errorStr = strdup(tempstr);
666		break;
667
668	    case IceNoAuth:
669
670		tempstr =
671		    "None of the authentication protocols specified are supported";
672		errorStr = strdup(tempstr);
673		break;
674
675	    case IceSetupFailed:
676
677		prefix = "Connection Setup Failed, reason : ";
678
679		EXTRACT_STRING (pData, swap, temp);
680		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
681		    errorStr = NULL;
682		free (temp);
683		break;
684
685	    case IceAuthRejected:
686
687		prefix = "Authentication Rejected, reason : ";
688		EXTRACT_STRING (pData, swap, temp);
689		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
690		    errorStr = NULL;
691		free (temp);
692		break;
693
694	    case IceAuthFailed:
695
696		prefix = "Authentication Failed, reason : ";
697		EXTRACT_STRING (pData, swap, temp);
698		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
699		    errorStr = NULL;
700		free (temp);
701		break;
702
703	    default:
704		invokeHandler = 1;
705	    }
706
707			if (!errorStr)
708			{
709				errorStr = strdup("");
710			}
711
712	    errorReply->type = ICE_CONNECTION_ERROR;
713	    errorReply->error_message = errorStr;
714	}
715	else if (iceConn->protosetup_to_you &&
716	    ((!iceConn->protosetup_to_you->auth_active &&
717            message->offendingMinorOpcode == ICE_ProtocolSetup) ||
718            (iceConn->protosetup_to_you->auth_active &&
719	    message->offendingMinorOpcode == ICE_AuthReply)))
720	{
721	    _IceProtocolError *errorReply =
722	        &(((_IceReply *) (replyWait->reply))->protocol_error);
723	    char *errorStr = NULL;
724	    const char *prefix;
725	    char *temp;
726
727	    invokeHandler = 0;
728	    errorReturned = True;
729
730	    switch (message->errorClass)
731	    {
732	    case IceNoVersion:
733
734		errorStr = strdup(
735		    "None of the protocol versions specified are supported");
736		break;
737
738	    case IceNoAuth:
739
740		errorStr = strdup(
741		    "None of the authentication protocols specified are supported");
742
743		break;
744
745	    case IceSetupFailed:
746
747		prefix = "Protocol Setup Failed, reason : ";
748
749		EXTRACT_STRING (pData, swap, temp);
750		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
751		    errorStr = NULL;
752		free (temp);
753		break;
754
755	    case IceAuthRejected:
756
757		prefix = "Authentication Rejected, reason : ";
758		EXTRACT_STRING (pData, swap, temp);
759		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
760		    errorStr = NULL;
761		free (temp);
762		break;
763
764	    case IceAuthFailed:
765
766		prefix = "Authentication Failed, reason : ";
767		EXTRACT_STRING (pData, swap, temp);
768		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
769		    errorStr = NULL;
770		free (temp);
771		break;
772
773	    case IceProtocolDuplicate:
774
775		prefix = "Protocol was already registered : ";
776		EXTRACT_STRING (pData, swap, temp);
777		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
778		    errorStr = NULL;
779		free (temp);
780		break;
781
782	    case IceMajorOpcodeDuplicate:
783
784		prefix = "The major opcode was already used : ";
785		if (asprintf (&errorStr, "%s%d", prefix, (int) *pData) == -1)
786		    errorStr = NULL;
787		break;
788
789	    case IceUnknownProtocol:
790
791		prefix = "Unknown Protocol : ";
792		EXTRACT_STRING (pData, swap, temp);
793		if (asprintf (&errorStr, "%s%s", prefix, temp) == -1)
794		    errorStr = NULL;
795		free (temp);
796		break;
797
798	    default:
799		invokeHandler = 1;
800	    }
801
802			if (!errorStr)
803			{
804				errorStr = strdup("");
805			}
806
807	    errorReply->type = ICE_PROTOCOL_ERROR;
808	    errorReply->error_message = errorStr;
809	}
810
811	if (errorReturned == True)
812	{
813	    /*
814	     * If we tried to authenticate, tell the authentication
815	     * procedure to clean up.
816	     */
817
818	    IcePoAuthProc authProc;
819
820	    if (iceConn->connect_to_you &&
821		iceConn->connect_to_you->auth_active)
822	    {
823		authProc = _IcePoAuthProcs[(int)
824		    (iceConn->connect_to_you->my_auth_index)];
825
826		(*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
827		    True /* clean up */, False /* swap */,
828		    0, NULL, NULL, NULL, NULL);
829	    }
830	    else if (iceConn->protosetup_to_you &&
831		iceConn->protosetup_to_you->auth_active)
832	    {
833		_IcePoProtocol *protocol = _IceProtocols[
834		    iceConn->protosetup_to_you->my_opcode - 1].orig_client;
835
836		authProc = protocol->auth_procs[(int)(iceConn->
837		    protosetup_to_you->my_auth_index)];
838
839		(*authProc) (iceConn,
840		    &iceConn->protosetup_to_you->my_auth_state,
841		    True /* clean up */, False /* swap */,
842		    0, NULL, NULL, NULL, NULL);
843	    }
844	}
845    }
846
847    if (invokeHandler)
848    {
849	(*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode,
850	    message->offendingSequenceNum, message->errorClass,
851	    message->severity, (IcePointer) pData);
852    }
853
854    IceDisposeCompleteMessage (iceConn, pStart);
855
856    return (errorReturned);
857}
858
859
860
861static int
862ProcessConnectionSetup (
863	IceConn		iceConn,
864	unsigned long	length,
865	Bool		swap
866)
867{
868    iceConnectionSetupMsg *message;
869    const int myVersionCount = _IceVersionCount;
870    int  hisVersionCount;
871    int	 myVersionIndex, hisVersionIndex;
872    int  hisMajorVersion, hisMinorVersion;
873    int	 myAuthCount, hisAuthCount;
874    int	 found, i, j;
875    char **hisAuthNames = NULL;
876    char *pData, *pStart, *pEnd;
877    char *vendor = NULL;
878    char *release = NULL;
879    int myAuthIndex = 0;
880    int hisAuthIndex = 0;
881    int accept_setup_now = 0;
882    char mustAuthenticate;
883    int	authUsableCount;
884    int	authUsableFlags[MAX_ICE_AUTH_NAMES];
885    int	authIndices[MAX_ICE_AUTH_NAMES];
886
887    CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup,
888	length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection);
889
890    IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg),
891	iceConnectionSetupMsg, message, pStart);
892
893    if (!IceValidIO (iceConn))
894    {
895	IceDisposeCompleteMessage (iceConn, pStart);
896	return (0);
897    }
898
899    pData = pStart;
900    pEnd = pStart + (length << 3);
901
902    SKIP_STRING (pData, swap, pEnd,
903		 BAIL_STRING(iceConn, ICE_ConnectionSetup,
904			     pStart));			       /* vendor */
905    SKIP_STRING (pData, swap, pEnd,
906		 BAIL_STRING(iceConn, ICE_ConnectionSetup,
907			    pStart));	        	       /* release */
908    SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
909			BAIL_STRING(iceConn, ICE_ConnectionSetup,
910				   pStart));		       /* auth names */
911
912    pData += (message->versionCount * 4);		       /* versions */
913
914    CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup,
915	length, pData - pStart + SIZEOF (iceConnectionSetupMsg),
916	pStart, IceFatalToConnection);
917
918    mustAuthenticate = message->mustAuthenticate;
919    if (mustAuthenticate != 0 && mustAuthenticate != 1)
920    {
921	_IceErrorBadValue (iceConn, 0,
922	    ICE_ConnectionSetup, 8, 1, &mustAuthenticate);
923	iceConn->connection_status = IceConnectRejected;
924	IceDisposeCompleteMessage (iceConn, pStart);
925	return (0);
926    }
927
928    pData = pStart;
929
930    EXTRACT_STRING (pData, swap, vendor);
931    EXTRACT_STRING (pData, swap, release);
932
933    hisAuthCount = message->authCount;
934    if (hisAuthCount > 0)
935    {
936	hisAuthNames = malloc (hisAuthCount * sizeof (char *));
937	EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
938    }
939
940    hisVersionCount = message->versionCount;
941
942    hisVersionIndex = myVersionIndex = found = 0;
943
944    for (i = 0; i < hisVersionCount && !found; i++)
945    {
946	EXTRACT_CARD16 (pData, swap, hisMajorVersion);
947	EXTRACT_CARD16 (pData, swap, hisMinorVersion);
948
949	for (j = 0; j < myVersionCount && !found; j++)
950	{
951	    if (_IceVersions[j].major_version == hisMajorVersion &&
952		_IceVersions[j].minor_version == hisMinorVersion)
953	    {
954		hisVersionIndex = i;
955		myVersionIndex = j;
956		found = 1;
957	    }
958	}
959    }
960
961    if (!found)
962    {
963	_IceErrorNoVersion (iceConn, ICE_ConnectionSetup);
964	iceConn->connection_status = IceConnectRejected;
965
966	free (vendor);
967	free (release);
968
969	if (hisAuthCount > 0)
970	{
971	    for (i = 0; i < hisAuthCount; i++)
972		free (hisAuthNames[i]);
973
974	    free (hisAuthNames);
975	}
976
977	IceDisposeCompleteMessage (iceConn, pStart);
978	return (0);
979    }
980
981    _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string,
982	_IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
983
984    for (i = 0; i < _IceAuthCount; i++)
985    {
986	authUsableFlags[i] = 0;
987	for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
988	    authUsableFlags[i] = (authIndices[j] == i);
989    }
990
991    myAuthCount = _IceAuthCount;
992
993    for (i = found = 0; i < myAuthCount && !found; i++)
994    {
995	if (authUsableFlags[i])
996	{
997	    const char *myAuthName = _IceAuthNames[i];
998
999	    for (j = 0; j < hisAuthCount && !found; j++)
1000		if (strcmp (myAuthName, hisAuthNames[j]) == 0)
1001		{
1002		    myAuthIndex = i;
1003		    hisAuthIndex = j;
1004		    found = 1;
1005		}
1006	}
1007    }
1008
1009    if (!found)
1010    {
1011	/*
1012	 * None of the authentication methods specified by the
1013	 * other client is supported.  If the other client requires
1014	 * authentication, we must reject the connection now.
1015	 * Otherwise, we can invoke the host-based authentication callback
1016	 * to see if we can accept this connection.
1017	 */
1018
1019	if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc)
1020	{
1021	    _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup);
1022	    iceConn->connection_status = IceConnectRejected;
1023	}
1024	else
1025	{
1026	    char *hostname = _IceGetPeerName (iceConn);
1027
1028	    if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1029	    {
1030		accept_setup_now = 1;
1031	    }
1032	    else
1033	    {
1034		_IceErrorAuthenticationRejected (iceConn,
1035	            ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
1036
1037		iceConn->connection_status = IceConnectRejected;
1038	    }
1039
1040	    free (hostname);
1041	}
1042
1043	if (iceConn->connection_status == IceConnectRejected)
1044	{
1045	    free (vendor);
1046	    free (release);
1047	}
1048    }
1049    else
1050    {
1051	IcePaAuthStatus	status;
1052	int		authDataLen;
1053	IcePointer	authData = NULL;
1054	IcePointer	authState;
1055	char		*errorString = NULL;
1056	IcePaAuthProc	authProc = _IcePaAuthProcs[myAuthIndex];
1057
1058	authState = NULL;
1059
1060	status = (*authProc) (iceConn, &authState,
1061	    swap, 0, NULL, &authDataLen, &authData, &errorString);
1062
1063	if (status == IcePaAuthContinue)
1064	{
1065	    _IceConnectToMeInfo *setupInfo;
1066
1067	    AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
1068
1069	    iceConn->connect_to_me = setupInfo =
1070		malloc (sizeof (_IceConnectToMeInfo));
1071
1072	    setupInfo->my_version_index = myVersionIndex;
1073	    setupInfo->his_version_index = hisVersionIndex;
1074	    setupInfo->his_vendor = vendor;
1075	    setupInfo->his_release = release;
1076	    setupInfo->my_auth_index = myAuthIndex;
1077	    setupInfo->my_auth_state = authState;
1078	    setupInfo->must_authenticate = mustAuthenticate;
1079	}
1080	else if (status == IcePaAuthAccepted)
1081	{
1082	    accept_setup_now = 1;
1083	}
1084	else
1085	{
1086	    free (vendor);
1087	    free (release);
1088	}
1089
1090	if (authData && authDataLen > 0)
1091	    free (authData);
1092
1093	free (errorString);
1094    }
1095
1096    if (accept_setup_now)
1097    {
1098	AcceptConnection (iceConn, hisVersionIndex);
1099
1100	iceConn->vendor = vendor;
1101	iceConn->release = release;
1102	iceConn->my_ice_version_index = myVersionIndex;
1103    }
1104
1105    if (hisAuthCount > 0)
1106    {
1107	for (i = 0; i < hisAuthCount; i++)
1108	    free (hisAuthNames[i]);
1109
1110	free (hisAuthNames);
1111    }
1112
1113    IceDisposeCompleteMessage (iceConn, pStart);
1114    return (0);
1115}
1116
1117
1118
1119static Bool
1120ProcessAuthRequired (
1121	IceConn			iceConn,
1122	unsigned long	 	length,
1123	Bool			swap,
1124	IceReplyWaitInfo	*replyWait
1125)
1126{
1127    iceAuthRequiredMsg  *message;
1128    int			authDataLen;
1129    IcePointer 		authData;
1130    int 		replyDataLen;
1131    IcePointer 		replyData = NULL;
1132    char		*errorString = NULL;
1133    IcePoAuthProc	authProc;
1134    IcePoAuthStatus	status;
1135    IcePointer 		authState;
1136    int			realAuthIndex = 0;
1137
1138    CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired,
1139	length, SIZEOF (iceAuthRequiredMsg),
1140	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1141
1142    IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg),
1143	iceAuthRequiredMsg, message, authData);
1144
1145    if (!IceValidIO (iceConn))
1146    {
1147	IceDisposeCompleteMessage (iceConn, authData);
1148	return (0);
1149    }
1150
1151    if (swap)
1152    {
1153	message->authDataLength = lswaps (message->authDataLength);
1154    }
1155
1156    CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length,
1157	message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData,
1158	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1159
1160    if (iceConn->connect_to_you)
1161    {
1162	if ((int) message->authIndex >= _IceAuthCount)
1163	{
1164	    _IceConnectionError *errorReply =
1165	        &(((_IceReply *) (replyWait->reply))->connection_error);
1166
1167	    const char *tempstr
1168		= "Received bad authIndex in the AuthRequired message";
1169	    char errIndex = (int) message->authIndex;
1170
1171	    errorString = strdup(tempstr);
1172
1173	    errorReply->type = ICE_CONNECTION_ERROR;
1174	    errorReply->error_message = errorString;
1175
1176	    _IceErrorBadValue (iceConn, 0,
1177		ICE_AuthRequired, 2, 1, &errIndex);
1178
1179	    IceDisposeCompleteMessage (iceConn, authData);
1180	    return (1);
1181	}
1182	else
1183	{
1184	    authProc = _IcePoAuthProcs[message->authIndex];
1185
1186	    iceConn->connect_to_you->auth_active = 1;
1187	}
1188    }
1189    else if (iceConn->protosetup_to_you)
1190    {
1191	if ((int) message->authIndex >=
1192	    iceConn->protosetup_to_you->my_auth_count)
1193	{
1194	    _IceProtocolError *errorReply =
1195	        &(((_IceReply *) (replyWait->reply))->protocol_error);
1196
1197	    const char *tempstr
1198		= "Received bad authIndex in the AuthRequired message";
1199	    char errIndex = (int) message->authIndex;
1200
1201	    errorString = strdup(tempstr);
1202
1203	    errorReply->type = ICE_PROTOCOL_ERROR;
1204	    errorReply->error_message = errorString;
1205
1206	    _IceErrorBadValue (iceConn, 0,
1207		ICE_AuthRequired, 2, 1, &errIndex);
1208
1209	    IceDisposeCompleteMessage (iceConn, authData);
1210	    return (1);
1211	}
1212	else
1213	{
1214	    _IcePoProtocol *myProtocol = _IceProtocols[
1215	        iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1216
1217	    realAuthIndex = iceConn->protosetup_to_you->
1218		my_auth_indices[message->authIndex];
1219
1220	    authProc = myProtocol->auth_procs[realAuthIndex];
1221
1222	    iceConn->protosetup_to_you->auth_active = 1;
1223	}
1224    }
1225    else
1226    {
1227	/*
1228	 * Unexpected message
1229	 */
1230
1231	_IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue);
1232
1233	IceDisposeCompleteMessage (iceConn, authData);
1234	return (0);
1235    }
1236
1237    authState = NULL;
1238    authDataLen = message->authDataLength;
1239
1240    status = (*authProc) (iceConn, &authState, False /* don't clean up */,
1241	swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1242
1243    if (status == IcePoAuthHaveReply)
1244    {
1245	AuthReply (iceConn, replyDataLen, replyData);
1246
1247	replyWait->sequence_of_request = iceConn->send_sequence;
1248	replyWait->minor_opcode_of_request = ICE_AuthReply;
1249
1250	if (iceConn->connect_to_you)
1251	{
1252	    iceConn->connect_to_you->my_auth_state = authState;
1253	    iceConn->connect_to_you->my_auth_index = message->authIndex;
1254	}
1255	else if (iceConn->protosetup_to_you)
1256	{
1257	    iceConn->protosetup_to_you->my_auth_state = authState;
1258	    iceConn->protosetup_to_you->my_auth_index = realAuthIndex;
1259	}
1260    }
1261    else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1262    {
1263	const char *prefix;
1264	char *returnErrorString;
1265
1266	if (status == IcePoAuthRejected)
1267	{
1268	    _IceErrorAuthenticationRejected (iceConn,
1269	        ICE_AuthRequired, errorString);
1270
1271	    prefix = "Authentication Rejected, reason : ";
1272	}
1273	else
1274	{
1275	    _IceErrorAuthenticationFailed (iceConn,
1276	       ICE_AuthRequired, errorString);
1277
1278	    prefix = "Authentication Failed, reason : ";
1279	}
1280
1281	if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1282	    returnErrorString = strdup("");
1283	free (errorString);
1284
1285	if (iceConn->connect_to_you)
1286	{
1287	    _IceConnectionError *errorReply =
1288	        &(((_IceReply *) (replyWait->reply))->connection_error);
1289
1290	    errorReply->type = ICE_CONNECTION_ERROR;
1291	    errorReply->error_message = returnErrorString;
1292	}
1293	else
1294	{
1295	    _IceProtocolError *errorReply =
1296	        &(((_IceReply *) (replyWait->reply))->protocol_error);
1297
1298	    errorReply->type = ICE_PROTOCOL_ERROR;
1299	    errorReply->error_message = returnErrorString;
1300	}
1301    }
1302
1303    if (replyData && replyDataLen > 0)
1304	free (replyData);
1305
1306    IceDisposeCompleteMessage (iceConn, authData);
1307
1308    return (status != IcePoAuthHaveReply);
1309}
1310
1311
1312
1313static int
1314ProcessAuthReply (
1315	IceConn		iceConn,
1316	unsigned long	length,
1317	Bool		swap
1318)
1319{
1320    iceAuthReplyMsg 	*message;
1321    int			replyDataLen;
1322    IcePointer		replyData;
1323    int 		authDataLen;
1324    IcePointer 		authData = NULL;
1325    char		*errorString = NULL;
1326
1327    CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply,
1328	length, SIZEOF (iceAuthReplyMsg),
1329	iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1330
1331    IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg),
1332	iceAuthReplyMsg, message, replyData);
1333
1334    if (!IceValidIO (iceConn))
1335    {
1336	IceDisposeCompleteMessage (iceConn, replyData);
1337	return (0);
1338    }
1339
1340    if (swap)
1341    {
1342	message->authDataLength = lswaps (message->authDataLength);
1343    }
1344
1345    CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length,
1346	message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData,
1347	iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
1348
1349    replyDataLen = message->authDataLength;
1350
1351    if (iceConn->connect_to_me)
1352    {
1353	IcePaAuthProc authProc = _IcePaAuthProcs[(int)
1354	    (iceConn->connect_to_me->my_auth_index)];
1355	IcePaAuthStatus status =
1356	    (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap,
1357	    replyDataLen, replyData, &authDataLen, &authData, &errorString);
1358
1359	if (status == IcePaAuthContinue)
1360	{
1361	    AuthNextPhase (iceConn, authDataLen, authData);
1362	}
1363	else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1364	{
1365	    /*
1366	     * Before we reject, invoke host-based authentication callback
1367	     * and give it a chance to accept the connection (only if the
1368	     * other client doesn't require authentication).
1369	     */
1370
1371	    if (!iceConn->connect_to_me->must_authenticate &&
1372		iceConn->listen_obj->host_based_auth_proc)
1373	    {
1374		char *hostname = _IceGetPeerName (iceConn);
1375
1376		if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
1377		{
1378		    status = IcePaAuthAccepted;
1379		}
1380
1381		free (hostname);
1382	    }
1383
1384	    if (status != IcePaAuthAccepted)
1385	    {
1386		free (iceConn->connect_to_me->his_vendor);
1387		free (iceConn->connect_to_me->his_release);
1388		free (iceConn->connect_to_me);
1389		iceConn->connect_to_me = NULL;
1390
1391		iceConn->connection_status = IceConnectRejected;
1392
1393		if (status == IcePaAuthRejected)
1394		{
1395		    _IceErrorAuthenticationRejected (iceConn,
1396	                ICE_AuthReply, errorString);
1397		}
1398		else
1399		{
1400		    _IceErrorAuthenticationFailed (iceConn,
1401	                ICE_AuthReply, errorString);
1402		}
1403	    }
1404	}
1405
1406	if (status == IcePaAuthAccepted)
1407	{
1408	    AcceptConnection (iceConn,
1409		iceConn->connect_to_me->his_version_index);
1410
1411	    iceConn->vendor = iceConn->connect_to_me->his_vendor;
1412	    iceConn->release = iceConn->connect_to_me->his_release;
1413	    iceConn->my_ice_version_index =
1414		iceConn->connect_to_me->my_version_index;
1415
1416	    free (iceConn->connect_to_me);
1417	    iceConn->connect_to_me = NULL;
1418	}
1419    }
1420    else if (iceConn->protosetup_to_me)
1421    {
1422	_IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me->
1423	    my_opcode - 1].accept_client;
1424	IcePaAuthProc authProc = myProtocol->auth_procs[(int)
1425	    (iceConn->protosetup_to_me->my_auth_index)];
1426	IcePaAuthStatus status =
1427	    (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state,
1428	    swap, replyDataLen, replyData,
1429	    &authDataLen, &authData, &errorString);
1430	int free_setup_info = 1;
1431
1432	if (status == IcePaAuthContinue)
1433	{
1434	    AuthNextPhase (iceConn, authDataLen, authData);
1435	    free_setup_info = 0;
1436	}
1437	else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
1438	{
1439	    /*
1440	     * Before we reject, invoke host-based authentication callback
1441	     * and give it a chance to accept the Protocol Setup (only if the
1442	     * other client doesn't require authentication).
1443	     */
1444
1445	    if (!iceConn->protosetup_to_me->must_authenticate &&
1446		myProtocol->host_based_auth_proc)
1447	    {
1448		char *hostname = _IceGetPeerName (iceConn);
1449
1450		if ((*myProtocol->host_based_auth_proc) (hostname))
1451		{
1452		    status = IcePaAuthAccepted;
1453		}
1454
1455		free (hostname);
1456	    }
1457
1458	    if (status == IcePaAuthRejected)
1459	    {
1460		_IceErrorAuthenticationRejected (iceConn,
1461	            ICE_AuthReply, errorString);
1462	    }
1463	    else
1464	    {
1465	        _IceErrorAuthenticationFailed (iceConn,
1466	            ICE_AuthReply, errorString);
1467	    }
1468	}
1469
1470	if (status == IcePaAuthAccepted)
1471	{
1472	    IcePaProcessMsgProc	processMsgProc;
1473	    IceProtocolSetupProc protocolSetupProc;
1474	    IceProtocolActivateProc protocolActivateProc;
1475	    _IceProcessMsgInfo *process_msg_info;
1476	    IcePointer clientData = NULL;
1477	    char *failureReason = NULL;
1478	    Status status = 1;
1479
1480	    protocolSetupProc = myProtocol->protocol_setup_proc;
1481	    protocolActivateProc = myProtocol->protocol_activate_proc;
1482
1483	    if (protocolSetupProc)
1484	    {
1485		/*
1486		 * Notify the client of the Protocol Setup.
1487		 */
1488
1489		status = (*protocolSetupProc) (iceConn,
1490		    myProtocol->version_recs[iceConn->protosetup_to_me->
1491		        my_version_index].major_version,
1492		    myProtocol->version_recs[iceConn->protosetup_to_me->
1493		        my_version_index].minor_version,
1494		    iceConn->protosetup_to_me->his_vendor,
1495		    iceConn->protosetup_to_me->his_release,
1496		    &clientData, &failureReason);
1497
1498		/*
1499		 * Set vendor and release pointers to NULL, so it won't
1500		 * get freed below.  The ProtocolSetupProc should
1501		 * free it.
1502		 */
1503
1504		iceConn->protosetup_to_me->his_vendor = NULL;
1505		iceConn->protosetup_to_me->his_release = NULL;
1506	    }
1507
1508	    if (status != 0)
1509	    {
1510		/*
1511		 * Send the Protocol Reply
1512		 */
1513
1514		AcceptProtocol (iceConn,
1515	            iceConn->protosetup_to_me->his_opcode,
1516	            iceConn->protosetup_to_me->my_opcode,
1517	            iceConn->protosetup_to_me->his_version_index,
1518		    myProtocol->vendor, myProtocol->release);
1519
1520
1521		/*
1522		 * Set info for this protocol.
1523		 */
1524
1525		processMsgProc = myProtocol->version_recs[
1526	            iceConn->protosetup_to_me->
1527	            my_version_index].process_msg_proc;
1528
1529		process_msg_info = &iceConn->process_msg_info[
1530	            iceConn->protosetup_to_me->
1531		    his_opcode -iceConn->his_min_opcode];
1532
1533		process_msg_info->client_data = clientData;
1534		process_msg_info->accept_flag = 1;
1535		process_msg_info->process_msg_proc.
1536		    accept_client = processMsgProc;
1537
1538
1539		/*
1540		 * Increase the reference count for the number
1541		 * of active protocols.
1542		 */
1543
1544		iceConn->proto_ref_count++;
1545
1546
1547		/*
1548		 * Notify the client that the protocol is active.  The reason
1549		 * we have this 2nd callback invoked is because the client
1550		 * may wish to immediately generate a message for this
1551		 * protocol, but it must wait until we send the Protocol Reply.
1552		 */
1553
1554		if (protocolActivateProc)
1555		{
1556		    (*protocolActivateProc) (iceConn,
1557		        process_msg_info->client_data);
1558		}
1559	    }
1560	    else
1561	    {
1562		/*
1563		 * An error was encountered.
1564		 */
1565
1566		_IceErrorSetupFailed (iceConn, ICE_ProtocolSetup,
1567		    failureReason);
1568
1569		free (failureReason);
1570	    }
1571	}
1572
1573
1574	if (free_setup_info)
1575	{
1576	    free (iceConn->protosetup_to_me->his_vendor);
1577	    free (iceConn->protosetup_to_me->his_release);
1578	    free (iceConn->protosetup_to_me);
1579	    iceConn->protosetup_to_me = NULL;
1580	}
1581    }
1582    else
1583    {
1584	/*
1585	 * Unexpected message
1586	 */
1587
1588	_IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue);
1589    }
1590
1591    if (authData && authDataLen > 0)
1592	free (authData);
1593
1594
1595    free (errorString);
1596
1597    IceDisposeCompleteMessage (iceConn, replyData);
1598    return (0);
1599}
1600
1601
1602
1603static Bool
1604ProcessAuthNextPhase (
1605	IceConn		  	iceConn,
1606	unsigned long	 	length,
1607	Bool			swap,
1608	IceReplyWaitInfo	*replyWait
1609)
1610{
1611    iceAuthNextPhaseMsg *message;
1612    int 		authDataLen;
1613    IcePointer		authData;
1614    int 		replyDataLen;
1615    IcePointer		replyData = NULL;
1616    char		*errorString = NULL;
1617    IcePoAuthProc 	authProc;
1618    IcePoAuthStatus	status;
1619    IcePointer 		*authState;
1620
1621    CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase,
1622	length, SIZEOF (iceAuthNextPhaseMsg),
1623	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1624
1625    IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg),
1626	iceAuthNextPhaseMsg, message, authData);
1627
1628    if (!IceValidIO (iceConn))
1629    {
1630	IceDisposeCompleteMessage (iceConn, authData);
1631	return (0);
1632    }
1633
1634    if (swap)
1635    {
1636	message->authDataLength = lswaps (message->authDataLength);
1637    }
1638
1639    CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length,
1640	message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData,
1641	iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
1642
1643    if (iceConn->connect_to_you)
1644    {
1645	authProc = _IcePoAuthProcs[(int)
1646	    (iceConn->connect_to_you->my_auth_index)];
1647
1648	authState = &iceConn->connect_to_you->my_auth_state;
1649    }
1650    else if (iceConn->protosetup_to_you)
1651    {
1652	_IcePoProtocol *myProtocol =
1653	  _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client;
1654
1655	authProc = myProtocol->auth_procs[(int)
1656	    (iceConn->protosetup_to_you->my_auth_index)];
1657
1658	authState = &iceConn->protosetup_to_you->my_auth_state;
1659    }
1660    else
1661    {
1662	/*
1663	 * Unexpected message
1664	 */
1665
1666	_IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue);
1667
1668	IceDisposeCompleteMessage (iceConn, authData);
1669	return (0);
1670    }
1671
1672    authDataLen = message->authDataLength;
1673
1674    status = (*authProc) (iceConn, authState, False /* don't clean up */,
1675	swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
1676
1677    if (status == IcePoAuthHaveReply)
1678    {
1679	AuthReply (iceConn, replyDataLen, replyData);
1680
1681	replyWait->sequence_of_request = iceConn->send_sequence;
1682    }
1683    else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
1684    {
1685	const char *prefix = NULL;
1686	char *returnErrorString;
1687
1688	if (status == IcePoAuthRejected)
1689	{
1690	    _IceErrorAuthenticationRejected (iceConn,
1691	       ICE_AuthNextPhase, errorString);
1692
1693	    prefix = "Authentication Rejected, reason : ";
1694	}
1695	else if (status == IcePoAuthFailed)
1696	{
1697	    _IceErrorAuthenticationFailed (iceConn,
1698	       ICE_AuthNextPhase, errorString);
1699
1700	    prefix = "Authentication Failed, reason : ";
1701	}
1702
1703	if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1)
1704	    returnErrorString = strdup("");
1705	free (errorString);
1706
1707	if (iceConn->connect_to_you)
1708	{
1709	    _IceConnectionError *errorReply =
1710	        &(((_IceReply *) (replyWait->reply))->connection_error);
1711
1712	    errorReply->type = ICE_CONNECTION_ERROR;
1713	    errorReply->error_message = returnErrorString;
1714	}
1715	else
1716	{
1717	    _IceProtocolError *errorReply =
1718	        &(((_IceReply *) (replyWait->reply))->protocol_error);
1719
1720	    errorReply->type = ICE_PROTOCOL_ERROR;
1721	    errorReply->error_message = returnErrorString;
1722	}
1723    }
1724
1725    if (replyData && replyDataLen > 0)
1726	free (replyData);
1727
1728    IceDisposeCompleteMessage (iceConn, authData);
1729
1730    return (status != IcePoAuthHaveReply);
1731}
1732
1733
1734
1735static Bool
1736ProcessConnectionReply (
1737	IceConn			iceConn,
1738	unsigned long	 	length,
1739	Bool			swap,
1740	IceReplyWaitInfo 	*replyWait
1741)
1742{
1743    iceConnectionReplyMsg 	*message;
1744    char 			*pData, *pStart, *pEnd;
1745    Bool			replyReady;
1746
1747#if 0 /* No-op */
1748    CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply,
1749	length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection);
1750#endif
1751
1752    IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg),
1753	iceConnectionReplyMsg, message, pStart);
1754
1755    if (!IceValidIO (iceConn))
1756    {
1757	IceDisposeCompleteMessage (iceConn, pStart);
1758	return (0);
1759    }
1760
1761    pData = pStart;
1762    pEnd = pStart + (length << 3);
1763
1764    SKIP_STRING (pData, swap, pEnd,
1765		 BAIL_STRING (iceConn, ICE_ConnectionReply,
1766			      pStart));		    	     /* vendor */
1767    SKIP_STRING (pData, swap, pEnd,
1768		 BAIL_STRING (iceConn, ICE_ConnectionReply,
1769			      pStart));			     /* release */
1770
1771    CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply,
1772	length, pData - pStart + SIZEOF (iceConnectionReplyMsg),
1773	pStart, IceFatalToConnection);
1774
1775    pData = pStart;
1776
1777    if (iceConn->connect_to_you)
1778    {
1779	if (iceConn->connect_to_you->auth_active)
1780	{
1781	    /*
1782	     * Tell the authentication procedure to clean up.
1783	     */
1784
1785	    IcePoAuthProc authProc = _IcePoAuthProcs[(int)
1786		(iceConn->connect_to_you->my_auth_index)];
1787
1788	    (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
1789		True /* clean up */, False /* swap */,
1790	        0, NULL, NULL, NULL, NULL);
1791	}
1792
1793	if ((int) message->versionIndex >= _IceVersionCount)
1794	{
1795	    _IceConnectionError *errorReply =
1796	        &(((_IceReply *) (replyWait->reply))->connection_error);
1797	    char errIndex = message->versionIndex;
1798
1799	    _IceErrorBadValue (iceConn, 0,
1800		ICE_ConnectionReply, 2, 1, &errIndex);
1801
1802	    errorReply->type = ICE_CONNECTION_ERROR;
1803	    errorReply->error_message =
1804		strdup("Received bad version index in Connection Reply");
1805	}
1806	else
1807	{
1808	    _IceReply *reply = (_IceReply *) (replyWait->reply);
1809
1810	    reply->type = ICE_CONNECTION_REPLY;
1811	    reply->connection_reply.version_index = message->versionIndex;
1812
1813	    EXTRACT_STRING (pData, swap, reply->connection_reply.vendor);
1814	    EXTRACT_STRING (pData, swap, reply->connection_reply.release);
1815	}
1816
1817	replyReady = True;
1818    }
1819    else
1820    {
1821	/*
1822	 * Unexpected message
1823	 */
1824
1825	_IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue);
1826
1827	replyReady = False;
1828    }
1829
1830    IceDisposeCompleteMessage (iceConn, pStart);
1831
1832    return (replyReady);
1833}
1834
1835
1836
1837static int
1838ProcessProtocolSetup (
1839	IceConn		iceConn,
1840	unsigned long	length,
1841	Bool		swap
1842)
1843{
1844    iceProtocolSetupMsg	*message;
1845    _IcePaProtocol 	*myProtocol;
1846    int  	      	myVersionCount, hisVersionCount;
1847    int	 	      	myVersionIndex, hisVersionIndex;
1848    int  	      	hisMajorVersion, hisMinorVersion;
1849    int	 	      	myAuthCount, hisAuthCount;
1850    int  	      	myOpcode, hisOpcode;
1851    int	 	      	found, i, j;
1852    char	      	**hisAuthNames = NULL;
1853    char 	      	*protocolName;
1854    char 		*pData, *pStart, *pEnd;
1855    char 	      	*vendor = NULL;
1856    char 	      	*release = NULL;
1857    int  	      	accept_setup_now = 0;
1858    int			myAuthIndex = 0;
1859    int			hisAuthIndex = 0;
1860    char		mustAuthenticate;
1861    int			authUsableCount;
1862    int			authUsableFlags[MAX_ICE_AUTH_NAMES];
1863    int			authIndices[MAX_ICE_AUTH_NAMES];
1864
1865    CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,
1866	length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);
1867
1868    if (iceConn->want_to_close)
1869    {
1870	/*
1871	 * If we sent a WantToClose message, but just got a ProtocolSetup,
1872	 * we must cancel our WantToClose.  It is the responsiblity of the
1873	 * other client to send a WantToClose later on.
1874	 */
1875
1876	iceConn->want_to_close = 0;
1877    }
1878
1879    IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),
1880	iceProtocolSetupMsg, message, pStart);
1881
1882    if (!IceValidIO (iceConn))
1883    {
1884	IceDisposeCompleteMessage (iceConn, pStart);
1885	return (0);
1886    }
1887
1888    pData = pStart;
1889    pEnd = pStart + (length << 3);
1890
1891    SKIP_STRING (pData, swap, pEnd,
1892		 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1893			     pStart));			       /* proto name */
1894    SKIP_STRING (pData, swap, pEnd,
1895		 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1896			     pStart));			       /* vendor */
1897    SKIP_STRING (pData, swap, pEnd,
1898		 BAIL_STRING(iceConn, ICE_ProtocolSetup,
1899			     pStart));			       /* release */
1900    SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd,
1901			BAIL_STRING(iceConn, ICE_ProtocolSetup,
1902				    pStart));		       /* auth names */
1903    pData += (message->versionCount * 4);		       /* versions */
1904
1905    CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,
1906	length, pData - pStart + SIZEOF (iceProtocolSetupMsg),
1907	pStart, IceFatalToProtocol);
1908
1909    mustAuthenticate = message->mustAuthenticate;
1910
1911    if (mustAuthenticate != 0 && mustAuthenticate != 1)
1912    {
1913	_IceErrorBadValue (iceConn, 0,
1914	    ICE_ProtocolSetup, 4, 1, &mustAuthenticate);
1915	IceDisposeCompleteMessage (iceConn, pStart);
1916	return (0);
1917    }
1918
1919    pData = pStart;
1920
1921    if (iceConn->process_msg_info &&
1922	(int) message->protocolOpcode >= iceConn->his_min_opcode &&
1923        (int) message->protocolOpcode <= iceConn->his_max_opcode &&
1924	iceConn->process_msg_info[
1925	message->protocolOpcode - iceConn->his_min_opcode].in_use)
1926    {
1927	_IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);
1928	IceDisposeCompleteMessage (iceConn, pStart);
1929	return (0);
1930    }
1931
1932    EXTRACT_STRING (pData, swap, protocolName);
1933
1934    if (iceConn->process_msg_info)
1935    {
1936	for (i = 0;
1937	    i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)
1938	{
1939	    if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,
1940	        iceConn->process_msg_info[i].protocol->protocol_name) == 0)
1941	    {
1942		_IceErrorProtocolDuplicate (iceConn, protocolName);
1943		free (protocolName);
1944		IceDisposeCompleteMessage (iceConn, pStart);
1945		return (0);
1946	    }
1947	}
1948    }
1949
1950    for (i = 0; i < _IceLastMajorOpcode; i++)
1951	if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)
1952	    break;
1953
1954    if (i < _IceLastMajorOpcode &&
1955        (myProtocol = _IceProtocols[i].accept_client) != NULL)
1956    {
1957	hisOpcode = message->protocolOpcode;
1958	myOpcode = i + 1;
1959	free (protocolName);
1960    }
1961    else
1962    {
1963	_IceErrorUnknownProtocol (iceConn, protocolName);
1964	free (protocolName);
1965	IceDisposeCompleteMessage (iceConn, pStart);
1966	return (0);
1967    }
1968
1969    EXTRACT_STRING (pData, swap, vendor);
1970    EXTRACT_STRING (pData, swap, release);
1971
1972    hisAuthCount = message->authCount;
1973    if (hisAuthCount > 0)
1974    {
1975	hisAuthNames = malloc (hisAuthCount * sizeof (char *));
1976	EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
1977    }
1978
1979    hisVersionCount = message->versionCount;
1980    myVersionCount = myProtocol->version_count;
1981
1982    hisVersionIndex = myVersionIndex = found = 0;
1983
1984    for (i = 0; i < hisVersionCount && !found; i++)
1985    {
1986	EXTRACT_CARD16 (pData, swap, hisMajorVersion);
1987	EXTRACT_CARD16 (pData, swap, hisMinorVersion);
1988
1989	for (j = 0; j < myVersionCount && !found; j++)
1990	{
1991	    if (myProtocol->version_recs[j].major_version == hisMajorVersion &&
1992		myProtocol->version_recs[j].minor_version == hisMinorVersion)
1993	    {
1994		hisVersionIndex = i;
1995		myVersionIndex = j;
1996		found = 1;
1997	    }
1998	}
1999    }
2000
2001    if (!found)
2002    {
2003	_IceErrorNoVersion (iceConn, ICE_ProtocolSetup);
2004
2005	free (vendor);
2006	free (release);
2007
2008	if (hisAuthCount > 0)
2009	{
2010	    for (i = 0; i < hisAuthCount; i++)
2011		free (hisAuthNames[i]);
2012
2013	    free (hisAuthNames);
2014	}
2015
2016	IceDisposeCompleteMessage (iceConn, pStart);
2017	return (0);
2018    }
2019
2020    myAuthCount = myProtocol->auth_count;
2021
2022    _IceGetPaValidAuthIndices (
2023	_IceProtocols[myOpcode - 1].protocol_name,
2024	iceConn->connection_string, myAuthCount,
2025	(const char **) myProtocol->auth_names,
2026        &authUsableCount, authIndices);
2027
2028    for (i = 0; i < myAuthCount; i++)
2029    {
2030	authUsableFlags[i] = 0;
2031	for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
2032	    authUsableFlags[i] = (authIndices[j] == i);
2033    }
2034
2035    for (i = found = 0; i < myAuthCount && !found; i++)
2036    {
2037	if (authUsableFlags[i])
2038	{
2039	    const char *myAuthName = myProtocol->auth_names[i];
2040
2041	    for (j = 0; j < hisAuthCount && !found; j++)
2042		if (strcmp (myAuthName, hisAuthNames[j]) == 0)
2043		{
2044		    myAuthIndex = i;
2045		    hisAuthIndex = j;
2046		    found = 1;
2047		}
2048	}
2049    }
2050
2051    if (!found)
2052    {
2053	/*
2054	 * None of the authentication methods specified by the
2055	 * other client is supported.  If the other client requires
2056	 * authentication, we must reject the Protocol Setup now.
2057	 * Otherwise, we can invoke the host-based authentication callback
2058	 * to see if we can accept this Protocol Setup.
2059	 */
2060
2061	if (mustAuthenticate || !myProtocol->host_based_auth_proc)
2062	{
2063	    _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);
2064	}
2065	else
2066	{
2067	    char *hostname = _IceGetPeerName (iceConn);
2068
2069	    if ((*myProtocol->host_based_auth_proc) (hostname))
2070	    {
2071		accept_setup_now = 1;
2072	    }
2073	    else
2074	    {
2075		_IceErrorAuthenticationRejected (iceConn,
2076	            ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
2077	    }
2078
2079	    free (hostname);
2080	}
2081    }
2082    else
2083    {
2084	IcePaAuthStatus	status;
2085	int 		authDataLen;
2086	IcePointer 	authData = NULL;
2087	IcePointer 	authState;
2088	char		*errorString = NULL;
2089	IcePaAuthProc	authProc =
2090		myProtocol->auth_procs[myAuthIndex];
2091
2092	authState = NULL;
2093
2094	status = (*authProc) (iceConn, &authState, swap, 0, NULL,
2095	    &authDataLen, &authData, &errorString);
2096
2097	if (status == IcePaAuthContinue)
2098	{
2099	    _IceProtoSetupToMeInfo *setupInfo;
2100
2101	    AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
2102
2103	    iceConn->protosetup_to_me = setupInfo =
2104		malloc (sizeof (_IceProtoSetupToMeInfo));
2105
2106	    setupInfo->his_opcode = hisOpcode;
2107	    setupInfo->my_opcode = myOpcode;
2108	    setupInfo->my_version_index = myVersionIndex;
2109	    setupInfo->his_version_index = hisVersionIndex;
2110	    setupInfo->his_vendor = vendor;
2111	    setupInfo->his_release = release;
2112	    vendor = release = NULL;   /* so we don't free it */
2113	    setupInfo->my_auth_index = myAuthIndex;
2114	    setupInfo->my_auth_state = authState;
2115	    setupInfo->must_authenticate = mustAuthenticate;
2116	}
2117	else if (status == IcePaAuthAccepted)
2118	{
2119	    accept_setup_now = 1;
2120	}
2121
2122	if (authData && authDataLen > 0)
2123	    free (authData);
2124
2125
2126	free (errorString);
2127    }
2128
2129    if (accept_setup_now)
2130    {
2131	IcePaProcessMsgProc		processMsgProc;
2132	IceProtocolSetupProc		protocolSetupProc;
2133	IceProtocolActivateProc		protocolActivateProc;
2134	_IceProcessMsgInfo		*process_msg_info;
2135	IcePointer			clientData = NULL;
2136	char 				*failureReason = NULL;
2137	Status				status = 1;
2138
2139	protocolSetupProc = myProtocol->protocol_setup_proc;
2140	protocolActivateProc = myProtocol->protocol_activate_proc;
2141
2142	if (protocolSetupProc)
2143	{
2144	    /*
2145	     * Notify the client of the Protocol Setup.
2146	     */
2147
2148	    status = (*protocolSetupProc) (iceConn,
2149		myProtocol->version_recs[myVersionIndex].major_version,
2150		myProtocol->version_recs[myVersionIndex].minor_version,
2151	        vendor, release, &clientData, &failureReason);
2152
2153	    vendor = release = NULL;   /* so we don't free it */
2154	}
2155
2156	if (status != 0)
2157	{
2158	    /*
2159	     * Send the Protocol Reply
2160	     */
2161
2162	    AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,
2163	        myProtocol->vendor, myProtocol->release);
2164
2165
2166	    /*
2167	     * Set info for this protocol.
2168	     */
2169
2170	    processMsgProc = myProtocol->version_recs[
2171	        myVersionIndex].process_msg_proc;
2172
2173	    process_msg_info = &iceConn->process_msg_info[hisOpcode -
2174	        iceConn->his_min_opcode];
2175
2176	    process_msg_info->client_data = clientData;
2177	    process_msg_info->accept_flag = 1;
2178	    process_msg_info->process_msg_proc.accept_client = processMsgProc;
2179
2180
2181	    /*
2182	     * Increase the reference count for the number of active protocols.
2183	     */
2184
2185	    iceConn->proto_ref_count++;
2186
2187
2188	    /*
2189	     * Notify the client that the protocol is active.  The reason
2190	     * we have this 2nd callback invoked is because the client
2191	     * may wish to immediately generate a message for this
2192	     * protocol, but it must wait until we send the Protocol Reply.
2193	     */
2194
2195	    if (protocolActivateProc)
2196	    {
2197		(*protocolActivateProc) (iceConn,
2198		    process_msg_info->client_data);
2199	    }
2200	}
2201	else
2202	{
2203	    /*
2204	     * An error was encountered.
2205	     */
2206
2207	    _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);
2208
2209	    free (failureReason);
2210	}
2211    }
2212
2213
2214    free (vendor);
2215    free (release);
2216
2217    if (hisAuthCount > 0)
2218    {
2219	for (i = 0; i < hisAuthCount; i++)
2220	    free (hisAuthNames[i]);
2221
2222	free (hisAuthNames);
2223    }
2224
2225    IceDisposeCompleteMessage (iceConn, pStart);
2226    return (0);
2227}
2228
2229
2230
2231static Bool
2232ProcessProtocolReply (
2233	IceConn		  	iceConn,
2234	unsigned long	 	length,
2235	Bool			swap,
2236	IceReplyWaitInfo 	*replyWait
2237)
2238{
2239    iceProtocolReplyMsg *message;
2240    char		*pData, *pStart, *pEnd;
2241    Bool		replyReady;
2242
2243#if 0 /* No-op */
2244    CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply,
2245	length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol);
2246#endif
2247
2248    IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg),
2249	iceProtocolReplyMsg, message, pStart);
2250
2251    if (!IceValidIO (iceConn))
2252    {
2253	IceDisposeCompleteMessage (iceConn, pStart);
2254	return (0);
2255    }
2256
2257    pData = pStart;
2258    pEnd = pStart + (length << 3);
2259
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 */
2266
2267    CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply,
2268	length, pData - pStart + SIZEOF (iceProtocolReplyMsg),
2269	pStart, IceFatalToProtocol);
2270
2271    pData = pStart;
2272
2273    if (iceConn->protosetup_to_you)
2274    {
2275	if (iceConn->protosetup_to_you->auth_active)
2276	{
2277	    /*
2278	     * Tell the authentication procedure to clean up.
2279	     */
2280
2281	    _IcePoProtocol *myProtocol = _IceProtocols[
2282		iceConn->protosetup_to_you->my_opcode - 1].orig_client;
2283
2284	    IcePoAuthProc authProc = myProtocol->auth_procs[(int)
2285		(iceConn->protosetup_to_you->my_auth_index)];
2286
2287	    (*authProc) (iceConn,
2288		&iceConn->protosetup_to_you->my_auth_state,
2289		True /* clean up */, False /* swap */,
2290	        0, NULL, NULL, NULL, NULL);
2291	}
2292
2293	if ((int) message->versionIndex >= _IceVersionCount)
2294	{
2295	    _IceProtocolError *errorReply =
2296	        &(((_IceReply *) (replyWait->reply))->protocol_error);
2297	    char errIndex = message->versionIndex;
2298
2299	    _IceErrorBadValue (iceConn, 0,
2300		ICE_ProtocolReply, 2, 1, &errIndex);
2301
2302	    errorReply->type = ICE_PROTOCOL_ERROR;
2303	    errorReply->error_message =
2304		strdup("Received bad version index in Protocol Reply");
2305	}
2306	else
2307	{
2308	    _IceProtocolReply *reply =
2309	        &(((_IceReply *) (replyWait->reply))->protocol_reply);
2310
2311	    reply->type = ICE_PROTOCOL_REPLY;
2312	    reply->major_opcode = message->protocolOpcode;
2313	    reply->version_index = message->versionIndex;
2314
2315	    EXTRACT_STRING (pData, swap, reply->vendor);
2316	    EXTRACT_STRING (pData, swap, reply->release);
2317	}
2318
2319	replyReady = True;
2320    }
2321    else
2322    {
2323	_IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue);
2324
2325	replyReady = False;
2326    }
2327
2328    IceDisposeCompleteMessage (iceConn, pStart);
2329
2330    return (replyReady);
2331}
2332
2333
2334
2335static int
2336ProcessPing (
2337	IceConn 	iceConn,
2338	unsigned long	length
2339)
2340{
2341    CHECK_SIZE_MATCH (iceConn, ICE_Ping,
2342	length, SIZEOF (icePingMsg), IceFatalToConnection, 0);
2343
2344    PingReply (iceConn);
2345
2346    return (0);
2347}
2348
2349
2350
2351static int
2352ProcessPingReply (
2353	IceConn 	iceConn,
2354	unsigned long	length
2355)
2356{
2357    CHECK_SIZE_MATCH (iceConn, ICE_PingReply,
2358	length, SIZEOF (icePingReplyMsg), IceFatalToConnection, 0);
2359
2360    if (iceConn->ping_waits)
2361    {
2362	_IcePingWait *next = iceConn->ping_waits->next;
2363
2364	(*iceConn->ping_waits->ping_reply_proc) (iceConn,
2365	    iceConn->ping_waits->client_data);
2366
2367	free (iceConn->ping_waits);
2368	iceConn->ping_waits = next;
2369    }
2370    else
2371    {
2372	_IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue);
2373    }
2374
2375    return (0);
2376}
2377
2378
2379
2380static int
2381ProcessWantToClose (
2382	IceConn 	iceConn,
2383	unsigned long	length,
2384	Bool		*connectionClosedRet
2385)
2386{
2387    *connectionClosedRet = False;
2388
2389    CHECK_SIZE_MATCH (iceConn, ICE_WantToClose,
2390	length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection, 0);
2391
2392    if (iceConn->want_to_close || iceConn->open_ref_count == 0)
2393    {
2394	/*
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.
2401	 */
2402
2403	_IceConnectionClosed (iceConn);		/* invoke watch procs */
2404	_IceFreeConnection (iceConn);
2405	*connectionClosedRet = True;
2406    }
2407    else if (iceConn->proto_ref_count > 0)
2408    {
2409	/*
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.
2412	 */
2413
2414	IceSimpleMessage (iceConn, 0, ICE_NoClose);
2415	IceFlush (iceConn);
2416    }
2417    else
2418    {
2419	/*
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
2424	 * later on.
2425	 */
2426
2427	if (!iceConn->protosetup_to_you)
2428	{
2429	    IceSimpleMessage (iceConn, 0, ICE_NoClose);
2430	    IceFlush (iceConn);
2431	}
2432    }
2433
2434    return (0);
2435}
2436
2437
2438
2439static int
2440ProcessNoClose (
2441	IceConn 	iceConn,
2442	unsigned long	length
2443)
2444{
2445    CHECK_SIZE_MATCH (iceConn, ICE_NoClose,
2446	length, SIZEOF (iceNoCloseMsg), IceFatalToConnection, 0);
2447
2448    if (iceConn->want_to_close)
2449    {
2450	/*
2451	 * The other side can't close now.  We cancel our WantToClose,
2452	 * and we can expect a WantToClose from the other side.
2453	 */
2454
2455	iceConn->want_to_close = 0;
2456    }
2457    else
2458    {
2459	_IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue);
2460    }
2461
2462    return (0);
2463}
2464
2465
2466
2467static void
2468_IceProcessCoreMessage (
2469	IceConn 	 iceConn,
2470	int     	 opcode,
2471	unsigned long	 length,
2472	Bool    	 swap,
2473	IceReplyWaitInfo *replyWait,
2474	Bool		 *replyReadyRet,
2475	Bool		 *connectionClosedRet
2476)
2477{
2478    Bool replyReady = False;
2479
2480    *connectionClosedRet = False;
2481
2482    switch (opcode)
2483    {
2484    case ICE_Error:
2485
2486	replyReady = ProcessError (iceConn, length, swap, replyWait);
2487	break;
2488
2489    case ICE_ConnectionSetup:
2490
2491	ProcessConnectionSetup (iceConn, length, swap);
2492	break;
2493
2494    case ICE_AuthRequired:
2495
2496	replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait);
2497        break;
2498
2499    case ICE_AuthReply:
2500
2501	ProcessAuthReply (iceConn, length, swap);
2502	break;
2503
2504    case ICE_AuthNextPhase:
2505
2506	replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait);
2507	break;
2508
2509    case ICE_ConnectionReply:
2510
2511	replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait);
2512	break;
2513
2514    case ICE_ProtocolSetup:
2515
2516	ProcessProtocolSetup (iceConn, length, swap);
2517	break;
2518
2519    case ICE_ProtocolReply:
2520
2521	replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait);
2522	break;
2523
2524    case ICE_Ping:
2525
2526	ProcessPing (iceConn, length);
2527	break;
2528
2529    case ICE_PingReply:
2530
2531	ProcessPingReply (iceConn, length);
2532	break;
2533
2534    case ICE_WantToClose:
2535
2536	ProcessWantToClose (iceConn, length, connectionClosedRet);
2537	break;
2538
2539    case ICE_NoClose:
2540
2541	ProcessNoClose (iceConn, length);
2542	break;
2543
2544    default:
2545
2546	_IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue);
2547	_IceReadSkip (iceConn, length << 3);
2548	break;
2549    }
2550
2551    if (replyWait)
2552	*replyReadyRet = replyReady;
2553}
2554
2555const int		_IceVersionCount = 1;
2556const _IceVersion	_IceVersions[] = {
2557			    {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};
2558
2559