diff options
author | Vic Lee <llyzs@163.com> | 2010-05-30 17:08:24 +0800 |
---|---|---|
committer | Vic Lee <llyzs@163.com> | 2010-05-30 17:19:02 +0800 |
commit | a9957d6417aff61be68117472075ebdd0996542f (patch) | |
tree | 0f2ba0a282982070c643385bffcbdc9643901374 |
Initial commit
-rw-r--r-- | .gitignore | 20 | ||||
-rw-r--r-- | AUTHORS | 5 | ||||
-rw-r--r-- | COPYING | 0 | ||||
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | INSTALL | 0 | ||||
-rw-r--r-- | Makefile.am | 47 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 8 | ||||
-rwxr-xr-x | autogen.sh | 13 | ||||
-rw-r--r-- | configure.ac | 35 | ||||
-rw-r--r-- | xdmcpclient.c | 530 | ||||
-rw-r--r-- | xdmcpclient.h | 51 | ||||
-rw-r--r-- | xqproxy.c | 170 | ||||
-rw-r--r-- | xqproxy.man | 144 | ||||
-rwxr-xr-x | xqssh | 19 |
15 files changed, 1042 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b295e48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +Makefile +Makefile.in +aclocal.m4 +config.guess +config.h.in +config.sub +configure +depcomp +install-sh +missing +.deps +autom4te.cache +config.h +*~ +config.log +config.status +stamp-h1 +*.o +xqproxy.1 +xqproxy @@ -0,0 +1,5 @@ +Maintainers: + + Vic Lee <llyzs@163.com> + + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ChangeLog diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..6e91105 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,47 @@ +bin_PROGRAMS = xqproxy + +AM_CFLAGS = $(libxdmcp_CFLAGS) +xqproxy_LDADD = $(libxdmcp_LIBS) + +xqproxy_SOURCES = \ + xdmcpclient.c \ + xdmcpclient.h \ + xqproxy.c + +appman_PRE = \ + xqproxy.man + +# App default files (*.ad) + +EXTRA_DIST = ChangeLog autogen.sh xqssh + +appmandir = $(APP_MAN_DIR) + +appman_DATA = $(appman_PRE:man=@APP_MAN_SUFFIX@) + +EXTRA_DIST += $(appman_PRE) +CLEANFILES = $(appman_DATA) + +SED = sed + +# Strings to replace in man pages +XORGRELSTRING = @PACKAGE_STRING@ + XORGMANNAME = X Version 11 + +MAN_SUBSTS = \ + -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ + -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ + -e 's|__xservername__|Xorg|g' \ + -e 's|__xconfigfile__|xorg.conf|g' \ + -e 's|__projectroot__|$(prefix)|g' \ + -e 's|__apploaddir__|$(appdefaultdir)|' \ + -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \ + -e 's|__libmansuffix__|$(LIB_MAN_SUFFIX)|g' \ + -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \ + -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \ + -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' + +SUFFIXES = .$(APP_MAN_SUFFIX) .man + +.man.$(APP_MAN_SUFFIX): + sed $(MAN_SUBSTS) < $< > $@ @@ -0,0 +1,8 @@ +This package contains the following binary executable: + +xqproxy - XDMCP Query Proxy + +Please see man pages for more information. + +To compile on Debian, you need libxdmcp-dev package installed. + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..e81f989 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,13 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure --enable-maintainer-mode "$@" + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..aa24b03 --- /dev/null +++ b/configure.ac @@ -0,0 +1,35 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.59]) +AC_INIT(xqproxy,[0.1.0]) +AM_INIT_AUTOMAKE([dist-bzip2]) +AM_MAINTAINER_MODE + +# Require xorg-macros version 1.2.0 or newer for XORG_CHANGELOG macro +m4_ifndef([XORG_MACROS_VERSION], [AC_FATAL([must install xorg-macros 1.2 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.2) + +AM_CONFIG_HEADER(config.h) + +AC_PROG_CC +AC_PROG_INSTALL + +# Only use -Wall if we have gcc +if test "x$GCC" = "xyes"; then + if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then + CFLAGS="$CFLAGS -Wall" + fi +fi + +PKG_CHECK_MODULES(libxdmcp, [ + xdmcp >= 1.0.0 +]) +AC_SUBST(libxdmcp_LIBS) +AC_SUBST(libxdmcp_CFLAGS) + +XORG_MANPAGE_SECTIONS +XORG_RELEASE_VERSION +XORG_CHANGELOG + +AC_OUTPUT([Makefile]) diff --git a/xdmcpclient.c b/xdmcpclient.c new file mode 100644 index 0000000..be27e25 --- /dev/null +++ b/xdmcpclient.c @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2009 Vic Lee + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * 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 AUTHORS OR COPYRIGHT + * HOLDERS 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/socket.h> +#include <X11/Xdmcp.h> +#include "xdmcpclient.h" + +static const char* HEX = "0123456789abcdef"; + +static void +PrintARRAY8 (ARRAY8Ptr arr, int ascii) +{ + int i; + for (i = 0; i < arr->length; i++) + { + if (ascii) + { + putc (arr->data[i], stdout); + } + else + { + putc (HEX[arr->data[i] / 16 % 16], stdout); + putc (HEX[arr->data[i] % 16], stdout); + } + } +} + +static char* +ConvertARRAY8toString (ARRAY8Ptr arr, int ascii) +{ + char *s; + int i; + + if (ascii) + { + s = (char*) malloc (arr->length + 1); + for (i = 0; i < arr->length; i++) + { + s[i] = arr->data[i]; + } + s[arr->length] = 0; + } + else + { + s = (char*) malloc (arr->length * 2 + 1); + for (i = 0; i < arr->length; i++) + { + s[i * 2] = HEX[arr->data[i] / 16 % 16]; + s[i * 2 + 1] = HEX[arr->data[i] % 16]; + } + s[arr->length * 2] = 0; + } + return s; +} + +static int +ARRAY8ofARRAY8Len (ARRAYofARRAY8Ptr arr) +{ + int i; + int len; + len = 0; + for (i = 0; i < arr->length; i++) + { + len += 2 + arr->data[i].length; + } + return len; +} + +struct _XdmcpClient +{ + struct sockaddr_storage Addr; + int AddrLen; + int Sock; + int Timeout; + + XdmcpHeader header; + XdmcpBuffer buffer; + + ARRAYofARRAY8 AuthenNames; + ARRAYofARRAY8 AuthenDatas; + ARRAY8 AuthenName; + ARRAY8 AuthenData; + + ARRAYofARRAY8 AuthorNames; + ARRAY8 AuthorName; + ARRAY8 AuthorData; + + int DisplayNumber; + ARRAY8 DisplayClass; + ARRAY8 DisplayID; + + CARD32 SessionID; +}; + +static void +XdmcpClientRegisterAuthen (XdmcpClient *client, const char *name, const char *data, int datalen) +{ + int i; + int len; + int namelen; + ARRAY8 n, d; + + namelen = strlen (name); + XdmcpAllocARRAY8 (&n, namelen); + XdmcpAllocARRAY8 (&d, datalen); + for (i = 0; i < namelen; i++) n.data[i] = name[i]; + for (i = 0; i < datalen; i++) d.data[i] = data[i]; + + len = client->AuthenNames.length + 1; + XdmcpReallocARRAYofARRAY8 (&client->AuthenNames, len); + XdmcpReallocARRAYofARRAY8 (&client->AuthenDatas, len); + client->AuthenNames.data[len - 1] = n; + client->AuthenDatas.data[len - 1] = d; +} + +static void +XdmcpClientRegisterDisplayClass (XdmcpClient *client, const char *displayclass) +{ + int len; + + XdmcpDisposeARRAY8 (&client->DisplayClass); + len = strlen (displayclass); + XdmcpAllocARRAY8 (&client->DisplayClass, len); + memcpy (client->DisplayClass.data, displayclass, len); +} + +static void +XdmcpClientRegisterDisplayID (XdmcpClient *client, const char *displayid) +{ + int len; + + XdmcpDisposeARRAY8 (&client->DisplayID); + len = strlen (displayid); + XdmcpAllocARRAY8 (&client->DisplayID, len); + memcpy (client->DisplayID.data, displayid, len); +} + +static void +XdmcpClientRegisterAuthor (XdmcpClient *client, const char *name) +{ + int i; + int len; + int namelen; + ARRAY8 n; + + namelen = strlen (name); + XdmcpAllocARRAY8 (&n, namelen); + for (i = 0; i < namelen; i++) n.data[i] = name[i]; + + len = client->AuthorNames.length + 1; + XdmcpReallocARRAYofARRAY8 (&client->AuthorNames, len); + client->AuthorNames.data[len - 1] = n; +} + +int +XdmcpClientRegisterServer (XdmcpClient *client, const char *host, const char *port) +{ + struct addrinfo hints; + struct addrinfo *res; + int error; + + memset (&hints, 0, sizeof (hints)); + hints.ai_family = PF_UNSPEC; + error = getaddrinfo (host, port, &hints, &res); + if (error) + { + printf ("Error> getaddrinfo on %s:%s failed: %s.\n", host, port, gai_strerror (error)); + return FALSE; + } + while (res) + { + /* TODO: Somehow gdm does not response on IPv6? will figure it out later */ + if (res->ai_family == AF_INET) + { + break; + } + res = res->ai_next; + } + if (res == NULL) + { + printf ("Error> host not on supported network type.\n"); + return FALSE; + } + + memmove (&client->Addr, res->ai_addr, res->ai_addrlen); + client->AddrLen = res->ai_addrlen; + + printf ("Client> Server address %s:%s registered.\n", host, port); + + return TRUE; +} + +XdmcpClient* +XdmcpClientNew (int display_number, int timeout) +{ + XdmcpClient *client; + int sock; + + sock = socket (AF_INET, SOCK_DGRAM, 0); + if (sock < 0) + { + printf ("Error> failed to create socket.\n"); + return NULL; + } + + client = (XdmcpClient*) malloc (sizeof (XdmcpClient)); + memset (client, 0, sizeof (XdmcpClient)); + client->Sock = sock; + client->Timeout = timeout; + + XdmcpClientRegisterAuthen (client, "XDM-AUTHENTICATION-1", "test", 4); + XdmcpClientRegisterDisplayClass (client, "xqproxy"); + XdmcpClientRegisterDisplayID (client, "xqproxy"); + XdmcpClientRegisterAuthor (client, "MIT-MAGIC-COOKIE-1"); + + client->DisplayNumber = display_number; + + printf ("Client> Initialized on display :%i.\n", display_number); + + return client; +} + +void +XdmcpClientFree (XdmcpClient *client) +{ + if (client->Sock > 0) + { + close (client->Sock); + } + XdmcpDisposeARRAYofARRAY8 (&client->AuthenNames); + XdmcpDisposeARRAYofARRAY8 (&client->AuthenDatas); + XdmcpDisposeARRAYofARRAY8 (&client->AuthorNames); + free (client); +} + +int +XdmcpClientReceivePacket (XdmcpClient *client) +{ + fd_set fsread; + fd_set fserr; + struct timeval timeout; + int ret; + + FD_ZERO (&fsread); + FD_SET (client->Sock, &fsread); + FD_ZERO (&fserr); + FD_SET (client->Sock, &fserr); + timeout.tv_sec = client->Timeout; + timeout.tv_usec = 0; + + ret = select(FD_SETSIZE, &fsread, NULL, &fserr, &timeout); + if (ret < 0) + { + printf("Error> Failed to call select().\n"); + return FALSE; + } + if (FD_ISSET (client->Sock, &fserr)) + { + printf("Error> Socket error.\n"); + return FALSE; + } + if (!FD_ISSET (client->Sock, &fsread)) + { + printf ("Error> No response from the server.\n"); + return FALSE; + } + + if (!XdmcpFill (client->Sock, &client->buffer, (XdmcpNetaddr) &client->Addr, &client->AddrLen)) + { + printf ("Error> Failed to receive from the server.\n"); + return FALSE; + } + if (!XdmcpReadHeader (&client->buffer, &client->header)) + { + printf ("Error> Received corrupted packet header.\n"); + return FALSE; + } + if (client->header.version != XDM_PROTOCOL_VERSION) + { + printf ("Error> Received unsupported version %i.\n", client->header.version); + return FALSE; + } + return TRUE; +} + +int +XdmcpClientSetAuth (XdmcpClient *client, ARRAY8Ptr authenname) +{ + int ret = FALSE; + int i; + if (authenname->length == 0) + { + ret = TRUE; + } + else + { + for (i = 0; i < client->AuthenNames.length; i++) + { + if (XdmcpARRAY8Equal (&client->AuthenNames.data[i], authenname)) + { + client->AuthenName = client->AuthenNames.data[i]; + client->AuthenData = client->AuthenDatas.data[i]; + ret = TRUE; + break; + } + } + } + return ret; +} + +int +XdmcpClientQuery (XdmcpClient *client) +{ + int ret; + ARRAY8 authenname = { 0 }; + ARRAY8 hostname = { 0 }; + ARRAY8 status = { 0 }; + + client->header.version = XDM_PROTOCOL_VERSION; + client->header.opcode = (CARD16) QUERY; + client->header.length = 1; + client->header.length += ARRAY8ofARRAY8Len (&client->AuthenNames); + XdmcpWriteHeader (&client->buffer, &client->header); + XdmcpWriteARRAYofARRAY8 (&client->buffer, &client->AuthenNames); + XdmcpFlush (client->Sock, &client->buffer, (XdmcpNetaddr) &client->Addr, client->AddrLen); + + printf ("Client> QUERY packet sent to server.\n"); + + if (!XdmcpClientReceivePacket (client)) return FALSE; + + switch (client->header.opcode) + { + case WILLING: + break; + case UNWILLING: + printf ("Error> Server is unwilling to accept remote login.\n"); + return FALSE; + default: + printf ("Error> Unexpected response %i\n", client->header.opcode); + return FALSE; + } + + ret = FALSE; + if (XdmcpReadARRAY8 (&client->buffer, &authenname) && + XdmcpReadARRAY8 (&client->buffer, &hostname) && + XdmcpReadARRAY8 (&client->buffer, &status)) + { + printf ("Server> WILLING (authen:"); + PrintARRAY8 (&authenname, TRUE); + printf (" host:"); + PrintARRAY8 (&hostname, TRUE); + printf (" status:"); + PrintARRAY8 (&status, TRUE); + printf (")\n"); + if (client->header.length == 6 + authenname.length + hostname.length + status.length) + { + ret = XdmcpClientSetAuth (client, &authenname); + if (!ret) + { + printf ("Error> Unsupported authentication name\n"); + } + } + else + { + printf ("Error> Header length unmatched\n"); + } + } + else + { + printf ("Error> Corrupted willing packet\n"); + } + XdmcpDisposeARRAY8 (&authenname); + XdmcpDisposeARRAY8 (&hostname); + XdmcpDisposeARRAY8 (&status); + + return ret; +} + +int +XdmcpClientAddXauth (XdmcpClient *client) +{ + char *cmd; + int len; + char *authorname, *authordata; + int ret; + + authorname = ConvertARRAY8toString (&client->AuthorName, TRUE); + authordata = ConvertARRAY8toString (&client->AuthorData, FALSE); + + len = 20 + strlen (authorname) + strlen (authordata); + cmd = (char*) malloc (len + 1); + snprintf (cmd, len, "xauth add :%i %s %s", client->DisplayNumber, authorname, authordata); + ret = system (cmd); + + printf ("Client> '%s' returns %i\n", cmd, ret); + + free (authorname); + free (authordata); + free (cmd); + + return (ret == 0); +} + +int +XdmcpClientRequest (XdmcpClient *client) +{ + int ret; + ARRAY8 AcceptAuthenName = { 0 }, AcceptAuthenData = { 0 }; + + client->header.version = XDM_PROTOCOL_VERSION; + client->header.opcode = (CARD16) REQUEST; + + client->header.length = 2; /* display number */ + /* TODO: Connection Types */ + client->header.length += 1 + 2 * 0; /* connection types */ + client->header.length += 1; /* connection addresses */ + /* for each connection type, += 2 + data.length */ + client->header.length += 2 + client->AuthenName.length; + client->header.length += 2 + client->AuthenData.length; + client->header.length += 1; /* authorization names */ + client->header.length += ARRAY8ofARRAY8Len (&client->AuthorNames); + client->header.length += 2 + client->DisplayID.length; + + XdmcpWriteHeader (&client->buffer, &client->header); + XdmcpWriteCARD16 (&client->buffer, (CARD16) client->DisplayNumber); + XdmcpWriteCARD8 (&client->buffer, (CARD8) 0); + /* connection types here */ + XdmcpWriteCARD8 (&client->buffer, (CARD8) 0); + /* connection addresses here */ + XdmcpWriteARRAY8 (&client->buffer, &client->AuthenName); + XdmcpWriteARRAY8 (&client->buffer, &client->AuthenData); + XdmcpWriteARRAYofARRAY8 (&client->buffer, &client->AuthorNames); + XdmcpWriteARRAY8 (&client->buffer, &client->DisplayID); + + XdmcpFlush (client->Sock, &client->buffer, (XdmcpNetaddr) &client->Addr, client->AddrLen); + + printf ("Client> REQUEST packet sent.\n"); + + if (!XdmcpClientReceivePacket (client)) return FALSE; + + switch (client->header.opcode) + { + case ACCEPT: + break; + case DECLINE: + printf ("Error> Server declined remote login request.\n"); + return FALSE; + default: + printf ("Error> Unexpected response %i\n", client->header.opcode); + return FALSE; + } + + ret = FALSE; + + if (XdmcpReadCARD32 (&client->buffer, &client->SessionID) && + XdmcpReadARRAY8 (&client->buffer, &AcceptAuthenName) && + XdmcpReadARRAY8 (&client->buffer, &AcceptAuthenData) && + XdmcpReadARRAY8 (&client->buffer, &client->AuthorName) && + XdmcpReadARRAY8 (&client->buffer, &client->AuthorData)) + { + printf ("Server> ACCEPT (sessionid:%u authen:", (unsigned int) client->SessionID); + PrintARRAY8 (&AcceptAuthenName, TRUE); + printf (" authendata:"); + PrintARRAY8 (&AcceptAuthenData, FALSE); + printf (" author:"); + PrintARRAY8 (&client->AuthorName, TRUE); + printf (" authordata:"); + PrintARRAY8 (&client->AuthorData, FALSE); + printf (")\n"); + ret = TRUE; + } + else + { + printf ("Error> Corrupted accept packet\n"); + } + + return ret; +} + +int +XdmcpClientManage (XdmcpClient *client, unsigned int sessionid) +{ + client->header.version = XDM_PROTOCOL_VERSION; + client->header.opcode = (CARD16) MANAGE; + client->header.length = 8 + client->DisplayClass.length; + + if (sessionid > 0) + { + client->SessionID = (CARD32) sessionid; + } + + XdmcpWriteHeader (&client->buffer, &client->header); + XdmcpWriteCARD32 (&client->buffer, client->SessionID); + XdmcpWriteCARD16 (&client->buffer, (CARD16) client->DisplayNumber); + XdmcpWriteARRAY8 (&client->buffer, &client->DisplayClass); + + XdmcpFlush (client->Sock, &client->buffer, (XdmcpNetaddr) &client->Addr, client->AddrLen); + + printf ("Client> MANAGE packet sent for session %u.\n", (unsigned int) client->SessionID); + + return TRUE; +} + diff --git a/xdmcpclient.h b/xdmcpclient.h new file mode 100644 index 0000000..2cc5a48 --- /dev/null +++ b/xdmcpclient.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009 Vic Lee + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * 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 AUTHORS OR COPYRIGHT + * HOLDERS 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. + */ + +#ifndef __XDMCPCLIENT_H__ +#define __XDMCPCLIENT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _XdmcpClient XdmcpClient; + +/* Constructor / Destructor */ +XdmcpClient* XdmcpClientNew (int display_number, int timeout); +void XdmcpClientFree (XdmcpClient *client); + +int XdmcpClientRegisterServer (XdmcpClient *client, const char *host, const char *port); + +/* Sending / Receiving */ +int XdmcpClientQuery (XdmcpClient *client); +int XdmcpClientRequest (XdmcpClient *client); +int XdmcpClientAddXauth (XdmcpClient *client); +int XdmcpClientManage (XdmcpClient *client, unsigned int sessionid); + +#ifdef __cplusplus +} +#endif + +#endif /* __XDMCPCLIENT_H__ */ diff --git a/xqproxy.c b/xqproxy.c new file mode 100644 index 0000000..21a0452 --- /dev/null +++ b/xqproxy.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2009 Vic Lee + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * 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 AUTHORS OR COPYRIGHT + * HOLDERS 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "xdmcpclient.h" + +#define XQPROXY_ERROR_ARGUMENT 1 +#define XQPROXY_ERROR_INIT 2 +#define XQPROXY_ERROR_RESOLVE 3 +#define XQPROXY_ERROR_QUERY 4 +#define XQPROXY_ERROR_REQUEST 5 +#define XQPROXY_ERROR_XAUTH 6 +#define XQPROXY_ERROR_MANAGE 7 + +int +main (int argc, char *argv[]) +{ + XdmcpClient *client; + int ret = 0; + int i; + int display = 0; + unsigned int sessionid = 0; + const char *host = "localhost", *port = "177"; + int do_query = 0; + int do_xauth = 0; + int do_manage = 0; + int timeout = 5; + + for (i = 1; i < argc; i++) + { + if (strcmp (argv[i], "-display") == 0) + { + if (i + 1 >= argc) + { + printf ("Error> Missing argument value %s\n", argv[i]); + return XQPROXY_ERROR_ARGUMENT; + } + display = atoi (argv[++i]); + continue; + } + if (strcmp (argv[i], "-host") == 0) + { + if (i + 1 >= argc) + { + printf ("Error> Missing argument value %s\n", argv[i]); + return XQPROXY_ERROR_ARGUMENT; + } + host = argv[++i]; + continue; + } + if (strcmp (argv[i], "-port") == 0) + { + if (i + 1 >= argc) + { + printf ("Error> Missing argument value %s\n", argv[i]); + return XQPROXY_ERROR_ARGUMENT; + } + port = argv[++i]; + continue; + } + if (strcmp (argv[i], "-sessionid") == 0) + { + if (i + 1 >= argc) + { + printf ("Error> Missing argument value %s\n", argv[i]); + return XQPROXY_ERROR_ARGUMENT; + } + sessionid = (unsigned int) atoi (argv[++i]); + continue; + } + if (strcmp (argv[i], "-timeout") == 0) + { + if (i + 1 >= argc) + { + printf ("Error> Missing argument value %s\n", argv[i]); + return XQPROXY_ERROR_ARGUMENT; + } + timeout = (unsigned int) atoi (argv[++i]); + continue; + } + if (strcmp (argv[i], "-query") == 0) + { + do_query = 1; + continue; + } + if (strcmp (argv[i], "-xauth") == 0) + { + do_xauth = 1; + continue; + } + if (strcmp (argv[i], "-manage") == 0) + { + do_manage = 1; + continue; + } + } + + if (do_xauth && !do_query) + { + printf ("Error> Argument -xauth must be used together with -query\n"); + return XQPROXY_ERROR_ARGUMENT; + } + + if (!do_query && !do_manage) + { + printf ("Error> Either -query or -manage must be supplied\n"); + return XQPROXY_ERROR_ARGUMENT; + } + + if (do_manage && !sessionid && !do_query) + { + printf ("Error> Argument -sessionid must be supplied if -manage is used without -query\n"); + return XQPROXY_ERROR_ARGUMENT; + } + + if (sessionid && do_query) + { + printf ("Error> Argument -sessionid cannot be used together with -query\n"); + return XQPROXY_ERROR_ARGUMENT; + } + + client = XdmcpClientNew (display, timeout); + if (!client) return XQPROXY_ERROR_INIT; + if (XdmcpClientRegisterServer (client, host, port)) + { + if (do_query) + { + if (!XdmcpClientQuery (client)) ret = XQPROXY_ERROR_QUERY; + else if (!XdmcpClientRequest (client)) ret = XQPROXY_ERROR_REQUEST; + else if (do_xauth && !XdmcpClientAddXauth (client)) ret = XQPROXY_ERROR_XAUTH; + } + if (ret == 0 && do_manage) + { + if (!XdmcpClientManage (client, sessionid)) + { + ret = XQPROXY_ERROR_MANAGE; + } + } + } + else + { + ret = XQPROXY_ERROR_RESOLVE; + } + XdmcpClientFree (client); + return ret; +} diff --git a/xqproxy.man b/xqproxy.man new file mode 100644 index 0000000..d8155bb --- /dev/null +++ b/xqproxy.man @@ -0,0 +1,144 @@ +.\" Copyright (c) 2009 Vic Lee +.\" +.\" Permission is hereby granted, free of charge, to any person +.\" obtaining a copy of this software and associated documentation +.\" files (the "Software"), to deal in the Software without +.\" restriction, including without limitation the rights to use, +.\" copy, modify, merge, publish, distribute, sublicense, and/or sell +.\" copies of the Software, and to permit persons to whom the +.\" Software is furnished to do so, subject to the following +.\" conditions: +.\" +.\" 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 AUTHORS OR COPYRIGHT +.\" HOLDERS 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. +.\" +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XQPROXY 1 __xorgversion__ +.SH NAME +xqproxy \- XDMCP Query Proxy +.SH SYNOPSIS +.B xqproxy +[-display n] [-host hostname] [-port port] [-timeout seconds] [-query [-xauth]] +[-manage [-sessionid session-id]] +.SH DESCRIPTION +.I xqproxy +is a proxy program that can send XDMCP query to a display manager to establish +XDM session for an existing local X display. +.SH OPTIONS +.PP +.TP 8 +.B \-display n +The local display number. Default is 0. +.PP +.TP 8 +.B \-host hostname +The hostname of the remote display manager. Default is localhost. +.PP +.TP 8 +.B \-port port +The XDMCP UDP port of the remote display manager. Default is 177. +.PP +.TP 8 +.B \-timeout seconds +Timeout value while waiting for response from the server. +.PP +.TP 8 +.B \-query +Sends QUERY and REQUEST to the display manager to request a new session. The +session id and magic cookie will be printed in stdout. +.PP +.TP 8 +.B \-xauth +When use together with -query option, xqproxy will call xauth to add the magic +cookie to local .Xauthority database. +.PP +.TP 8 +.B \-manage +Sends MANAGE to the display manager to start the session. If this option is +used together with -query, it will always use the session id returned from the +display manager. Otherwise, it will uses the session id assigned by -sessionid +argument. +.PP +.TP 8 +.B \-sessionid session-id +The new session id returned from the display manager. This option is useful +only if -manage option is used separately. +.SH EXAMPLES +.PP +The following command request the display manager on REMOTEHOST to establish +an XDM session directly to a local X server on display :1 : +.PP + xqproxy -display 1 -host \fIREMOTEHOST\fP -query -xauth -manage +.PP +The following shell script request the display manager supplied by the first +argument to establish an XDM session over a secure SSH tunnel on a local +display supplied by the second argument (note that xqproxy runs on the server) +: +.PP + #!/bin/sh +.br + # Usage: xqssh <server> <local_display_number> +.br + SSH=$(which ssh) +.br + if [ "x$SSH" = "x" ]; then +.br + echo openssh is required in order to use xqssh. +.br + exit 1 +.br + fi +.br + QUERY=$(ssh $1 xqproxy -display $2 -query) +.br + echo "$QUERY" +.br + SESSIONID=$(echo "$QUERY" | awk '/ACCEPT/ {print substr($3,12)}') +.br + COOKIE=$(echo "$QUERY" | awk '/ACCEPT/ {print substr($7,12,32)}') +.br + if [ "x$SESSIONID" = "x" ] || [ "x$COOKIE" = "x" ]; then +.br + exit 1 +.br + fi +.br + xauth add :$2 MIT-MAGIC-COOKIE-1 $COOKIE +.br + PORT=$(expr 6000 + $2) +.br + ssh -R $PORT:localhost:$PORT -fN $1 +.br + ssh $1 xqproxy -display $2 -manage -sessionid $SESSIONID +.br + exit 0 +.PP +.SH "SEE ALSO" +ssh(1) +.SH BUGS +.PP +Please send bugs to Vic Lee <llyzs@163.com> +.SH AUTHORS +Vic Lee + @@ -0,0 +1,19 @@ +#!/bin/sh +# Usage: xqssh <server> <local_display_number> +SSH=$(which ssh) +if [ "x$SSH" = "x" ]; then + echo openssh is required in order to use xqssh. + exit 1 +fi +QUERY=$(ssh $1 xqproxy -display $2 -query) +echo "$QUERY" +SESSIONID=$(echo "$QUERY" | awk '/ACCEPT/ {print substr($3,12)}') +COOKIE=$(echo "$QUERY" | awk '/ACCEPT/ {print substr($7,12,32)}') +if [ "x$SESSIONID" = "x" ] || [ "x$COOKIE" = "x" ]; then + exit 1 +fi +xauth add :$2 MIT-MAGIC-COOKIE-1 $COOKIE +PORT=$(expr 6000 + $2) +ssh -R $PORT:localhost:$PORT -fN $1 +ssh $1 xqproxy -display $2 -manage -sessionid $SESSIONID +exit 0 |