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