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