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