1 /* 2 3 Copyright 1993, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21 Except as contained in this notice, the name of The Open Group shall not be 22 used in advertising or otherwise to promote the sale, use or other dealings 23 in this Software without prior written authorization from The Open Group. 24 25 */ 26 27 /* 28 * Author: Ralph Mor, X Consortium 29 */ 30 31 #ifdef HAVE_CONFIG_H 32 #include <config.h> 33 #endif 34 #include <X11/SM/SMlib.h> 35 #include <limits.h> 36 #include "SMlibint.h" 37 38 39 /* 40 * Check for bad length 41 */ 42 43 #define CHECK_SIZE_MATCH(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \ 44 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \ 45 { \ 46 _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \ 47 return; \ 48 } 49 50 #define CHECK_AT_LEAST_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \ 51 if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \ 52 { \ 53 _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \ 54 return; \ 55 } 56 57 58 static char * 60 extractArray8(char **pBuf, char *pEnd, Bool swap, int *len) 61 { 62 char *p; 63 int n; 64 65 if (pEnd - *pBuf < 4) 66 return NULL; 67 EXTRACT_CARD32 (*pBuf, swap, n); 68 if (n < 0 || n > INT_MAX - 7) 69 return NULL; 70 71 if ((p = malloc (n + 1)) == NULL) 72 return NULL; 73 memcpy(p, *pBuf, n); 74 p[n] = '\0'; 75 76 *pBuf += n + PAD64 (4 + n); 77 if (len != NULL) 78 *len = n; 79 80 return p; 81 } 82 83 84 static SmProp ** 86 extractListofProperty(char *pBuf, char *pEnd, Bool swap, int *count) 87 { 88 int i, j, n; 89 SmProp **props; 90 91 if (pEnd - pBuf < 4) 92 return NULL; 93 EXTRACT_CARD32 (pBuf, swap, n); 94 if (n < 0 || n > INT_MAX / sizeof (SmProp *)) 95 return NULL; 96 pBuf += 4; 97 98 props = malloc (n * sizeof(SmProp *)); 99 if (props == NULL) 100 return NULL; 101 102 for (i = 0; i < n; i++) 103 { 104 props[i] = calloc (1, sizeof (SmProp)); 105 if (props[i] == NULL) 106 goto fail; 107 if ((props[i]->name = extractArray8 (&pBuf, pEnd, swap, NULL)) == NULL) 108 goto fail; 109 if ((props[i]->type = extractArray8 (&pBuf, pEnd, swap, NULL)) == NULL) 110 goto fail; 111 112 if (pEnd - pBuf < 4) 113 goto fail; 114 EXTRACT_CARD32 (pBuf, swap, props[i]->num_vals); 115 if (props[i]->num_vals < 0) 116 goto fail; 117 pBuf += 4; 118 props[i]->vals = calloc (props[i]->num_vals, sizeof (SmPropValue)); 119 if (props[i]->vals == NULL) 120 goto fail; 121 122 for (j = 0; j < props[i]->num_vals; j++) 123 { 124 props[i]->vals[j].value = extractArray8 (&pBuf, pEnd, swap, 125 &props[i]->vals[j].length); 126 if (props[i]->vals[j].value == NULL) 127 goto fail; 128 } 129 } 130 131 *count = n; 132 return props; 133 134 fail: 135 for (; i >= 0; i--) 136 { 137 if (props[i] != NULL) 138 { 139 free (props[i]->name); 140 free (props[i]->type); 141 if (props[i]->vals != NULL) 142 { 143 for (j = 0; j < props[i]->num_vals; j++) 144 free (props[i]->vals[j].value); 145 free (props[i]->vals); 146 } 147 free (props[i]); 148 } 149 } 150 free (props); 151 return NULL; 152 } 153 154 155 static Bool 157 validErrorMessage(char *pData, char *pEnd, int errorClass, Bool swap) 158 { 159 if (errorClass == IceBadValue) 160 { 161 unsigned int length; 162 163 if (pEnd - pData < 8) 164 return False; 165 166 pData += 4; 167 EXTRACT_CARD32 (pData, swap, length); 168 if (length > pEnd - pData) 169 return False; 170 } 171 172 return True; 173 } 174 175 176 void 178 _SmcProcessMessage(IceConn iceConn, IcePointer clientData, int opcode, 179 unsigned long length, Bool swap, 180 IceReplyWaitInfo *replyWait, Bool *replyReadyRet) 181 { 182 SmcConn smcConn = (SmcConn) clientData; 183 184 if (replyWait) 185 *replyReadyRet = False; 186 187 if (!smcConn->client_id && 188 opcode != SM_RegisterClientReply && opcode != SM_Error) 189 { 190 _IceReadSkip (iceConn, length << 3); 191 192 _IceErrorBadState (iceConn, _SmcOpcode, opcode, IceFatalToProtocol); 193 return; 194 } 195 196 switch (opcode) 197 { 198 case SM_Error: 199 { 200 iceErrorMsg *pMsg; 201 char *pData, *pEnd; 202 203 CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode, 204 length, SIZEOF (iceErrorMsg), IceFatalToProtocol); 205 206 IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg), 207 iceErrorMsg, pMsg, pData); 208 209 if (!IceValidIO (iceConn) || pData == NULL) 210 { 211 IceDisposeCompleteMessage (iceConn, pData); 212 return; 213 } 214 215 if (swap) 216 { 217 pMsg->errorClass = lswaps (pMsg->errorClass); 218 pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum); 219 } 220 221 pEnd = pData + (length << 3) - (SIZEOF (iceErrorMsg) - SIZEOF(iceMsg)); 222 223 if (replyWait && 224 replyWait->minor_opcode_of_request == SM_RegisterClient && 225 pMsg->errorClass == IceBadValue && 226 pMsg->offendingMinorOpcode == SM_RegisterClient && 227 pMsg->offendingSequenceNum == replyWait->sequence_of_request) 228 { 229 /* 230 * For Register Client, the previous ID was bad. 231 */ 232 233 _SmcRegisterClientReply *reply = 234 (_SmcRegisterClientReply *) (replyWait->reply); 235 236 reply->status = 0; 237 238 *replyReadyRet = True; 239 } 240 else if (!validErrorMessage(pData, pEnd, pMsg->errorClass, swap)) 241 { 242 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 243 IceFatalToProtocol); 244 IceDisposeCompleteMessage (iceConn, pData); 245 return; 246 } 247 else 248 { 249 (*_SmcErrorHandler) (smcConn, swap, 250 pMsg->offendingMinorOpcode, 251 pMsg->offendingSequenceNum, 252 pMsg->errorClass, pMsg->severity, 253 (SmPointer) pData); 254 } 255 256 IceDisposeCompleteMessage (iceConn, pData); 257 break; 258 } 259 260 case SM_RegisterClientReply: 261 262 if (!replyWait || 263 replyWait->minor_opcode_of_request != SM_RegisterClient) 264 { 265 _IceReadSkip (iceConn, length << 3); 266 267 _IceErrorBadState (iceConn, _SmcOpcode, 268 SM_RegisterClientReply, IceFatalToProtocol); 269 } 270 else 271 { 272 smRegisterClientReplyMsg *pMsg; 273 char *pData, *pStart, *pEnd; 274 _SmcRegisterClientReply *reply = 275 (_SmcRegisterClientReply *) (replyWait->reply); 276 277 CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode, 278 length, SIZEOF (smRegisterClientReplyMsg), IceFatalToProtocol); 279 280 IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientReplyMsg), 281 smRegisterClientReplyMsg, pMsg, pStart); 282 283 if (!IceValidIO (iceConn) || pStart == NULL) 284 { 285 IceDisposeCompleteMessage (iceConn, pStart); 286 return; 287 } 288 289 pData = pStart; 290 pEnd = pStart + (length << 3) - 291 (SIZEOF (smRegisterClientReplyMsg) - SIZEOF (iceMsg)); 292 293 reply->client_id = extractArray8(&pData, pEnd, swap, NULL); 294 if (reply->client_id == NULL) { 295 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 296 IceFatalToProtocol); 297 IceDisposeCompleteMessage (iceConn, pStart); 298 return; 299 } 300 301 reply->status = 1; 302 *replyReadyRet = True; 303 304 IceDisposeCompleteMessage (iceConn, pStart); 305 } 306 break; 307 308 case SM_SaveYourself: 309 { 310 smSaveYourselfMsg *pMsg; 311 unsigned char errVal; 312 int errOffset = -1; 313 314 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode, 315 length, SIZEOF (smSaveYourselfMsg), 316 IceFatalToProtocol); 317 318 IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfMsg), 319 smSaveYourselfMsg, pMsg); 320 321 if (!IceValidIO (iceConn)) 322 { 323 return; 324 } 325 326 if (pMsg->saveType != SmSaveGlobal && 327 pMsg->saveType != SmSaveLocal && 328 pMsg->saveType != SmSaveBoth) 329 { 330 errVal = pMsg->saveType; 331 errOffset = 8; 332 } 333 else if (pMsg->shutdown != 1 && pMsg->shutdown != 0) 334 { 335 errVal = pMsg->shutdown; 336 errOffset = 9; 337 } 338 else if (pMsg->interactStyle != SmInteractStyleNone && 339 pMsg->interactStyle != SmInteractStyleErrors && 340 pMsg->interactStyle != SmInteractStyleAny) 341 { 342 errVal = pMsg->interactStyle; 343 errOffset = 10; 344 } 345 else if (pMsg->fast != 1 && pMsg->fast != 0) 346 { 347 errVal = pMsg->fast; 348 errOffset = 11; 349 } 350 351 if (errOffset >= 0) 352 { 353 _IceErrorBadValue (iceConn, _SmcOpcode, 354 SM_SaveYourself, errOffset, 1, (IcePointer) &errVal); 355 } 356 else 357 { 358 (*smcConn->callbacks.save_yourself.callback) (smcConn, 359 smcConn->callbacks.save_yourself.client_data, 360 pMsg->saveType, pMsg->shutdown, 361 pMsg->interactStyle, pMsg->fast); 362 363 smcConn->save_yourself_in_progress = True; 364 365 if (pMsg->shutdown) 366 smcConn->shutdown_in_progress = True; 367 } 368 break; 369 } 370 371 case SM_SaveYourselfPhase2: 372 373 if (!smcConn->phase2_wait) 374 { 375 _IceErrorBadState (iceConn, _SmcOpcode, 376 SM_SaveYourselfPhase2, IceCanContinue); 377 } 378 else 379 { 380 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode, 381 length, SIZEOF (smSaveYourselfPhase2Msg), 382 IceFatalToProtocol); 383 384 (*smcConn->phase2_wait->phase2_proc) (smcConn, 385 smcConn->phase2_wait->client_data); 386 387 free (smcConn->phase2_wait); 388 smcConn->phase2_wait = NULL; 389 } 390 break; 391 392 case SM_Interact: 393 394 if (!smcConn->interact_waits) 395 { 396 _IceErrorBadState (iceConn, _SmcOpcode, 397 SM_Interact, IceCanContinue); 398 } 399 else 400 { 401 _SmcInteractWait *next = smcConn->interact_waits->next; 402 403 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode, 404 length, SIZEOF (smInteractMsg), 405 IceFatalToProtocol); 406 407 (*smcConn->interact_waits->interact_proc) (smcConn, 408 smcConn->interact_waits->client_data); 409 410 free (smcConn->interact_waits); 411 smcConn->interact_waits = next; 412 } 413 break; 414 415 case SM_SaveComplete: 416 417 if (!smcConn->save_yourself_in_progress) 418 { 419 _IceErrorBadState (iceConn, _SmcOpcode, 420 SM_SaveComplete, IceCanContinue); 421 } 422 else 423 { 424 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode, 425 length, SIZEOF (smSaveCompleteMsg), 426 IceFatalToProtocol); 427 428 smcConn->save_yourself_in_progress = False; 429 430 (*smcConn->callbacks.save_complete.callback) (smcConn, 431 smcConn->callbacks.save_complete.client_data); 432 } 433 break; 434 435 case SM_Die: 436 437 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode, 438 length, SIZEOF (smDieMsg), 439 IceFatalToProtocol); 440 441 (*smcConn->callbacks.die.callback) (smcConn, 442 smcConn->callbacks.die.client_data); 443 break; 444 445 case SM_ShutdownCancelled: 446 447 if (!smcConn->shutdown_in_progress) 448 { 449 _IceErrorBadState (iceConn, _SmcOpcode, 450 SM_ShutdownCancelled, IceCanContinue); 451 } 452 else 453 { 454 CHECK_SIZE_MATCH (iceConn, _SmcOpcode, opcode, 455 length, SIZEOF (smShutdownCancelledMsg), 456 IceFatalToProtocol); 457 458 smcConn->shutdown_in_progress = False; 459 460 (*smcConn->callbacks.shutdown_cancelled.callback) (smcConn, 461 smcConn->callbacks.shutdown_cancelled.client_data); 462 } 463 break; 464 465 case SM_PropertiesReply: 466 467 if (!smcConn->prop_reply_waits) 468 { 469 _IceReadSkip (iceConn, length << 3); 470 471 _IceErrorBadState (iceConn, _SmcOpcode, 472 SM_PropertiesReply, IceCanContinue); 473 } 474 else 475 { 476 smPropertiesReplyMsg *pMsg; 477 char *pStart, *pEnd; 478 int numProps = 0; 479 SmProp **props = NULL; 480 _SmcPropReplyWait *next; 481 482 CHECK_AT_LEAST_SIZE (iceConn, _SmcOpcode, opcode, 483 length, SIZEOF (smPropertiesReplyMsg), IceFatalToProtocol); 484 485 IceReadCompleteMessage (iceConn, SIZEOF (smPropertiesReplyMsg), 486 smPropertiesReplyMsg, pMsg, pStart); 487 488 if (!IceValidIO (iceConn) || pStart == NULL) 489 { 490 IceDisposeCompleteMessage (iceConn, pStart); 491 return; 492 } 493 494 pEnd = pStart + (length << 3) - 495 (SIZEOF (smPropertiesReplyMsg) - SIZEOF (iceMsg)); 496 497 props = extractListofProperty(pStart, pEnd, swap, &numProps); 498 if (props == NULL) 499 { 500 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 501 IceFatalToProtocol); 502 IceDisposeCompleteMessage (iceConn, pStart); 503 return; 504 } 505 506 next = smcConn->prop_reply_waits->next; 507 508 (*smcConn->prop_reply_waits->prop_reply_proc) (smcConn, 509 smcConn->prop_reply_waits->client_data, numProps, props); 510 511 free (smcConn->prop_reply_waits); 512 smcConn->prop_reply_waits = next; 513 514 IceDisposeCompleteMessage (iceConn, pStart); 515 } 516 break; 517 518 default: 519 { 520 _IceErrorBadMinor (iceConn, _SmcOpcode, opcode, IceCanContinue); 521 _IceReadSkip (iceConn, length << 3); 522 break; 523 } 524 } 525 } 526 527 528 529 void 531 _SmsProcessMessage(IceConn iceConn, IcePointer clientData, int opcode, 532 unsigned long length, Bool swap) 533 { 534 SmsConn smsConn = (SmsConn) clientData; 535 536 if (!smsConn->client_id && 537 opcode != SM_RegisterClient && opcode != SM_Error) 538 { 539 _IceReadSkip (iceConn, length << 3); 540 541 _IceErrorBadState (iceConn, _SmsOpcode, opcode, IceFatalToProtocol); 542 543 return; 544 } 545 546 switch (opcode) 547 { 548 case SM_Error: 549 { 550 iceErrorMsg *pMsg; 551 char *pData, *pEnd; 552 553 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode, 554 length, SIZEOF (iceErrorMsg), IceFatalToProtocol); 555 556 IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg), 557 iceErrorMsg, pMsg, pData); 558 559 if (!IceValidIO (iceConn) || pData == NULL) 560 { 561 IceDisposeCompleteMessage (iceConn, pData); 562 return; 563 } 564 565 if (swap) 566 { 567 pMsg->errorClass = lswaps (pMsg->errorClass); 568 pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum); 569 } 570 571 pEnd = pData + (length << 3) - (SIZEOF (iceErrorMsg) - SIZEOF (iceMsg)); 572 573 if (!validErrorMessage(pData, pEnd, pMsg->errorClass, swap)) 574 { 575 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 576 IceFatalToProtocol); 577 IceDisposeCompleteMessage (iceConn, pData); 578 return; 579 } 580 581 (*_SmsErrorHandler) (smsConn, swap, 582 pMsg->offendingMinorOpcode, 583 pMsg->offendingSequenceNum, 584 pMsg->errorClass, pMsg->severity, 585 (SmPointer) pData); 586 587 IceDisposeCompleteMessage (iceConn, pData); 588 break; 589 } 590 591 case SM_RegisterClient: 592 { 593 smRegisterClientMsg *pMsg; 594 char *pData, *pStart, *pEnd; 595 char *previousId; 596 int idLen; 597 598 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode, 599 length, SIZEOF (smRegisterClientMsg), IceFatalToProtocol); 600 601 IceReadCompleteMessage (iceConn, SIZEOF (smRegisterClientMsg), 602 smRegisterClientMsg, pMsg, pStart); 603 604 if (!IceValidIO (iceConn) || pStart == NULL) 605 { 606 IceDisposeCompleteMessage (iceConn, pStart); 607 return; 608 } 609 610 pData = pStart; 611 pEnd = pStart + (length << 3) - 612 (SIZEOF (smRegisterClientMsg) - SIZEOF (iceMsg)); 613 614 previousId = extractArray8(&pData, pEnd, swap, &idLen); 615 if (previousId == NULL) 616 { 617 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 618 IceFatalToProtocol); 619 IceDisposeCompleteMessage (iceConn, pStart); 620 return; 621 } 622 623 if (*previousId == '\0') 624 { 625 free (previousId); 626 previousId = NULL; 627 } 628 629 if (!(*smsConn->callbacks.register_client.callback) (smsConn, 630 smsConn->callbacks.register_client.manager_data, previousId)) 631 { 632 /* 633 * The previoudId was bad. Generate BadValue error. 634 */ 635 636 _IceErrorBadValue (smsConn->iceConn, _SmsOpcode, SM_RegisterClient, 637 8, ARRAY8_BYTES (idLen), (IcePointer) pStart); 638 } 639 640 IceDisposeCompleteMessage (iceConn, pStart); 641 break; 642 } 643 644 case SM_InteractRequest: 645 646 if (!smsConn->save_yourself_in_progress || 647 smsConn->interaction_allowed == SmInteractStyleNone) 648 { 649 _IceErrorBadState (iceConn, _SmsOpcode, 650 SM_InteractRequest, IceCanContinue); 651 } 652 else 653 { 654 smInteractRequestMsg *pMsg; 655 656 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode, 657 length, SIZEOF (smInteractRequestMsg), 658 IceFatalToProtocol); 659 660 IceReadSimpleMessage (iceConn, smInteractRequestMsg, pMsg); 661 662 if (pMsg->dialogType != SmDialogNormal && 663 pMsg->dialogType != SmDialogError) 664 { 665 unsigned char errVal = pMsg->dialogType; 666 667 _IceErrorBadValue (iceConn, _SmsOpcode, 668 SM_InteractRequest, 2, 1, (IcePointer) &errVal); 669 } 670 else if (pMsg->dialogType == SmDialogNormal && 671 smsConn->interaction_allowed != SmInteractStyleAny) 672 { 673 _IceErrorBadState (iceConn, _SmsOpcode, 674 SM_InteractRequest, IceCanContinue); 675 } 676 else 677 { 678 (*smsConn->callbacks.interact_request.callback) (smsConn, 679 smsConn->callbacks.interact_request.manager_data, 680 pMsg->dialogType); 681 } 682 } 683 break; 684 685 case SM_InteractDone: 686 687 if (!smsConn->interact_in_progress) 688 { 689 _IceErrorBadState (iceConn, _SmsOpcode, 690 SM_InteractDone, IceCanContinue); 691 } 692 else 693 { 694 smInteractDoneMsg *pMsg; 695 696 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode, 697 length, SIZEOF (smInteractDoneMsg), 698 IceFatalToProtocol); 699 700 IceReadSimpleMessage (iceConn, smInteractDoneMsg, pMsg); 701 702 if (pMsg->cancelShutdown != 1 && 703 pMsg->cancelShutdown != 0) 704 { 705 unsigned char errVal = pMsg->cancelShutdown; 706 707 _IceErrorBadValue (iceConn, _SmsOpcode, 708 SM_InteractDone, 2, 1, (IcePointer) &errVal); 709 } 710 else if (pMsg->cancelShutdown && !smsConn->can_cancel_shutdown) 711 { 712 _IceErrorBadState (iceConn, _SmsOpcode, 713 SM_InteractDone, IceCanContinue); 714 } 715 else 716 { 717 smsConn->interact_in_progress = False; 718 719 (*smsConn->callbacks.interact_done.callback) (smsConn, 720 smsConn->callbacks.interact_done.manager_data, 721 pMsg->cancelShutdown); 722 } 723 } 724 break; 725 726 case SM_SaveYourselfRequest: 727 { 728 smSaveYourselfRequestMsg *pMsg; 729 unsigned char errVal; 730 int errOffset = -1; 731 732 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode, 733 length, SIZEOF (smSaveYourselfRequestMsg), 734 IceFatalToProtocol); 735 736 IceReadMessageHeader (iceConn, SIZEOF (smSaveYourselfRequestMsg), 737 smSaveYourselfRequestMsg, pMsg); 738 739 if (!IceValidIO (iceConn)) 740 { 741 IceDisposeCompleteMessage (iceConn, pMsg); 742 return; 743 } 744 745 if (pMsg->saveType != SmSaveGlobal && 746 pMsg->saveType != SmSaveLocal && 747 pMsg->saveType != SmSaveBoth) 748 { 749 errVal = pMsg->saveType; 750 errOffset = 8; 751 } 752 else if (pMsg->shutdown != 1 && pMsg->shutdown != 0) 753 { 754 errVal = pMsg->shutdown; 755 errOffset = 9; 756 } 757 else if (pMsg->interactStyle != SmInteractStyleNone && 758 pMsg->interactStyle != SmInteractStyleErrors && 759 pMsg->interactStyle != SmInteractStyleAny) 760 { 761 errVal = pMsg->interactStyle; 762 errOffset = 10; 763 } 764 else if (pMsg->fast != 1 && pMsg->fast != 0) 765 { 766 errVal = pMsg->fast; 767 errOffset = 11; 768 } 769 else if (pMsg->global != 1 && pMsg->global != 0) 770 { 771 errVal = pMsg->fast; 772 errOffset = 11; 773 } 774 775 if (errOffset >= 0) 776 { 777 _IceErrorBadValue (iceConn, _SmsOpcode, 778 SM_SaveYourselfRequest, errOffset, 1, (IcePointer) &errVal); 779 } 780 else 781 { 782 (*smsConn->callbacks.save_yourself_request.callback) (smsConn, 783 smsConn->callbacks.save_yourself_request.manager_data, 784 pMsg->saveType, pMsg->shutdown, pMsg->interactStyle, 785 pMsg->fast, pMsg->global); 786 } 787 break; 788 } 789 790 case SM_SaveYourselfPhase2Request: 791 792 if (!smsConn->save_yourself_in_progress) 793 { 794 _IceErrorBadState (iceConn, _SmsOpcode, 795 SM_SaveYourselfPhase2Request, IceCanContinue); 796 } 797 else 798 { 799 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode, 800 length, SIZEOF (smSaveYourselfPhase2RequestMsg), 801 IceFatalToProtocol); 802 803 (*smsConn->callbacks.save_yourself_phase2_request.callback) ( 804 smsConn, smsConn->callbacks. 805 save_yourself_phase2_request.manager_data); 806 } 807 break; 808 809 case SM_SaveYourselfDone: 810 811 if (!smsConn->save_yourself_in_progress) 812 { 813 _IceErrorBadState (iceConn, _SmsOpcode, 814 SM_SaveYourselfDone, IceCanContinue); 815 } 816 else 817 { 818 smSaveYourselfDoneMsg *pMsg; 819 820 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode, 821 length, SIZEOF (smSaveYourselfDoneMsg), 822 IceFatalToProtocol); 823 824 IceReadSimpleMessage (iceConn, smSaveYourselfDoneMsg, pMsg); 825 826 if (pMsg->success != 1 && pMsg->success != 0) 827 { 828 unsigned char errVal = pMsg->success; 829 830 _IceErrorBadValue (iceConn, _SmsOpcode, 831 SM_SaveYourselfDone, 2, 1, (IcePointer) &errVal); 832 } 833 else 834 { 835 smsConn->save_yourself_in_progress = False; 836 smsConn->interaction_allowed = SmInteractStyleNone; 837 838 (*smsConn->callbacks.save_yourself_done.callback) (smsConn, 839 smsConn->callbacks.save_yourself_done.manager_data, 840 pMsg->success); 841 } 842 } 843 break; 844 845 case SM_CloseConnection: 846 { 847 smCloseConnectionMsg *pMsg; 848 char *pData, *pStart, *pEnd; 849 int count, i; 850 char **reasonMsgs = NULL; 851 852 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode, 853 length, SIZEOF (smCloseConnectionMsg) + 8, IceFatalToProtocol); 854 855 IceReadCompleteMessage (iceConn, SIZEOF (smCloseConnectionMsg), 856 smCloseConnectionMsg, pMsg, pStart); 857 858 if (!IceValidIO (iceConn) || pStart == NULL) 859 { 860 IceDisposeCompleteMessage (iceConn, pStart); 861 return; 862 } 863 864 pData = pStart; 865 pEnd = pStart + (length << 3) - 866 (SIZEOF (smCloseConnectionMsg) - SIZEOF (iceMsg)); 867 868 EXTRACT_CARD32 (pData, swap, count); 869 pData += 4; 870 871 if (count < 0 || count > INT_MAX / sizeof (char *) || 872 (reasonMsgs = malloc (count * sizeof (char *))) == NULL) 873 { 874 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, IceFatalToProtocol); 875 IceDisposeCompleteMessage (iceConn, pStart); 876 return; 877 } 878 879 for (i = 0; i < count; i++) 880 { 881 reasonMsgs[i] = extractArray8(&pData, pEnd, swap, NULL); 882 if (reasonMsgs[i] == NULL) 883 break; 884 } 885 if (i != count) { 886 while (i-- > 0) 887 free (reasonMsgs[i]); 888 free (reasonMsgs); 889 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 890 IceFatalToProtocol); 891 IceDisposeCompleteMessage (iceConn, pStart); 892 return; 893 } 894 895 IceDisposeCompleteMessage (iceConn, pStart); 896 897 (*smsConn->callbacks.close_connection.callback) (smsConn, 898 smsConn->callbacks.close_connection.manager_data, 899 count, reasonMsgs); 900 break; 901 } 902 903 case SM_SetProperties: 904 { 905 smSetPropertiesMsg *pMsg; 906 char *pStart, *pEnd; 907 SmProp **props = NULL; 908 int numProps = 0; 909 910 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode, 911 length, SIZEOF (smSetPropertiesMsg), IceFatalToProtocol); 912 913 IceReadCompleteMessage (iceConn, SIZEOF (smSetPropertiesMsg), 914 smSetPropertiesMsg, pMsg, pStart); 915 916 if (!IceValidIO (iceConn) || pStart == NULL) 917 { 918 IceDisposeCompleteMessage (iceConn, pStart); 919 return; 920 } 921 922 pEnd = pStart + (length << 3) - 923 (SIZEOF (smSetPropertiesMsg) - SIZEOF (iceMsg)); 924 925 props = extractListofProperty(pStart, pEnd, swap, &numProps); 926 if (props == NULL) 927 { 928 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 929 IceFatalToProtocol); 930 IceDisposeCompleteMessage (iceConn, pStart); 931 return; 932 } 933 934 (*smsConn->callbacks.set_properties.callback) (smsConn, 935 smsConn->callbacks.set_properties.manager_data, numProps, props); 936 937 IceDisposeCompleteMessage (iceConn, pStart); 938 break; 939 } 940 941 case SM_DeleteProperties: 942 { 943 smDeletePropertiesMsg *pMsg; 944 char *pData, *pStart, *pEnd; 945 int count, i; 946 char **propNames = NULL; 947 948 CHECK_AT_LEAST_SIZE (iceConn, _SmsOpcode, opcode, 949 length, SIZEOF (smDeletePropertiesMsg) + 8, IceFatalToProtocol); 950 951 IceReadCompleteMessage (iceConn, SIZEOF (smDeletePropertiesMsg), 952 smDeletePropertiesMsg, pMsg, pStart); 953 954 if (!IceValidIO (iceConn) || pStart == NULL) 955 { 956 IceDisposeCompleteMessage (iceConn, pStart); 957 return; 958 } 959 960 pData = pStart; 961 pEnd = pStart + (length << 3) - 962 (SIZEOF (smDeletePropertiesMsg) - SIZEOF (iceMsg)); 963 964 EXTRACT_CARD32 (pData, swap, count); 965 pData += 4; 966 967 if (count < 0 || count > INT_MAX / sizeof (char *) || 968 (propNames = malloc (count * sizeof (char *))) == NULL) 969 { 970 IceDisposeCompleteMessage (iceConn, pStart); 971 return; 972 } 973 974 for (i = 0; i < count; i++) 975 { 976 propNames[i] = extractArray8(&pData, pEnd, swap, NULL); 977 if (propNames[i] == NULL) 978 break; 979 } 980 if (i != count) 981 { 982 while (i-- > 0) 983 free (propNames[i]); 984 free (propNames); 985 _IceErrorBadLength (iceConn, _SmcOpcode, opcode, 986 IceFatalToProtocol); 987 IceDisposeCompleteMessage (iceConn, pStart); 988 return; 989 } 990 991 IceDisposeCompleteMessage (iceConn, pStart); 992 993 (*smsConn->callbacks.delete_properties.callback) (smsConn, 994 smsConn->callbacks.delete_properties.manager_data, 995 count, propNames); 996 997 break; 998 } 999 1000 case SM_GetProperties: 1001 1002 CHECK_SIZE_MATCH (iceConn, _SmsOpcode, opcode, 1003 length, SIZEOF (smGetPropertiesMsg), 1004 IceFatalToProtocol); 1005 1006 (*smsConn->callbacks.get_properties.callback) (smsConn, 1007 smsConn->callbacks.get_properties.manager_data); 1008 break; 1009 1010 default: 1011 { 1012 _IceErrorBadMinor (iceConn, _SmsOpcode, opcode, IceCanContinue); 1013 _IceReadSkip (iceConn, length << 3); 1014 break; 1015 } 1016 } 1017 } 1018