process.c revision fb5e8d76
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 = 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 (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 = 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 (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 (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 (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 (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 (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 (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 (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 (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 = 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 (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 malloc (sizeof (_IceProtoSetupToMeInfo)); 2101 2102 setupInfo->his_opcode = hisOpcode; 2103 setupInfo->my_opcode = myOpcode; 2104 setupInfo->my_version_index = myVersionIndex; 2105 setupInfo->his_version_index = hisVersionIndex; 2106 setupInfo->his_vendor = vendor; 2107 setupInfo->his_release = release; 2108 vendor = release = NULL; /* so we don't free it */ 2109 setupInfo->my_auth_index = myAuthIndex; 2110 setupInfo->my_auth_state = authState; 2111 setupInfo->must_authenticate = mustAuthenticate; 2112 } 2113 else if (status == IcePaAuthAccepted) 2114 { 2115 accept_setup_now = 1; 2116 } 2117 2118 if (authData && authDataLen > 0) 2119 free (authData); 2120 2121 if (errorString) 2122 free (errorString); 2123 } 2124 2125 if (accept_setup_now) 2126 { 2127 IcePaProcessMsgProc processMsgProc; 2128 IceProtocolSetupProc protocolSetupProc; 2129 IceProtocolActivateProc protocolActivateProc; 2130 _IceProcessMsgInfo *process_msg_info; 2131 IcePointer clientData = NULL; 2132 char *failureReason = NULL; 2133 Status status = 1; 2134 2135 protocolSetupProc = myProtocol->protocol_setup_proc; 2136 protocolActivateProc = myProtocol->protocol_activate_proc; 2137 2138 if (protocolSetupProc) 2139 { 2140 /* 2141 * Notify the client of the Protocol Setup. 2142 */ 2143 2144 status = (*protocolSetupProc) (iceConn, 2145 myProtocol->version_recs[myVersionIndex].major_version, 2146 myProtocol->version_recs[myVersionIndex].minor_version, 2147 vendor, release, &clientData, &failureReason); 2148 2149 vendor = release = NULL; /* so we don't free it */ 2150 } 2151 2152 if (status != 0) 2153 { 2154 /* 2155 * Send the Protocol Reply 2156 */ 2157 2158 AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex, 2159 myProtocol->vendor, myProtocol->release); 2160 2161 2162 /* 2163 * Set info for this protocol. 2164 */ 2165 2166 processMsgProc = myProtocol->version_recs[ 2167 myVersionIndex].process_msg_proc; 2168 2169 process_msg_info = &iceConn->process_msg_info[hisOpcode - 2170 iceConn->his_min_opcode]; 2171 2172 process_msg_info->client_data = clientData; 2173 process_msg_info->accept_flag = 1; 2174 process_msg_info->process_msg_proc.accept_client = processMsgProc; 2175 2176 2177 /* 2178 * Increase the reference count for the number of active protocols. 2179 */ 2180 2181 iceConn->proto_ref_count++; 2182 2183 2184 /* 2185 * Notify the client that the protocol is active. The reason 2186 * we have this 2nd callback invoked is because the client 2187 * may wish to immediately generate a message for this 2188 * protocol, but it must wait until we send the Protocol Reply. 2189 */ 2190 2191 if (protocolActivateProc) 2192 { 2193 (*protocolActivateProc) (iceConn, 2194 process_msg_info->client_data); 2195 } 2196 } 2197 else 2198 { 2199 /* 2200 * An error was encountered. 2201 */ 2202 2203 _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason); 2204 2205 if (failureReason) 2206 free (failureReason); 2207 } 2208 } 2209 2210 if (vendor) 2211 free (vendor); 2212 2213 if (release) 2214 free (release); 2215 2216 if (hisAuthCount > 0) 2217 { 2218 for (i = 0; i < hisAuthCount; i++) 2219 free (hisAuthNames[i]); 2220 2221 free (hisAuthNames); 2222 } 2223 2224 IceDisposeCompleteMessage (iceConn, pStart); 2225 return (0); 2226} 2227 2228 2229 2230static Bool 2231ProcessProtocolReply ( 2232 IceConn iceConn, 2233 unsigned long length, 2234 Bool swap, 2235 IceReplyWaitInfo *replyWait 2236) 2237{ 2238 iceProtocolReplyMsg *message; 2239 char *pData, *pStart, *pEnd; 2240 Bool replyReady; 2241 2242#if 0 /* No-op */ 2243 CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply, 2244 length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol); 2245#endif 2246 2247 IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg), 2248 iceProtocolReplyMsg, message, pStart); 2249 2250 if (!IceValidIO (iceConn)) 2251 { 2252 IceDisposeCompleteMessage (iceConn, pStart); 2253 return (0); 2254 } 2255 2256 pData = pStart; 2257 pEnd = pStart + (length << 3); 2258 2259 SKIP_STRING (pData, swap, pEnd, 2260 BAIL_STRING(iceConn, ICE_ProtocolReply, 2261 pStart)); /* vendor */ 2262 SKIP_STRING (pData, swap, pEnd, 2263 BAIL_STRING(iceConn, ICE_ProtocolReply, 2264 pStart)); /* release */ 2265 2266 CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply, 2267 length, pData - pStart + SIZEOF (iceProtocolReplyMsg), 2268 pStart, IceFatalToProtocol); 2269 2270 pData = pStart; 2271 2272 if (iceConn->protosetup_to_you) 2273 { 2274 if (iceConn->protosetup_to_you->auth_active) 2275 { 2276 /* 2277 * Tell the authentication procedure to clean up. 2278 */ 2279 2280 _IcePoProtocol *myProtocol = _IceProtocols[ 2281 iceConn->protosetup_to_you->my_opcode - 1].orig_client; 2282 2283 IcePoAuthProc authProc = myProtocol->auth_procs[(int) 2284 (iceConn->protosetup_to_you->my_auth_index)]; 2285 2286 (*authProc) (iceConn, 2287 &iceConn->protosetup_to_you->my_auth_state, 2288 True /* clean up */, False /* swap */, 2289 0, NULL, NULL, NULL, NULL); 2290 } 2291 2292 if ((int) message->versionIndex >= _IceVersionCount) 2293 { 2294 _IceProtocolError *errorReply = 2295 &(((_IceReply *) (replyWait->reply))->protocol_error); 2296 char errIndex = message->versionIndex; 2297 2298 _IceErrorBadValue (iceConn, 0, 2299 ICE_ProtocolReply, 2, 1, &errIndex); 2300 2301 errorReply->type = ICE_PROTOCOL_ERROR; 2302 errorReply->error_message = 2303 "Received bad version index in Protocol Reply"; 2304 } 2305 else 2306 { 2307 _IceProtocolReply *reply = 2308 &(((_IceReply *) (replyWait->reply))->protocol_reply); 2309 2310 reply->type = ICE_PROTOCOL_REPLY; 2311 reply->major_opcode = message->protocolOpcode; 2312 reply->version_index = message->versionIndex; 2313 2314 EXTRACT_STRING (pData, swap, reply->vendor); 2315 EXTRACT_STRING (pData, swap, reply->release); 2316 } 2317 2318 replyReady = True; 2319 } 2320 else 2321 { 2322 _IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue); 2323 2324 replyReady = False; 2325 } 2326 2327 IceDisposeCompleteMessage (iceConn, pStart); 2328 2329 return (replyReady); 2330} 2331 2332 2333 2334static int 2335ProcessPing ( 2336 IceConn iceConn, 2337 unsigned long length 2338) 2339{ 2340 CHECK_SIZE_MATCH (iceConn, ICE_Ping, 2341 length, SIZEOF (icePingMsg), IceFatalToConnection, 0); 2342 2343 PingReply (iceConn); 2344 2345 return (0); 2346} 2347 2348 2349 2350static int 2351ProcessPingReply ( 2352 IceConn iceConn, 2353 unsigned long length 2354) 2355{ 2356 CHECK_SIZE_MATCH (iceConn, ICE_PingReply, 2357 length, SIZEOF (icePingReplyMsg), IceFatalToConnection, 0); 2358 2359 if (iceConn->ping_waits) 2360 { 2361 _IcePingWait *next = iceConn->ping_waits->next; 2362 2363 (*iceConn->ping_waits->ping_reply_proc) (iceConn, 2364 iceConn->ping_waits->client_data); 2365 2366 free (iceConn->ping_waits); 2367 iceConn->ping_waits = next; 2368 } 2369 else 2370 { 2371 _IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue); 2372 } 2373 2374 return (0); 2375} 2376 2377 2378 2379static int 2380ProcessWantToClose ( 2381 IceConn iceConn, 2382 unsigned long length, 2383 Bool *connectionClosedRet 2384) 2385{ 2386 *connectionClosedRet = False; 2387 2388 CHECK_SIZE_MATCH (iceConn, ICE_WantToClose, 2389 length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection, 0); 2390 2391 if (iceConn->want_to_close || iceConn->open_ref_count == 0) 2392 { 2393 /* 2394 * We just received a WantToClose. Either we also sent a 2395 * WantToClose, so we close the connection, or the iceConn 2396 * is not being used, so we close the connection. This 2397 * second case is possible if we sent a WantToClose because 2398 * the iceConn->open_ref_count reached zero, but then we 2399 * received a NoClose. 2400 */ 2401 2402 _IceConnectionClosed (iceConn); /* invoke watch procs */ 2403 _IceFreeConnection (iceConn); 2404 *connectionClosedRet = True; 2405 } 2406 else if (iceConn->proto_ref_count > 0) 2407 { 2408 /* 2409 * We haven't shut down all of our protocols yet. We send a NoClose, 2410 * and it's up to us to generate a WantToClose later on. 2411 */ 2412 2413 IceSimpleMessage (iceConn, 0, ICE_NoClose); 2414 IceFlush (iceConn); 2415 } 2416 else 2417 { 2418 /* 2419 * The reference count on this iceConn is zero. This means that 2420 * there are no active protocols, but the client didn't explicitly 2421 * close the connection yet. If we didn't just send a Protocol Setup, 2422 * we send a NoClose, and it's up to us to generate a WantToClose 2423 * later on. 2424 */ 2425 2426 if (!iceConn->protosetup_to_you) 2427 { 2428 IceSimpleMessage (iceConn, 0, ICE_NoClose); 2429 IceFlush (iceConn); 2430 } 2431 } 2432 2433 return (0); 2434} 2435 2436 2437 2438static int 2439ProcessNoClose ( 2440 IceConn iceConn, 2441 unsigned long length 2442) 2443{ 2444 CHECK_SIZE_MATCH (iceConn, ICE_NoClose, 2445 length, SIZEOF (iceNoCloseMsg), IceFatalToConnection, 0); 2446 2447 if (iceConn->want_to_close) 2448 { 2449 /* 2450 * The other side can't close now. We cancel our WantToClose, 2451 * and we can expect a WantToClose from the other side. 2452 */ 2453 2454 iceConn->want_to_close = 0; 2455 } 2456 else 2457 { 2458 _IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue); 2459 } 2460 2461 return (0); 2462} 2463 2464 2465 2466static void 2467_IceProcessCoreMessage ( 2468 IceConn iceConn, 2469 int opcode, 2470 unsigned long length, 2471 Bool swap, 2472 IceReplyWaitInfo *replyWait, 2473 Bool *replyReadyRet, 2474 Bool *connectionClosedRet 2475) 2476{ 2477 Bool replyReady = False; 2478 2479 *connectionClosedRet = False; 2480 2481 switch (opcode) 2482 { 2483 case ICE_Error: 2484 2485 replyReady = ProcessError (iceConn, length, swap, replyWait); 2486 break; 2487 2488 case ICE_ConnectionSetup: 2489 2490 ProcessConnectionSetup (iceConn, length, swap); 2491 break; 2492 2493 case ICE_AuthRequired: 2494 2495 replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait); 2496 break; 2497 2498 case ICE_AuthReply: 2499 2500 ProcessAuthReply (iceConn, length, swap); 2501 break; 2502 2503 case ICE_AuthNextPhase: 2504 2505 replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait); 2506 break; 2507 2508 case ICE_ConnectionReply: 2509 2510 replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait); 2511 break; 2512 2513 case ICE_ProtocolSetup: 2514 2515 ProcessProtocolSetup (iceConn, length, swap); 2516 break; 2517 2518 case ICE_ProtocolReply: 2519 2520 replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait); 2521 break; 2522 2523 case ICE_Ping: 2524 2525 ProcessPing (iceConn, length); 2526 break; 2527 2528 case ICE_PingReply: 2529 2530 ProcessPingReply (iceConn, length); 2531 break; 2532 2533 case ICE_WantToClose: 2534 2535 ProcessWantToClose (iceConn, length, connectionClosedRet); 2536 break; 2537 2538 case ICE_NoClose: 2539 2540 ProcessNoClose (iceConn, length); 2541 break; 2542 2543 default: 2544 2545 _IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue); 2546 _IceReadSkip (iceConn, length << 3); 2547 break; 2548 } 2549 2550 if (replyWait) 2551 *replyReadyRet = replyReady; 2552} 2553 2554int _IceVersionCount = 1; 2555_IceVersion _IceVersions[] = { 2556 {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}}; 2557 2558