diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ICElibint.h | 588 | ||||
-rw-r--r-- | src/accept.c | 185 | ||||
-rw-r--r-- | src/authutil.c | 536 | ||||
-rw-r--r-- | src/connect.c | 544 | ||||
-rw-r--r-- | src/error.c | 641 | ||||
-rw-r--r-- | src/getauth.c | 270 | ||||
-rw-r--r-- | src/globals.h | 57 | ||||
-rw-r--r-- | src/iceauth.c | 278 | ||||
-rw-r--r-- | src/listen.c | 280 | ||||
-rw-r--r-- | src/listenwk.c | 157 | ||||
-rw-r--r-- | src/locking.c | 64 | ||||
-rw-r--r-- | src/misc.c | 621 | ||||
-rw-r--r-- | src/ping.c | 63 | ||||
-rw-r--r-- | src/process.c | 2490 | ||||
-rw-r--r-- | src/protosetup.c | 289 | ||||
-rw-r--r-- | src/register.c | 253 | ||||
-rw-r--r-- | src/replywait.c | 158 | ||||
-rw-r--r-- | src/setauth.c | 113 | ||||
-rw-r--r-- | src/shutdown.c | 325 | ||||
-rw-r--r-- | src/watch.c | 203 |
20 files changed, 8115 insertions, 0 deletions
diff --git a/src/ICElibint.h b/src/ICElibint.h new file mode 100644 index 0000000..0a1ffcb --- /dev/null +++ b/src/ICElibint.h @@ -0,0 +1,588 @@ +/* $Xorg: ICElibint.h,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#ifndef _ICELIBINT_H_ +#define _ICELIBINT_H_ + +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/Xmd.h> +#include <X11/ICE/ICEproto.h> +#include <X11/ICE/ICEconn.h> +#include <X11/ICE/ICEmsg.h> + +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#else +char *malloc(); +#endif + +#ifndef NULL +#define NULL 0 +#endif + + +/* + * Vendor & Release + */ + +#define IceVendorString "MIT" +#define IceReleaseString "1.0" + + +/* + * Pad to a 64 bit boundary + */ + +#define PAD64(_bytes) ((8 - ((unsigned int) (_bytes) % 8)) % 8) + +#define PADDED_BYTES64(_bytes) (_bytes + PAD64 (_bytes)) + + +/* + * Pad to 32 bit boundary + */ + +#define PAD32(_bytes) ((4 - ((unsigned int) (_bytes) % 4)) % 4) + +#define PADDED_BYTES32(_bytes) (_bytes + PAD32 (_bytes)) + + +/* + * Number of 8 byte units in _bytes. + */ + +#define WORD64COUNT(_bytes) (((unsigned int) ((_bytes) + 7)) >> 3) + + +/* + * Number of 4 byte units in _bytes. + */ + +#define WORD32COUNT(_bytes) (((unsigned int) ((_bytes) + 3)) >> 2) + + +/* + * Given a string, compute the number of bytes for the STRING representation + */ + +#define STRING_BYTES(_string) \ + (2 + strlen (_string) + PAD32 (2 + strlen (_string))) + + +/* + * Size of ICE input/output buffers + */ + +#define ICE_INBUFSIZE 1024 + +#define ICE_OUTBUFSIZE 1024 + + +/* + * Maxium number of ICE authentication methods allowed, and maxiumum + * number of authentication data entries allowed to be set in the + * IceSetPaAuthData function. + * + * We should use linked lists, but this is easier and should suffice. + */ + +#define MAX_ICE_AUTH_NAMES 32 +#define ICE_MAX_AUTH_DATA_ENTRIES 100 + + +/* + * ICE listen object + */ + +struct _IceListenObj { + struct _XtransConnInfo *trans_conn; /* transport connection object */ + char *network_id; + IceHostBasedAuthProc host_based_auth_proc; +}; + + +/* + * Some internal data structures for processing ICE messages. + */ + +typedef void (*_IceProcessCoreMsgProc) ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* opcode */, + unsigned long /* length */, + Bool /* swap */, + IceReplyWaitInfo * /* replyWait */, + Bool * /* replyReadyRet */, + Bool * /* connectionClosedRet */ +#endif +); + +typedef struct { + int major_version; + int minor_version; + _IceProcessCoreMsgProc process_core_msg_proc; +} _IceVersion; + + +/* + * STORE FOO + */ + +#define STORE_CARD8(_pBuf, _val) \ +{ \ + *((CARD8 *) _pBuf) = _val; \ + _pBuf += 1; \ +} + +#ifndef WORD64 + +#define STORE_CARD16(_pBuf, _val) \ +{ \ + *((CARD16 *) _pBuf) = _val; \ + _pBuf += 2; \ +} + +#define STORE_CARD32(_pBuf, _val) \ +{ \ + *((CARD32 *) _pBuf) = _val; \ + _pBuf += 4; \ +} + +#else /* WORD64 */ + +#define STORE_CARD16(_pBuf, _val) \ +{ \ + struct { \ + int value :16; \ + int pad :16; \ + } _d; \ + _d.value = _val; \ + memcpy (_pBuf, &_d, 2); \ + _pBuf += 2; \ +} + +#define STORE_CARD32(_pBuf, _val) \ +{ \ + struct { \ + int value :32; \ + } _d; \ + _d.value = _val; \ + memcpy (_pBuf, &_d, 4); \ + _pBuf += 4; \ +} + +#endif /* WORD64 */ + +#define STORE_STRING(_pBuf, _string) \ +{ \ + CARD16 _len = strlen (_string); \ + STORE_CARD16 (_pBuf, _len); \ + memcpy (_pBuf, _string, _len); \ + _pBuf += _len; \ + if (PAD32 (2 + _len)) \ + _pBuf += PAD32 (2 + _len); \ +} + + +/* + * EXTRACT FOO + */ + +#define EXTRACT_CARD8(_pBuf, _val) \ +{ \ + _val = *((CARD8 *) _pBuf); \ + _pBuf += 1; \ +} + +#ifndef WORD64 + +#define EXTRACT_CARD16(_pBuf, _swap, _val) \ +{ \ + _val = *((CARD16 *) _pBuf); \ + _pBuf += 2; \ + if (_swap) \ + _val = lswaps (_val); \ +} + +#define EXTRACT_CARD32(_pBuf, _swap, _val) \ +{ \ + _val = *((CARD32 *) _pBuf); \ + _pBuf += 4; \ + if (_swap) \ + _val = lswapl (_val); \ +} + +#else /* WORD64 */ + +#define EXTRACT_CARD16(_pBuf, _swap, _val) \ +{ \ + _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \ + _val <<= 8; \ + _val |= *(_pBuf + 1) & 0xff;\ + _pBuf += 2; \ + if (_swap) \ + _val = lswaps (_val); \ +} + +#define EXTRACT_CARD32(_pBuf, _swap, _val) \ +{ \ + _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \ + _val <<= 8; \ + _val |= *(_pBuf + 1) & 0xff;\ + _val <<= 8; \ + _val |= *(_pBuf + 2) & 0xff;\ + _val <<= 8; \ + _val |= *(_pBuf + 3) & 0xff;\ + _pBuf += 4; \ + if (_swap) \ + _val = lswapl (_val); \ +} + +#endif /* WORD64 */ + +#define EXTRACT_STRING(_pBuf, _swap, _string) \ +{ \ + CARD16 _len; \ + EXTRACT_CARD16 (_pBuf, _swap, _len); \ + _string = (char *) malloc (_len + 1); \ + memcpy (_string, _pBuf, _len); \ + _pBuf += _len; \ + _string[_len] = '\0'; \ + if (PAD32 (2 + _len)) \ + _pBuf += PAD32 (2 + _len); \ +} + +#define EXTRACT_LISTOF_STRING(_pBuf, _swap, _count, _strings) \ +{ \ + int _i; \ + for (_i = 0; _i < _count; _i++) \ + EXTRACT_STRING (_pBuf, _swap, _strings[_i]); \ +} + + +#define SKIP_STRING(_pBuf, _swap) \ +{ \ + CARD16 _len; \ + EXTRACT_CARD16 (_pBuf, _swap, _len); \ + _pBuf += _len; \ + if (PAD32 (2 + _len)) \ + _pBuf += PAD32 (2 + _len); \ +} + +#define SKIP_LISTOF_STRING(_pBuf, _swap, _count) \ +{ \ + int _i; \ + for (_i = 0; _i < _count; _i++) \ + SKIP_STRING (_pBuf, _swap); \ +} + + + +/* + * Byte swapping + */ + +/* byte swap a long literal */ +#define lswapl(_val) ((((_val) & 0xff) << 24) |\ + (((_val) & 0xff00) << 8) |\ + (((_val) & 0xff0000) >> 8) |\ + (((_val) >> 24) & 0xff)) + +/* byte swap a short literal */ +#define lswaps(_val) ((((_val) & 0xff) << 8) | (((_val) >> 8) & 0xff)) + + + +/* + * ICE replies (not processed via callbacks because we block) + */ + +#define ICE_CONNECTION_REPLY 1 +#define ICE_CONNECTION_ERROR 2 +#define ICE_PROTOCOL_REPLY 3 +#define ICE_PROTOCOL_ERROR 4 + +typedef struct { + int type; + int version_index; + char *vendor; + char *release; +} _IceConnectionReply; + +typedef struct { + int type; + char *error_message; +} _IceConnectionError; + +typedef struct { + int type; + int major_opcode; + int version_index; + char *vendor; + char *release; +} _IceProtocolReply; + +typedef struct { + int type; + char *error_message; +} _IceProtocolError; + + +typedef union { + int type; + _IceConnectionReply connection_reply; + _IceConnectionError connection_error; + _IceProtocolReply protocol_reply; + _IceProtocolError protocol_error; +} _IceReply; + + +/* + * Watch for ICE connection create/destroy. + */ + +typedef struct _IceWatchedConnection { + IceConn iceConn; + IcePointer watch_data; + struct _IceWatchedConnection *next; +} _IceWatchedConnection; + +typedef struct _IceWatchProc { + IceWatchProc watch_proc; + IcePointer client_data; + _IceWatchedConnection *watched_connections; + struct _IceWatchProc *next; +} _IceWatchProc; + + +/* + * Locking + */ + +#define IceLockConn(_iceConn) +#define IceUnlockConn(_iceConn) + + +/* + * Extern declarations + */ + +extern IceConn _IceConnectionObjs[]; +extern char *_IceConnectionStrings[]; +extern int _IceConnectionCount; + +extern _IceProtocol _IceProtocols[]; +extern int _IceLastMajorOpcode; + +extern int _IceAuthCount; +extern char *_IceAuthNames[]; +extern IcePoAuthProc _IcePoAuthProcs[]; +extern IcePaAuthProc _IcePaAuthProcs[]; + +extern int _IceVersionCount; +extern _IceVersion _IceVersions[]; + +extern _IceWatchProc *_IceWatchProcs; + +extern IceErrorHandler _IceErrorHandler; +extern IceIOErrorHandler _IceIOErrorHandler; + + +extern void _IceErrorBadMajor ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* offendingMajor */, + int /* offendingMinor */, + int /* severity */ +#endif +); + +extern void _IceErrorNoAuthentication ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* offendingMinor */ +#endif +); + +extern void _IceErrorNoVersion ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* offendingMinor */ +#endif +); + +extern void _IceErrorSetupFailed ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* offendingMinor */, + char * /* reason */ +#endif +); + +extern void _IceErrorAuthenticationRejected ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* offendingMinor */, + char * /* reason */ +#endif +); + +extern void _IceErrorAuthenticationFailed ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* offendingMinor */, + char * /* reason */ +#endif +); + +extern void _IceErrorProtocolDuplicate ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + char * /* protocolName */ +#endif +); + +extern void _IceErrorMajorOpcodeDuplicate ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* majorOpcode */ +#endif +); + +extern void _IceErrorUnknownProtocol ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + char * /* protocolName */ +#endif +); + +extern void _IceAddOpcodeMapping ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* hisOpcode */, + int /* myOpcode */ +#endif +); + +extern char *_IceGetPeerName ( +#if NeedFunctionPrototypes + IceConn /* iceConn */ +#endif +); + +extern void _IceFreeConnection ( +#if NeedFunctionPrototypes + IceConn /* iceConn */ +#endif +); + +extern void _IceAddReplyWait ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + IceReplyWaitInfo * /* replyWait */ +#endif +); + +extern IceReplyWaitInfo *_IceSearchReplyWaits ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + int /* majorOpcode */ +#endif +); + +extern void _IceSetReplyReady ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + IceReplyWaitInfo * /* replyWait */ +#endif +); + +extern Bool _IceCheckReplyReady ( +#if NeedFunctionPrototypes + IceConn /* iceConn */, + IceReplyWaitInfo * /* replyWait */ +#endif +); + +extern void _IceConnectionOpened ( +#if NeedFunctionPrototypes + IceConn /* iceConn */ +#endif +); + +extern void _IceConnectionClosed ( +#if NeedFunctionPrototypes + IceConn /* iceConn */ +#endif +); + +extern void _IceGetPoAuthData ( +#if NeedFunctionPrototypes + char * /* protocol_name */, + char * /* address */, + char * /* auth_name */, + unsigned short * /* auth_data_length_ret */, + char ** /* auth_data_ret */ +#endif +); + +extern void _IceGetPaAuthData ( +#if NeedFunctionPrototypes + char * /* protocol_name */, + char * /* address */, + char * /* auth_name */, + unsigned short * /* auth_data_length_ret */, + char ** /* auth_data_ret */ +#endif +); + +extern void _IceGetPoValidAuthIndices ( +#if NeedFunctionPrototypes + char * /* protocol_name */, + char * /* address */, + int /* num_auth_names */, + char ** /* auth_names */, + int * /* num_indices_ret */, + int * /* indices_ret */ +#endif +); + +extern void _IceGetPaValidAuthIndices ( +#if NeedFunctionPrototypes + char * /* protocol_name */, + char * /* address */, + int /* num_auth_names */, + char ** /* auth_names */, + int * /* num_indices_ret */, + int * /* indices_ret */ +#endif +); + +#endif /* _ICELIBINT_H_ */ diff --git a/src/accept.c b/src/accept.c new file mode 100644 index 0000000..eea5389 --- /dev/null +++ b/src/accept.c @@ -0,0 +1,185 @@ +/* $Xorg: accept.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/Xtrans.h> + + +IceConn +IceAcceptConnection (listenObj, statusRet) + +IceListenObj listenObj; +IceAcceptStatus *statusRet; + +{ + IceConn iceConn; + XtransConnInfo newconn; + iceByteOrderMsg *pMsg; + int endian, status; + + /* + * Accept the connection. + */ + + if ((newconn = _IceTransAccept (listenObj->trans_conn, &status)) == 0) + { + if (status == TRANS_ACCEPT_BAD_MALLOC) + *statusRet = IceAcceptBadMalloc; + else + *statusRet = IceAcceptFailure; + return (NULL); + } + + + /* + * Set close-on-exec so that programs that fork() don't get confused. + */ + + _IceTransSetOption (newconn, TRANS_CLOSEONEXEC, 1); + + + /* + * Create an ICE object for this connection. + */ + + if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL) + { + _IceTransClose (newconn); + *statusRet = IceAcceptBadMalloc; + return (NULL); + } + + iceConn->listen_obj = listenObj; + + iceConn->waiting_for_byteorder = True; + iceConn->connection_status = IceConnectPending; + iceConn->io_ok = True; + iceConn->dispatch_level = 0; + iceConn->context = NULL; + iceConn->my_ice_version_index = 0; + + iceConn->trans_conn = newconn; + iceConn->send_sequence = 0; + iceConn->receive_sequence = 0; + + iceConn->connection_string = (char *) malloc ( + strlen (listenObj->network_id) + 1); + + if (iceConn->connection_string == NULL) + { + _IceTransClose (newconn); + free ((char *) iceConn); + *statusRet = IceAcceptBadMalloc; + return (NULL); + } + else + strcpy (iceConn->connection_string, listenObj->network_id); + + iceConn->vendor = NULL; + iceConn->release = NULL; + + if ((iceConn->inbuf = iceConn->inbufptr = + (char *) malloc (ICE_INBUFSIZE)) != NULL) + { + iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE; + } + else + { + _IceTransClose (newconn); + free ((char *) iceConn); + *statusRet = IceAcceptBadMalloc; + return (NULL); + } + + if ((iceConn->outbuf = iceConn->outbufptr = + (char *) malloc (ICE_OUTBUFSIZE)) != NULL) + { + iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE; + } + else + { + _IceTransClose (newconn); + free (iceConn->inbuf); + free ((char *) iceConn); + *statusRet = IceAcceptBadMalloc; + return (NULL); + } + + iceConn->scratch = NULL; + iceConn->scratch_size = 0; + + iceConn->open_ref_count = 1; + iceConn->proto_ref_count = 0; + + iceConn->skip_want_to_close = False; + iceConn->want_to_close = False; + iceConn->free_asap = False; + + iceConn->saved_reply_waits = NULL; + iceConn->ping_waits = NULL; + + iceConn->process_msg_info = NULL; + + iceConn->connect_to_you = NULL; + iceConn->protosetup_to_you = NULL; + + iceConn->connect_to_me = NULL; + iceConn->protosetup_to_me = NULL; + + + /* + * Send our byte order. + */ + + IceGetHeader (iceConn, 0, ICE_ByteOrder, + SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pMsg); + + endian = 1; + if (*(char *) &endian) + pMsg->byteOrder = IceLSBfirst; + else + pMsg->byteOrder = IceMSBfirst; + + IceFlush (iceConn); + + + if (_IceWatchProcs) + { + /* + * Notify the watch procedures that an iceConn was opened. + */ + + _IceConnectionOpened (iceConn); + } + + *statusRet = IceAcceptSuccess; + + return (iceConn); +} diff --git a/src/authutil.c b/src/authutil.c new file mode 100644 index 0000000..64ad848 --- /dev/null +++ b/src/authutil.c @@ -0,0 +1,536 @@ +/* $Xorg: authutil.c,v 1.5 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/ICE/ICEutil.h> +#include <X11/Xos.h> +#include <sys/stat.h> +#include <errno.h> + +#ifdef X_NOT_STDC_ENV +extern int errno; +extern long time (); +extern char *getenv(); +#define Time_t long +#else +#include <time.h> +#define Time_t time_t +#endif +#ifndef X_NOT_POSIX +#include <unistd.h> +#else +#ifndef WIN32 +extern unsigned sleep (); +#else +#define link rename +#endif +#endif + +static Status read_short (); +static Status read_string (); +static Status read_counted_string (); +static Status write_short (); +static Status write_string (); +static Status write_counted_string (); + + + +/* + * The following routines are for manipulating the .ICEauthority file + * These are utility functions - they are not part of the standard + * ICE library specification. + */ + +char * +IceAuthFileName () + +{ + static char slashDotICEauthority[] = "/.ICEauthority"; + char *name; + static char *buf; + static int bsize; + int size; +#ifdef WIN32 +#ifndef PATH_MAX +#define PATH_MAX 512 +#endif + char dir[PATH_MAX]; +#endif + + if ((name = getenv ("ICEAUTHORITY"))) + return (name); + + name = getenv ("HOME"); + + if (!name) + { +#ifdef WIN32 + register char *ptr1; + register char *ptr2; + int len1 = 0, len2 = 0; + + if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) { + len1 = strlen (ptr1); + len2 = strlen (ptr2); + } else if (ptr2 = getenv("USERNAME")) { + len1 = strlen (ptr1 = "/users/"); + len2 = strlen (ptr2); + } + if ((len1 + len2 + 1) < PATH_MAX) { + sprintf (dir, "%s%s", ptr1, (ptr2) ? ptr2 : ""); + name = dir; + } + if (!name) +#endif + return (NULL); + } + + size = strlen (name) + strlen (&slashDotICEauthority[1]) + 2; + + if (size > bsize) + { + if (buf) + free (buf); + buf = malloc ((unsigned) size); + if (!buf) + return (NULL); + bsize = size; + } + + strcpy (buf, name); + strcat (buf, slashDotICEauthority + (name[1] == '\0' ? 1 : 0)); + + return (buf); +} + + + +int +IceLockAuthFile (file_name, retries, timeout, dead) + +char *file_name; +int retries; +int timeout; +long dead; + +{ + char creat_name[1025], link_name[1025]; + struct stat statb; + Time_t now; + int creat_fd = -1; + + if ((int) strlen (file_name) > 1022) + return (IceAuthLockError); + + strcpy (creat_name, file_name); + strcat (creat_name, "-c"); + strcpy (link_name, file_name); + strcat (link_name, "-l"); + + if (stat (creat_name, &statb) != -1) + { + now = time ((Time_t *) 0); + + /* + * NFS may cause ctime to be before now, special + * case a 0 deadtime to force lock removal + */ + + if (dead == 0 || now - statb.st_ctime > dead) + { + unlink (creat_name); + unlink (link_name); + } + } + + while (retries > 0) + { + if (creat_fd == -1) + { + creat_fd = creat (creat_name, 0666); + + if (creat_fd == -1) + { + if (errno != EACCES) + return (IceAuthLockError); + } + else + close (creat_fd); + } + + if (creat_fd != -1) + { + if (link (creat_name, link_name) != -1) + return (IceAuthLockSuccess); + + if (errno == ENOENT) + { + creat_fd = -1; /* force re-creat next time around */ + continue; + } + + if (errno != EEXIST) + return (IceAuthLockError); + } + + sleep ((unsigned) timeout); + --retries; + } + + return (IceAuthLockTimeout); +} + + + +void +IceUnlockAuthFile (file_name) + +char *file_name; + +{ +#ifndef WIN32 + char creat_name[1025]; +#endif + char link_name[1025]; + + if ((int) strlen (file_name) > 1022) + return; + +#ifndef WIN32 + strcpy (creat_name, file_name); + strcat (creat_name, "-c"); +#endif + strcpy (link_name, file_name); + strcat (link_name, "-l"); + +#ifndef WIN32 + unlink (creat_name); +#endif + unlink (link_name); +} + + + +IceAuthFileEntry * +IceReadAuthFileEntry (auth_file) + +FILE *auth_file; + +{ + IceAuthFileEntry local; + IceAuthFileEntry *ret; + + local.protocol_name = NULL; + local.protocol_data = NULL; + local.network_id = NULL; + local.auth_name = NULL; + local.auth_data = NULL; + + if (!read_string (auth_file, &local.protocol_name)) + return (NULL); + + if (!read_counted_string (auth_file, + &local.protocol_data_length, &local.protocol_data)) + goto bad; + + if (!read_string (auth_file, &local.network_id)) + goto bad; + + if (!read_string (auth_file, &local.auth_name)) + goto bad; + + if (!read_counted_string (auth_file, + &local.auth_data_length, &local.auth_data)) + goto bad; + + if (!(ret = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry)))) + goto bad; + + *ret = local; + + return (ret); + + bad: + + if (local.protocol_name) free (local.protocol_name); + if (local.protocol_data) free (local.protocol_data); + if (local.network_id) free (local.network_id); + if (local.auth_name) free (local.auth_name); + if (local.auth_data) free (local.auth_data); + + return (NULL); +} + + + +void +IceFreeAuthFileEntry (auth) + +IceAuthFileEntry *auth; + +{ + if (auth) + { + if (auth->protocol_name) free (auth->protocol_name); + if (auth->protocol_data) free (auth->protocol_data); + if (auth->network_id) free (auth->network_id); + if (auth->auth_name) free (auth->auth_name); + if (auth->auth_data) free (auth->auth_data); + free ((char *) auth); + } +} + + + +Status +IceWriteAuthFileEntry (auth_file, auth) + +FILE *auth_file; +IceAuthFileEntry *auth; + +{ + if (!write_string (auth_file, auth->protocol_name)) + return (0); + + if (!write_counted_string (auth_file, + auth->protocol_data_length, auth->protocol_data)) + return (0); + + if (!write_string (auth_file, auth->network_id)) + return (0); + + if (!write_string (auth_file, auth->auth_name)) + return (0); + + if (!write_counted_string (auth_file, + auth->auth_data_length, auth->auth_data)) + return (0); + + return (1); +} + + + +IceAuthFileEntry * +IceGetAuthFileEntry (protocol_name, network_id, auth_name) + +char *protocol_name; +char *network_id; +char *auth_name; + +{ + FILE *auth_file; + char *filename; + IceAuthFileEntry *entry; + + if (!(filename = IceAuthFileName ())) + return (NULL); + + if (access (filename, R_OK) != 0) /* checks REAL id */ + return (NULL); + + if (!(auth_file = fopen (filename, "rb"))) + return (NULL); + + for (;;) + { + if (!(entry = IceReadAuthFileEntry (auth_file))) + break; + + if (strcmp (protocol_name, entry->protocol_name) == 0 && + strcmp (network_id, entry->network_id) == 0 && + strcmp (auth_name, entry->auth_name) == 0) + { + break; + } + + IceFreeAuthFileEntry (entry); + } + + fclose (auth_file); + + return (entry); +} + + + +/* + * local routines + */ + +static Status +read_short (file, shortp) + +FILE *file; +unsigned short *shortp; + +{ + unsigned char file_short[2]; + + if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) + return (0); + + *shortp = file_short[0] * 256 + file_short[1]; + return (1); +} + + +static Status +read_string (file, stringp) + +FILE *file; +char **stringp; + +{ + unsigned short len; + char *data; + + if (!read_short (file, &len)) + return (0); + + if (len == 0) + { + data = 0; + } + else + { + data = malloc ((unsigned) len + 1); + + if (!data) + return (0); + + if (fread (data, (int) sizeof (char), (int) len, file) != len) + { + free (data); + return (0); + } + + data[len] = '\0'; + } + + *stringp = data; + + return (1); +} + + +static Status +read_counted_string (file, countp, stringp) + +FILE *file; +unsigned short *countp; +char **stringp; + +{ + unsigned short len; + char *data; + + if (!read_short (file, &len)) + return (0); + + if (len == 0) + { + data = 0; + } + else + { + data = malloc ((unsigned) len); + + if (!data) + return (0); + + if (fread (data, (int) sizeof (char), (int) len, file) != len) + { + free (data); + return (0); + } + } + + *stringp = data; + *countp = len; + + return (1); +} + + +static Status +write_short (file, s) + +FILE *file; +unsigned short s; + +{ + unsigned char file_short[2]; + + file_short[0] = (s & (unsigned) 0xff00) >> 8; + file_short[1] = s & 0xff; + + if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1) + return (0); + + return (1); +} + + +static Status +write_string (file, string) + +FILE *file; +char *string; + +{ + unsigned short count = strlen (string); + + if (!write_short (file, count)) + return (0); + + if (fwrite (string, (int) sizeof (char), (int) count, file) != count) + return (0); + + return (1); +} + + +static Status +write_counted_string (file, count, string) + +FILE *file; +unsigned short count; +char *string; + +{ + if (!write_short (file, count)) + return (0); + + if (fwrite (string, (int) sizeof (char), (int) count, file) != count) + return (0); + + return (1); +} diff --git a/src/connect.c b/src/connect.c new file mode 100644 index 0000000..57ee86a --- /dev/null +++ b/src/connect.c @@ -0,0 +1,544 @@ +/* $Xorg: connect.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/Xtrans.h> +#include "globals.h" + +static XtransConnInfo ConnectToPeer(); + +#ifndef X_NOT_STDC_ENV +#define Strstr strstr +#else +static char *Strstr(s1, s2) + char *s1, *s2; +{ + int n1, n2; + + n1 = strlen(s1); + n2 = strlen(s2); + for ( ; n1 >= n2; s1++, n1--) { + if (!strncmp(s1, s2, n2)) + return s1; + } + return NULL; +} +#endif + +IceConn +IceOpenConnection (networkIdsList, context, mustAuthenticate, majorOpcodeCheck, + errorLength, errorStringRet) + +char *networkIdsList; +IcePointer context; +Bool mustAuthenticate; +int majorOpcodeCheck; +int errorLength; +char *errorStringRet; + +{ + IceConn iceConn; + int extra, i, j; + int endian; + Bool gotReply, ioErrorOccured; + unsigned long setup_sequence; + iceByteOrderMsg *pByteOrderMsg; + iceConnectionSetupMsg *pSetupMsg; + char *pData; + IceReplyWaitInfo replyWait; + _IceReply reply; + int authUsableCount; + int authUsableFlags[MAX_ICE_AUTH_NAMES]; + int authIndices[MAX_ICE_AUTH_NAMES]; + + if (errorStringRet && errorLength > 0) + *errorStringRet = '\0'; + + if (networkIdsList == NULL || *networkIdsList == '\0') + { + strncpy (errorStringRet, + "networkIdsList argument is NULL", errorLength); + return (NULL); + } + + /* + * Check to see if we can use a previously created ICE connection. + * + * If iceConn->want_to_close is True, or iceConn->free_asap is True, + * we can not use the iceConn. + * + * If 'context' is non-NULL, we will only use a previously opened ICE + * connection if the specified 'context' is equal to the context + * associated with the ICE connection, or if the context associated + * with the ICE connection is NULL. + * + * If 'majorOpcodeCheck' is non-zero, it will contain a protocol major + * opcode that we should make sure is not already active on the ICE + * connection. Some clients will want two seperate connections for the + * same protocol to the same destination client. + */ + + for (i = 0; i < _IceConnectionCount; i++) + { + char *strptr; + if ((strptr = (char *) Strstr ( + networkIdsList, _IceConnectionStrings[i])) != NULL) + { + char ch = *(strptr + strlen (_IceConnectionStrings[i])); + if (ch == ',' || ch == '\0') + { + /* + * OK, we found a connection. Make sure we can reuse it. + */ + + IceConn iceConn = _IceConnectionObjs[i]; + + if (iceConn->want_to_close || iceConn->free_asap || + (context && iceConn->context && + iceConn->context != context)) + { + /* force a new connection to be created */ + break; + } + + if (majorOpcodeCheck) + { + for (j = iceConn->his_min_opcode; + j <= iceConn->his_max_opcode; j++) + { + if (iceConn->process_msg_info[ + j - iceConn->his_min_opcode].in_use && + iceConn->process_msg_info[ + j - iceConn->his_min_opcode].my_opcode == + majorOpcodeCheck) + break; + } + + if (j <= iceConn->his_max_opcode || + (iceConn->protosetup_to_you && + iceConn->protosetup_to_you->my_opcode == + majorOpcodeCheck)) + { + /* force a new connection to be created */ + break; + } + } + + iceConn->open_ref_count++; + if (context && !iceConn->context) + iceConn->context = context; + return (iceConn); + } + } + } + + if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL) + { + strncpy (errorStringRet, "Can't malloc", errorLength); + return (NULL); + } + + + /* + * Open a network connection with the peer client. + */ + + if ((iceConn->trans_conn = ConnectToPeer (networkIdsList, + &iceConn->connection_string)) == NULL) + { + free ((char *) iceConn); + strncpy (errorStringRet, "Could not open network socket", errorLength); + return (NULL); + } + + /* + * Set close-on-exec so that programs that fork() don't get confused. + */ + + _IceTransSetOption (iceConn->trans_conn, TRANS_CLOSEONEXEC, 1); + + iceConn->listen_obj = NULL; + + iceConn->connection_status = IceConnectPending; + iceConn->io_ok = True; + iceConn->dispatch_level = 0; + iceConn->context = context; + iceConn->my_ice_version_index = 0; + iceConn->send_sequence = 0; + iceConn->receive_sequence = 0; + + iceConn->vendor = NULL; + iceConn->release = NULL; + iceConn->outbuf = NULL; + + iceConn->scratch = NULL; + iceConn->scratch_size = 0; + + iceConn->process_msg_info = NULL; + + iceConn->connect_to_you = NULL; + iceConn->protosetup_to_you = NULL; + + iceConn->connect_to_me = NULL; + iceConn->protosetup_to_me = NULL; + + if ((iceConn->inbuf = iceConn->inbufptr = + (char *) malloc (ICE_INBUFSIZE)) == NULL) + { + _IceFreeConnection (iceConn); + strncpy (errorStringRet, "Can't malloc", errorLength); + return (NULL); + } + + iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE; + + if ((iceConn->outbuf = iceConn->outbufptr = + (char *) malloc (ICE_OUTBUFSIZE)) == NULL) + { + _IceFreeConnection (iceConn); + strncpy (errorStringRet, "Can't malloc", errorLength); + return (NULL); + } + + iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE; + + iceConn->open_ref_count = 1; + iceConn->proto_ref_count = 0; + + iceConn->skip_want_to_close = False; + iceConn->want_to_close = False; + iceConn->free_asap = False; + + iceConn->saved_reply_waits = NULL; + iceConn->ping_waits = NULL; + + iceConn->connect_to_you = (_IceConnectToYouInfo *) malloc ( + sizeof (_IceConnectToYouInfo)); + iceConn->connect_to_you->auth_active = 0; + + /* + * Send our byte order. + */ + + IceGetHeader (iceConn, 0, ICE_ByteOrder, + SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pByteOrderMsg); + + endian = 1; + if (*(char *) &endian) + pByteOrderMsg->byteOrder = IceLSBfirst; + else + pByteOrderMsg->byteOrder = IceMSBfirst; + + IceFlush (iceConn); + + + /* + * Now read the ByteOrder message from the other client. + * iceConn->swap should be set to the appropriate boolean + * value after the call to IceProcessMessages. + */ + + iceConn->waiting_for_byteorder = True; + + ioErrorOccured = False; + while (iceConn->waiting_for_byteorder == True && !ioErrorOccured) + { + ioErrorOccured = (IceProcessMessages ( + iceConn, NULL, NULL) == IceProcessMessagesIOError); + } + + if (ioErrorOccured) + { + _IceFreeConnection (iceConn); + strncpy (errorStringRet, "IO error occured opening connection", + errorLength); + return (NULL); + } + + if (iceConn->connection_status == IceConnectRejected) + { + /* + * We failed to get the required ByteOrder message. + */ + + _IceFreeConnection (iceConn); + strncpy (errorStringRet, + "Internal error - did not receive the expected ByteOrder message", + errorLength); + return (NULL); + } + + + /* + * Determine which authentication methods are available for + * the Connection Setup authentication. + */ + + _IceGetPoValidAuthIndices ( + "ICE", iceConn->connection_string, + _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices); + + for (i = 0; i < _IceAuthCount; i++) + { + authUsableFlags[i] = 0; + for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) + authUsableFlags[i] = (authIndices[j] == i); + } + + + /* + * Now send a Connection Setup message. + */ + + extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString); + + for (i = 0; i < _IceAuthCount; i++) + if (authUsableFlags[i]) + { + extra += STRING_BYTES (_IceAuthNames[i]); + } + + extra += (_IceVersionCount * 4); + + IceGetHeaderExtra (iceConn, 0, ICE_ConnectionSetup, + SIZEOF (iceConnectionSetupMsg), WORD64COUNT (extra), + iceConnectionSetupMsg, pSetupMsg, pData); + + setup_sequence = iceConn->send_sequence; + + pSetupMsg->versionCount = _IceVersionCount; + pSetupMsg->authCount = authUsableCount; + pSetupMsg->mustAuthenticate = mustAuthenticate; + + STORE_STRING (pData, IceVendorString); + STORE_STRING (pData, IceReleaseString); + + for (i = 0; i < _IceAuthCount; i++) + if (authUsableFlags[i]) + { + STORE_STRING (pData, _IceAuthNames[i]); + } + + for (i = 0; i < _IceVersionCount; i++) + { + STORE_CARD16 (pData, _IceVersions[i].major_version); + STORE_CARD16 (pData, _IceVersions[i].minor_version); + } + + IceFlush (iceConn); + + + /* + * Process messages until we get a Connection Reply or an Error Message. + * Authentication will take place behind the scenes. + */ + + replyWait.sequence_of_request = setup_sequence; + replyWait.major_opcode_of_request = 0; + replyWait.minor_opcode_of_request = ICE_ConnectionSetup; + replyWait.reply = (IcePointer) &reply; + + gotReply = False; + ioErrorOccured = False; + + while (!gotReply && !ioErrorOccured) + { + ioErrorOccured = (IceProcessMessages ( + iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); + + if (ioErrorOccured) + { + strncpy (errorStringRet, "IO error occured opening connection", + errorLength); + _IceFreeConnection (iceConn); + iceConn = NULL; + } + else if (gotReply) + { + if (reply.type == ICE_CONNECTION_REPLY) + { + if (reply.connection_reply.version_index >= _IceVersionCount) + { + strncpy (errorStringRet, + "Got a bad version index in the Connection Reply", + errorLength); + + free (reply.connection_reply.vendor); + free (reply.connection_reply.release); + _IceFreeConnection (iceConn); + iceConn = NULL; + } + else + { + iceConn->my_ice_version_index = + reply.connection_reply.version_index; + iceConn->vendor = reply.connection_reply.vendor; + iceConn->release = reply.connection_reply.release; + + _IceConnectionObjs[_IceConnectionCount] = iceConn; + _IceConnectionStrings[_IceConnectionCount] = + iceConn->connection_string; + _IceConnectionCount++; + + free ((char *) iceConn->connect_to_you); + iceConn->connect_to_you = NULL; + + iceConn->connection_status = IceConnectAccepted; + } + } + else /* reply.type == ICE_CONNECTION_ERROR */ + { + /* Connection failed */ + + strncpy (errorStringRet, reply.connection_error.error_message, + errorLength); + + free (reply.connection_error.error_message); + + _IceFreeConnection (iceConn); + iceConn = NULL; + } + } + } + + if (iceConn && _IceWatchProcs) + { + /* + * Notify the watch procedures that an iceConn was opened. + */ + + _IceConnectionOpened (iceConn); + } + + return (iceConn); +} + + + +IcePointer +IceGetConnectionContext (iceConn) + +IceConn iceConn; + +{ + return (iceConn->context); +} + + + +/* ------------------------------------------------------------------------- * + * local routines * + * ------------------------------------------------------------------------- */ + +#define ICE_CONNECTION_RETRIES 5 + + +static XtransConnInfo +ConnectToPeer (networkIdsList, actualConnectionRet) + +char *networkIdsList; +char **actualConnectionRet; + +{ + char addrbuf[256]; + char* address; + char *ptr, *endptr, *delim; + int madeConnection = 0; + int len, retry; + int connect_stat; + XtransConnInfo trans_conn = NULL; + + *actualConnectionRet = NULL; + + ptr = networkIdsList; + len = strlen (networkIdsList); + endptr = networkIdsList + len; + + if (len < sizeof addrbuf) address = addrbuf; + else address = malloc (len + 1); + + while (ptr < endptr && !madeConnection) + { + if ((delim = (char *) strchr (ptr, ',')) == NULL) + delim = endptr; + + len = delim - ptr; + strncpy (address, ptr, len); + address[len] = '\0'; + + ptr = delim + 1; + + for (retry = ICE_CONNECTION_RETRIES; retry >= 0; retry--) + { + if ((trans_conn = _IceTransOpenCOTSClient (address)) == NULL) + { + break; + } + + if ((connect_stat = _IceTransConnect (trans_conn, address)) < 0) + { + _IceTransClose (trans_conn); + + if (connect_stat == TRANS_TRY_CONNECT_AGAIN) + { + sleep(1); + continue; + } + else + break; + } + else + { + madeConnection = 1; + break; + } + } + } + + if (madeConnection) + { + /* + * We need to return the actual network connection string + */ + + *actualConnectionRet = (char *) malloc (strlen (address) + 1); + strcpy (*actualConnectionRet, address); + + + /* + * Return the file descriptor + */ + } + else trans_conn = NULL; + + if (address != addrbuf) free (address); + + return trans_conn; +} diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..6caf66f --- /dev/null +++ b/src/error.c @@ -0,0 +1,641 @@ +/* $Xorg: error.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <stdio.h> + +#include <errno.h> + +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + + +void +_IceErrorBadMinor (iceConn, majorOpcode, offendingMinor, severity) + +IceConn iceConn; +int majorOpcode; +int offendingMinor; +int severity; + +{ + IceErrorHeader (iceConn, + majorOpcode, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadMinor, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorBadState (iceConn, majorOpcode, offendingMinor, severity) + +IceConn iceConn; +int majorOpcode; +int offendingMinor; +int severity; + +{ + IceErrorHeader (iceConn, + majorOpcode, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadState, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorBadLength (iceConn, majorOpcode, offendingMinor, severity) + +IceConn iceConn; +int majorOpcode; +int offendingMinor; +int severity; + +{ + IceErrorHeader (iceConn, + majorOpcode, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadLength, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorBadValue (iceConn, majorOpcode, offendingMinor, offset, length, value) + +IceConn iceConn; +int majorOpcode; +int offendingMinor; +int offset; +int length; /* in bytes */ +IcePointer value; + +{ + IceErrorHeader (iceConn, + majorOpcode, offendingMinor, + iceConn->receive_sequence, + IceCanContinue, + IceBadValue, + WORD64COUNT (8 + length)); + + IceWriteData32 (iceConn, 4, &offset); + IceWriteData32 (iceConn, 4, &length); + IceWriteData (iceConn, length, (char *) value); + + if (PAD64 (length)) + IceWritePad (iceConn, PAD64 (length)); + + IceFlush (iceConn); +} + + +void +_IceErrorNoAuthentication (iceConn, offendingMinor) + +IceConn iceConn; +int offendingMinor; + +{ + int severity = (offendingMinor == ICE_ConnectionSetup) ? + IceFatalToConnection : IceFatalToProtocol; + + IceErrorHeader (iceConn, + 0, offendingMinor, + iceConn->receive_sequence, + severity, + IceNoAuth, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorNoVersion (iceConn, offendingMinor) + +IceConn iceConn; +int offendingMinor; + +{ + int severity = (offendingMinor == ICE_ConnectionSetup) ? + IceFatalToConnection : IceFatalToProtocol; + + IceErrorHeader (iceConn, + 0, offendingMinor, + iceConn->receive_sequence, + severity, + IceNoVersion, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorSetupFailed (iceConn, offendingMinor, reason) + +IceConn iceConn; +int offendingMinor; +char *reason; + +{ + char *pBuf, *pStart; + int bytes; + int severity = (offendingMinor == ICE_ConnectionSetup) ? + IceFatalToConnection : IceFatalToProtocol; + + if (!reason) + reason = ""; + bytes = STRING_BYTES (reason); + + IceErrorHeader (iceConn, + 0, offendingMinor, + iceConn->receive_sequence, + severity, + IceSetupFailed, + WORD64COUNT (bytes)); + + pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes)); + STORE_STRING (pBuf, reason); + + IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart); + IceFlush (iceConn); +} + + +void +_IceErrorAuthenticationRejected (iceConn, offendingMinor, reason) + +IceConn iceConn; +int offendingMinor; +char *reason; + +{ + char *pBuf, *pStart; + int bytes; + + if (!reason) + reason = ""; + bytes = STRING_BYTES (reason); + + IceErrorHeader (iceConn, + 0, offendingMinor, + iceConn->receive_sequence, + IceFatalToProtocol, + IceAuthRejected, + WORD64COUNT (bytes)); + + pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes)); + STORE_STRING (pBuf, reason); + + IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart); + IceFlush (iceConn); +} + + +void +_IceErrorAuthenticationFailed (iceConn, offendingMinor, reason) + +IceConn iceConn; +int offendingMinor; +char *reason; + +{ + char *pBuf, *pStart; + int bytes; + + if (!reason) + reason = ""; + bytes = STRING_BYTES (reason); + + IceErrorHeader (iceConn, + 0, offendingMinor, + iceConn->receive_sequence, + IceFatalToProtocol, + IceAuthFailed, + WORD64COUNT (bytes)); + + pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes)); + STORE_STRING (pBuf, reason); + + IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart); + IceFlush (iceConn); +} + + +void +_IceErrorProtocolDuplicate (iceConn, protocolName) + +IceConn iceConn; +char *protocolName; + +{ + char *pBuf, *pStart; + int bytes; + + if (!protocolName) + protocolName = ""; + bytes = STRING_BYTES (protocolName); + + IceErrorHeader (iceConn, + 0, ICE_ProtocolSetup, + iceConn->receive_sequence, + IceFatalToProtocol, + IceProtocolDuplicate, + WORD64COUNT (bytes)); + + pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes)); + STORE_STRING (pBuf, protocolName); + + IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart); + IceFlush (iceConn); +} + + +void +_IceErrorMajorOpcodeDuplicate (iceConn, majorOpcode) + +IceConn iceConn; +int majorOpcode; + +{ + char mOp = (char) majorOpcode; + + IceErrorHeader (iceConn, + 0, ICE_ProtocolSetup, + iceConn->receive_sequence, + IceFatalToProtocol, + IceMajorOpcodeDuplicate, + 1 /* length */); + + IceWriteData (iceConn, 8, &mOp); + IceFlush (iceConn); +} + + +void +_IceErrorUnknownProtocol (iceConn, protocolName) + +IceConn iceConn; +char *protocolName; + +{ + char *pBuf, *pStart; + int bytes; + + if (!protocolName) + protocolName = ""; + bytes = STRING_BYTES (protocolName); + + IceErrorHeader (iceConn, + 0, ICE_ProtocolSetup, + iceConn->receive_sequence, + IceFatalToProtocol, + IceUnknownProtocol, + WORD64COUNT (bytes)); + + pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes)); + STORE_STRING (pBuf, protocolName); + + IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart); + IceFlush (iceConn); +} + + +void +_IceErrorBadMajor (iceConn, offendingMajor, offendingMinor, severity) + +IceConn iceConn; +int offendingMajor; +int offendingMinor; +int severity; + +{ + char maj = (char) offendingMajor; + + IceErrorHeader (iceConn, + 0, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadMajor, + 1 /* length */); + + IceWriteData (iceConn, 8, &maj); + IceFlush (iceConn); +} + + + +/* + * Default error handler. + */ + +void +_IceDefaultErrorHandler (iceConn, swap, + offendingMinorOpcode, offendingSequence, errorClass, severity, values) + +IceConn iceConn; +Bool swap; +int offendingMinorOpcode; +unsigned long offendingSequence; +int errorClass; +int severity; +IcePointer values; + +{ + char *str; + char *pData = (char *) values; + + switch (offendingMinorOpcode) + { + case ICE_ConnectionSetup: + str = "ConnectionSetup"; + break; + case ICE_AuthRequired: + str = "AuthRequired"; + break; + case ICE_AuthReply: + str = "AuthReply"; + break; + case ICE_AuthNextPhase: + str = "AuthNextPhase"; + break; + case ICE_ConnectionReply: + str = "ConnectionReply"; + break; + case ICE_ProtocolSetup: + str = "ProtocolSetup"; + break; + case ICE_ProtocolReply: + str = "ProtocolReply"; + break; + case ICE_Ping: + str = "Ping"; + break; + case ICE_PingReply: + str = "PingReply"; + break; + case ICE_WantToClose: + str = "WantToClose"; + break; + case ICE_NoClose: + str = "NoClose"; + break; + default: + str = ""; + } + + fprintf (stderr, "\n"); + + fprintf (stderr, "ICE error: Offending minor opcode = %d (%s)\n", + offendingMinorOpcode, str); + + fprintf (stderr, " Offending sequence number = %d\n", + offendingSequence); + + switch (errorClass) + { + case IceBadMinor: + str = "BadMinor"; + break; + case IceBadState: + str = "BadState"; + break; + case IceBadLength: + str = "BadLength"; + break; + case IceBadValue: + str = "BadValue"; + break; + case IceBadMajor: + str = "BadMajor"; + break; + case IceNoAuth: + str = "NoAuthentication"; + break; + case IceNoVersion: + str = "NoVersion"; + break; + case IceSetupFailed: + str = "SetupFailed"; + break; + case IceAuthRejected: + str = "AuthenticationRejected"; + break; + case IceAuthFailed: + str = "AuthenticationFailed"; + break; + case IceProtocolDuplicate: + str = "ProtocolDuplicate"; + break; + case IceMajorOpcodeDuplicate: + str = "MajorOpcodeDuplicate"; + break; + case IceUnknownProtocol: + str = "UnknownProtocol"; + break; + default: + str = "???"; + } + + fprintf (stderr, " Error class = %s\n", str); + + if (severity == IceCanContinue) + str = "CanContinue"; + else if (severity == IceFatalToProtocol) + str = "FatalToProtocol"; + else if (severity == IceFatalToConnection) + str = "FatalToConnection"; + else + str = "???"; + + fprintf (stderr, " Severity = %s\n", str); + + switch (errorClass) + { + case IceBadValue: + { + int offset, length, val; + + EXTRACT_CARD32 (pData, swap, offset); + EXTRACT_CARD32 (pData, swap, length); + + fprintf (stderr, + " BadValue Offset = %d\n", offset); + fprintf (stderr, + " BadValue Length = %d\n", length); + + if (length <= 4) + { + if (length == 1) + val = (int) *pData; + else if (length == 2) + { + EXTRACT_CARD16 (pData, swap, val); + } + else + { + EXTRACT_CARD32 (pData, swap, val); + } + + fprintf (stderr, + " BadValue = %d\n", val); + } + break; + } + + case IceBadMajor: + + fprintf (stderr, "Major opcode : %d\n", (int) *pData); + break; + + case IceSetupFailed: + + EXTRACT_STRING (pData, swap, str); + fprintf (stderr, "Reason : %s\n", str); + break; + + case IceAuthRejected: + + EXTRACT_STRING (pData, swap, str); + fprintf (stderr, "Reason : %s\n", str); + break; + + case IceAuthFailed: + + EXTRACT_STRING (pData, swap, str); + fprintf (stderr, "Reason : %s\n", str); + break; + + case IceProtocolDuplicate: + + EXTRACT_STRING (pData, swap, str); + fprintf (stderr, "Protocol name : %s\n", str); + break; + + case IceMajorOpcodeDuplicate: + + fprintf (stderr, "Major opcode : %d\n", (int) *pData); + break; + + case IceUnknownProtocol: + + EXTRACT_STRING (pData, swap, str); + fprintf (stderr, "Protocol name : %s\n", str); + break; + + default: + break; + } + + fprintf (stderr, "\n"); + + if (severity != IceCanContinue) + exit (1); +} + + + +/* + * This procedure sets the ICE error handler to be the specified + * routine. If NULL is passed in the default error handler is restored. + * The function's return value is the previous error handler. + */ + +IceErrorHandler +IceSetErrorHandler (handler) + +IceErrorHandler handler; + +{ + IceErrorHandler oldHandler = _IceErrorHandler; + + if (handler != NULL) + _IceErrorHandler = handler; + else + _IceErrorHandler = _IceDefaultErrorHandler; + + return (oldHandler); +} + + + +/* + * Default IO error handler. + */ + +void +_IceDefaultIOErrorHandler (iceConn) + +IceConn iceConn; + +{ + fprintf (stderr, + "ICE default IO error handler doing an exit(), pid = %d, errno = %d\n", + getpid(), errno); + + exit (1); +} + + + +/* + * This procedure sets the ICE fatal I/O error handler to be the + * specified routine. If NULL is passed in the default error + * handler is restored. The function's return value is the + * previous error handler. + */ + +IceIOErrorHandler +IceSetIOErrorHandler (handler) + +IceIOErrorHandler handler; + +{ + IceIOErrorHandler oldHandler = _IceIOErrorHandler; + + if (handler != NULL) + _IceIOErrorHandler = handler; + else + _IceIOErrorHandler = _IceDefaultIOErrorHandler; + + return (oldHandler); +} diff --git a/src/getauth.c b/src/getauth.c new file mode 100644 index 0000000..50024bd --- /dev/null +++ b/src/getauth.c @@ -0,0 +1,270 @@ +/* $Xorg: getauth.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/ICE/ICEutil.h> + +static Bool auth_valid (); + +extern int _IcePaAuthDataEntryCount; +extern IceAuthDataEntry _IcePaAuthDataEntries[]; + + +/* + * The functions in this file are not a standard part of ICElib. + * + * The sample implementation uses an .ICEauthority to manipulate + * authentication data. + * + * For the client that initiates a Protocol Setup, we look in the + * .ICEauthority file to get the data. + * + * For the client accepting the Protocol Setup, we get the data + * from an in-memory database of authentication data (set by the + * application calling IceSetPaAuthData). We have to get the data + * from memory because getting it directly from the .ICEauthority + * file is not secure - someone can just modify the contents of the + * .ICEauthority file behind our back. + */ + +void +_IceGetPoAuthData (protocolName, networkId, authName, + authDataLenRet, authDataRet) + +char *protocolName; +char *networkId; +char *authName; +unsigned short *authDataLenRet; +char **authDataRet; + +{ + IceAuthFileEntry *entry; + + entry = IceGetAuthFileEntry (protocolName, networkId, authName); + + if (entry) + { + *authDataLenRet = entry->auth_data_length; + + if ((*authDataRet = (char *) malloc (entry->auth_data_length)) != NULL) + memcpy (*authDataRet, entry->auth_data, entry->auth_data_length); + } + else + { + *authDataLenRet = 0; + *authDataRet = NULL; + } + + IceFreeAuthFileEntry (entry); +} + + + +void +_IceGetPaAuthData (protocolName, networkId, authName, + authDataLenRet, authDataRet) + +char *protocolName; +char *networkId; +char *authName; +unsigned short *authDataLenRet; +char **authDataRet; + +{ + IceAuthDataEntry *entry; + int found = 0; + int i; + + for (i = 0; i < _IcePaAuthDataEntryCount && !found; i++) + { + entry = &_IcePaAuthDataEntries[i]; + + found = + strcmp (protocolName, entry->protocol_name) == 0 && + strcmp (networkId, entry->network_id) == 0 && + strcmp (authName, entry->auth_name) == 0; + } + + if (found) + { + *authDataLenRet = entry->auth_data_length; + + if ((*authDataRet = (char *) malloc (entry->auth_data_length)) != NULL) + memcpy (*authDataRet, entry->auth_data, entry->auth_data_length); + } + else + { + *authDataLenRet = 0; + *authDataRet = NULL; + } +} + + + +void +_IceGetPoValidAuthIndices (protocol_name, network_id, + num_auth_names, auth_names, num_indices_ret, indices_ret) + +char *protocol_name; +char *network_id; +int num_auth_names; +char **auth_names; +int *num_indices_ret; +int *indices_ret; /* in/out arg */ + +{ + FILE *auth_file; + char *filename; + IceAuthFileEntry *entry; + int index_ret, i; + + *num_indices_ret = 0; + + if (!(filename = IceAuthFileName ())) + return; + + if (access (filename, R_OK) != 0) /* checks REAL id */ + return; + + if (!(auth_file = fopen (filename, "rb"))) + return; + + for (;;) + { + if (!(entry = IceReadAuthFileEntry (auth_file))) + break; + + if (strcmp (protocol_name, entry->protocol_name) == 0 && + strcmp (network_id, entry->network_id) == 0 && + auth_valid (entry->auth_name, num_auth_names, + auth_names, &index_ret)) + { + /* + * Make sure we didn't store this index already. + */ + + for (i = 0; i < *num_indices_ret; i++) + if (index_ret == indices_ret[i]) + break; + + if (i >= *num_indices_ret) + { + indices_ret[*num_indices_ret] = index_ret; + *num_indices_ret += 1; + } + } + + IceFreeAuthFileEntry (entry); + } + + fclose (auth_file); +} + + + +void +_IceGetPaValidAuthIndices (protocol_name, network_id, + num_auth_names, auth_names, num_indices_ret, indices_ret) + +char *protocol_name; +char *network_id; +int num_auth_names; +char **auth_names; +int *num_indices_ret; +int *indices_ret; /* in/out arg */ + +{ + int index_ret; + int i, j; + IceAuthDataEntry *entry; + + *num_indices_ret = 0; + + for (i = 0; i < _IcePaAuthDataEntryCount; i++) + { + entry = &_IcePaAuthDataEntries[i]; + + if (strcmp (protocol_name, entry->protocol_name) == 0 && + strcmp (network_id, entry->network_id) == 0 && + auth_valid (entry->auth_name, num_auth_names, + auth_names, &index_ret)) + { + /* + * Make sure we didn't store this index already. + */ + + for (j = 0; j < *num_indices_ret; j++) + if (index_ret == indices_ret[j]) + break; + + if (j >= *num_indices_ret) + { + indices_ret[*num_indices_ret] = index_ret; + *num_indices_ret += 1; + } + } + } +} + + + +/* + * local routines + */ + +static Bool +auth_valid (auth_name, num_auth_names, auth_names, index_ret) + +char *auth_name; +int num_auth_names; +char **auth_names; +int *index_ret; + +{ + /* + * Check if auth_name is in auth_names. Return index. + */ + + int i; + + for (i = 0; i < num_auth_names; i++) + if (strcmp (auth_name, auth_names[i]) == 0) + { + break; + } + + if (i < num_auth_names) + { + *index_ret = i; + return (1); + } + else + return (0); +} diff --git a/src/globals.h b/src/globals.h new file mode 100644 index 0000000..6bffe7c --- /dev/null +++ b/src/globals.h @@ -0,0 +1,57 @@ +/* $Xorg: globals.h,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +extern void _IceDefaultErrorHandler (); +extern void _IceDefaultIOErrorHandler (); + +extern IcePoAuthStatus _IcePoMagicCookie1Proc (); +extern IcePaAuthStatus _IcePaMagicCookie1Proc (); + +extern void _IceProcessCoreMessage (); + +IceConn _IceConnectionObjs[256]; +char *_IceConnectionStrings[256]; +int _IceConnectionCount = 0; + +_IceProtocol _IceProtocols[255]; +int _IceLastMajorOpcode = 0; + +int _IceAuthCount = 1; +char *_IceAuthNames[] = {"MIT-MAGIC-COOKIE-1"}; +IcePoAuthProc _IcePoAuthProcs[] = {_IcePoMagicCookie1Proc}; +IcePaAuthProc _IcePaAuthProcs[] = {_IcePaMagicCookie1Proc}; + +int _IceVersionCount = 1; +_IceVersion _IceVersions[] = { + {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}}; + +_IceWatchProc *_IceWatchProcs = NULL; + +IceErrorHandler _IceErrorHandler = _IceDefaultErrorHandler; +IceIOErrorHandler _IceIOErrorHandler = _IceDefaultIOErrorHandler; diff --git a/src/iceauth.c b/src/iceauth.c new file mode 100644 index 0000000..4556b9a --- /dev/null +++ b/src/iceauth.c @@ -0,0 +1,278 @@ +/* $Xorg: iceauth.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/ICE/ICEutil.h> + +#ifdef X_NOT_STDC_ENV +#define Time_t long +extern Time_t time (); +#else +#include <time.h> +#define Time_t time_t +#endif + +static int binaryEqual (); + +static int was_called_state; + +/* + * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by + * the SI. It is not part of standard ICElib. + */ + + +char * +IceGenerateMagicCookie (len) + +int len; + +{ + char *auth; + long ldata[2]; + int seed; + int value; + int i; + + if ((auth = (char *) malloc (len + 1)) == NULL) + return (NULL); + +#ifdef ITIMER_REAL + { + struct timeval now; + X_GETTIMEOFDAY (&now); + ldata[0] = now.tv_sec; + ldata[1] = now.tv_usec; + } +#else + { + long time (); + + ldata[0] = time ((long *) 0); + ldata[1] = getpid (); + } +#endif + seed = (ldata[0]) + (ldata[1] << 16); + srand (seed); + for (i = 0; i < len; i++) + { + value = rand (); + auth[i] = value & 0xff; + } + auth[len] = '\0'; + + return (auth); +} + + + +IcePoAuthStatus +_IcePoMagicCookie1Proc (iceConn, authStatePtr, cleanUp, swap, + authDataLen, authData, replyDataLenRet, replyDataRet, errorStringRet) + +IceConn iceConn; +IcePointer *authStatePtr; +Bool cleanUp; +Bool swap; +int authDataLen; +IcePointer authData; +int *replyDataLenRet; +IcePointer *replyDataRet; +char **errorStringRet; + +{ + if (cleanUp) + { + /* + * We didn't allocate any state. We're done. + */ + + return (IcePoAuthDoneCleanup); + } + + *errorStringRet = NULL; + + if (*authStatePtr == NULL) + { + /* + * This is the first time we're being called. Search the + * authentication data for the first occurence of + * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string. + */ + + unsigned short length; + char *data; + + _IceGetPoAuthData ("ICE", iceConn->connection_string, + "MIT-MAGIC-COOKIE-1", &length, &data); + + if (!data) + { + char *tempstr = + "Could not find correct MIT-MAGIC-COOKIE-1 authentication"; + + *errorStringRet = (char *) malloc (strlen (tempstr) + 1); + if (*errorStringRet) + strcpy (*errorStringRet, tempstr); + + return (IcePoAuthFailed); + } + else + { + *authStatePtr = (IcePointer) &was_called_state; + + *replyDataLenRet = length; + *replyDataRet = data; + + return (IcePoAuthHaveReply); + } + } + else + { + /* + * We should never get here for MIT-MAGIC-COOKIE-1 since it is + * a single pass authentication method. + */ + + char *tempstr = "MIT-MAGIC-COOKIE-1 authentication internal error"; + + *errorStringRet = (char *) malloc (strlen (tempstr) + 1); + if (*errorStringRet) + strcpy (*errorStringRet, tempstr); + + return (IcePoAuthFailed); + } +} + + + +IcePaAuthStatus +_IcePaMagicCookie1Proc (iceConn, authStatePtr, swap, + authDataLen, authData, replyDataLenRet, replyDataRet, errorStringRet) + +IceConn iceConn; +IcePointer *authStatePtr; +Bool swap; +int authDataLen; +IcePointer authData; +int *replyDataLenRet; +IcePointer *replyDataRet; +char **errorStringRet; + +{ + *errorStringRet = NULL; + *replyDataLenRet = 0; + *replyDataRet = NULL; + + if (*authStatePtr == NULL) + { + /* + * This is the first time we're being called. We don't have + * any data to pass to the other client. + */ + + *authStatePtr = (IcePointer) &was_called_state; + + return (IcePaAuthContinue); + } + else + { + /* + * Search the authentication data for the first occurence of + * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string. + */ + + unsigned short length; + char *data; + + _IceGetPaAuthData ("ICE", iceConn->connection_string, + "MIT-MAGIC-COOKIE-1", &length, &data); + + if (data) + { + IcePaAuthStatus stat; + + if (authDataLen == length && + binaryEqual ((char *) authData, data, authDataLen)) + { + stat = IcePaAuthAccepted; + } + else + { + char *tempstr = "MIT-MAGIC-COOKIE-1 authentication rejected"; + + *errorStringRet = (char *) malloc (strlen (tempstr) + 1); + if (*errorStringRet) + strcpy (*errorStringRet, tempstr); + + stat = IcePaAuthRejected; + } + + free (data); + return (stat); + } + else + { + /* + * We should never get here because in the ConnectionReply + * we should have passed all the valid methods. So we should + * always find a valid entry. + */ + + char *tempstr = + "MIT-MAGIC-COOKIE-1 authentication internal error"; + + *errorStringRet = (char *) malloc (strlen (tempstr) + 1); + if (*errorStringRet) + strcpy (*errorStringRet, tempstr); + + return (IcePaAuthFailed); + } + } +} + + + +/* + * local routines + */ + +static int +binaryEqual (a, b, len) + +register char *a, *b; +register unsigned len; + +{ + while (len--) + if (*a++ != *b++) + return 0; + return 1; +} diff --git a/src/listen.c b/src/listen.c new file mode 100644 index 0000000..cee141f --- /dev/null +++ b/src/listen.c @@ -0,0 +1,280 @@ +/* $Xorg: listen.c,v 1.5 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/Xtrans.h> +#include <stdio.h> + + +Status +IceListenForConnections (countRet, listenObjsRet, errorLength, errorStringRet) + +int *countRet; +IceListenObj **listenObjsRet; +int errorLength; +char *errorStringRet; + +{ + struct _IceListenObj *listenObjs; + char *networkId; + int transCount, partial, i, j; + Status status = 1; + XtransConnInfo *transConns = NULL; + + + if ((_IceTransMakeAllCOTSServerListeners (NULL, &partial, + &transCount, &transConns) < 0) || (transCount < 1)) + { + *listenObjsRet = NULL; + *countRet = 0; + + strncpy (errorStringRet, + "Cannot establish any listening sockets", errorLength); + + return (0); + } + + if ((listenObjs = (struct _IceListenObj *) malloc ( + transCount * sizeof (struct _IceListenObj))) == NULL) + { + for (i = 0; i < transCount; i++) + _IceTransClose (transConns[i]); + free ((char *) transConns); + return (0); + } + + *countRet = 0; + + for (i = 0; i < transCount; i++) + { + networkId = _IceTransGetMyNetworkId (transConns[i]); + + if (networkId) + { + listenObjs[*countRet].trans_conn = transConns[i]; + listenObjs[*countRet].network_id = networkId; + + (*countRet)++; + } + } + + if (*countRet == 0) + { + *listenObjsRet = NULL; + + strncpy (errorStringRet, + "Cannot establish any listening sockets", errorLength); + + status = 0; + } + else + { + *listenObjsRet = (IceListenObj *) malloc ( + *countRet * sizeof (IceListenObj)); + + if (*listenObjsRet == NULL) + { + strncpy (errorStringRet, "Malloc failed", errorLength); + + status = 0; + } + else + { + for (i = 0; i < *countRet; i++) + { + (*listenObjsRet)[i] = (IceListenObj) malloc ( + sizeof (struct _IceListenObj)); + + if ((*listenObjsRet)[i] == NULL) + { + strncpy (errorStringRet, "Malloc failed", errorLength); + + for (j = 0; j < i; j++) + free ((char *) (*listenObjsRet)[j]); + + free ((char *) *listenObjsRet); + + status = 0; + } + else + { + *((*listenObjsRet)[i]) = listenObjs[i]; + } + } + } + } + + if (status == 1) + { + if (errorStringRet && errorLength > 0) + *errorStringRet = '\0'; + + for (i = 0; i < *countRet; i++) + { + (*listenObjsRet)[i]->host_based_auth_proc = NULL; + } + } + else + { + for (i = 0; i < transCount; i++) + _IceTransClose (transConns[i]); + } + + free ((char *) listenObjs); + free ((char *) transConns); + + return (status); +} + + + +int +IceGetListenConnectionNumber (listenObj) + +IceListenObj listenObj; + +{ + return (_IceTransGetConnectionNumber (listenObj->trans_conn)); +} + + + +char * +IceGetListenConnectionString (listenObj) + +IceListenObj listenObj; + +{ + char *networkId; + + networkId = (char *) malloc (strlen (listenObj->network_id) + 1); + + if (networkId) + strcpy (networkId, listenObj->network_id); + + return (networkId); +} + + + +char * +IceComposeNetworkIdList (count, listenObjs) + +int count; +IceListenObj *listenObjs; + +{ + char *list; + int len = 0; + int i; + + if (count < 1 || listenObjs == NULL) + return (NULL); + + for (i = 0; i < count; i++) + len += (strlen (listenObjs[i]->network_id) + 1); + + list = (char *) malloc (len); + + if (list == NULL) + return (NULL); + else + { + int doneCount = 0; + + list[0] = '\0'; + + for (i = 0; i < count; i++) + { + if (_IceTransIsLocal (listenObjs[i]->trans_conn)) + { + strcat (list, listenObjs[i]->network_id); + doneCount++; + if (doneCount < count) + strcat (list, ","); + } + } + + if (doneCount < count) + { + for (i = 0; i < count; i++) + { + if (!_IceTransIsLocal (listenObjs[i]->trans_conn)) + { + strcat (list, listenObjs[i]->network_id); + doneCount++; + if (doneCount < count) + strcat (list, ","); + } + } + } + + return (list); + } +} + + + +void +IceFreeListenObjs (count, listenObjs) + +int count; +IceListenObj *listenObjs; + +{ + int i; + + for (i = 0; i < count; i++) + { + free (listenObjs[i]->network_id); + _IceTransClose (listenObjs[i]->trans_conn); + free ((char *) listenObjs[i]); + } + + free ((char *) listenObjs); +} + + + +/* + * Allow host based authentication for the ICE Connection Setup. + * Do not confuse with the host based authentication callbacks that + * can be set up in IceRegisterForProtocolReply. + */ + +void +IceSetHostBasedAuthProc (listenObj, hostBasedAuthProc) + +IceListenObj listenObj; +IceHostBasedAuthProc hostBasedAuthProc; + +{ + listenObj->host_based_auth_proc = hostBasedAuthProc; +} diff --git a/src/listenwk.c b/src/listenwk.c new file mode 100644 index 0000000..156fc61 --- /dev/null +++ b/src/listenwk.c @@ -0,0 +1,157 @@ +/* $Xorg: listenwk.c,v 1.5 2001/02/09 02:03:26 xorgcvs Exp $ */ + +/* + +Copyright 1996, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + + +/* Author: Ralph Mor, X Consortium */ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/Xtrans.h> +#include <stdio.h> + + +Status +IceListenForWellKnownConnections (port, countRet, listenObjsRet, errorLength, errorStringRet) + +char *port; +int *countRet; +IceListenObj **listenObjsRet; +int errorLength; +char *errorStringRet; + +{ + struct _IceListenObj *listenObjs; + char *networkId; + int transCount, partial, i, j; + Status status = 1; + XtransConnInfo *transConns = NULL; + + + if ((_IceTransMakeAllCOTSServerListeners (port, &partial, + &transCount, &transConns) < 0) || (transCount < 1)) + { + *listenObjsRet = NULL; + *countRet = 0; + + strncpy (errorStringRet, + "Cannot establish any listening sockets", errorLength); + + return (0); + } + + if ((listenObjs = (struct _IceListenObj *) malloc ( + transCount * sizeof (struct _IceListenObj))) == NULL) + { + for (i = 0; i < transCount; i++) + _IceTransClose (transConns[i]); + free ((char *) transConns); + return (0); + } + + *countRet = 0; + + for (i = 0; i < transCount; i++) + { + networkId = (char *)_IceTransGetMyNetworkId (transConns[i]); + + if (networkId) + { + listenObjs[*countRet].trans_conn = transConns[i]; + listenObjs[*countRet].network_id = networkId; + + (*countRet)++; + } + } + + if (*countRet == 0) + { + *listenObjsRet = NULL; + + strncpy (errorStringRet, + "Cannot establish any listening sockets", errorLength); + + status = 0; + } + else + { + *listenObjsRet = (IceListenObj *) malloc ( + *countRet * sizeof (IceListenObj)); + + if (*listenObjsRet == NULL) + { + strncpy (errorStringRet, "Malloc failed", errorLength); + + status = 0; + } + else + { + for (i = 0; i < *countRet; i++) + { + (*listenObjsRet)[i] = (IceListenObj) malloc ( + sizeof (struct _IceListenObj)); + + if ((*listenObjsRet)[i] == NULL) + { + strncpy (errorStringRet, "Malloc failed", errorLength); + + for (j = 0; j < i; j++) + free ((char *) (*listenObjsRet)[j]); + + free ((char *) *listenObjsRet); + + status = 0; + } + else + { + *((*listenObjsRet)[i]) = listenObjs[i]; + } + } + } + } + + if (status == 1) + { + if (errorStringRet && errorLength > 0) + *errorStringRet = '\0'; + + for (i = 0; i < *countRet; i++) + { + (*listenObjsRet)[i]->host_based_auth_proc = NULL; + } + } + else + { + for (i = 0; i < transCount; i++) + _IceTransClose (transConns[i]); + } + + free ((char *) listenObjs); + free ((char *) transConns); + + return (status); +} diff --git a/src/locking.c b/src/locking.c new file mode 100644 index 0000000..c16c3a1 --- /dev/null +++ b/src/locking.c @@ -0,0 +1,64 @@ +/* $Xorg: locking.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + + +/* + * NOT IMPLEMENTED YET + */ + + +Status +IceInitThreads () + +{ + return (0); +} + + +void +IceAppLockConn (iceConn) + +IceConn iceConn; + +{ + IceLockConn (iceConn); +} + + +void +IceAppUnlockConn (iceConn) + +IceConn iceConn; + +{ + IceUnlockConn (iceConn); +} diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..0ed98b0 --- /dev/null +++ b/src/misc.c @@ -0,0 +1,621 @@ +/* $Xorg: misc.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#ifdef WIN32 +#define _WILLWINSOCK_ +#endif +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/Xtrans.h> +#include <stdio.h> +#ifdef WIN32 +#include <X11/Xwinsock.h> +#include <X11/Xw32defs.h> +#endif + + +/* + * scratch buffer + */ + +char * +IceAllocScratch (iceConn, size) + +IceConn iceConn; +unsigned long size; + +{ + if (!iceConn->scratch || size > iceConn->scratch_size) + { + if (iceConn->scratch) + free (iceConn->scratch); + + iceConn->scratch = (char *) malloc ((unsigned) size); + iceConn->scratch_size = size; + } + + return (iceConn->scratch); +} + + + +/* + * Output/Input buffer functions + */ + +IceFlush (iceConn) + +IceConn iceConn; + +{ + _IceWrite (iceConn, + (unsigned long) (iceConn->outbufptr - iceConn->outbuf), + iceConn->outbuf); + + iceConn->outbufptr = iceConn->outbuf; + return 1; +} + + +int +IceGetOutBufSize (iceConn) + +IceConn iceConn; + +{ + return (iceConn->outbufmax - iceConn->outbuf); +} + + +int +IceGetInBufSize (iceConn) + +IceConn iceConn; + +{ + return (iceConn->inbufmax - iceConn->inbuf); +} + + + +/* + * informational functions + */ + +IceConnectStatus +IceConnectionStatus (iceConn) + +IceConn iceConn; + +{ + return (iceConn->connection_status); +} + + +char * +IceVendor (iceConn) + +IceConn iceConn; + +{ + char *string = (char *) malloc (strlen (iceConn->vendor) + 1); + + if (string) + strcpy (string, iceConn->vendor); + + return (string); +} + + +char * +IceRelease (iceConn) + +IceConn iceConn; + +{ + char *string = (char *) malloc (strlen (iceConn->release) + 1); + + if (string) + strcpy (string, iceConn->release); + + return (string); +} + + +int +IceProtocolVersion (iceConn) + +IceConn iceConn; + +{ + return (_IceVersions[iceConn->my_ice_version_index].major_version); +} + + +int +IceProtocolRevision (iceConn) + +IceConn iceConn; + +{ + return (_IceVersions[iceConn->my_ice_version_index].minor_version); +} + + +int +IceConnectionNumber (iceConn) + +IceConn iceConn; + +{ + return (_IceTransGetConnectionNumber (iceConn->trans_conn)); +} + + +char * +IceConnectionString (iceConn) + +IceConn iceConn; + +{ + if (iceConn->connection_string) + { + char *string = (char *) malloc ( + strlen (iceConn->connection_string) + 1); + + if (string) + strcpy (string, iceConn->connection_string); + + return (string); + } + else + return (NULL); +} + + +unsigned long +IceLastSentSequenceNumber (iceConn) + +IceConn iceConn; + +{ + return (iceConn->send_sequence); +} + + +unsigned long +IceLastReceivedSequenceNumber (iceConn) + +IceConn iceConn; + +{ + return (iceConn->receive_sequence); +} + + +Bool +IceSwapping (iceConn) + +IceConn iceConn; + +{ + return (iceConn->swap); +} + + + +/* + * Read "n" bytes from a connection. + * + * Return Status 0 if we detected an EXPECTED closed connection. + * + */ + +Status +_IceRead (iceConn, nbytes, ptr) + +register IceConn iceConn; +unsigned long nbytes; +register char *ptr; + +{ + register unsigned long nleft; + + nleft = nbytes; + while (nleft > 0) + { + int nread; + + if (iceConn->io_ok) + nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft); + else + return (1); + + if (nread <= 0) + { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (iceConn->want_to_close) + { + /* + * We sent a WantToClose message and now we detected that + * the other side closed the connection. + */ + + _IceConnectionClosed (iceConn); /* invoke watch procs */ + _IceFreeConnection (iceConn); + + return (0); + } + else + { + /* + * Fatal IO error. First notify each protocol's IceIOErrorProc + * callback, then invoke the application IO error handler. + */ + + iceConn->io_ok = False; + + if (iceConn->connection_status == IceConnectPending) + { + /* + * Don't invoke IO error handler if we are in the + * middle of a connection setup. + */ + + return (1); + } + + if (iceConn->process_msg_info) + { + int i; + + for (i = iceConn->his_min_opcode; + i <= iceConn->his_max_opcode; i++) + { + _IceProcessMsgInfo *process; + + process = &iceConn->process_msg_info[ + i - iceConn->his_min_opcode]; + + if (process->in_use) + { + IceIOErrorProc IOErrProc = process->accept_flag ? + process->protocol->accept_client->io_error_proc : + process->protocol->orig_client->io_error_proc; + + if (IOErrProc) + (*IOErrProc) (iceConn); + } + } + } + + (*_IceIOErrorHandler) (iceConn); + return (1); + } + } + + nleft -= nread; + ptr += nread; + } + + return (1); +} + + + +/* + * If we read a message header with a bad major or minor opcode, + * we need to advance to the end of the message. This way, the next + * message can be processed correctly. + */ + +void +_IceReadSkip (iceConn, nbytes) + +register IceConn iceConn; +register unsigned long nbytes; + +{ + char temp[512]; + + while (nbytes > 0) + { + unsigned long rbytes = nbytes > 512 ? 512 : nbytes; + + _IceRead (iceConn, rbytes, temp); + nbytes -= rbytes; + } +} + + + +/* + * Write "n" bytes to a connection. + */ + +void +_IceWrite (iceConn, nbytes, ptr) + +register IceConn iceConn; +unsigned long nbytes; +register char *ptr; + +{ + register unsigned long nleft; + + nleft = nbytes; + while (nleft > 0) + { + int nwritten; + + if (iceConn->io_ok) + nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft); + else + return; + + if (nwritten <= 0) + { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + /* + * Fatal IO error. First notify each protocol's IceIOErrorProc + * callback, then invoke the application IO error handler. + */ + + iceConn->io_ok = False; + + if (iceConn->connection_status == IceConnectPending) + { + /* + * Don't invoke IO error handler if we are in the + * middle of a connection setup. + */ + + return; + } + + if (iceConn->process_msg_info) + { + int i; + + for (i = iceConn->his_min_opcode; + i <= iceConn->his_max_opcode; i++) + { + _IceProcessMsgInfo *process; + + process = &iceConn->process_msg_info[ + i - iceConn->his_min_opcode]; + + if (process->in_use) + { + IceIOErrorProc IOErrProc = process->accept_flag ? + process->protocol->accept_client->io_error_proc : + process->protocol->orig_client->io_error_proc; + + if (IOErrProc) + (*IOErrProc) (iceConn); + } + } + } + + (*_IceIOErrorHandler) (iceConn); + return; + } + + nleft -= nwritten; + ptr += nwritten; + } +} + +#ifdef WORD64 + +IceWriteData16 (iceConn, nbytes, data) + +IceConn iceConn; +unsigned long nbytes; +short *data; + +{ + int numShorts = nbytes / 2; + int index = 0; + + while (index < numShorts) + { + int spaceLeft, count, i; + int shortsLeft = numShorts - index; + + spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1; + + if (spaceLeft < 2) + { + IceFlush (iceConn); + spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1; + } + + count = (shortsLeft < spaceLeft / 2) ? shortsLeft : spaceLeft / 2; + + for (i = 0; i < count; i++) + STORE_CARD16 (iceConn->outbufptr, data[index++]); + } +} + + +IceWriteData32 (iceConn, nbytes, data) + +IceConn iceConn; +unsigned long nbytes; +int *data; + +{ + int numLongs = nbytes / 4; + int index = 0; + + while (index < numLongs) + { + int spaceLeft, count, i; + int longsLeft = numLongs - index; + + spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1; + + if (spaceLeft < 4) + { + IceFlush (iceConn); + spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1; + } + + count = (longsLeft < spaceLeft / 4) ? longsLeft : spaceLeft / 4; + + for (i = 0; i < count; i++) + STORE_CARD32 (iceConn->outbufptr, data[index++]); + } +} + + +IceReadData16 (iceConn, swap, nbytes, data) + +IceConn iceConn; +Bool swap; +unsigned long nbytes; +short *data; + +{ + /* NOT IMPLEMENTED YET */ +} + + +IceReadData32 (iceConn, swap, nbytes, data) + +IceConn iceConn; +Bool swap; +unsigned long nbytes; +int *data; + +{ + /* NOT IMPLEMENTED YET */ +} + +#endif /* WORD64 */ + + + +void +_IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode) + +IceConn iceConn; +int hisOpcode; +int myOpcode; + +{ + if (hisOpcode <= 0 || hisOpcode > 255) + { + return; + } + else if (iceConn->process_msg_info == NULL) + { + iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc ( + sizeof (_IceProcessMsgInfo)); + iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode; + } + else if (hisOpcode < iceConn->his_min_opcode) + { + _IceProcessMsgInfo *oldVec = iceConn->process_msg_info; + int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1; + int newsize = iceConn->his_max_opcode - hisOpcode + 1; + int i; + + iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc ( + newsize * sizeof (_IceProcessMsgInfo)); + + memcpy (&iceConn->process_msg_info[ + iceConn->his_min_opcode - hisOpcode], oldVec, + oldsize * sizeof (_IceProcessMsgInfo)); + + free ((char *) oldVec); + + for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++) + { + iceConn->process_msg_info[i - + iceConn->his_min_opcode].in_use = False; + + iceConn->process_msg_info[i - + iceConn->his_min_opcode].protocol = NULL; + } + + iceConn->his_min_opcode = hisOpcode; + } + else if (hisOpcode > iceConn->his_max_opcode) + { + _IceProcessMsgInfo *oldVec = iceConn->process_msg_info; + int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1; + int newsize = hisOpcode - iceConn->his_min_opcode + 1; + int i; + + iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc ( + newsize * sizeof (_IceProcessMsgInfo)); + + memcpy (iceConn->process_msg_info, oldVec, + oldsize * sizeof (_IceProcessMsgInfo)); + + free ((char *) oldVec); + + for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++) + { + iceConn->process_msg_info[i - + iceConn->his_min_opcode].in_use = False; + + iceConn->process_msg_info[i - + iceConn->his_min_opcode].protocol = NULL; + } + + iceConn->his_max_opcode = hisOpcode; + } + + iceConn->process_msg_info[hisOpcode - + iceConn->his_min_opcode].in_use = True; + + iceConn->process_msg_info[hisOpcode - + iceConn->his_min_opcode].my_opcode = myOpcode; + + iceConn->process_msg_info[hisOpcode - + iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1]; +} + + + +char * +_IceGetPeerName (iceConn) + +IceConn iceConn; + +{ + return (_IceTransGetPeerNetworkId (iceConn->trans_conn)); +} diff --git a/src/ping.c b/src/ping.c new file mode 100644 index 0000000..bee042a --- /dev/null +++ b/src/ping.c @@ -0,0 +1,63 @@ +/* $Xorg: ping.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + +Status +IcePing (iceConn, pingReplyProc, clientData) + +IceConn iceConn; +IcePingReplyProc pingReplyProc; +IcePointer clientData; + +{ + _IcePingWait *newping = (_IcePingWait *) malloc (sizeof (_IcePingWait)); + _IcePingWait *ptr = iceConn->ping_waits; + + if (newping == NULL) + return (0); + + newping->ping_reply_proc = pingReplyProc; + newping->client_data = clientData; + newping->next = NULL; + + while (ptr && ptr->next) + ptr = ptr->next; + + if (ptr == NULL) + iceConn->ping_waits = newping; + else + ptr->next = newping; + + IceSimpleMessage (iceConn, 0, ICE_Ping); + IceFlush (iceConn); + + return (1); +} diff --git a/src/process.c b/src/process.c new file mode 100644 index 0000000..159348d --- /dev/null +++ b/src/process.c @@ -0,0 +1,2490 @@ +/* $Xorg: process.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + + +/* + * Check for bad length + */ + +#define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity) \ + if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \ + { \ + _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \ + return (0); \ + } + +#define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \ + if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \ + { \ + _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \ + return (0); \ + } + +#define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \ + if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \ + != _expected_len) \ + { \ + _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \ + IceDisposeCompleteMessage (iceConn, _pStart); \ + return (0); \ + } + + + +/* + * IceProcessMessages: + * + * If replyWait == NULL, the client is not waiting for a reply. + * + * If replyWait != NULL, the client is waiting for a reply... + * + * - replyWait->sequence_of_request is the sequence number of the + * message for which the client is waiting a reply. This is needed + * to determine if an error matches a replyWait. + * + * - replyWait->major_opcode_of_request is the major opcode of the + * message for which we are waiting a reply. + * + * - replyWait->minor_opcode_of_request is the minor opcode of the + * message for which we are waiting a reply. + * + * - replyWait->reply is a pointer to the reply message which will be + * filled in when the reply is ready (the protocol library should + * cast this IcePointer to the appropriate reply type). In most cases, + * the reply will have some fixed-size part, and the sender function + * will have provided a pointer to a structure (e.g.) to hold this + * fixed-size data. If there is variable-length data, it would be + * expected that the reply function will have to allocate additional + * memory and store pointer(s) to that memory in the fixed-size + * structure. If the entire data is variable length (e.g., a single + * variable-length string), then the sender function would probably + * just pass a pointer to fixed-size space to hold a pointer, and the + * reply function would allocate the storage and store the pointer. + * It is the responsibility of the client receiving the reply to + * free up any memory allocated on it's behalf. + * + * We might be waiting for several different replies (a function can wait + * for a reply, and while calling IceProcessMessages, a callback can be + * invoked which will wait for another reply). We take advantage of the + * fact that for a given protocol, we are guaranteed that messages are + * processed in the order we sent them. So, everytime we have a new + * replyWait, we add it to the END of the 'saved_reply_waits' list. When + * we read a message and want to see if it matches a replyWait, we use the + * FIRST replyWait in the list with the major opcode of the message. If the + * reply is ready, we remove that replyWait from the list. + * + * If the reply/error is ready for the replyWait passed in to + * IceProcessMessages, *replyReadyRet is set to True. + * + * The return value of IceProcessMessages is one of the following: + * + * IceProcessMessagesSuccess - the message was processed successfully. + * IceProcessMessagesIOError - an IO error occured. The caller should + * invoked IceCloseConnection. + * IceProcessMessagesConnectionClosed - the connection was closed as a + * result of shutdown negotiation. + */ + +IceProcessMessagesStatus +IceProcessMessages (iceConn, replyWait, replyReadyRet) + +IceConn iceConn; +IceReplyWaitInfo *replyWait; +Bool *replyReadyRet; + +{ + iceMsg *header; + Bool replyReady = False; + IceReplyWaitInfo *useThisReplyWait = NULL; + IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess; + + if (replyWait) + *replyReadyRet = False; + + /* + * Each time IceProcessMessages is entered, we increment the dispatch + * level. Each time we leave it, we decrement the dispatch level. + */ + + iceConn->dispatch_level++; + + + /* + * Read the ICE message header. + */ + + if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf)) + { + /* + * If we previously sent a WantToClose and now we detected + * that the connection was closed, _IceRead returns status 0. + * Since the connection was closed, we just want to return here. + */ + + return (IceProcessMessagesConnectionClosed); + } + + if (!iceConn->io_ok) + { + /* + * An unexpected IO error occured. The caller of IceProcessMessages + * should call IceCloseConnection which will cause the watch procedures + * to be invoked and the ICE connection to be freed. + */ + + iceConn->dispatch_level--; + iceConn->connection_status = IceConnectIOError; + return (IceProcessMessagesIOError); + } + + header = (iceMsg *) iceConn->inbuf; + iceConn->inbufptr = iceConn->inbuf + SIZEOF (iceMsg); + + iceConn->receive_sequence++; + + if (iceConn->waiting_for_byteorder) + { + if (header->majorOpcode == 0 && + header->minorOpcode == ICE_ByteOrder) + { + char byteOrder = ((iceByteOrderMsg *) header)->byteOrder; + int endian = 1; + + CHECK_SIZE_MATCH (iceConn, ICE_ByteOrder, + header->length, SIZEOF (iceByteOrderMsg), + IceFatalToConnection); + + if (byteOrder != IceMSBfirst && byteOrder != IceLSBfirst) + { + _IceErrorBadValue (iceConn, 0, + ICE_ByteOrder, 2, 1, &byteOrder); + + iceConn->connection_status = IceConnectRejected; + } + else + { + iceConn->swap = + (((*(char *) &endian) && byteOrder == IceMSBfirst) || + !(*(char *) &endian) && byteOrder == IceLSBfirst); + + iceConn->waiting_for_byteorder = 0; + } + } + else + { + if (header->majorOpcode != 0) + { + _IceErrorBadMajor (iceConn, header->majorOpcode, + header->minorOpcode, IceFatalToConnection); + } + else + { + _IceErrorBadState (iceConn, 0, + header->minorOpcode, IceFatalToConnection); + } + + iceConn->connection_status = IceConnectRejected; + } + + iceConn->dispatch_level--; + if (!iceConn->io_ok) + { + iceConn->connection_status = IceConnectIOError; + retStatus = IceProcessMessagesIOError; + } + + return (retStatus); + } + + if (iceConn->swap) + { + /* swap the length field */ + + header->length = lswapl (header->length); + } + + if (replyWait) + { + /* + * Add to the list of replyWaits (only if it doesn't exist + * in the list already. + */ + + _IceAddReplyWait (iceConn, replyWait); + + + /* + * Note that there are two different replyWaits. The first is + * the one passed into IceProcessMessages, and is the replyWait + * for the message the client is blocking on. The second is + * the replyWait for the message currently being processed + * by IceProcessMessages. We call it "useThisReplyWait". + */ + + useThisReplyWait = _IceSearchReplyWaits (iceConn, header->majorOpcode); + } + + if (header->majorOpcode == 0) + { + /* + * ICE protocol + */ + + Bool connectionClosed; + + _IceProcessCoreMsgProc processIce = + _IceVersions[iceConn->my_ice_version_index].process_core_msg_proc; + + (*processIce) (iceConn, header->minorOpcode, + header->length, iceConn->swap, + useThisReplyWait, &replyReady, &connectionClosed); + + if (connectionClosed) + { + /* + * As a result of shutdown negotiation, the connection was closed. + */ + + return (IceProcessMessagesConnectionClosed); + } + } + else + { + /* + * Sub protocol + */ + + if ((int) header->majorOpcode < iceConn->his_min_opcode || + (int) header->majorOpcode > iceConn->his_max_opcode || + !(iceConn->process_msg_info[header->majorOpcode - + iceConn->his_min_opcode].in_use)) + { + /* + * The protocol of the message we just read is not supported. + */ + + _IceErrorBadMajor (iceConn, header->majorOpcode, + header->minorOpcode, IceCanContinue); + + _IceReadSkip (iceConn, header->length << 3); + } + else + { + _IceProcessMsgInfo *processMsgInfo = &iceConn->process_msg_info[ + header->majorOpcode - iceConn->his_min_opcode]; + + if (processMsgInfo->accept_flag) + { + IcePaProcessMsgProc processProc = + processMsgInfo->process_msg_proc.accept_client; + + (*processProc) (iceConn, processMsgInfo->client_data, + header->minorOpcode, header->length, iceConn->swap); + } + else + { + IcePoProcessMsgProc processProc = + processMsgInfo->process_msg_proc.orig_client; + + (*processProc) (iceConn, + processMsgInfo->client_data, header->minorOpcode, + header->length, iceConn->swap, + useThisReplyWait, &replyReady); + } + } + } + + if (replyReady) + { + _IceSetReplyReady (iceConn, useThisReplyWait); + } + + + /* + * Now we check if the reply is ready for the replyWait passed + * into IceProcessMessages. The replyWait is removed from the + * replyWait list if it is ready. + */ + + if (replyWait) + *replyReadyRet = _IceCheckReplyReady (iceConn, replyWait); + + + /* + * Decrement the dispatch level. If we reach level 0, and the + * free_asap bit is set, free the connection now. Also check for + * possible bad IO status. + */ + + iceConn->dispatch_level--; + + if (iceConn->dispatch_level == 0 && iceConn->free_asap) + { + _IceFreeConnection (iceConn); + retStatus = IceProcessMessagesConnectionClosed; + } + else if (!iceConn->io_ok) + { + iceConn->connection_status = IceConnectIOError; + retStatus = IceProcessMessagesIOError; + } + + return (retStatus); +} + + + +static void +AuthRequired (iceConn, authIndex, authDataLen, authData) + +IceConn iceConn; +int authIndex; +int authDataLen; +IcePointer authData; + +{ + iceAuthRequiredMsg *pMsg; + + IceGetHeader (iceConn, 0, ICE_AuthRequired, + SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg); + + pMsg->authIndex = authIndex; + pMsg->authDataLength = authDataLen; + pMsg->length += WORD64COUNT (authDataLen); + + IceWriteData (iceConn, authDataLen, (char *) authData); + + if (PAD64 (authDataLen)) + IceWritePad (iceConn, PAD64 (authDataLen)); + + IceFlush (iceConn); +} + + + +static void +AuthReply (iceConn, authDataLen, authData) + +IceConn iceConn; +int authDataLen; +IcePointer authData; + +{ + iceAuthReplyMsg *pMsg; + + IceGetHeader (iceConn, 0, ICE_AuthReply, + SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg); + + pMsg->authDataLength = authDataLen; + pMsg->length += WORD64COUNT (authDataLen); + + IceWriteData (iceConn, authDataLen, (char *) authData); + + if (PAD64 (authDataLen)) + IceWritePad (iceConn, PAD64 (authDataLen)); + + IceFlush (iceConn); +} + + + +static void +AuthNextPhase (iceConn, authDataLen, authData) + +IceConn iceConn; +int authDataLen; +IcePointer authData; + +{ + iceAuthNextPhaseMsg *pMsg; + + IceGetHeader (iceConn, 0, ICE_AuthNextPhase, + SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg); + + pMsg->authDataLength = authDataLen; + pMsg->length += WORD64COUNT (authDataLen); + + IceWriteData (iceConn, authDataLen, (char *) authData); + + if (PAD64 (authDataLen)) + IceWritePad (iceConn, PAD64 (authDataLen)); + + IceFlush (iceConn); +} + + + +static void +AcceptConnection (iceConn, versionIndex) + +IceConn iceConn; +int versionIndex; + +{ + iceConnectionReplyMsg *pMsg; + char *pData; + int extra; + + extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString); + + IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply, + SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra), + iceConnectionReplyMsg, pMsg, pData); + + pMsg->versionIndex = versionIndex; + + STORE_STRING (pData, IceVendorString); + STORE_STRING (pData, IceReleaseString); + + IceFlush (iceConn); + + iceConn->connection_status = IceConnectAccepted; +} + + + +static void +AcceptProtocol (iceConn, hisOpcode, myOpcode, versionIndex, vendor, release) + +IceConn iceConn; +int hisOpcode; +int myOpcode; +int versionIndex; +char *vendor; +char *release; + +{ + iceProtocolReplyMsg *pMsg; + char *pData; + int extra; + + extra = STRING_BYTES (vendor) + STRING_BYTES (release); + + IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply, + SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra), + iceProtocolReplyMsg, pMsg, pData); + + pMsg->protocolOpcode = myOpcode; + pMsg->versionIndex = versionIndex; + + STORE_STRING (pData, vendor); + STORE_STRING (pData, release); + + IceFlush (iceConn); + + + /* + * We may be using a different major opcode for this protocol + * than the other client. Whenever we get a message, we must + * map to our own major opcode. + */ + + _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode); +} + + + +static void +PingReply (iceConn) + +IceConn iceConn; + +{ + IceSimpleMessage (iceConn, 0, ICE_PingReply); + IceFlush (iceConn); +} + + + +static Bool +ProcessError (iceConn, length, swap, replyWait) + +IceConn iceConn; +unsigned long length; +Bool swap; +IceReplyWaitInfo *replyWait; + +{ + int invokeHandler; + Bool errorReturned = False; + iceErrorMsg *message; + char *pData, *pStart; + char severity; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_Error, + length, SIZEOF (iceErrorMsg), + (iceConn->connect_to_you || iceConn->connect_to_me) ? + IceFatalToConnection : IceFatalToProtocol); + + IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg), + iceErrorMsg, message, pStart); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + severity = message->severity; + + if (severity != IceCanContinue && severity != IceFatalToProtocol && + severity != IceFatalToConnection) + { + _IceErrorBadValue (iceConn, 0, + ICE_Error, 9, 1, &severity); + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + + if (swap) + { + message->errorClass = lswaps (message->errorClass); + message->offendingSequenceNum = lswapl (message->offendingSequenceNum); + } + + if (!replyWait || + message->offendingSequenceNum != replyWait->sequence_of_request) + { + invokeHandler = 1; + } + else + { + if (iceConn->connect_to_you && + ((!iceConn->connect_to_you->auth_active && + message->offendingMinorOpcode == ICE_ConnectionSetup) || + (iceConn->connect_to_you->auth_active && + message->offendingMinorOpcode == ICE_AuthReply))) + { + _IceConnectionError *errorReply = + &(((_IceReply *) (replyWait->reply))->connection_error); + char *errorStr = NULL; + char *tempstr; + char *prefix, *temp; + + invokeHandler = 0; + errorReturned = True; + + switch (message->errorClass) + { + case IceNoVersion: + + tempstr = + "None of the ICE versions specified are supported"; + errorStr = (char *) malloc (strlen (tempstr) + 1); + strcpy (errorStr, tempstr); + break; + + case IceNoAuth: + + tempstr = + "None of the authentication protocols specified are supported"; + errorStr = (char *) malloc (strlen (tempstr) + 1); + strcpy (errorStr, tempstr); + break; + + case IceSetupFailed: + + prefix = "Connection Setup Failed, reason : "; + + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + case IceAuthRejected: + + prefix = "Authentication Rejected, reason : "; + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + case IceAuthFailed: + + prefix = "Authentication Failed, reason : "; + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + default: + invokeHandler = 1; + } + + errorReply->type = ICE_CONNECTION_ERROR; + errorReply->error_message = errorStr; + } + else if (iceConn->protosetup_to_you && + ((!iceConn->protosetup_to_you->auth_active && + message->offendingMinorOpcode == ICE_ProtocolSetup) || + (iceConn->protosetup_to_you->auth_active && + message->offendingMinorOpcode == ICE_AuthReply))) + { + _IceProtocolError *errorReply = + &(((_IceReply *) (replyWait->reply))->protocol_error); + char *errorStr = ""; + char *prefix, *temp; + + invokeHandler = 0; + errorReturned = True; + + switch (message->errorClass) + { + case IceNoVersion: + + temp = + "None of the protocol versions specified are supported"; + errorStr = (char *) malloc (strlen (temp) + 1); + strcpy (errorStr, temp); + break; + + case IceNoAuth: + + temp = + "None of the authentication protocols specified are supported"; + errorStr = (char *) malloc (strlen (temp) + 1); + strcpy (errorStr, temp); + break; + + case IceSetupFailed: + + prefix = "Protocol Setup Failed, reason : "; + + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + case IceAuthRejected: + + prefix = "Authentication Rejected, reason : "; + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + case IceAuthFailed: + + prefix = "Authentication Failed, reason : "; + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + case IceProtocolDuplicate: + + prefix = "Protocol was already registered : "; + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + case IceMajorOpcodeDuplicate: + + prefix = "The major opcode was already used : "; + errorStr = (char *) malloc (strlen (prefix) + 2); + sprintf (errorStr, "%s%d", prefix, (int) *pData); + break; + + case IceUnknownProtocol: + + prefix = "Unknown Protocol : "; + EXTRACT_STRING (pData, swap, temp); + errorStr = (char *) malloc ( + strlen (prefix) + strlen (temp) + 1); + sprintf (errorStr, "%s%s", prefix, temp); + free (temp); + break; + + default: + invokeHandler = 1; + } + + errorReply->type = ICE_PROTOCOL_ERROR; + errorReply->error_message = errorStr; + } + + if (errorReturned == True) + { + /* + * If we tried to authenticate, tell the authentication + * procedure to clean up. + */ + + IcePoAuthProc authProc; + + if (iceConn->connect_to_you && + iceConn->connect_to_you->auth_active) + { + authProc = _IcePoAuthProcs[ + iceConn->connect_to_you->my_auth_index]; + + (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state, + True /* clean up */, False /* swap */, + 0, NULL, NULL, NULL, NULL); + } + else if (iceConn->protosetup_to_you && + iceConn->protosetup_to_you->auth_active) + { + _IcePoProtocol *protocol = _IceProtocols[ + iceConn->protosetup_to_you->my_opcode - 1].orig_client; + + authProc = protocol->auth_procs[iceConn-> + protosetup_to_you->my_auth_index]; + + (*authProc) (iceConn, + &iceConn->protosetup_to_you->my_auth_state, + True /* clean up */, False /* swap */, + 0, NULL, NULL, NULL, NULL); + } + } + } + + if (invokeHandler) + { + (*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode, + message->offendingSequenceNum, message->errorClass, + message->severity, (IcePointer) pData); + } + + IceDisposeCompleteMessage (iceConn, pStart); + + return (errorReturned); +} + + + +static +ProcessConnectionSetup (iceConn, length, swap) + +IceConn iceConn; +unsigned long length; +Bool swap; + +{ + iceConnectionSetupMsg *message; + int myVersionCount, hisVersionCount; + int myVersionIndex, hisVersionIndex; + int hisMajorVersion, hisMinorVersion; + int myAuthCount, hisAuthCount; + int found, i, j; + char *myAuthName, **hisAuthNames; + char *pData, *pStart; + char *vendor = NULL; + char *release = NULL; + int myAuthIndex = 0; + int hisAuthIndex = 0; + int accept_setup_now = 0; + char mustAuthenticate; + int authUsableCount; + int authUsableFlags[MAX_ICE_AUTH_NAMES]; + int authIndices[MAX_ICE_AUTH_NAMES]; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup, + length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection); + + IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg), + iceConnectionSetupMsg, message, pStart); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + + SKIP_STRING (pData, swap); /* vendor */ + SKIP_STRING (pData, swap); /* release */ + SKIP_LISTOF_STRING (pData, swap, (int) message->authCount);/* auth names */ + pData += (message->versionCount * 4); /* versions */ + + CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup, + length, pData - pStart + SIZEOF (iceConnectionSetupMsg), + pStart, IceFatalToConnection); + + mustAuthenticate = message->mustAuthenticate; + if (mustAuthenticate != 0 && mustAuthenticate != 1) + { + _IceErrorBadValue (iceConn, 0, + ICE_ConnectionSetup, 8, 1, &mustAuthenticate); + iceConn->connection_status = IceConnectRejected; + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + + EXTRACT_STRING (pData, swap, vendor); + EXTRACT_STRING (pData, swap, release); + + if ((hisAuthCount = message->authCount) > 0) + { + hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *)); + EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames); + } + + hisVersionCount = message->versionCount; + myVersionCount = _IceVersionCount; + + hisVersionIndex = myVersionIndex = found = 0; + + for (i = 0; i < hisVersionCount && !found; i++) + { + EXTRACT_CARD16 (pData, swap, hisMajorVersion); + EXTRACT_CARD16 (pData, swap, hisMinorVersion); + + for (j = 0; j < myVersionCount && !found; j++) + { + if (_IceVersions[j].major_version == hisMajorVersion && + _IceVersions[j].minor_version == hisMinorVersion) + { + hisVersionIndex = i; + myVersionIndex = j; + found = 1; + } + } + } + + if (!found) + { + _IceErrorNoVersion (iceConn, ICE_ConnectionSetup); + iceConn->connection_status = IceConnectRejected; + + free (vendor); + free (release); + + if (hisAuthCount > 0) + { + for (i = 0; i < hisAuthCount; i++) + free (hisAuthNames[i]); + + free ((char *) hisAuthNames); + } + + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string, + _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices); + + for (i = 0; i < _IceAuthCount; i++) + { + authUsableFlags[i] = 0; + for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) + authUsableFlags[i] = (authIndices[j] == i); + } + + myAuthCount = _IceAuthCount; + + for (i = found = 0; i < myAuthCount && !found; i++) + { + if (authUsableFlags[i]) + { + myAuthName = _IceAuthNames[i]; + + for (j = 0; j < hisAuthCount && !found; j++) + if (strcmp (myAuthName, hisAuthNames[j]) == 0) + { + myAuthIndex = i; + hisAuthIndex = j; + found = 1; + } + } + } + + if (!found) + { + /* + * None of the authentication methods specified by the + * other client is supported. If the other client requires + * authentication, we must reject the connection now. + * Otherwise, we can invoke the host-based authentication callback + * to see if we can accept this connection. + */ + + if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc) + { + _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup); + iceConn->connection_status = IceConnectRejected; + } + else + { + char *hostname = _IceGetPeerName (iceConn); + + if ((*iceConn->listen_obj->host_based_auth_proc) (hostname)) + { + accept_setup_now = 1; + } + else + { + _IceErrorAuthenticationRejected (iceConn, + ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed"); + + iceConn->connection_status = IceConnectRejected; + } + + if (hostname) + free (hostname); + } + + if (iceConn->connection_status == IceConnectRejected) + { + free (vendor); + free (release); + } + } + else + { + IcePaAuthStatus status; + int authDataLen; + IcePointer authData = NULL; + IcePointer authState; + char *errorString = NULL; + IcePaAuthProc authProc = _IcePaAuthProcs[myAuthIndex]; + + authState = NULL; + + status = (*authProc) (iceConn, &authState, + swap, 0, NULL, &authDataLen, &authData, &errorString); + + if (status == IcePaAuthContinue) + { + _IceConnectToMeInfo *setupInfo; + + AuthRequired (iceConn, hisAuthIndex, authDataLen, authData); + + iceConn->connect_to_me = setupInfo = (_IceConnectToMeInfo *) + malloc (sizeof (_IceConnectToMeInfo)); + + setupInfo->my_version_index = myVersionIndex; + setupInfo->his_version_index = hisVersionIndex; + setupInfo->his_vendor = vendor; + setupInfo->his_release = release; + setupInfo->my_auth_index = myAuthIndex; + setupInfo->my_auth_state = authState; + setupInfo->must_authenticate = mustAuthenticate; + } + else if (status == IcePaAuthAccepted) + { + accept_setup_now = 1; + } + + if (authData && authDataLen > 0) + free ((char *) authData); + + if (errorString) + free (errorString); + } + + if (accept_setup_now) + { + AcceptConnection (iceConn, hisVersionIndex); + + iceConn->vendor = vendor; + iceConn->release = release; + iceConn->my_ice_version_index = myVersionIndex; + } + + if (hisAuthCount > 0) + { + for (i = 0; i < hisAuthCount; i++) + free (hisAuthNames[i]); + + free ((char *) hisAuthNames); + } + + IceDisposeCompleteMessage (iceConn, pStart); + return (0); +} + + + +static Bool +ProcessAuthRequired (iceConn, length, swap, replyWait) + +IceConn iceConn; +unsigned long length; +Bool swap; +IceReplyWaitInfo *replyWait; + +{ + iceAuthRequiredMsg *message; + int authDataLen; + IcePointer authData; + int replyDataLen; + IcePointer replyData = NULL; + char *errorString = NULL; + IcePoAuthProc authProc; + IcePoAuthStatus status; + IcePointer authState; + int realAuthIndex; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired, + length, SIZEOF (iceAuthRequiredMsg), + iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); + + IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg), + iceAuthRequiredMsg, message, authData); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, authData); + return (0); + } + + if (swap) + { + message->authDataLength = lswaps (message->authDataLength); + } + + CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length, + message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData, + iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); + + if (iceConn->connect_to_you) + { + if ((int) message->authIndex >= _IceAuthCount) + { + _IceConnectionError *errorReply = + &(((_IceReply *) (replyWait->reply))->connection_error); + + char *tempstr = "Received bad authIndex in the AuthRequired message"; + char errIndex = (int) message->authIndex; + + errorString = (char *) malloc (strlen (tempstr) + 1); + strcpy (errorString, tempstr); + + errorReply->type = ICE_CONNECTION_ERROR; + errorReply->error_message = errorString; + + _IceErrorBadValue (iceConn, 0, + ICE_AuthRequired, 2, 1, &errIndex); + + IceDisposeCompleteMessage (iceConn, authData); + return (1); + } + else + { + authProc = _IcePoAuthProcs[message->authIndex]; + + iceConn->connect_to_you->auth_active = 1; + } + } + else if (iceConn->protosetup_to_you) + { + if ((int) message->authIndex >= + iceConn->protosetup_to_you->my_auth_count) + { + _IceProtocolError *errorReply = + &(((_IceReply *) (replyWait->reply))->protocol_error); + + char *tempstr = "Received bad authIndex in the AuthRequired message"; + char errIndex = (int) message->authIndex; + + errorString = (char *) malloc (strlen (tempstr) + 1); + strcpy (errorString, tempstr); + + errorReply->type = ICE_PROTOCOL_ERROR; + errorReply->error_message = errorString; + + _IceErrorBadValue (iceConn, 0, + ICE_AuthRequired, 2, 1, &errIndex); + + IceDisposeCompleteMessage (iceConn, authData); + return (1); + } + else + { + _IcePoProtocol *myProtocol = _IceProtocols[ + iceConn->protosetup_to_you->my_opcode - 1].orig_client; + + realAuthIndex = iceConn->protosetup_to_you-> + my_auth_indices[message->authIndex]; + + authProc = myProtocol->auth_procs[realAuthIndex]; + + iceConn->protosetup_to_you->auth_active = 1; + } + } + else + { + /* + * Unexpected message + */ + + _IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue); + + IceDisposeCompleteMessage (iceConn, authData); + return (0); + } + + authState = NULL; + authDataLen = message->authDataLength; + + status = (*authProc) (iceConn, &authState, False /* don't clean up */, + swap, authDataLen, authData, &replyDataLen, &replyData, &errorString); + + if (status == IcePoAuthHaveReply) + { + AuthReply (iceConn, replyDataLen, replyData); + + replyWait->sequence_of_request = iceConn->send_sequence; + replyWait->minor_opcode_of_request = ICE_AuthReply; + + if (iceConn->connect_to_you) + { + iceConn->connect_to_you->my_auth_state = authState; + iceConn->connect_to_you->my_auth_index = message->authIndex; + } + else if (iceConn->protosetup_to_you) + { + iceConn->protosetup_to_you->my_auth_state = authState; + iceConn->protosetup_to_you->my_auth_index = realAuthIndex; + } + } + else if (status == IcePoAuthRejected || status == IcePoAuthFailed) + { + char *prefix, *returnErrorString; + + if (status == IcePoAuthRejected) + { + _IceErrorAuthenticationRejected (iceConn, + ICE_AuthRequired, errorString); + + prefix = "Authentication Rejected, reason : "; + } + else + { + _IceErrorAuthenticationFailed (iceConn, + ICE_AuthRequired, errorString); + + prefix = "Authentication Failed, reason : "; + } + + returnErrorString = (char *) malloc (strlen (prefix) + + strlen (errorString) + 1); + sprintf (returnErrorString, "%s%s", prefix, errorString); + free (errorString); + + if (iceConn->connect_to_you) + { + _IceConnectionError *errorReply = + &(((_IceReply *) (replyWait->reply))->connection_error); + + errorReply->type = ICE_CONNECTION_ERROR; + errorReply->error_message = returnErrorString; + } + else + { + _IceProtocolError *errorReply = + &(((_IceReply *) (replyWait->reply))->protocol_error); + + errorReply->type = ICE_PROTOCOL_ERROR; + errorReply->error_message = returnErrorString; + } + } + + if (replyData && replyDataLen > 0) + free ((char *) replyData); + + IceDisposeCompleteMessage (iceConn, authData); + + return (status != IcePoAuthHaveReply); +} + + + +static +ProcessAuthReply (iceConn, length, swap) + +IceConn iceConn; +unsigned long length; +Bool swap; + +{ + iceAuthReplyMsg *message; + int replyDataLen; + IcePointer replyData; + int authDataLen; + IcePointer authData = NULL; + char *errorString = NULL; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply, + length, SIZEOF (iceAuthReplyMsg), + iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol); + + IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg), + iceAuthReplyMsg, message, replyData); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, replyData); + return (0); + } + + if (swap) + { + message->authDataLength = lswaps (message->authDataLength); + } + + CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length, + message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData, + iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol); + + replyDataLen = message->authDataLength; + + if (iceConn->connect_to_me) + { + IcePaAuthProc authProc = _IcePaAuthProcs[ + iceConn->connect_to_me->my_auth_index]; + IcePaAuthStatus status = + (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap, + replyDataLen, replyData, &authDataLen, &authData, &errorString); + + if (status == IcePaAuthContinue) + { + AuthNextPhase (iceConn, authDataLen, authData); + } + else if (status == IcePaAuthRejected || status == IcePaAuthFailed) + { + /* + * Before we reject, invoke host-based authentication callback + * and give it a chance to accept the connection (only if the + * other client doesn't require authentication). + */ + + if (!iceConn->connect_to_me->must_authenticate && + iceConn->listen_obj->host_based_auth_proc) + { + char *hostname = _IceGetPeerName (iceConn); + + if ((*iceConn->listen_obj->host_based_auth_proc) (hostname)) + { + status = IcePaAuthAccepted; + } + + if (hostname) + free (hostname); + } + + if (status != IcePaAuthAccepted) + { + free (iceConn->connect_to_me->his_vendor); + free (iceConn->connect_to_me->his_release); + free ((char *) iceConn->connect_to_me); + iceConn->connect_to_me = NULL; + + iceConn->connection_status = IceConnectRejected; + + if (status == IcePaAuthRejected) + { + _IceErrorAuthenticationRejected (iceConn, + ICE_AuthReply, errorString); + } + else + { + _IceErrorAuthenticationFailed (iceConn, + ICE_AuthReply, errorString); + } + } + } + + if (status == IcePaAuthAccepted) + { + AcceptConnection (iceConn, + iceConn->connect_to_me->his_version_index); + + iceConn->vendor = iceConn->connect_to_me->his_vendor; + iceConn->release = iceConn->connect_to_me->his_release; + iceConn->my_ice_version_index = + iceConn->connect_to_me->my_version_index; + + free ((char *) iceConn->connect_to_me); + iceConn->connect_to_me = NULL; + } + } + else if (iceConn->protosetup_to_me) + { + _IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me-> + my_opcode - 1].accept_client; + IcePaAuthProc authProc = myProtocol->auth_procs[ + iceConn->protosetup_to_me->my_auth_index]; + IcePaAuthStatus status = + (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state, + swap, replyDataLen, replyData, + &authDataLen, &authData, &errorString); + int free_setup_info = 1; + + if (status == IcePaAuthContinue) + { + AuthNextPhase (iceConn, authDataLen, authData); + free_setup_info = 0; + } + else if (status == IcePaAuthRejected || status == IcePaAuthFailed) + { + /* + * Before we reject, invoke host-based authentication callback + * and give it a chance to accept the Protocol Setup (only if the + * other client doesn't require authentication). + */ + + if (!iceConn->protosetup_to_me->must_authenticate && + myProtocol->host_based_auth_proc) + { + char *hostname = _IceGetPeerName (iceConn); + + if ((*myProtocol->host_based_auth_proc) (hostname)) + { + status = IcePaAuthAccepted; + } + + if (hostname) + free (hostname); + } + + if (status == IcePaAuthRejected) + { + _IceErrorAuthenticationRejected (iceConn, + ICE_AuthReply, errorString); + } + else + { + _IceErrorAuthenticationFailed (iceConn, + ICE_AuthReply, errorString); + } + } + + if (status == IcePaAuthAccepted) + { + IcePaProcessMsgProc processMsgProc; + IceProtocolSetupProc protocolSetupProc; + IceProtocolActivateProc protocolActivateProc; + _IceProcessMsgInfo *process_msg_info; + IcePointer clientData = NULL; + char *failureReason = NULL; + Status status = 1; + + protocolSetupProc = myProtocol->protocol_setup_proc; + protocolActivateProc = myProtocol->protocol_activate_proc; + + if (protocolSetupProc) + { + /* + * Notify the client of the Protocol Setup. + */ + + status = (*protocolSetupProc) (iceConn, + myProtocol->version_recs[iceConn->protosetup_to_me-> + my_version_index].major_version, + myProtocol->version_recs[iceConn->protosetup_to_me-> + my_version_index].minor_version, + iceConn->protosetup_to_me->his_vendor, + iceConn->protosetup_to_me->his_release, + &clientData, &failureReason); + + /* + * Set vendor and release pointers to NULL, so it won't + * get freed below. The ProtocolSetupProc should + * free it. + */ + + iceConn->protosetup_to_me->his_vendor = NULL; + iceConn->protosetup_to_me->his_release = NULL; + } + + if (status != 0) + { + /* + * Send the Protocol Reply + */ + + AcceptProtocol (iceConn, + iceConn->protosetup_to_me->his_opcode, + iceConn->protosetup_to_me->my_opcode, + iceConn->protosetup_to_me->his_version_index, + myProtocol->vendor, myProtocol->release); + + + /* + * Set info for this protocol. + */ + + processMsgProc = myProtocol->version_recs[ + iceConn->protosetup_to_me-> + my_version_index].process_msg_proc; + + process_msg_info = &iceConn->process_msg_info[ + iceConn->protosetup_to_me-> + his_opcode -iceConn->his_min_opcode]; + + process_msg_info->client_data = clientData; + process_msg_info->accept_flag = 1; + process_msg_info->process_msg_proc. + accept_client = processMsgProc; + + + /* + * Increase the reference count for the number + * of active protocols. + */ + + iceConn->proto_ref_count++; + + + /* + * Notify the client that the protocol is active. The reason + * we have this 2nd callback invoked is because the client + * may wish to immediately generate a message for this + * protocol, but it must wait until we send the Protocol Reply. + */ + + if (protocolActivateProc) + { + (*protocolActivateProc) (iceConn, + process_msg_info->client_data); + } + } + else + { + /* + * An error was encountered. + */ + + _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, + failureReason); + + if (failureReason) + free (failureReason); + } + } + + + if (free_setup_info) + { + if (iceConn->protosetup_to_me->his_vendor) + free (iceConn->protosetup_to_me->his_vendor); + if (iceConn->protosetup_to_me->his_release) + free (iceConn->protosetup_to_me->his_release); + free ((char *) iceConn->protosetup_to_me); + iceConn->protosetup_to_me = NULL; + } + } + else + { + /* + * Unexpected message + */ + + _IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue); + } + + if (authData && authDataLen > 0) + free ((char *) authData); + + if (errorString) + free (errorString); + + IceDisposeCompleteMessage (iceConn, replyData); + return (0); +} + + + +static Bool +ProcessAuthNextPhase (iceConn, length, swap, replyWait) + +IceConn iceConn; +unsigned long length; +Bool swap; +IceReplyWaitInfo *replyWait; + +{ + iceAuthNextPhaseMsg *message; + int authDataLen; + IcePointer authData; + int replyDataLen; + IcePointer replyData = NULL; + char *errorString = NULL; + IcePoAuthProc authProc; + IcePoAuthStatus status; + IcePointer *authState; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase, + length, SIZEOF (iceAuthNextPhaseMsg), + iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); + + IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg), + iceAuthNextPhaseMsg, message, authData); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, authData); + return (0); + } + + if (swap) + { + message->authDataLength = lswaps (message->authDataLength); + } + + CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length, + message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData, + iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol); + + if (iceConn->connect_to_you) + { + authProc = _IcePoAuthProcs[ + iceConn->connect_to_you->my_auth_index]; + + authState = &iceConn->connect_to_you->my_auth_state; + } + else if (iceConn->protosetup_to_you) + { + _IcePoProtocol *myProtocol = + _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client; + + authProc = myProtocol->auth_procs[ + iceConn->protosetup_to_you->my_auth_index]; + + authState = &iceConn->protosetup_to_you->my_auth_state; + } + else + { + /* + * Unexpected message + */ + + _IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue); + + IceDisposeCompleteMessage (iceConn, authData); + return (0); + } + + authDataLen = message->authDataLength; + + status = (*authProc) (iceConn, authState, False /* don't clean up */, + swap, authDataLen, authData, &replyDataLen, &replyData, &errorString); + + if (status == IcePoAuthHaveReply) + { + AuthReply (iceConn, replyDataLen, replyData); + + replyWait->sequence_of_request = iceConn->send_sequence; + } + else if (status == IcePoAuthRejected || status == IcePoAuthFailed) + { + char *prefix, *returnErrorString; + + if (status == IcePoAuthRejected) + { + _IceErrorAuthenticationRejected (iceConn, + ICE_AuthNextPhase, errorString); + + prefix = "Authentication Rejected, reason : "; + } + else if (status == IcePoAuthFailed) + { + _IceErrorAuthenticationFailed (iceConn, + ICE_AuthNextPhase, errorString); + + prefix = "Authentication Failed, reason : "; + } + + returnErrorString = (char *) malloc (strlen (prefix) + + strlen (errorString) + 1); + sprintf (returnErrorString, "%s%s", prefix, errorString); + free (errorString); + + if (iceConn->connect_to_you) + { + _IceConnectionError *errorReply = + &(((_IceReply *) (replyWait->reply))->connection_error); + + errorReply->type = ICE_CONNECTION_ERROR; + errorReply->error_message = returnErrorString; + } + else + { + _IceProtocolError *errorReply = + &(((_IceReply *) (replyWait->reply))->protocol_error); + + errorReply->type = ICE_PROTOCOL_ERROR; + errorReply->error_message = returnErrorString; + } + } + + if (replyData && replyDataLen > 0) + free ((char *) replyData); + + IceDisposeCompleteMessage (iceConn, authData); + + return (status != IcePoAuthHaveReply); +} + + + +static Bool +ProcessConnectionReply (iceConn, length, swap, replyWait) + +IceConn iceConn; +unsigned long length; +Bool swap; +IceReplyWaitInfo *replyWait; + +{ + iceConnectionReplyMsg *message; + char *pData, *pStart; + Bool replyReady; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply, + length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection); + + IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg), + iceConnectionReplyMsg, message, pStart); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + + SKIP_STRING (pData, swap); /* vendor */ + SKIP_STRING (pData, swap); /* release */ + + CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply, + length, pData - pStart + SIZEOF (iceConnectionReplyMsg), + pStart, IceFatalToConnection); + + pData = pStart; + + if (iceConn->connect_to_you) + { + if (iceConn->connect_to_you->auth_active) + { + /* + * Tell the authentication procedure to clean up. + */ + + IcePoAuthProc authProc = _IcePoAuthProcs[ + iceConn->connect_to_you->my_auth_index]; + + (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state, + True /* clean up */, False /* swap */, + 0, NULL, NULL, NULL, NULL); + } + + if ((int) message->versionIndex >= _IceVersionCount) + { + _IceConnectionError *errorReply = + &(((_IceReply *) (replyWait->reply))->connection_error); + char errIndex = message->versionIndex; + + _IceErrorBadValue (iceConn, 0, + ICE_ConnectionReply, 2, 1, &errIndex); + + errorReply->type = ICE_CONNECTION_ERROR; + errorReply->error_message = + "Received bad version index in Connection Reply"; + } + else + { + _IceReply *reply = (_IceReply *) (replyWait->reply); + + reply->type = ICE_CONNECTION_REPLY; + reply->connection_reply.version_index = message->versionIndex; + + EXTRACT_STRING (pData, swap, reply->connection_reply.vendor); + EXTRACT_STRING (pData, swap, reply->connection_reply.release); + } + + replyReady = True; + } + else + { + /* + * Unexpected message + */ + + _IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue); + + replyReady = False; + } + + IceDisposeCompleteMessage (iceConn, pStart); + + return (replyReady); +} + + + +static +ProcessProtocolSetup (iceConn, length, swap) + +IceConn iceConn; +unsigned long length; +Bool swap; + +{ + iceProtocolSetupMsg *message; + _IcePaProtocol *myProtocol; + int myVersionCount, hisVersionCount; + int myVersionIndex, hisVersionIndex; + int hisMajorVersion, hisMinorVersion; + int myAuthCount, hisAuthCount; + int myOpcode, hisOpcode; + int found, i, j; + char *myAuthName, **hisAuthNames; + char *protocolName; + char *pData, *pStart; + char *vendor = NULL; + char *release = NULL; + int accept_setup_now = 0; + int myAuthIndex = 0; + int hisAuthIndex = 0; + char mustAuthenticate; + int authUsableCount; + int authUsableFlags[MAX_ICE_AUTH_NAMES]; + int authIndices[MAX_ICE_AUTH_NAMES]; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup, + length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol); + + if (iceConn->want_to_close) + { + /* + * If we sent a WantToClose message, but just got a ProtocolSetup, + * we must cancel our WantToClose. It is the responsiblity of the + * other client to send a WantToClose later on. + */ + + iceConn->want_to_close = 0; + } + + IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg), + iceProtocolSetupMsg, message, pStart); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + + SKIP_STRING (pData, swap); /* proto name */ + SKIP_STRING (pData, swap); /* vendor */ + SKIP_STRING (pData, swap); /* release */ + SKIP_LISTOF_STRING (pData, swap, (int) message->authCount);/* auth names */ + pData += (message->versionCount * 4); /* versions */ + + CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup, + length, pData - pStart + SIZEOF (iceProtocolSetupMsg), + pStart, IceFatalToProtocol); + + mustAuthenticate = message->mustAuthenticate; + + if (mustAuthenticate != 0 && mustAuthenticate != 1) + { + _IceErrorBadValue (iceConn, 0, + ICE_ProtocolSetup, 4, 1, &mustAuthenticate); + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + + if (iceConn->process_msg_info && + (int) message->protocolOpcode >= iceConn->his_min_opcode && + (int) message->protocolOpcode <= iceConn->his_max_opcode && + iceConn->process_msg_info[ + message->protocolOpcode - iceConn->his_min_opcode].in_use) + { + _IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode); + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + EXTRACT_STRING (pData, swap, protocolName); + + if (iceConn->process_msg_info) + { + for (i = 0; + i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++) + { + if (iceConn->process_msg_info[i].in_use && strcmp (protocolName, + iceConn->process_msg_info[i].protocol->protocol_name) == 0) + { + _IceErrorProtocolDuplicate (iceConn, protocolName); + free (protocolName); + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + } + } + + for (i = 0; i < _IceLastMajorOpcode; i++) + if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0) + break; + + if (i < _IceLastMajorOpcode && + (myProtocol = _IceProtocols[i].accept_client) != NULL) + { + hisOpcode = message->protocolOpcode; + myOpcode = i + 1; + free (protocolName); + } + else + { + _IceErrorUnknownProtocol (iceConn, protocolName); + free (protocolName); + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + EXTRACT_STRING (pData, swap, vendor); + EXTRACT_STRING (pData, swap, release); + + if ((hisAuthCount = message->authCount) > 0) + { + hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *)); + EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames); + } + + hisVersionCount = message->versionCount; + myVersionCount = myProtocol->version_count; + + hisVersionIndex = myVersionIndex = found = 0; + + for (i = 0; i < hisVersionCount && !found; i++) + { + EXTRACT_CARD16 (pData, swap, hisMajorVersion); + EXTRACT_CARD16 (pData, swap, hisMinorVersion); + + for (j = 0; j < myVersionCount && !found; j++) + { + if (myProtocol->version_recs[j].major_version == hisMajorVersion && + myProtocol->version_recs[j].minor_version == hisMinorVersion) + { + hisVersionIndex = i; + myVersionIndex = j; + found = 1; + } + } + } + + if (!found) + { + _IceErrorNoVersion (iceConn, ICE_ProtocolSetup); + + free (vendor); + free (release); + + if (hisAuthCount > 0) + { + for (i = 0; i < hisAuthCount; i++) + free (hisAuthNames[i]); + + free ((char *) hisAuthNames); + } + + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + myAuthCount = myProtocol->auth_count; + + _IceGetPaValidAuthIndices ( + _IceProtocols[myOpcode - 1].protocol_name, + iceConn->connection_string, myAuthCount, myProtocol->auth_names, + &authUsableCount, authIndices); + + for (i = 0; i < myAuthCount; i++) + { + authUsableFlags[i] = 0; + for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) + authUsableFlags[i] = (authIndices[j] == i); + } + + for (i = found = 0; i < myAuthCount && !found; i++) + { + if (authUsableFlags[i]) + { + myAuthName = myProtocol->auth_names[i]; + + for (j = 0; j < hisAuthCount && !found; j++) + if (strcmp (myAuthName, hisAuthNames[j]) == 0) + { + myAuthIndex = i; + hisAuthIndex = j; + found = 1; + } + } + } + + if (!found) + { + /* + * None of the authentication methods specified by the + * other client is supported. If the other client requires + * authentication, we must reject the Protocol Setup now. + * Otherwise, we can invoke the host-based authentication callback + * to see if we can accept this Protocol Setup. + */ + + if (mustAuthenticate || !myProtocol->host_based_auth_proc) + { + _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup); + } + else + { + char *hostname = _IceGetPeerName (iceConn); + + if ((*myProtocol->host_based_auth_proc) (hostname)) + { + accept_setup_now = 1; + } + else + { + _IceErrorAuthenticationRejected (iceConn, + ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed"); + } + + if (hostname) + free (hostname); + } + } + else + { + IcePaAuthStatus status; + int authDataLen; + IcePointer authData = NULL; + IcePointer authState; + char *errorString = NULL; + IcePaAuthProc authProc = + myProtocol->auth_procs[myAuthIndex]; + + authState = NULL; + + status = (*authProc) (iceConn, &authState, swap, 0, NULL, + &authDataLen, &authData, &errorString); + + if (status == IcePaAuthContinue) + { + _IceProtoSetupToMeInfo *setupInfo; + + AuthRequired (iceConn, hisAuthIndex, authDataLen, authData); + + iceConn->protosetup_to_me = setupInfo = + (_IceProtoSetupToMeInfo *) malloc ( + sizeof (_IceProtoSetupToMeInfo)); + + setupInfo->his_opcode = hisOpcode; + setupInfo->my_opcode = myOpcode; + setupInfo->my_version_index = myVersionIndex; + setupInfo->his_version_index = hisVersionIndex; + setupInfo->his_vendor = vendor; + setupInfo->his_release = release; + vendor = release = NULL; /* so we don't free it */ + setupInfo->my_auth_index = myAuthIndex; + setupInfo->my_auth_state = authState; + setupInfo->must_authenticate = mustAuthenticate; + } + else if (status == IcePaAuthAccepted) + { + accept_setup_now = 1; + } + + if (authData && authDataLen > 0) + free ((char *) authData); + + if (errorString) + free (errorString); + } + + if (accept_setup_now) + { + IcePaProcessMsgProc processMsgProc; + IceProtocolSetupProc protocolSetupProc; + IceProtocolActivateProc protocolActivateProc; + _IceProcessMsgInfo *process_msg_info; + IcePointer clientData = NULL; + char *failureReason = NULL; + Status status = 1; + + protocolSetupProc = myProtocol->protocol_setup_proc; + protocolActivateProc = myProtocol->protocol_activate_proc; + + if (protocolSetupProc) + { + /* + * Notify the client of the Protocol Setup. + */ + + status = (*protocolSetupProc) (iceConn, + myProtocol->version_recs[myVersionIndex].major_version, + myProtocol->version_recs[myVersionIndex].minor_version, + vendor, release, &clientData, &failureReason); + + vendor = release = NULL; /* so we don't free it */ + } + + if (status != 0) + { + /* + * Send the Protocol Reply + */ + + AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex, + myProtocol->vendor, myProtocol->release); + + + /* + * Set info for this protocol. + */ + + processMsgProc = myProtocol->version_recs[ + myVersionIndex].process_msg_proc; + + process_msg_info = &iceConn->process_msg_info[hisOpcode - + iceConn->his_min_opcode]; + + process_msg_info->client_data = clientData; + process_msg_info->accept_flag = 1; + process_msg_info->process_msg_proc.accept_client = processMsgProc; + + + /* + * Increase the reference count for the number of active protocols. + */ + + iceConn->proto_ref_count++; + + + /* + * Notify the client that the protocol is active. The reason + * we have this 2nd callback invoked is because the client + * may wish to immediately generate a message for this + * protocol, but it must wait until we send the Protocol Reply. + */ + + if (protocolActivateProc) + { + (*protocolActivateProc) (iceConn, + process_msg_info->client_data); + } + } + else + { + /* + * An error was encountered. + */ + + _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason); + + if (failureReason) + free (failureReason); + } + } + + if (vendor) + free (vendor); + + if (release) + free (release); + + if (hisAuthCount > 0) + { + for (i = 0; i < hisAuthCount; i++) + free (hisAuthNames[i]); + + free ((char *) hisAuthNames); + } + + IceDisposeCompleteMessage (iceConn, pStart); + return (0); +} + + + +static Bool +ProcessProtocolReply (iceConn, length, swap, replyWait) + +IceConn iceConn; +unsigned long length; +Bool swap; +IceReplyWaitInfo *replyWait; + +{ + iceProtocolReplyMsg *message; + char *pData, *pStart; + Bool replyReady; + + CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply, + length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol); + + IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg), + iceProtocolReplyMsg, message, pStart); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + + SKIP_STRING (pData, swap); /* vendor */ + SKIP_STRING (pData, swap); /* release */ + + CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply, + length, pData - pStart + SIZEOF (iceProtocolReplyMsg), + pStart, IceFatalToProtocol); + + pData = pStart; + + if (iceConn->protosetup_to_you) + { + if (iceConn->protosetup_to_you->auth_active) + { + /* + * Tell the authentication procedure to clean up. + */ + + _IcePoProtocol *myProtocol = _IceProtocols[ + iceConn->protosetup_to_you->my_opcode - 1].orig_client; + + IcePoAuthProc authProc = myProtocol->auth_procs[ + iceConn->protosetup_to_you->my_auth_index]; + +#ifdef SVR4 + +/* + * authProc is never NULL, but the cc compiler on UNIX System V/386 + * Release 4.2 Version 1 screws up an optimization. Unless there is + * some sort of reference to authProc before the function call, the + * function call will seg fault. + */ + if (authProc) +#endif + (*authProc) (iceConn, + &iceConn->protosetup_to_you->my_auth_state, + True /* clean up */, False /* swap */, + 0, NULL, NULL, NULL, NULL); + } + + if ((int) message->versionIndex >= _IceVersionCount) + { + _IceProtocolError *errorReply = + &(((_IceReply *) (replyWait->reply))->protocol_error); + char errIndex = message->versionIndex; + + _IceErrorBadValue (iceConn, 0, + ICE_ProtocolReply, 2, 1, &errIndex); + + errorReply->type = ICE_PROTOCOL_ERROR; + errorReply->error_message = + "Received bad version index in Protocol Reply"; + } + else + { + _IceProtocolReply *reply = + &(((_IceReply *) (replyWait->reply))->protocol_reply); + + reply->type = ICE_PROTOCOL_REPLY; + reply->major_opcode = message->protocolOpcode; + reply->version_index = message->versionIndex; + + EXTRACT_STRING (pData, swap, reply->vendor); + EXTRACT_STRING (pData, swap, reply->release); + } + + replyReady = True; + } + else + { + _IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue); + + replyReady = False; + } + + IceDisposeCompleteMessage (iceConn, pStart); + + return (replyReady); +} + + + +static +ProcessPing (iceConn, length) + +IceConn iceConn; +unsigned long length; + +{ + CHECK_SIZE_MATCH (iceConn, ICE_Ping, + length, SIZEOF (icePingMsg), IceFatalToConnection); + + PingReply (iceConn); + + return (0); +} + + + +static +ProcessPingReply (iceConn, length) + +IceConn iceConn; +unsigned long length; + +{ + CHECK_SIZE_MATCH (iceConn, ICE_PingReply, + length, SIZEOF (icePingReplyMsg), IceFatalToConnection); + + if (iceConn->ping_waits) + { + _IcePingWait *next = iceConn->ping_waits->next; + + (*iceConn->ping_waits->ping_reply_proc) (iceConn, + iceConn->ping_waits->client_data); + + free ((char *) iceConn->ping_waits); + iceConn->ping_waits = next; + } + else + { + _IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue); + } + + return (0); +} + + + +static +ProcessWantToClose (iceConn, length, connectionClosedRet) + +IceConn iceConn; +unsigned long length; +Bool *connectionClosedRet; + +{ + *connectionClosedRet = False; + + CHECK_SIZE_MATCH (iceConn, ICE_WantToClose, + length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection); + + if (iceConn->want_to_close || iceConn->open_ref_count == 0) + { + /* + * We just received a WantToClose. Either we also sent a + * WantToClose, so we close the connection, or the iceConn + * is not being used, so we close the connection. This + * second case is possible if we sent a WantToClose because + * the iceConn->open_ref_count reached zero, but then we + * received a NoClose. + */ + + _IceConnectionClosed (iceConn); /* invoke watch procs */ + _IceFreeConnection (iceConn); + *connectionClosedRet = True; + } + else if (iceConn->proto_ref_count > 0) + { + /* + * We haven't shut down all of our protocols yet. We send a NoClose, + * and it's up to us to generate a WantToClose later on. + */ + + IceSimpleMessage (iceConn, 0, ICE_NoClose); + IceFlush (iceConn); + } + else + { + /* + * The reference count on this iceConn is zero. This means that + * there are no active protocols, but the client didn't explicitly + * close the connection yet. If we didn't just send a Protocol Setup, + * we send a NoClose, and it's up to us to generate a WantToClose + * later on. + */ + + if (!iceConn->protosetup_to_you) + { + IceSimpleMessage (iceConn, 0, ICE_NoClose); + IceFlush (iceConn); + } + } + + return (0); +} + + + +static +ProcessNoClose (iceConn, length) + +IceConn iceConn; +unsigned long length; + +{ + CHECK_SIZE_MATCH (iceConn, ICE_NoClose, + length, SIZEOF (iceNoCloseMsg), IceFatalToConnection); + + if (iceConn->want_to_close) + { + /* + * The other side can't close now. We cancel our WantToClose, + * and we can expect a WantToClose from the other side. + */ + + iceConn->want_to_close = 0; + } + else + { + _IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue); + } + + return (0); +} + + + +void +_IceProcessCoreMessage (iceConn, opcode, length, swap, + replyWait, replyReadyRet, connectionClosedRet) + +IceConn iceConn; +int opcode; +unsigned long length; +Bool swap; +IceReplyWaitInfo *replyWait; +Bool *replyReadyRet; +Bool *connectionClosedRet; + +{ + Bool replyReady = False; + + *connectionClosedRet = False; + + switch (opcode) + { + case ICE_Error: + + replyReady = ProcessError (iceConn, length, swap, replyWait); + break; + + case ICE_ConnectionSetup: + + ProcessConnectionSetup (iceConn, length, swap); + break; + + case ICE_AuthRequired: + + replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait); + break; + + case ICE_AuthReply: + + ProcessAuthReply (iceConn, length, swap); + break; + + case ICE_AuthNextPhase: + + replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait); + break; + + case ICE_ConnectionReply: + + replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait); + break; + + case ICE_ProtocolSetup: + + ProcessProtocolSetup (iceConn, length, swap); + break; + + case ICE_ProtocolReply: + + replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait); + break; + + case ICE_Ping: + + ProcessPing (iceConn, length); + break; + + case ICE_PingReply: + + ProcessPingReply (iceConn, length); + break; + + case ICE_WantToClose: + + ProcessWantToClose (iceConn, length, connectionClosedRet); + break; + + case ICE_NoClose: + + ProcessNoClose (iceConn, length); + break; + + default: + + _IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue); + _IceReadSkip (iceConn, length << 3); + break; + } + + if (replyWait) + *replyReadyRet = replyReady; +} diff --git a/src/protosetup.c b/src/protosetup.c new file mode 100644 index 0000000..78be316 --- /dev/null +++ b/src/protosetup.c @@ -0,0 +1,289 @@ +/* $Xorg: protosetup.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + + +IceProtocolSetupStatus +IceProtocolSetup (iceConn, myOpcode, clientData, mustAuthenticate, + majorVersionRet, minorVersionRet, vendorRet, releaseRet, + errorLength, errorStringRet) + +IceConn iceConn; +int myOpcode; +IcePointer clientData; +Bool mustAuthenticate; +int *majorVersionRet; +int *minorVersionRet; +char **vendorRet; +char **releaseRet; +int errorLength; +char *errorStringRet; + +{ + iceProtocolSetupMsg *pMsg; + char *pData; + _IceProtocol *myProtocol; + int extra; + Bool gotReply, ioErrorOccured; + int accepted, i; + int hisOpcode; + unsigned long setup_sequence; + IceReplyWaitInfo replyWait; + _IceReply reply; + IcePoVersionRec *versionRec; + int authCount; + int *authIndices; + + if (errorStringRet && errorLength > 0) + *errorStringRet = '\0'; + + *majorVersionRet = 0; + *minorVersionRet = 0; + *vendorRet = NULL; + *releaseRet = NULL; + + if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode) + { + strncpy (errorStringRet, "myOpcode out of range", errorLength); + return (IceProtocolSetupFailure); + } + + myProtocol = &_IceProtocols[myOpcode - 1]; + + if (myProtocol->orig_client == NULL) + { + strncpy (errorStringRet, + "IceRegisterForProtocolSetup was not called", errorLength); + return (IceProtocolSetupFailure); + } + + + /* + * Make sure this protocol hasn't been activated already. + */ + + if (iceConn->process_msg_info) + { + for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++) + { + if (iceConn->process_msg_info[ + i - iceConn->his_min_opcode].in_use && + iceConn->process_msg_info[ + i - iceConn->his_min_opcode ].my_opcode == myOpcode) + break; + } + + if (i <= iceConn->his_max_opcode) + { + return (IceProtocolAlreadyActive); + } + } + + /* + * Generate the message. + */ + + if (myProtocol->orig_client->auth_count > 0) + { + authIndices = (int *) malloc ( + myProtocol->orig_client->auth_count * sizeof (int)); + + _IceGetPoValidAuthIndices (myProtocol->protocol_name, + iceConn->connection_string, + myProtocol->orig_client->auth_count, + myProtocol->orig_client->auth_names, + &authCount, authIndices); + + } + else + { + authCount = 0; + authIndices = NULL; + } + + extra = STRING_BYTES (myProtocol->protocol_name) + + STRING_BYTES (myProtocol->orig_client->vendor) + + STRING_BYTES (myProtocol->orig_client->release); + + for (i = 0; i < authCount; i++) + { + extra += STRING_BYTES (myProtocol->orig_client->auth_names[ + authIndices[i]]); + } + + extra += (myProtocol->orig_client->version_count * 4); + + IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup, + SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra), + iceProtocolSetupMsg, pMsg, pData); + + setup_sequence = iceConn->send_sequence; + + pMsg->protocolOpcode = myOpcode; + pMsg->versionCount = myProtocol->orig_client->version_count; + pMsg->authCount = authCount; + pMsg->mustAuthenticate = mustAuthenticate; + + STORE_STRING (pData, myProtocol->protocol_name); + STORE_STRING (pData, myProtocol->orig_client->vendor); + STORE_STRING (pData, myProtocol->orig_client->release); + + for (i = 0; i < authCount; i++) + { + STORE_STRING (pData, myProtocol->orig_client->auth_names[ + authIndices[i]]); + } + + for (i = 0; i < myProtocol->orig_client->version_count; i++) + { + STORE_CARD16 (pData, + myProtocol->orig_client->version_recs[i].major_version); + STORE_CARD16 (pData, + myProtocol->orig_client->version_recs[i].minor_version); + } + + IceFlush (iceConn); + + + /* + * Process messages until we get a Protocol Reply. + */ + + replyWait.sequence_of_request = setup_sequence; + replyWait.major_opcode_of_request = 0; + replyWait.minor_opcode_of_request = ICE_ProtocolSetup; + replyWait.reply = (IcePointer) &reply; + + iceConn->protosetup_to_you = (_IceProtoSetupToYouInfo *) malloc ( + sizeof (_IceProtoSetupToYouInfo)); + iceConn->protosetup_to_you->my_opcode = myOpcode; + iceConn->protosetup_to_you->my_auth_count = authCount; + iceConn->protosetup_to_you->auth_active = 0; + iceConn->protosetup_to_you->my_auth_indices = authIndices; + + gotReply = False; + ioErrorOccured = False; + accepted = 0; + + while (!gotReply && !ioErrorOccured) + { + ioErrorOccured = (IceProcessMessages ( + iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); + + if (ioErrorOccured) + { + strncpy (errorStringRet, + "IO error occured doing Protocol Setup on connection", + errorLength); + return (IceProtocolSetupIOError); + } + else if (gotReply) + { + if (reply.type == ICE_PROTOCOL_REPLY) + { + if (reply.protocol_reply.version_index >= + myProtocol->orig_client->version_count) + { + strncpy (errorStringRet, + "Got a bad version index in the Protocol Reply", + errorLength); + + free (reply.protocol_reply.vendor); + free (reply.protocol_reply.release); + } + else + { + versionRec = &(myProtocol->orig_client->version_recs[ + reply.protocol_reply.version_index]); + + accepted = 1; + } + } + else /* reply.type == ICE_PROTOCOL_ERROR */ + { + /* Protocol Setup failed */ + + strncpy (errorStringRet, reply.protocol_error.error_message, + errorLength); + + free (reply.protocol_error.error_message); + } + + if (iceConn->protosetup_to_you->my_auth_indices) + free ((char *) iceConn->protosetup_to_you->my_auth_indices); + free ((char *) iceConn->protosetup_to_you); + iceConn->protosetup_to_you = NULL; + } + } + + if (accepted) + { + _IceProcessMsgInfo *process_msg_info; + + *majorVersionRet = versionRec->major_version; + *minorVersionRet = versionRec->minor_version; + *vendorRet = reply.protocol_reply.vendor; + *releaseRet = reply.protocol_reply.release; + + + /* + * Increase the reference count for the number of active protocols. + */ + + iceConn->proto_ref_count++; + + + /* + * We may be using a different major opcode for this protocol + * than the other client. Whenever we get a message, we must + * map to our own major opcode. + */ + + hisOpcode = reply.protocol_reply.major_opcode; + + _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode); + + process_msg_info = &iceConn->process_msg_info[hisOpcode - + iceConn->his_min_opcode]; + + process_msg_info->client_data = clientData; + process_msg_info->accept_flag = 0; + + process_msg_info->process_msg_proc.orig_client = + versionRec->process_msg_proc; + + return (IceProtocolSetupSuccess); + } + else + { + return (IceProtocolSetupFailure); + } +} diff --git a/src/register.c b/src/register.c new file mode 100644 index 0000000..45ec62c --- /dev/null +++ b/src/register.c @@ -0,0 +1,253 @@ +/* $Xorg: register.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + +int +IceRegisterForProtocolSetup (protocolName, vendor, release, + versionCount, versionRecs, authCount, authNames, authProcs, IOErrorProc) + +char *protocolName; +char *vendor; +char *release; +int versionCount; +IcePoVersionRec *versionRecs; +int authCount; +char **authNames; +IcePoAuthProc *authProcs; +IceIOErrorProc IOErrorProc; + +{ + _IcePoProtocol *p; + int opcodeRet, i; + + for (i = 1; i <= _IceLastMajorOpcode; i++) + if (strcmp (protocolName, _IceProtocols[i - 1].protocol_name) == 0) + { + if (_IceProtocols[i - 1].orig_client != NULL) + { + /* + * We've already registered this protocol. + */ + + return (i); + } + else + { + break; + } + } + + if (i <= _IceLastMajorOpcode) + { + p = _IceProtocols[i - 1].orig_client = + (_IcePoProtocol *) malloc (sizeof (_IcePoProtocol)); + opcodeRet = i; + } + else if (_IceLastMajorOpcode == 255 || + versionCount < 1 || + strlen (protocolName) == 0) + { + return (-1); + } + else + { + char *name; + + _IceProtocols[_IceLastMajorOpcode].protocol_name = name = + (char *) malloc (strlen (protocolName) + 1); + strcpy (name, protocolName); + + p = _IceProtocols[_IceLastMajorOpcode].orig_client = + (_IcePoProtocol *) malloc (sizeof (_IcePoProtocol)); + + _IceProtocols[_IceLastMajorOpcode].accept_client = NULL; + + opcodeRet = ++_IceLastMajorOpcode; + } + + p->vendor = (char *) malloc (strlen (vendor) + 1); + strcpy (p->vendor, vendor); + + p->release = (char *) malloc (strlen (release) + 1); + strcpy (p->release, release); + + p->version_count = versionCount; + + p->version_recs = (IcePoVersionRec *) malloc ( + versionCount * sizeof (IcePoVersionRec)); + memcpy (p->version_recs, versionRecs, + versionCount * sizeof (IcePoVersionRec)); + + if ((p->auth_count = authCount) > 0) + { + p->auth_names = (char **) malloc ( + authCount * sizeof (char *)); + + p->auth_procs = (IcePoAuthProc *) malloc ( + authCount * sizeof (IcePoAuthProc)); + + for (i = 0; i < authCount; i++) + { + p->auth_names[i] = + (char *) malloc (strlen (authNames[i]) + 1); + strcpy (p->auth_names[i], authNames[i]); + + p->auth_procs[i] = authProcs[i]; + } + } + else + { + p->auth_names = NULL; + p->auth_procs = NULL; + } + + p->io_error_proc = IOErrorProc; + + return (opcodeRet); +} + + + +int +IceRegisterForProtocolReply (protocolName, vendor, release, + versionCount, versionRecs, authCount, authNames, authProcs, + hostBasedAuthProc, protocolSetupProc, protocolActivateProc, + IOErrorProc) + +char *protocolName; +char *vendor; +char *release; +int versionCount; +IcePaVersionRec *versionRecs; +int authCount; +char **authNames; +IcePaAuthProc *authProcs; +IceHostBasedAuthProc hostBasedAuthProc; +IceProtocolSetupProc protocolSetupProc; +IceProtocolActivateProc protocolActivateProc; +IceIOErrorProc IOErrorProc; + +{ + _IcePaProtocol *p; + int opcodeRet, i; + + for (i = 1; i <= _IceLastMajorOpcode; i++) + if (strcmp (protocolName, _IceProtocols[i - 1].protocol_name) == 0) + { + if (_IceProtocols[i - 1].accept_client != NULL) + { + /* + * We've already registered this protocol. + */ + + return (i); + } + else + { + break; + } + } + + + if (i <= _IceLastMajorOpcode) + { + p = _IceProtocols[i - 1].accept_client = + (_IcePaProtocol *) malloc (sizeof (_IcePaProtocol)); + opcodeRet = i; + } + else if (_IceLastMajorOpcode == 255 || + versionCount < 1 || + strlen (protocolName) == 0) + { + return (-1); + } + else + { + char *name; + + _IceProtocols[_IceLastMajorOpcode].protocol_name = name = + (char *) malloc (strlen (protocolName) + 1); + strcpy (name, protocolName); + + _IceProtocols[_IceLastMajorOpcode].orig_client = NULL; + + p = _IceProtocols[_IceLastMajorOpcode].accept_client = + (_IcePaProtocol *) malloc (sizeof (_IcePaProtocol)); + + opcodeRet = ++_IceLastMajorOpcode; + } + + p->vendor = (char *) malloc (strlen (vendor) + 1); + strcpy (p->vendor, vendor); + + p->release = (char *) malloc (strlen (release) + 1); + strcpy (p->release, release); + + p->version_count = versionCount; + + p->version_recs = (IcePaVersionRec *) malloc ( + versionCount * sizeof (IcePaVersionRec)); + memcpy (p->version_recs, versionRecs, + versionCount * sizeof (IcePaVersionRec)); + + p->protocol_setup_proc = protocolSetupProc; + p->protocol_activate_proc = protocolActivateProc; + + if ((p->auth_count = authCount) > 0) + { + p->auth_names = (char **) malloc ( + authCount * sizeof (char *)); + + p->auth_procs = (IcePaAuthProc *) malloc ( + authCount * sizeof (IcePaAuthProc)); + + for (i = 0; i < authCount; i++) + { + p->auth_names[i] = + (char *) malloc (strlen (authNames[i]) + 1); + strcpy (p->auth_names[i], authNames[i]); + + p->auth_procs[i] = authProcs[i]; + } + } + else + { + p->auth_names = NULL; + p->auth_procs = NULL; + } + + p->host_based_auth_proc = hostBasedAuthProc; + + p->io_error_proc = IOErrorProc; + + return (opcodeRet); +} + diff --git a/src/replywait.c b/src/replywait.c new file mode 100644 index 0000000..2c816f2 --- /dev/null +++ b/src/replywait.c @@ -0,0 +1,158 @@ +/* $Xorg: replywait.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + + +void +_IceAddReplyWait (iceConn, replyWait) + +IceConn iceConn; +IceReplyWaitInfo *replyWait; + +{ + /* + * Add this replyWait to the end of the list (only if the + * replyWait is not already in the list). + */ + + _IceSavedReplyWait *savedReplyWait; + _IceSavedReplyWait *prev, *last; + + prev = NULL; + last = iceConn->saved_reply_waits; + + while (last) + { + if (last->reply_wait == replyWait) + return; + + prev = last; + last = last->next; + } + + savedReplyWait = (_IceSavedReplyWait *) malloc ( + sizeof (_IceSavedReplyWait)); + + savedReplyWait->reply_wait = replyWait; + savedReplyWait->reply_ready = False; + savedReplyWait->next = NULL; + + if (prev == NULL) + iceConn->saved_reply_waits = savedReplyWait; + else + prev->next = savedReplyWait; +} + + + +IceReplyWaitInfo * +_IceSearchReplyWaits (iceConn, majorOpcode) + +IceConn iceConn; +int majorOpcode; + +{ + /* + * Return the first replyWait in the list with the given majorOpcode + */ + + _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits; + + while (savedReplyWait && !savedReplyWait->reply_ready && + savedReplyWait->reply_wait->major_opcode_of_request != majorOpcode) + { + savedReplyWait = savedReplyWait->next; + } + + return (savedReplyWait ? savedReplyWait->reply_wait : NULL); +} + + + +void +_IceSetReplyReady (iceConn, replyWait) + +IceConn iceConn; +IceReplyWaitInfo *replyWait; + +{ + /* + * The replyWait specified has a reply ready. + */ + + _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits; + + while (savedReplyWait && savedReplyWait->reply_wait != replyWait) + savedReplyWait = savedReplyWait->next; + + if (savedReplyWait) + savedReplyWait->reply_ready = True; +} + + + +Bool +_IceCheckReplyReady (iceConn, replyWait) + +IceConn iceConn; +IceReplyWaitInfo *replyWait; + +{ + _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits; + _IceSavedReplyWait *prev = NULL; + Bool found = False; + Bool ready; + + while (savedReplyWait && !found) + { + if (savedReplyWait->reply_wait == replyWait) + found = True; + else + { + prev = savedReplyWait; + savedReplyWait = savedReplyWait->next; + } + } + + ready = found && savedReplyWait->reply_ready; + + if (ready) + { + if (prev == NULL) + iceConn->saved_reply_waits = savedReplyWait->next; + else + prev->next = savedReplyWait->next; + + free ((char *) savedReplyWait); + } + + return (ready); +} diff --git a/src/setauth.c b/src/setauth.c new file mode 100644 index 0000000..5df13ec --- /dev/null +++ b/src/setauth.c @@ -0,0 +1,113 @@ +/* $Xorg: setauth.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" +#include <X11/ICE/ICEutil.h> + + +/* + * IceSetPaAuthData is not a standard part of ICElib, it is specific + * to the sample implementation. + * + * For the client that initiates a Protocol Setup, we look in the + * .ICEauthority file to get authentication data. + * + * For the client accepting the Protocol Setup, we get the data + * from an in-memory database of authentication data (set by the + * application calling IceSetPaAuthData). We have to get the data + * from memory because getting it directly from the .ICEauthority + * file is not secure - someone can just modify the contents of the + * .ICEauthority file behind our back. + */ + +int _IcePaAuthDataEntryCount = 0; +IceAuthDataEntry _IcePaAuthDataEntries[ICE_MAX_AUTH_DATA_ENTRIES]; + + +void +IceSetPaAuthData (numEntries, entries) + +int numEntries; +IceAuthDataEntry *entries; + +{ + /* + * _IcePaAuthDataEntries should really be a linked list. + * On my list of TO DO stuff. + */ + + int i, j; + + for (i = 0; i < numEntries; i++) + { + for (j = 0; j < _IcePaAuthDataEntryCount; j++) + if (strcmp (entries[i].protocol_name, + _IcePaAuthDataEntries[j].protocol_name) == 0 && + strcmp (entries[i].network_id, + _IcePaAuthDataEntries[j].network_id) == 0 && + strcmp (entries[i].auth_name, + _IcePaAuthDataEntries[j].auth_name) == 0) + break; + + if (j < _IcePaAuthDataEntryCount) + { + free (_IcePaAuthDataEntries[j].protocol_name); + free (_IcePaAuthDataEntries[j].network_id); + free (_IcePaAuthDataEntries[j].auth_name); + free (_IcePaAuthDataEntries[j].auth_data); + } + else + { + _IcePaAuthDataEntryCount++; + } + + _IcePaAuthDataEntries[j].protocol_name = (char *) malloc ( + strlen (entries[i].protocol_name) + 1); + strcpy (_IcePaAuthDataEntries[j].protocol_name, + entries[i].protocol_name); + + _IcePaAuthDataEntries[j].network_id = (char *) malloc ( + strlen (entries[i].network_id) + 1); + strcpy (_IcePaAuthDataEntries[j].network_id, + entries[i].network_id); + + _IcePaAuthDataEntries[j].auth_name = (char *) malloc ( + strlen (entries[i].auth_name) + 1); + strcpy (_IcePaAuthDataEntries[j].auth_name, + entries[i].auth_name); + + _IcePaAuthDataEntries[j].auth_data_length = + entries[i].auth_data_length; + _IcePaAuthDataEntries[j].auth_data = (char *) malloc ( + entries[i].auth_data_length); + memcpy (_IcePaAuthDataEntries[j].auth_data, + entries[i].auth_data, entries[i].auth_data_length); + } +} diff --git a/src/shutdown.c b/src/shutdown.c new file mode 100644 index 0000000..94a7eb9 --- /dev/null +++ b/src/shutdown.c @@ -0,0 +1,325 @@ +/* $Xorg: shutdown.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + + +Status +IceProtocolShutdown (iceConn, majorOpcode) + +IceConn iceConn; +int majorOpcode; + +{ + if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL || + majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode) + { + return (0); + } + else + { + /* + * Make sure this majorOpcode is really being used. + */ + + int i; + + for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++) + { + if (iceConn->process_msg_info[ + i - iceConn->his_min_opcode].in_use && + iceConn->process_msg_info[ + i - iceConn->his_min_opcode].my_opcode == majorOpcode) + break; + } + + if (i > iceConn->his_max_opcode) + { + return (0); + } + else + { + /* + * OK, we can shut down the protocol. + */ + + iceConn->process_msg_info[ + i - iceConn->his_min_opcode].in_use = False; + iceConn->proto_ref_count--; + + return (1); + } + } +} + + + +void +IceSetShutdownNegotiation (iceConn, negotiate) + +IceConn iceConn; +Bool negotiate; + +{ + iceConn->skip_want_to_close = negotiate ? False : True; +} + + + +Bool +IceCheckShutdownNegotiation (iceConn) + +IceConn iceConn; + +{ + return (iceConn->skip_want_to_close ? False : True); +} + + + +IceCloseStatus +IceCloseConnection (iceConn) + +IceConn iceConn; + +{ + int refCountReachedZero; + IceCloseStatus status; + + /* + * If this connection object was never valid, we can close + * it right now. This happens if IceAcceptConnection was + * called, but after calling IceProcessMessages several times + * the connection was rejected (because of authentication or + * some other reason). + */ + + if (iceConn->listen_obj && + iceConn->connection_status != IceConnectAccepted) + { + _IceConnectionClosed (iceConn); /* invoke watch procs */ + _IceFreeConnection (iceConn); + return (IceClosedNow); + } + + + /*--------------------------------------------------------------- + + ACTIONS: + + A = Invoke Watch Procedures + B = Set free-asap bit + C = Free connection + D = Initialize shutdown negotiation + N = do nothing + + + ACTION TABLE: + + IO free- dispatch protocol shutdown + error asap bit level refcount negotiation ACTION + occured set reached 0 reached 0 + + 0 0 0 0 0 N + 0 0 0 0 1 N + 0 0 0 1 0 AB + 0 0 0 1 1 N + 0 0 1 0 0 N + 0 0 1 0 1 N + 0 0 1 1 0 AC + 0 0 1 1 1 D + 0 1 0 0 0 N + 0 1 0 0 1 N + 0 1 0 1 0 N + 0 1 0 1 1 N + 0 1 1 0 0 C + 0 1 1 0 1 D + 0 1 1 1 0 C + 0 1 1 1 1 D + 1 0 0 0 0 AB + 1 0 0 0 1 AB + 1 0 0 1 0 AB + 1 0 0 1 1 AB + 1 0 1 0 0 AC + 1 0 1 0 1 AC + 1 0 1 1 0 AC + 1 0 1 1 1 AC + 1 1 0 0 0 N + 1 1 0 0 1 N + 1 1 0 1 0 N + 1 1 0 1 1 N + 1 1 1 0 0 C + 1 1 1 0 1 C + 1 1 1 1 0 C + 1 1 1 1 1 C + + ---------------------------------------------------------------*/ + + if (iceConn->open_ref_count > 0) + iceConn->open_ref_count--; + + refCountReachedZero = iceConn->open_ref_count == 0 && + iceConn->proto_ref_count == 0; + + status = IceConnectionInUse; + + if (!iceConn->free_asap && (!iceConn->io_ok || + (iceConn->io_ok && refCountReachedZero && + iceConn->skip_want_to_close))) + { + /* + * Invoke the watch procedures now. + */ + + _IceConnectionClosed (iceConn); + status = IceClosedNow; /* may be overwritten by IceClosedASAP */ + } + + if (!iceConn->free_asap && iceConn->dispatch_level != 0 && + (!iceConn->io_ok || + (iceConn->io_ok && refCountReachedZero && + iceConn->skip_want_to_close))) + { + /* + * Set flag so we free the connection as soon as possible. + */ + + iceConn->free_asap = True; + status = IceClosedASAP; + } + + if (iceConn->io_ok && iceConn->dispatch_level == 0 && + !iceConn->skip_want_to_close && refCountReachedZero) + { + /* + * Initiate shutdown negotiation. + */ + + IceSimpleMessage (iceConn, 0, ICE_WantToClose); + IceFlush (iceConn); + + iceConn->want_to_close = 1; + + status = IceStartedShutdownNegotiation; + } + else if (iceConn->dispatch_level == 0 && + (!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close && + (iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero))))) + { + /* + * Free the connection. + */ + + _IceFreeConnection (iceConn); + + status = IceClosedNow; + } + + return (status); +} + + + +void +_IceFreeConnection (iceConn) + +IceConn iceConn; + +{ + if (iceConn->listen_obj == NULL) + { + /* + * This iceConn was created with IceOpenConnection. + * We keep track of all open IceConn's, so we need + * to remove it from the list. + */ + + int i; + + for (i = 0; i < _IceConnectionCount; i++) + if (_IceConnectionObjs[i] == iceConn) + break; + + if (i < _IceConnectionCount) + { + if (i < _IceConnectionCount - 1) + { + _IceConnectionObjs[i] = + _IceConnectionObjs[_IceConnectionCount - 1]; + _IceConnectionStrings[i] = + _IceConnectionStrings[_IceConnectionCount - 1]; + } + + _IceConnectionCount--; + } + } + + if (iceConn->trans_conn) + _IceTransClose (iceConn->trans_conn); + + if (iceConn->connection_string) + free (iceConn->connection_string); + + if (iceConn->vendor) + free (iceConn->vendor); + + if (iceConn->release) + free (iceConn->release); + + if (iceConn->inbuf) + free (iceConn->inbuf); + + if (iceConn->outbuf) + free (iceConn->outbuf); + + if (iceConn->scratch) + free (iceConn->scratch); + + if (iceConn->process_msg_info) + free ((char *) iceConn->process_msg_info); + + if (iceConn->connect_to_you) + free ((char *) iceConn->connect_to_you); + + if (iceConn->protosetup_to_you) + free ((char *) iceConn->protosetup_to_you); + + if (iceConn->connect_to_me) + free ((char *) iceConn->connect_to_me); + + if (iceConn->protosetup_to_me) + free ((char *) iceConn->protosetup_to_me); + + free ((char *) iceConn); +} + + + + diff --git a/src/watch.c b/src/watch.c new file mode 100644 index 0000000..6c33192 --- /dev/null +++ b/src/watch.c @@ -0,0 +1,203 @@ +/* $Xorg: watch.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#include <X11/ICE/ICElib.h> +#include "ICElibint.h" + + +Status +IceAddConnectionWatch (watchProc, clientData) + +IceWatchProc watchProc; +IcePointer clientData; + +{ + /* + * watchProc will be called each time an ICE connection is + * created/destroyed by ICElib. + */ + + _IceWatchProc *ptr = _IceWatchProcs; + _IceWatchProc *newWatchProc; + int i; + + if ((newWatchProc = (_IceWatchProc *) malloc ( + sizeof (_IceWatchProc))) == NULL) + { + return (0); + } + + newWatchProc->watch_proc = watchProc; + newWatchProc->client_data = clientData; + newWatchProc->watched_connections = NULL; + newWatchProc->next = NULL; + + while (ptr && ptr->next) + ptr = ptr->next; + + if (ptr == NULL) + _IceWatchProcs = newWatchProc; + else + ptr->next = newWatchProc; + + + /* + * Invoke the watch proc with any previously opened ICE connections. + */ + + for (i = 0; i < _IceConnectionCount; i++) + { + _IceWatchedConnection *newWatchedConn = (_IceWatchedConnection *) + malloc (sizeof (_IceWatchedConnection)); + + newWatchedConn->iceConn = _IceConnectionObjs[i]; + newWatchedConn->next = NULL; + + newWatchProc->watched_connections = newWatchedConn; + + (*newWatchProc->watch_proc) (_IceConnectionObjs[i], + newWatchProc->client_data, True, &newWatchedConn->watch_data); + } + + return (1); +} + + + +void +IceRemoveConnectionWatch (watchProc, clientData) + +IceWatchProc watchProc; +IcePointer clientData; + +{ + _IceWatchProc *currWatchProc = _IceWatchProcs; + _IceWatchProc *prevWatchProc = NULL; + + while (currWatchProc && (currWatchProc->watch_proc != watchProc || + currWatchProc->client_data != clientData)) + { + prevWatchProc = currWatchProc; + currWatchProc = currWatchProc->next; + } + + if (currWatchProc) + { + _IceWatchProc *nextWatchProc = currWatchProc->next; + _IceWatchedConnection *watchedConn; + + watchedConn = currWatchProc->watched_connections; + while (watchedConn) + { + _IceWatchedConnection *nextWatchedConn = watchedConn->next; + free ((char *) watchedConn); + watchedConn = nextWatchedConn; + } + + if (prevWatchProc == NULL) + _IceWatchProcs = nextWatchProc; + else + prevWatchProc->next = nextWatchProc; + + free ((char *) currWatchProc); + } +} + + + +void +_IceConnectionOpened (iceConn) + +IceConn iceConn; + +{ + _IceWatchProc *watchProc = _IceWatchProcs; + + while (watchProc) + { + _IceWatchedConnection *newWatchedConn = (_IceWatchedConnection *) + malloc (sizeof (_IceWatchedConnection)); + _IceWatchedConnection *watchedConn; + + watchedConn = watchProc->watched_connections; + while (watchedConn && watchedConn->next) + watchedConn = watchedConn->next; + + newWatchedConn->iceConn = iceConn; + newWatchedConn->next = NULL; + + if (watchedConn == NULL) + watchProc->watched_connections = newWatchedConn; + else + watchedConn->next = newWatchedConn; + + (*watchProc->watch_proc) (iceConn, + watchProc->client_data, True, &newWatchedConn->watch_data); + + watchProc = watchProc->next; + } +} + + + +void +_IceConnectionClosed (iceConn) + +IceConn iceConn; + +{ + _IceWatchProc *watchProc = _IceWatchProcs; + + while (watchProc) + { + _IceWatchedConnection *watchedConn = watchProc->watched_connections; + _IceWatchedConnection *prev = NULL; + + while (watchedConn && watchedConn->iceConn != iceConn) + { + prev = watchedConn; + watchedConn = watchedConn->next; + } + + if (watchedConn) + { + (*watchProc->watch_proc) (iceConn, + watchProc->client_data, False, &watchedConn->watch_data); + + if (prev == NULL) + watchProc->watched_connections = watchedConn->next; + else + prev->next = watchedConn->next; + + free ((char *) watchedConn); + } + + watchProc = watchProc->next; + } +} |