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