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