1 /******************************************************************************
2
3
4 Copyright 1993, 1998 The Open Group
5
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25
26 Author: 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 */
74 static int _X_ATTRIBUTE_PRINTF(2,3)
asprintf(char ** ret,const char * format,...)75 asprintf(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
169 IceProcessMessagesStatus
IceProcessMessages(IceConn iceConn,IceReplyWaitInfo * replyWait,Bool * replyReadyRet)170 IceProcessMessages (
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
434 static void
AuthRequired(IceConn iceConn,int authIndex,int authDataLen,IcePointer authData)435 AuthRequired (
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
461 static void
AuthReply(IceConn iceConn,int authDataLen,IcePointer authData)462 AuthReply (
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
486 static void
AuthNextPhase(IceConn iceConn,int authDataLen,IcePointer authData)487 AuthNextPhase (
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
511 static void
AcceptConnection(IceConn iceConn,int versionIndex)512 AcceptConnection (
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
539 static void
AcceptProtocol(IceConn iceConn,int hisOpcode,int myOpcode,int versionIndex,char * vendor,char * release)540 AcceptProtocol (
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
579 static void
PingReply(IceConn iceConn)580 PingReply (
581 IceConn iceConn
582 )
583 {
584 IceSimpleMessage (iceConn, 0, ICE_PingReply);
585 IceFlush (iceConn);
586 }
587
588
589
590 static Bool
ProcessError(IceConn iceConn,unsigned long length,Bool swap,IceReplyWaitInfo * replyWait)591 ProcessError (
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
861 static int
ProcessConnectionSetup(IceConn iceConn,unsigned long length,Bool swap)862 ProcessConnectionSetup (
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
1119 static Bool
ProcessAuthRequired(IceConn iceConn,unsigned long length,Bool swap,IceReplyWaitInfo * replyWait)1120 ProcessAuthRequired (
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
1313 static int
ProcessAuthReply(IceConn iceConn,unsigned long length,Bool swap)1314 ProcessAuthReply (
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
1603 static Bool
ProcessAuthNextPhase(IceConn iceConn,unsigned long length,Bool swap,IceReplyWaitInfo * replyWait)1604 ProcessAuthNextPhase (
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
1735 static Bool
ProcessConnectionReply(IceConn iceConn,unsigned long length,Bool swap,IceReplyWaitInfo * replyWait)1736 ProcessConnectionReply (
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
1837 static int
ProcessProtocolSetup(IceConn iceConn,unsigned long length,Bool swap)1838 ProcessProtocolSetup (
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
2231 static Bool
ProcessProtocolReply(IceConn iceConn,unsigned long length,Bool swap,IceReplyWaitInfo * replyWait)2232 ProcessProtocolReply (
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
2335 static int
ProcessPing(IceConn iceConn,unsigned long length)2336 ProcessPing (
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
2351 static int
ProcessPingReply(IceConn iceConn,unsigned long length)2352 ProcessPingReply (
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
2380 static int
ProcessWantToClose(IceConn iceConn,unsigned long length,Bool * connectionClosedRet)2381 ProcessWantToClose (
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
2439 static int
ProcessNoClose(IceConn iceConn,unsigned long length)2440 ProcessNoClose (
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
2467 static void
_IceProcessCoreMessage(IceConn iceConn,int opcode,unsigned long length,Bool swap,IceReplyWaitInfo * replyWait,Bool * replyReadyRet,Bool * connectionClosedRet)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
2555 const int _IceVersionCount = 1;
2556 const _IceVersion _IceVersions[] = {
2557 {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};
2558
2559