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 *
extractArray8(char ** pBuf,char * pEnd,Bool swap,int * len)59 extractArray8(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
83 static SmProp **
extractListofProperty(char * pBuf,char * pEnd,Bool swap,int * count)84 extractListofProperty(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
132 fail:
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
153 static Bool
validErrorMessage(char * pData,char * pEnd,int errorClass,Bool swap)154 validErrorMessage(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
173 void
_SmcProcessMessage(IceConn iceConn,IcePointer clientData,int opcode,unsigned long length,Bool swap,IceReplyWaitInfo * replyWait,Bool * replyReadyRet)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))
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))
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))
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
525 void
_SmsProcessMessage(IceConn iceConn,IcePointer clientData,int opcode,unsigned long length,Bool swap)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))
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))
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))
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))
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))
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