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