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