process.c revision a3129944
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 if (!errorStr) 708 { 709 errorStr = strdup(""); 710 } 711 712 errorReply->type = ICE_CONNECTION_ERROR; 713 errorReply->error_message = errorStr; 714 } 715 else if (iceConn->protosetup_to_you && 716 ((!iceConn->protosetup_to_you->auth_active && 717 message->offendingMinorOpcode == ICE_ProtocolSetup) || 718 (iceConn->protosetup_to_you->auth_active && 719 message->offendingMinorOpcode == ICE_AuthReply))) 720 { 721 _IceProtocolError *errorReply = 722 &(((_IceReply *) (replyWait->reply))->protocol_error); 723 char *errorStr = NULL; 724 const char *prefix; 725 char *temp; 726 727 invokeHandler = 0; 728 errorReturned = True; 729 730 switch (message->errorClass) 731 { 732 case IceNoVersion: 733 734 errorStr = strdup( 735 "None of the protocol versions specified are supported"); 736 break; 737 738 case IceNoAuth: 739 740 errorStr = strdup( 741 "None of the authentication protocols specified are supported"); 742 743 break; 744 745 case IceSetupFailed: 746 747 prefix = "Protocol Setup Failed, reason : "; 748 749 EXTRACT_STRING (pData, swap, temp); 750 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) 751 errorStr = NULL; 752 free (temp); 753 break; 754 755 case IceAuthRejected: 756 757 prefix = "Authentication Rejected, reason : "; 758 EXTRACT_STRING (pData, swap, temp); 759 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) 760 errorStr = NULL; 761 free (temp); 762 break; 763 764 case IceAuthFailed: 765 766 prefix = "Authentication Failed, reason : "; 767 EXTRACT_STRING (pData, swap, temp); 768 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) 769 errorStr = NULL; 770 free (temp); 771 break; 772 773 case IceProtocolDuplicate: 774 775 prefix = "Protocol was already registered : "; 776 EXTRACT_STRING (pData, swap, temp); 777 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) 778 errorStr = NULL; 779 free (temp); 780 break; 781 782 case IceMajorOpcodeDuplicate: 783 784 prefix = "The major opcode was already used : "; 785 if (asprintf (&errorStr, "%s%d", prefix, (int) *pData) == -1) 786 errorStr = NULL; 787 break; 788 789 case IceUnknownProtocol: 790 791 prefix = "Unknown Protocol : "; 792 EXTRACT_STRING (pData, swap, temp); 793 if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) 794 errorStr = NULL; 795 free (temp); 796 break; 797 798 default: 799 invokeHandler = 1; 800 } 801 802 if (!errorStr) 803 { 804 errorStr = strdup(""); 805 } 806 807 errorReply->type = ICE_PROTOCOL_ERROR; 808 errorReply->error_message = errorStr; 809 } 810 811 if (errorReturned == True) 812 { 813 /* 814 * If we tried to authenticate, tell the authentication 815 * procedure to clean up. 816 */ 817 818 IcePoAuthProc authProc; 819 820 if (iceConn->connect_to_you && 821 iceConn->connect_to_you->auth_active) 822 { 823 authProc = _IcePoAuthProcs[(int) 824 (iceConn->connect_to_you->my_auth_index)]; 825 826 (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state, 827 True /* clean up */, False /* swap */, 828 0, NULL, NULL, NULL, NULL); 829 } 830 else if (iceConn->protosetup_to_you && 831 iceConn->protosetup_to_you->auth_active) 832 { 833 _IcePoProtocol *protocol = _IceProtocols[ 834 iceConn->protosetup_to_you->my_opcode - 1].orig_client; 835 836 authProc = protocol->auth_procs[(int)(iceConn-> 837 protosetup_to_you->my_auth_index)]; 838 839 (*authProc) (iceConn, 840 &iceConn->protosetup_to_you->my_auth_state, 841 True /* clean up */, False /* swap */, 842 0, NULL, NULL, NULL, NULL); 843 } 844 } 845 } 846 847 if (invokeHandler) 848 { 849 (*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode, 850 message->offendingSequenceNum, message->errorClass, 851 message->severity, (IcePointer) pData); 852 } 853 854 IceDisposeCompleteMessage (iceConn, pStart); 855 856 return (errorReturned); 857} 858 859 860 861static int 862ProcessConnectionSetup ( 863 IceConn iceConn, 864 unsigned long length, 865 Bool swap 866) 867{ 868 iceConnectionSetupMsg *message; 869 const int myVersionCount = _IceVersionCount; 870 int hisVersionCount; 871 int myVersionIndex, hisVersionIndex; 872 int hisMajorVersion, hisMinorVersion; 873 int myAuthCount, hisAuthCount; 874 int found, i, j; 875 char **hisAuthNames = NULL; 876 char *pData, *pStart, *pEnd; 877 char *vendor = NULL; 878 char *release = NULL; 879 int myAuthIndex = 0; 880 int hisAuthIndex = 0; 881 int accept_setup_now = 0; 882 char mustAuthenticate; 883 int authUsableCount; 884 int authUsableFlags[MAX_ICE_AUTH_NAMES]; 885 int authIndices[MAX_ICE_AUTH_NAMES]; 886 887 CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup, 888 length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection); 889 890 IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg), 891 iceConnectionSetupMsg, message, pStart); 892 893 if (!IceValidIO (iceConn)) 894 { 895 IceDisposeCompleteMessage (iceConn, pStart); 896 return (0); 897 } 898 899 pData = pStart; 900 pEnd = pStart + (length << 3); 901 902 SKIP_STRING (pData, swap, pEnd, 903 BAIL_STRING(iceConn, ICE_ConnectionSetup, 904 pStart)); /* vendor */ 905 SKIP_STRING (pData, swap, pEnd, 906 BAIL_STRING(iceConn, ICE_ConnectionSetup, 907 pStart)); /* release */ 908 SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd, 909 BAIL_STRING(iceConn, ICE_ConnectionSetup, 910 pStart)); /* auth names */ 911 912 pData += (message->versionCount * 4); /* versions */ 913 914 CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup, 915 length, pData - pStart + SIZEOF (iceConnectionSetupMsg), 916 pStart, IceFatalToConnection); 917 918 mustAuthenticate = message->mustAuthenticate; 919 if (mustAuthenticate != 0 && mustAuthenticate != 1) 920 { 921 _IceErrorBadValue (iceConn, 0, 922 ICE_ConnectionSetup, 8, 1, &mustAuthenticate); 923 iceConn->connection_status = IceConnectRejected; 924 IceDisposeCompleteMessage (iceConn, pStart); 925 return (0); 926 } 927 928 pData = pStart; 929 930 EXTRACT_STRING (pData, swap, vendor); 931 EXTRACT_STRING (pData, swap, release); 932 933 hisAuthCount = message->authCount; 934 if (hisAuthCount > 0) 935 { 936 hisAuthNames = malloc (hisAuthCount * sizeof (char *)); 937 EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames); 938 } 939 940 hisVersionCount = message->versionCount; 941 942 hisVersionIndex = myVersionIndex = found = 0; 943 944 for (i = 0; i < hisVersionCount && !found; i++) 945 { 946 EXTRACT_CARD16 (pData, swap, hisMajorVersion); 947 EXTRACT_CARD16 (pData, swap, hisMinorVersion); 948 949 for (j = 0; j < myVersionCount && !found; j++) 950 { 951 if (_IceVersions[j].major_version == hisMajorVersion && 952 _IceVersions[j].minor_version == hisMinorVersion) 953 { 954 hisVersionIndex = i; 955 myVersionIndex = j; 956 found = 1; 957 } 958 } 959 } 960 961 if (!found) 962 { 963 _IceErrorNoVersion (iceConn, ICE_ConnectionSetup); 964 iceConn->connection_status = IceConnectRejected; 965 966 free (vendor); 967 free (release); 968 969 if (hisAuthCount > 0) 970 { 971 for (i = 0; i < hisAuthCount; i++) 972 free (hisAuthNames[i]); 973 974 free (hisAuthNames); 975 } 976 977 IceDisposeCompleteMessage (iceConn, pStart); 978 return (0); 979 } 980 981 _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string, 982 _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices); 983 984 for (i = 0; i < _IceAuthCount; i++) 985 { 986 authUsableFlags[i] = 0; 987 for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) 988 authUsableFlags[i] = (authIndices[j] == i); 989 } 990 991 myAuthCount = _IceAuthCount; 992 993 for (i = found = 0; i < myAuthCount && !found; i++) 994 { 995 if (authUsableFlags[i]) 996 { 997 const char *myAuthName = _IceAuthNames[i]; 998 999 for (j = 0; j < hisAuthCount && !found; j++) 1000 if (strcmp (myAuthName, hisAuthNames[j]) == 0) 1001 { 1002 myAuthIndex = i; 1003 hisAuthIndex = j; 1004 found = 1; 1005 } 1006 } 1007 } 1008 1009 if (!found) 1010 { 1011 /* 1012 * None of the authentication methods specified by the 1013 * other client is supported. If the other client requires 1014 * authentication, we must reject the connection now. 1015 * Otherwise, we can invoke the host-based authentication callback 1016 * to see if we can accept this connection. 1017 */ 1018 1019 if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc) 1020 { 1021 _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup); 1022 iceConn->connection_status = IceConnectRejected; 1023 } 1024 else 1025 { 1026 char *hostname = _IceGetPeerName (iceConn); 1027 1028 if ((*iceConn->listen_obj->host_based_auth_proc) (hostname)) 1029 { 1030 accept_setup_now = 1; 1031 } 1032 else 1033 { 1034 _IceErrorAuthenticationRejected (iceConn, 1035 ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed"); 1036 1037 iceConn->connection_status = IceConnectRejected; 1038 } 1039 1040 free (hostname); 1041 } 1042 1043 if (iceConn->connection_status == IceConnectRejected) 1044 { 1045 free (vendor); 1046 free (release); 1047 } 1048 } 1049 else 1050 { 1051 IcePaAuthStatus status; 1052 int authDataLen; 1053 IcePointer authData = NULL; 1054 IcePointer authState; 1055 char *errorString = NULL; 1056 IcePaAuthProc authProc = _IcePaAuthProcs[myAuthIndex]; 1057 1058 authState = NULL; 1059 1060 status = (*authProc) (iceConn, &authState, 1061 swap, 0, NULL, &authDataLen, &authData, &errorString); 1062 1063 if (status == IcePaAuthContinue) 1064 { 1065 _IceConnectToMeInfo *setupInfo; 1066 1067 AuthRequired (iceConn, hisAuthIndex, authDataLen, authData); 1068 1069 iceConn->connect_to_me = setupInfo = 1070 malloc (sizeof (_IceConnectToMeInfo)); 1071 1072 setupInfo->my_version_index = myVersionIndex; 1073 setupInfo->his_version_index = hisVersionIndex; 1074 setupInfo->his_vendor = vendor; 1075 setupInfo->his_release = release; 1076 setupInfo->my_auth_index = myAuthIndex; 1077 setupInfo->my_auth_state = authState; 1078 setupInfo->must_authenticate = mustAuthenticate; 1079 } 1080 else if (status == IcePaAuthAccepted) 1081 { 1082 accept_setup_now = 1; 1083 } 1084 else 1085 { 1086 free (vendor); 1087 free (release); 1088 } 1089 1090 if (authData && authDataLen > 0) 1091 free (authData); 1092 1093 free (errorString); 1094 } 1095 1096 if (accept_setup_now) 1097 { 1098 AcceptConnection (iceConn, hisVersionIndex); 1099 1100 iceConn->vendor = vendor; 1101 iceConn->release = release; 1102 iceConn->my_ice_version_index = myVersionIndex; 1103 } 1104 1105 if (hisAuthCount > 0) 1106 { 1107 for (i = 0; i < hisAuthCount; i++) 1108 free (hisAuthNames[i]); 1109 1110 free (hisAuthNames); 1111 } 1112 1113 IceDisposeCompleteMessage (iceConn, pStart); 1114 return (0); 1115} 1116 1117 1118 1119static Bool 1120ProcessAuthRequired ( 1121 IceConn iceConn, 1122 unsigned long length, 1123 Bool swap, 1124 IceReplyWaitInfo *replyWait 1125) 1126{ 1127 iceAuthRequiredMsg *message; 1128 int authDataLen; 1129 IcePointer authData; 1130 int replyDataLen; 1131 IcePointer replyData = NULL; 1132 char *errorString = NULL; 1133 IcePoAuthProc authProc; 1134 IcePoAuthStatus status; 1135 IcePointer authState; 1136 int realAuthIndex = 0; 1137 1138 CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired, 1139 length, SIZEOF (iceAuthRequiredMsg), 1140 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); 1141 1142 IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg), 1143 iceAuthRequiredMsg, message, authData); 1144 1145 if (!IceValidIO (iceConn)) 1146 { 1147 IceDisposeCompleteMessage (iceConn, authData); 1148 return (0); 1149 } 1150 1151 if (swap) 1152 { 1153 message->authDataLength = lswaps (message->authDataLength); 1154 } 1155 1156 CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length, 1157 message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData, 1158 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); 1159 1160 if (iceConn->connect_to_you) 1161 { 1162 if ((int) message->authIndex >= _IceAuthCount) 1163 { 1164 _IceConnectionError *errorReply = 1165 &(((_IceReply *) (replyWait->reply))->connection_error); 1166 1167 const char *tempstr 1168 = "Received bad authIndex in the AuthRequired message"; 1169 char errIndex = (int) message->authIndex; 1170 1171 errorString = strdup(tempstr); 1172 1173 errorReply->type = ICE_CONNECTION_ERROR; 1174 errorReply->error_message = errorString; 1175 1176 _IceErrorBadValue (iceConn, 0, 1177 ICE_AuthRequired, 2, 1, &errIndex); 1178 1179 IceDisposeCompleteMessage (iceConn, authData); 1180 return (1); 1181 } 1182 else 1183 { 1184 authProc = _IcePoAuthProcs[message->authIndex]; 1185 1186 iceConn->connect_to_you->auth_active = 1; 1187 } 1188 } 1189 else if (iceConn->protosetup_to_you) 1190 { 1191 if ((int) message->authIndex >= 1192 iceConn->protosetup_to_you->my_auth_count) 1193 { 1194 _IceProtocolError *errorReply = 1195 &(((_IceReply *) (replyWait->reply))->protocol_error); 1196 1197 const char *tempstr 1198 = "Received bad authIndex in the AuthRequired message"; 1199 char errIndex = (int) message->authIndex; 1200 1201 errorString = strdup(tempstr); 1202 1203 errorReply->type = ICE_PROTOCOL_ERROR; 1204 errorReply->error_message = errorString; 1205 1206 _IceErrorBadValue (iceConn, 0, 1207 ICE_AuthRequired, 2, 1, &errIndex); 1208 1209 IceDisposeCompleteMessage (iceConn, authData); 1210 return (1); 1211 } 1212 else 1213 { 1214 _IcePoProtocol *myProtocol = _IceProtocols[ 1215 iceConn->protosetup_to_you->my_opcode - 1].orig_client; 1216 1217 realAuthIndex = iceConn->protosetup_to_you-> 1218 my_auth_indices[message->authIndex]; 1219 1220 authProc = myProtocol->auth_procs[realAuthIndex]; 1221 1222 iceConn->protosetup_to_you->auth_active = 1; 1223 } 1224 } 1225 else 1226 { 1227 /* 1228 * Unexpected message 1229 */ 1230 1231 _IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue); 1232 1233 IceDisposeCompleteMessage (iceConn, authData); 1234 return (0); 1235 } 1236 1237 authState = NULL; 1238 authDataLen = message->authDataLength; 1239 1240 status = (*authProc) (iceConn, &authState, False /* don't clean up */, 1241 swap, authDataLen, authData, &replyDataLen, &replyData, &errorString); 1242 1243 if (status == IcePoAuthHaveReply) 1244 { 1245 AuthReply (iceConn, replyDataLen, replyData); 1246 1247 replyWait->sequence_of_request = iceConn->send_sequence; 1248 replyWait->minor_opcode_of_request = ICE_AuthReply; 1249 1250 if (iceConn->connect_to_you) 1251 { 1252 iceConn->connect_to_you->my_auth_state = authState; 1253 iceConn->connect_to_you->my_auth_index = message->authIndex; 1254 } 1255 else if (iceConn->protosetup_to_you) 1256 { 1257 iceConn->protosetup_to_you->my_auth_state = authState; 1258 iceConn->protosetup_to_you->my_auth_index = realAuthIndex; 1259 } 1260 } 1261 else if (status == IcePoAuthRejected || status == IcePoAuthFailed) 1262 { 1263 const char *prefix; 1264 char *returnErrorString; 1265 1266 if (status == IcePoAuthRejected) 1267 { 1268 _IceErrorAuthenticationRejected (iceConn, 1269 ICE_AuthRequired, errorString); 1270 1271 prefix = "Authentication Rejected, reason : "; 1272 } 1273 else 1274 { 1275 _IceErrorAuthenticationFailed (iceConn, 1276 ICE_AuthRequired, errorString); 1277 1278 prefix = "Authentication Failed, reason : "; 1279 } 1280 1281 if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1) 1282 returnErrorString = strdup(""); 1283 free (errorString); 1284 1285 if (iceConn->connect_to_you) 1286 { 1287 _IceConnectionError *errorReply = 1288 &(((_IceReply *) (replyWait->reply))->connection_error); 1289 1290 errorReply->type = ICE_CONNECTION_ERROR; 1291 errorReply->error_message = returnErrorString; 1292 } 1293 else 1294 { 1295 _IceProtocolError *errorReply = 1296 &(((_IceReply *) (replyWait->reply))->protocol_error); 1297 1298 errorReply->type = ICE_PROTOCOL_ERROR; 1299 errorReply->error_message = returnErrorString; 1300 } 1301 } 1302 1303 if (replyData && replyDataLen > 0) 1304 free (replyData); 1305 1306 IceDisposeCompleteMessage (iceConn, authData); 1307 1308 return (status != IcePoAuthHaveReply); 1309} 1310 1311 1312 1313static int 1314ProcessAuthReply ( 1315 IceConn iceConn, 1316 unsigned long length, 1317 Bool swap 1318) 1319{ 1320 iceAuthReplyMsg *message; 1321 int replyDataLen; 1322 IcePointer replyData; 1323 int authDataLen; 1324 IcePointer authData = NULL; 1325 char *errorString = NULL; 1326 1327 CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply, 1328 length, SIZEOF (iceAuthReplyMsg), 1329 iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol); 1330 1331 IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg), 1332 iceAuthReplyMsg, message, replyData); 1333 1334 if (!IceValidIO (iceConn)) 1335 { 1336 IceDisposeCompleteMessage (iceConn, replyData); 1337 return (0); 1338 } 1339 1340 if (swap) 1341 { 1342 message->authDataLength = lswaps (message->authDataLength); 1343 } 1344 1345 CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length, 1346 message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData, 1347 iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol); 1348 1349 replyDataLen = message->authDataLength; 1350 1351 if (iceConn->connect_to_me) 1352 { 1353 IcePaAuthProc authProc = _IcePaAuthProcs[(int) 1354 (iceConn->connect_to_me->my_auth_index)]; 1355 IcePaAuthStatus status = 1356 (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap, 1357 replyDataLen, replyData, &authDataLen, &authData, &errorString); 1358 1359 if (status == IcePaAuthContinue) 1360 { 1361 AuthNextPhase (iceConn, authDataLen, authData); 1362 } 1363 else if (status == IcePaAuthRejected || status == IcePaAuthFailed) 1364 { 1365 /* 1366 * Before we reject, invoke host-based authentication callback 1367 * and give it a chance to accept the connection (only if the 1368 * other client doesn't require authentication). 1369 */ 1370 1371 if (!iceConn->connect_to_me->must_authenticate && 1372 iceConn->listen_obj->host_based_auth_proc) 1373 { 1374 char *hostname = _IceGetPeerName (iceConn); 1375 1376 if ((*iceConn->listen_obj->host_based_auth_proc) (hostname)) 1377 { 1378 status = IcePaAuthAccepted; 1379 } 1380 1381 free (hostname); 1382 } 1383 1384 if (status != IcePaAuthAccepted) 1385 { 1386 free (iceConn->connect_to_me->his_vendor); 1387 free (iceConn->connect_to_me->his_release); 1388 free (iceConn->connect_to_me); 1389 iceConn->connect_to_me = NULL; 1390 1391 iceConn->connection_status = IceConnectRejected; 1392 1393 if (status == IcePaAuthRejected) 1394 { 1395 _IceErrorAuthenticationRejected (iceConn, 1396 ICE_AuthReply, errorString); 1397 } 1398 else 1399 { 1400 _IceErrorAuthenticationFailed (iceConn, 1401 ICE_AuthReply, errorString); 1402 } 1403 } 1404 } 1405 1406 if (status == IcePaAuthAccepted) 1407 { 1408 AcceptConnection (iceConn, 1409 iceConn->connect_to_me->his_version_index); 1410 1411 iceConn->vendor = iceConn->connect_to_me->his_vendor; 1412 iceConn->release = iceConn->connect_to_me->his_release; 1413 iceConn->my_ice_version_index = 1414 iceConn->connect_to_me->my_version_index; 1415 1416 free (iceConn->connect_to_me); 1417 iceConn->connect_to_me = NULL; 1418 } 1419 } 1420 else if (iceConn->protosetup_to_me) 1421 { 1422 _IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me-> 1423 my_opcode - 1].accept_client; 1424 IcePaAuthProc authProc = myProtocol->auth_procs[(int) 1425 (iceConn->protosetup_to_me->my_auth_index)]; 1426 IcePaAuthStatus status = 1427 (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state, 1428 swap, replyDataLen, replyData, 1429 &authDataLen, &authData, &errorString); 1430 int free_setup_info = 1; 1431 1432 if (status == IcePaAuthContinue) 1433 { 1434 AuthNextPhase (iceConn, authDataLen, authData); 1435 free_setup_info = 0; 1436 } 1437 else if (status == IcePaAuthRejected || status == IcePaAuthFailed) 1438 { 1439 /* 1440 * Before we reject, invoke host-based authentication callback 1441 * and give it a chance to accept the Protocol Setup (only if the 1442 * other client doesn't require authentication). 1443 */ 1444 1445 if (!iceConn->protosetup_to_me->must_authenticate && 1446 myProtocol->host_based_auth_proc) 1447 { 1448 char *hostname = _IceGetPeerName (iceConn); 1449 1450 if ((*myProtocol->host_based_auth_proc) (hostname)) 1451 { 1452 status = IcePaAuthAccepted; 1453 } 1454 1455 free (hostname); 1456 } 1457 1458 if (status == IcePaAuthRejected) 1459 { 1460 _IceErrorAuthenticationRejected (iceConn, 1461 ICE_AuthReply, errorString); 1462 } 1463 else 1464 { 1465 _IceErrorAuthenticationFailed (iceConn, 1466 ICE_AuthReply, errorString); 1467 } 1468 } 1469 1470 if (status == IcePaAuthAccepted) 1471 { 1472 IcePaProcessMsgProc processMsgProc; 1473 IceProtocolSetupProc protocolSetupProc; 1474 IceProtocolActivateProc protocolActivateProc; 1475 _IceProcessMsgInfo *process_msg_info; 1476 IcePointer clientData = NULL; 1477 char *failureReason = NULL; 1478 Status status = 1; 1479 1480 protocolSetupProc = myProtocol->protocol_setup_proc; 1481 protocolActivateProc = myProtocol->protocol_activate_proc; 1482 1483 if (protocolSetupProc) 1484 { 1485 /* 1486 * Notify the client of the Protocol Setup. 1487 */ 1488 1489 status = (*protocolSetupProc) (iceConn, 1490 myProtocol->version_recs[iceConn->protosetup_to_me-> 1491 my_version_index].major_version, 1492 myProtocol->version_recs[iceConn->protosetup_to_me-> 1493 my_version_index].minor_version, 1494 iceConn->protosetup_to_me->his_vendor, 1495 iceConn->protosetup_to_me->his_release, 1496 &clientData, &failureReason); 1497 1498 /* 1499 * Set vendor and release pointers to NULL, so it won't 1500 * get freed below. The ProtocolSetupProc should 1501 * free it. 1502 */ 1503 1504 iceConn->protosetup_to_me->his_vendor = NULL; 1505 iceConn->protosetup_to_me->his_release = NULL; 1506 } 1507 1508 if (status != 0) 1509 { 1510 /* 1511 * Send the Protocol Reply 1512 */ 1513 1514 AcceptProtocol (iceConn, 1515 iceConn->protosetup_to_me->his_opcode, 1516 iceConn->protosetup_to_me->my_opcode, 1517 iceConn->protosetup_to_me->his_version_index, 1518 myProtocol->vendor, myProtocol->release); 1519 1520 1521 /* 1522 * Set info for this protocol. 1523 */ 1524 1525 processMsgProc = myProtocol->version_recs[ 1526 iceConn->protosetup_to_me-> 1527 my_version_index].process_msg_proc; 1528 1529 process_msg_info = &iceConn->process_msg_info[ 1530 iceConn->protosetup_to_me-> 1531 his_opcode -iceConn->his_min_opcode]; 1532 1533 process_msg_info->client_data = clientData; 1534 process_msg_info->accept_flag = 1; 1535 process_msg_info->process_msg_proc. 1536 accept_client = processMsgProc; 1537 1538 1539 /* 1540 * Increase the reference count for the number 1541 * of active protocols. 1542 */ 1543 1544 iceConn->proto_ref_count++; 1545 1546 1547 /* 1548 * Notify the client that the protocol is active. The reason 1549 * we have this 2nd callback invoked is because the client 1550 * may wish to immediately generate a message for this 1551 * protocol, but it must wait until we send the Protocol Reply. 1552 */ 1553 1554 if (protocolActivateProc) 1555 { 1556 (*protocolActivateProc) (iceConn, 1557 process_msg_info->client_data); 1558 } 1559 } 1560 else 1561 { 1562 /* 1563 * An error was encountered. 1564 */ 1565 1566 _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, 1567 failureReason); 1568 1569 free (failureReason); 1570 } 1571 } 1572 1573 1574 if (free_setup_info) 1575 { 1576 free (iceConn->protosetup_to_me->his_vendor); 1577 free (iceConn->protosetup_to_me->his_release); 1578 free (iceConn->protosetup_to_me); 1579 iceConn->protosetup_to_me = NULL; 1580 } 1581 } 1582 else 1583 { 1584 /* 1585 * Unexpected message 1586 */ 1587 1588 _IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue); 1589 } 1590 1591 if (authData && authDataLen > 0) 1592 free (authData); 1593 1594 1595 free (errorString); 1596 1597 IceDisposeCompleteMessage (iceConn, replyData); 1598 return (0); 1599} 1600 1601 1602 1603static Bool 1604ProcessAuthNextPhase ( 1605 IceConn iceConn, 1606 unsigned long length, 1607 Bool swap, 1608 IceReplyWaitInfo *replyWait 1609) 1610{ 1611 iceAuthNextPhaseMsg *message; 1612 int authDataLen; 1613 IcePointer authData; 1614 int replyDataLen; 1615 IcePointer replyData = NULL; 1616 char *errorString = NULL; 1617 IcePoAuthProc authProc; 1618 IcePoAuthStatus status; 1619 IcePointer *authState; 1620 1621 CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase, 1622 length, SIZEOF (iceAuthNextPhaseMsg), 1623 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); 1624 1625 IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg), 1626 iceAuthNextPhaseMsg, message, authData); 1627 1628 if (!IceValidIO (iceConn)) 1629 { 1630 IceDisposeCompleteMessage (iceConn, authData); 1631 return (0); 1632 } 1633 1634 if (swap) 1635 { 1636 message->authDataLength = lswaps (message->authDataLength); 1637 } 1638 1639 CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length, 1640 message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData, 1641 iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); 1642 1643 if (iceConn->connect_to_you) 1644 { 1645 authProc = _IcePoAuthProcs[(int) 1646 (iceConn->connect_to_you->my_auth_index)]; 1647 1648 authState = &iceConn->connect_to_you->my_auth_state; 1649 } 1650 else if (iceConn->protosetup_to_you) 1651 { 1652 _IcePoProtocol *myProtocol = 1653 _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client; 1654 1655 authProc = myProtocol->auth_procs[(int) 1656 (iceConn->protosetup_to_you->my_auth_index)]; 1657 1658 authState = &iceConn->protosetup_to_you->my_auth_state; 1659 } 1660 else 1661 { 1662 /* 1663 * Unexpected message 1664 */ 1665 1666 _IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue); 1667 1668 IceDisposeCompleteMessage (iceConn, authData); 1669 return (0); 1670 } 1671 1672 authDataLen = message->authDataLength; 1673 1674 status = (*authProc) (iceConn, authState, False /* don't clean up */, 1675 swap, authDataLen, authData, &replyDataLen, &replyData, &errorString); 1676 1677 if (status == IcePoAuthHaveReply) 1678 { 1679 AuthReply (iceConn, replyDataLen, replyData); 1680 1681 replyWait->sequence_of_request = iceConn->send_sequence; 1682 } 1683 else if (status == IcePoAuthRejected || status == IcePoAuthFailed) 1684 { 1685 const char *prefix = NULL; 1686 char *returnErrorString; 1687 1688 if (status == IcePoAuthRejected) 1689 { 1690 _IceErrorAuthenticationRejected (iceConn, 1691 ICE_AuthNextPhase, errorString); 1692 1693 prefix = "Authentication Rejected, reason : "; 1694 } 1695 else if (status == IcePoAuthFailed) 1696 { 1697 _IceErrorAuthenticationFailed (iceConn, 1698 ICE_AuthNextPhase, errorString); 1699 1700 prefix = "Authentication Failed, reason : "; 1701 } 1702 1703 if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1) 1704 returnErrorString = strdup(""); 1705 free (errorString); 1706 1707 if (iceConn->connect_to_you) 1708 { 1709 _IceConnectionError *errorReply = 1710 &(((_IceReply *) (replyWait->reply))->connection_error); 1711 1712 errorReply->type = ICE_CONNECTION_ERROR; 1713 errorReply->error_message = returnErrorString; 1714 } 1715 else 1716 { 1717 _IceProtocolError *errorReply = 1718 &(((_IceReply *) (replyWait->reply))->protocol_error); 1719 1720 errorReply->type = ICE_PROTOCOL_ERROR; 1721 errorReply->error_message = returnErrorString; 1722 } 1723 } 1724 1725 if (replyData && replyDataLen > 0) 1726 free (replyData); 1727 1728 IceDisposeCompleteMessage (iceConn, authData); 1729 1730 return (status != IcePoAuthHaveReply); 1731} 1732 1733 1734 1735static Bool 1736ProcessConnectionReply ( 1737 IceConn iceConn, 1738 unsigned long length, 1739 Bool swap, 1740 IceReplyWaitInfo *replyWait 1741) 1742{ 1743 iceConnectionReplyMsg *message; 1744 char *pData, *pStart, *pEnd; 1745 Bool replyReady; 1746 1747#if 0 /* No-op */ 1748 CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply, 1749 length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection); 1750#endif 1751 1752 IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg), 1753 iceConnectionReplyMsg, message, pStart); 1754 1755 if (!IceValidIO (iceConn)) 1756 { 1757 IceDisposeCompleteMessage (iceConn, pStart); 1758 return (0); 1759 } 1760 1761 pData = pStart; 1762 pEnd = pStart + (length << 3); 1763 1764 SKIP_STRING (pData, swap, pEnd, 1765 BAIL_STRING (iceConn, ICE_ConnectionReply, 1766 pStart)); /* vendor */ 1767 SKIP_STRING (pData, swap, pEnd, 1768 BAIL_STRING (iceConn, ICE_ConnectionReply, 1769 pStart)); /* release */ 1770 1771 CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply, 1772 length, pData - pStart + SIZEOF (iceConnectionReplyMsg), 1773 pStart, IceFatalToConnection); 1774 1775 pData = pStart; 1776 1777 if (iceConn->connect_to_you) 1778 { 1779 if (iceConn->connect_to_you->auth_active) 1780 { 1781 /* 1782 * Tell the authentication procedure to clean up. 1783 */ 1784 1785 IcePoAuthProc authProc = _IcePoAuthProcs[(int) 1786 (iceConn->connect_to_you->my_auth_index)]; 1787 1788 (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state, 1789 True /* clean up */, False /* swap */, 1790 0, NULL, NULL, NULL, NULL); 1791 } 1792 1793 if ((int) message->versionIndex >= _IceVersionCount) 1794 { 1795 _IceConnectionError *errorReply = 1796 &(((_IceReply *) (replyWait->reply))->connection_error); 1797 char errIndex = message->versionIndex; 1798 1799 _IceErrorBadValue (iceConn, 0, 1800 ICE_ConnectionReply, 2, 1, &errIndex); 1801 1802 errorReply->type = ICE_CONNECTION_ERROR; 1803 errorReply->error_message = 1804 strdup("Received bad version index in Connection Reply"); 1805 } 1806 else 1807 { 1808 _IceReply *reply = (_IceReply *) (replyWait->reply); 1809 1810 reply->type = ICE_CONNECTION_REPLY; 1811 reply->connection_reply.version_index = message->versionIndex; 1812 1813 EXTRACT_STRING (pData, swap, reply->connection_reply.vendor); 1814 EXTRACT_STRING (pData, swap, reply->connection_reply.release); 1815 } 1816 1817 replyReady = True; 1818 } 1819 else 1820 { 1821 /* 1822 * Unexpected message 1823 */ 1824 1825 _IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue); 1826 1827 replyReady = False; 1828 } 1829 1830 IceDisposeCompleteMessage (iceConn, pStart); 1831 1832 return (replyReady); 1833} 1834 1835 1836 1837static int 1838ProcessProtocolSetup ( 1839 IceConn iceConn, 1840 unsigned long length, 1841 Bool swap 1842) 1843{ 1844 iceProtocolSetupMsg *message; 1845 _IcePaProtocol *myProtocol; 1846 int myVersionCount, hisVersionCount; 1847 int myVersionIndex, hisVersionIndex; 1848 int hisMajorVersion, hisMinorVersion; 1849 int myAuthCount, hisAuthCount; 1850 int myOpcode, hisOpcode; 1851 int found, i, j; 1852 char **hisAuthNames = NULL; 1853 char *protocolName; 1854 char *pData, *pStart, *pEnd; 1855 char *vendor = NULL; 1856 char *release = NULL; 1857 int accept_setup_now = 0; 1858 int myAuthIndex = 0; 1859 int hisAuthIndex = 0; 1860 char mustAuthenticate; 1861 int authUsableCount; 1862 int authUsableFlags[MAX_ICE_AUTH_NAMES]; 1863 int authIndices[MAX_ICE_AUTH_NAMES]; 1864 1865 CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup, 1866 length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol); 1867 1868 if (iceConn->want_to_close) 1869 { 1870 /* 1871 * If we sent a WantToClose message, but just got a ProtocolSetup, 1872 * we must cancel our WantToClose. It is the responsiblity of the 1873 * other client to send a WantToClose later on. 1874 */ 1875 1876 iceConn->want_to_close = 0; 1877 } 1878 1879 IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg), 1880 iceProtocolSetupMsg, message, pStart); 1881 1882 if (!IceValidIO (iceConn)) 1883 { 1884 IceDisposeCompleteMessage (iceConn, pStart); 1885 return (0); 1886 } 1887 1888 pData = pStart; 1889 pEnd = pStart + (length << 3); 1890 1891 SKIP_STRING (pData, swap, pEnd, 1892 BAIL_STRING(iceConn, ICE_ProtocolSetup, 1893 pStart)); /* proto name */ 1894 SKIP_STRING (pData, swap, pEnd, 1895 BAIL_STRING(iceConn, ICE_ProtocolSetup, 1896 pStart)); /* vendor */ 1897 SKIP_STRING (pData, swap, pEnd, 1898 BAIL_STRING(iceConn, ICE_ProtocolSetup, 1899 pStart)); /* release */ 1900 SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd, 1901 BAIL_STRING(iceConn, ICE_ProtocolSetup, 1902 pStart)); /* auth names */ 1903 pData += (message->versionCount * 4); /* versions */ 1904 1905 CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup, 1906 length, pData - pStart + SIZEOF (iceProtocolSetupMsg), 1907 pStart, IceFatalToProtocol); 1908 1909 mustAuthenticate = message->mustAuthenticate; 1910 1911 if (mustAuthenticate != 0 && mustAuthenticate != 1) 1912 { 1913 _IceErrorBadValue (iceConn, 0, 1914 ICE_ProtocolSetup, 4, 1, &mustAuthenticate); 1915 IceDisposeCompleteMessage (iceConn, pStart); 1916 return (0); 1917 } 1918 1919 pData = pStart; 1920 1921 if (iceConn->process_msg_info && 1922 (int) message->protocolOpcode >= iceConn->his_min_opcode && 1923 (int) message->protocolOpcode <= iceConn->his_max_opcode && 1924 iceConn->process_msg_info[ 1925 message->protocolOpcode - iceConn->his_min_opcode].in_use) 1926 { 1927 _IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode); 1928 IceDisposeCompleteMessage (iceConn, pStart); 1929 return (0); 1930 } 1931 1932 EXTRACT_STRING (pData, swap, protocolName); 1933 1934 if (iceConn->process_msg_info) 1935 { 1936 for (i = 0; 1937 i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++) 1938 { 1939 if (iceConn->process_msg_info[i].in_use && strcmp (protocolName, 1940 iceConn->process_msg_info[i].protocol->protocol_name) == 0) 1941 { 1942 _IceErrorProtocolDuplicate (iceConn, protocolName); 1943 free (protocolName); 1944 IceDisposeCompleteMessage (iceConn, pStart); 1945 return (0); 1946 } 1947 } 1948 } 1949 1950 for (i = 0; i < _IceLastMajorOpcode; i++) 1951 if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0) 1952 break; 1953 1954 if (i < _IceLastMajorOpcode && 1955 (myProtocol = _IceProtocols[i].accept_client) != NULL) 1956 { 1957 hisOpcode = message->protocolOpcode; 1958 myOpcode = i + 1; 1959 free (protocolName); 1960 } 1961 else 1962 { 1963 _IceErrorUnknownProtocol (iceConn, protocolName); 1964 free (protocolName); 1965 IceDisposeCompleteMessage (iceConn, pStart); 1966 return (0); 1967 } 1968 1969 EXTRACT_STRING (pData, swap, vendor); 1970 EXTRACT_STRING (pData, swap, release); 1971 1972 hisAuthCount = message->authCount; 1973 if (hisAuthCount > 0) 1974 { 1975 hisAuthNames = malloc (hisAuthCount * sizeof (char *)); 1976 EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames); 1977 } 1978 1979 hisVersionCount = message->versionCount; 1980 myVersionCount = myProtocol->version_count; 1981 1982 hisVersionIndex = myVersionIndex = found = 0; 1983 1984 for (i = 0; i < hisVersionCount && !found; i++) 1985 { 1986 EXTRACT_CARD16 (pData, swap, hisMajorVersion); 1987 EXTRACT_CARD16 (pData, swap, hisMinorVersion); 1988 1989 for (j = 0; j < myVersionCount && !found; j++) 1990 { 1991 if (myProtocol->version_recs[j].major_version == hisMajorVersion && 1992 myProtocol->version_recs[j].minor_version == hisMinorVersion) 1993 { 1994 hisVersionIndex = i; 1995 myVersionIndex = j; 1996 found = 1; 1997 } 1998 } 1999 } 2000 2001 if (!found) 2002 { 2003 _IceErrorNoVersion (iceConn, ICE_ProtocolSetup); 2004 2005 free (vendor); 2006 free (release); 2007 2008 if (hisAuthCount > 0) 2009 { 2010 for (i = 0; i < hisAuthCount; i++) 2011 free (hisAuthNames[i]); 2012 2013 free (hisAuthNames); 2014 } 2015 2016 IceDisposeCompleteMessage (iceConn, pStart); 2017 return (0); 2018 } 2019 2020 myAuthCount = myProtocol->auth_count; 2021 2022 _IceGetPaValidAuthIndices ( 2023 _IceProtocols[myOpcode - 1].protocol_name, 2024 iceConn->connection_string, myAuthCount, 2025 (const char **) myProtocol->auth_names, 2026 &authUsableCount, authIndices); 2027 2028 for (i = 0; i < myAuthCount; i++) 2029 { 2030 authUsableFlags[i] = 0; 2031 for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) 2032 authUsableFlags[i] = (authIndices[j] == i); 2033 } 2034 2035 for (i = found = 0; i < myAuthCount && !found; i++) 2036 { 2037 if (authUsableFlags[i]) 2038 { 2039 const char *myAuthName = myProtocol->auth_names[i]; 2040 2041 for (j = 0; j < hisAuthCount && !found; j++) 2042 if (strcmp (myAuthName, hisAuthNames[j]) == 0) 2043 { 2044 myAuthIndex = i; 2045 hisAuthIndex = j; 2046 found = 1; 2047 } 2048 } 2049 } 2050 2051 if (!found) 2052 { 2053 /* 2054 * None of the authentication methods specified by the 2055 * other client is supported. If the other client requires 2056 * authentication, we must reject the Protocol Setup now. 2057 * Otherwise, we can invoke the host-based authentication callback 2058 * to see if we can accept this Protocol Setup. 2059 */ 2060 2061 if (mustAuthenticate || !myProtocol->host_based_auth_proc) 2062 { 2063 _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup); 2064 } 2065 else 2066 { 2067 char *hostname = _IceGetPeerName (iceConn); 2068 2069 if ((*myProtocol->host_based_auth_proc) (hostname)) 2070 { 2071 accept_setup_now = 1; 2072 } 2073 else 2074 { 2075 _IceErrorAuthenticationRejected (iceConn, 2076 ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed"); 2077 } 2078 2079 free (hostname); 2080 } 2081 } 2082 else 2083 { 2084 IcePaAuthStatus status; 2085 int authDataLen; 2086 IcePointer authData = NULL; 2087 IcePointer authState; 2088 char *errorString = NULL; 2089 IcePaAuthProc authProc = 2090 myProtocol->auth_procs[myAuthIndex]; 2091 2092 authState = NULL; 2093 2094 status = (*authProc) (iceConn, &authState, swap, 0, NULL, 2095 &authDataLen, &authData, &errorString); 2096 2097 if (status == IcePaAuthContinue) 2098 { 2099 _IceProtoSetupToMeInfo *setupInfo; 2100 2101 AuthRequired (iceConn, hisAuthIndex, authDataLen, authData); 2102 2103 iceConn->protosetup_to_me = setupInfo = 2104 malloc (sizeof (_IceProtoSetupToMeInfo)); 2105 2106 setupInfo->his_opcode = hisOpcode; 2107 setupInfo->my_opcode = myOpcode; 2108 setupInfo->my_version_index = myVersionIndex; 2109 setupInfo->his_version_index = hisVersionIndex; 2110 setupInfo->his_vendor = vendor; 2111 setupInfo->his_release = release; 2112 vendor = release = NULL; /* so we don't free it */ 2113 setupInfo->my_auth_index = myAuthIndex; 2114 setupInfo->my_auth_state = authState; 2115 setupInfo->must_authenticate = mustAuthenticate; 2116 } 2117 else if (status == IcePaAuthAccepted) 2118 { 2119 accept_setup_now = 1; 2120 } 2121 2122 if (authData && authDataLen > 0) 2123 free (authData); 2124 2125 2126 free (errorString); 2127 } 2128 2129 if (accept_setup_now) 2130 { 2131 IcePaProcessMsgProc processMsgProc; 2132 IceProtocolSetupProc protocolSetupProc; 2133 IceProtocolActivateProc protocolActivateProc; 2134 _IceProcessMsgInfo *process_msg_info; 2135 IcePointer clientData = NULL; 2136 char *failureReason = NULL; 2137 Status status = 1; 2138 2139 protocolSetupProc = myProtocol->protocol_setup_proc; 2140 protocolActivateProc = myProtocol->protocol_activate_proc; 2141 2142 if (protocolSetupProc) 2143 { 2144 /* 2145 * Notify the client of the Protocol Setup. 2146 */ 2147 2148 status = (*protocolSetupProc) (iceConn, 2149 myProtocol->version_recs[myVersionIndex].major_version, 2150 myProtocol->version_recs[myVersionIndex].minor_version, 2151 vendor, release, &clientData, &failureReason); 2152 2153 vendor = release = NULL; /* so we don't free it */ 2154 } 2155 2156 if (status != 0) 2157 { 2158 /* 2159 * Send the Protocol Reply 2160 */ 2161 2162 AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex, 2163 myProtocol->vendor, myProtocol->release); 2164 2165 2166 /* 2167 * Set info for this protocol. 2168 */ 2169 2170 processMsgProc = myProtocol->version_recs[ 2171 myVersionIndex].process_msg_proc; 2172 2173 process_msg_info = &iceConn->process_msg_info[hisOpcode - 2174 iceConn->his_min_opcode]; 2175 2176 process_msg_info->client_data = clientData; 2177 process_msg_info->accept_flag = 1; 2178 process_msg_info->process_msg_proc.accept_client = processMsgProc; 2179 2180 2181 /* 2182 * Increase the reference count for the number of active protocols. 2183 */ 2184 2185 iceConn->proto_ref_count++; 2186 2187 2188 /* 2189 * Notify the client that the protocol is active. The reason 2190 * we have this 2nd callback invoked is because the client 2191 * may wish to immediately generate a message for this 2192 * protocol, but it must wait until we send the Protocol Reply. 2193 */ 2194 2195 if (protocolActivateProc) 2196 { 2197 (*protocolActivateProc) (iceConn, 2198 process_msg_info->client_data); 2199 } 2200 } 2201 else 2202 { 2203 /* 2204 * An error was encountered. 2205 */ 2206 2207 _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason); 2208 2209 free (failureReason); 2210 } 2211 } 2212 2213 2214 free (vendor); 2215 free (release); 2216 2217 if (hisAuthCount > 0) 2218 { 2219 for (i = 0; i < hisAuthCount; i++) 2220 free (hisAuthNames[i]); 2221 2222 free (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 strdup("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 (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 2555const int _IceVersionCount = 1; 2556const _IceVersion _IceVersions[] = { 2557 {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}}; 2558 2559