1/****************************************************************************** 2 3 4Copyright 1993, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 25 26Author: Ralph Mor, X Consortium 27******************************************************************************/ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include <X11/ICE/ICElib.h> 33#include "ICElibint.h" 34 35#include <stdio.h> /* sprintf */ 36 37/* 38 * Check for bad length 39 */ 40 41#define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity, _return) \ 42 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \ 43 { \ 44 _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \ 45 return (_return); \ 46 } 47 48#define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \ 49 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \ 50 { \ 51 _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \ 52 return (0); \ 53 } 54 55#define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \ 56 if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \ 57 != _expected_len) \ 58 { \ 59 _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \ 60 IceDisposeCompleteMessage (iceConn, _pStart); \ 61 return (0); \ 62 } 63 64#define BAIL_STRING(_iceConn, _opcode, _pStart) {\ 65 _IceErrorBadLength (_iceConn, 0, _opcode, IceFatalToConnection);\ 66 IceDisposeCompleteMessage (_iceConn, _pStart);\ 67 return (0);\ 68} 69 70#ifndef HAVE_ASPRINTF 71# include <stdarg.h> 72 73/* sprintf variant found in newer libc's which allocates string to print to */ 74static int _X_ATTRIBUTE_PRINTF(2,3) 75asprintf(char ** ret, const char *format, ...) 76{ 77 char buf[256]; 78 int len; 79 va_list ap; 80 81 va_start(ap, format); 82 len = vsnprintf(buf, sizeof(buf), format, ap); 83 va_end(ap); 84 85 if (len < 0) 86 return -1; 87 88 if (len < sizeof(buf)) 89 { 90 *ret = strdup(buf); 91 } 92 else 93 { 94 *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */ 95 if (*ret != NULL) 96 { 97 va_start(ap, format); 98 len = vsnprintf(*ret, len + 1, format, ap); 99 va_end(ap); 100 if (len < 0) { 101 free(*ret); 102 *ret = NULL; 103 } 104 } 105 } 106 107 if (*ret == NULL) 108 return -1; 109 110 return len; 111} 112#endif 113 114 115/* 116 * IceProcessMessages: 117 * 118 * If replyWait == NULL, the client is not waiting for a reply. 119 * 120 * If replyWait != NULL, the client is waiting for a reply... 121 * 122 * - replyWait->sequence_of_request is the sequence number of the 123 * message for which the client is waiting a reply. This is needed 124 * to determine if an error matches a replyWait. 125 * 126 * - replyWait->major_opcode_of_request is the major opcode of the 127 * message for which we are waiting a reply. 128 * 129 * - replyWait->minor_opcode_of_request is the minor opcode of the 130 * message for which we are waiting a reply. 131 * 132 * - replyWait->reply is a pointer to the reply message which will be 133 * filled in when the reply is ready (the protocol library should 134 * cast this IcePointer to the appropriate reply type). In most cases, 135 * the reply will have some fixed-size part, and the sender function 136 * will have provided a pointer to a structure (e.g.) to hold this 137 * fixed-size data. If there is variable-length data, it would be 138 * expected that the reply function will have to allocate additional 139 * memory and store pointer(s) to that memory in the fixed-size 140 * structure. If the entire data is variable length (e.g., a single 141 * variable-length string), then the sender function would probably 142 * just pass a pointer to fixed-size space to hold a pointer, and the 143 * reply function would allocate the storage and store the pointer. 144 * It is the responsibility of the client receiving the reply to 145 * free up any memory allocated on it's behalf. 146 * 147 * We might be waiting for several different replies (a function can wait 148 * for a reply, and while calling IceProcessMessages, a callback can be 149 * invoked which will wait for another reply). We take advantage of the 150 * fact that for a given protocol, we are guaranteed that messages are 151 * processed in the order we sent them. So, 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 169IceProcessMessagesStatus 170IceProcessMessages ( 171 IceConn iceConn, 172 IceReplyWaitInfo *replyWait, 173 Bool *replyReadyRet 174) 175{ 176 iceMsg *header; 177 Bool replyReady = False; 178 IceReplyWaitInfo *useThisReplyWait = NULL; 179 IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess; 180 181 if (replyWait) 182 *replyReadyRet = False; 183 184 /* 185 * Each time IceProcessMessages is entered, we increment the dispatch 186 * level. Each time we leave it, we decrement the dispatch level. 187 */ 188 189 iceConn->dispatch_level++; 190 191 192 /* 193 * Read the ICE message header. 194 */ 195 196 if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf)) 197 { 198 /* 199 * If we previously sent a WantToClose and now we detected 200 * that the connection was closed, _IceRead returns status 0. 201 * Since the connection was closed, we just want to return here. 202 */ 203 204 return (IceProcessMessagesConnectionClosed); 205 } 206 207 if (!iceConn->io_ok) 208 { 209 /* 210 * An unexpected IO error 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 434static void 435AuthRequired ( 436 IceConn iceConn, 437 int authIndex, 438 int authDataLen, 439 IcePointer authData 440) 441{ 442 iceAuthRequiredMsg *pMsg; 443 444 IceGetHeader (iceConn, 0, ICE_AuthRequired, 445 SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg); 446 447 pMsg->authIndex = authIndex; 448 pMsg->authDataLength = authDataLen; 449 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 464static void 465AuthReply ( 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 489static void 490AuthNextPhase ( 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 514static void 515AcceptConnection ( 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 547static void 548AcceptProtocol ( 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 592static void 593PingReply ( 594 IceConn iceConn 595) 596{ 597 IceSimpleMessage (iceConn, 0, ICE_PingReply); 598 IceFlush (iceConn); 599} 600 601 602 603static Bool 604ProcessError ( 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 874static int 875ProcessConnectionSetup ( 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 1140static Bool 1141ProcessAuthRequired ( 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 1334static int 1335ProcessAuthReply ( 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 1624static Bool 1625ProcessAuthNextPhase ( 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 1756static Bool 1757ProcessConnectionReply ( 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 1858static int 1859ProcessProtocolSetup ( 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 2259static Bool 2260ProcessProtocolReply ( 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 2363static int 2364ProcessPing ( 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 2379static int 2380ProcessPingReply ( 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 2408static int 2409ProcessWantToClose ( 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 2467static int 2468ProcessNoClose ( 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 2495static 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 2583const int _IceVersionCount = 1; 2584const _IceVersion _IceVersions[] = { 2585 {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}}; 2586