Support XDM-AUTHORIZATION-1 for connecting to local X servers. If
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 11 Jan 2003 09:31:54 +0000 (09:31 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 11 Jan 2003 09:31:54 +0000 (09:31 +0000)
we're going to be a security program, we can at least make a token
effort to use the most secure local X auth available! And I'm still
half-tempted to see if I can support it for remote X servers too...

git-svn-id: svn://svn.tartarus.org/sgt/putty@2537 cda61777-01e9-0310-a592-d414129be87e

mac/macstuff.h
putty.h
ssh.h
sshdes.c
unix/unix.h
unix/uxnet.c
winstuff.h
x11fwd.c

index 6dc3df2..ce3b58f 100644 (file)
@@ -26,6 +26,13 @@ typedef void *Context; /* FIXME */
 
 #define OPTIMISE_SCROLL
 
+/*
+ * sk_getxdmdata() does not exist under the Mac (SGT: I have no
+ * idea whatsoever how to write it, and furthermore I'm unconvinced
+ * it's necessary), so it's a macro which always returns FALSE.
+ */
+#define sk_getxdmdata(socket, ip, port) (0)
+
 /* To make it compile */
 
 #include <stdarg.h>
diff --git a/putty.h b/putty.h
index 6f32be3..e4d8d1f 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -697,6 +697,7 @@ void cmdline_error(char *, ...);
 enum {
     X11_NO_AUTH,
     X11_MIT,                           /* MIT-MAGIC-COOKIE-1 */
+    X11_XDM,                          /* XDM-AUTHORIZATION-1 */
     X11_NAUTHS
 };
 extern const char *const x11_authnames[];  /* declared in x11fwd.c */
diff --git a/ssh.h b/ssh.h
index 0a38e94..4ad0543 100644 (file)
--- a/ssh.h
+++ b/ssh.h
@@ -363,6 +363,8 @@ void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk,
 void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk,
                           int len);
 
+void des_encrypt_xdmauth(unsigned char *key, unsigned char *blk, int len);
+
 /*
  * For progress updates in the key generation utility.
  */
index fa8e53c..ce4bdfe 100644 (file)
--- a/sshdes.c
+++ b/sshdes.c
@@ -897,6 +897,32 @@ void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
     memset(ourkeys, 0, sizeof(ourkeys));
 }
 
+void des_encrypt_xdmauth(unsigned char *keydata, unsigned char *blk, int len)
+{
+    unsigned char key[8];
+    DESContext dc;
+    int i, nbits, j;
+    unsigned int bits;
+
+    bits = 0;
+    nbits = 0;
+    j = 0;
+    for (i = 0; i < 8; i++) {
+       if (nbits < 7) {
+           bits = (bits << 8) | keydata[j];
+           nbits += 8;
+           j++;
+       }
+       key[i] = (bits >> (nbits - 7)) << 1;
+       bits &= ~(0x7F << (nbits - 7));
+       nbits -= 7;
+    }
+
+    des_key_setup(GET_32BIT_MSB_FIRST(key), GET_32BIT_MSB_FIRST(key + 4),
+                 &dc);
+    des_cbc_encrypt(blk, blk, 24, &dc);
+}
+
 static const struct ssh2_cipher ssh_3des_ssh2 = {
     des3_make_context, des3_free_context, des3_iv, des3_key,
     des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk,
index ecacebd..4e006eb 100644 (file)
@@ -71,4 +71,9 @@ void (*putty_signal(int sig, void (*func)(int)))(int);
  */
 int init_ucs(int font_charset);
 
+/*
+ * Spare function exported directly from uxnet.c.
+ */
+int sk_getxdmdata(void *sock, unsigned long *ip, int *port);
+
 #endif
index 722ab47..6b8729e 100644 (file)
@@ -305,27 +305,27 @@ static void *sk_tcp_get_private_ptr(Socket s);
 static void sk_tcp_set_frozen(Socket s, int is_frozen);
 static char *sk_tcp_socket_error(Socket s);
 
+static struct socket_function_table tcp_fn_table = {
+    sk_tcp_plug,
+    sk_tcp_close,
+    sk_tcp_write,
+    sk_tcp_write_oob,
+    sk_tcp_flush,
+    sk_tcp_set_private_ptr,
+    sk_tcp_get_private_ptr,
+    sk_tcp_set_frozen,
+    sk_tcp_socket_error
+};
+
 Socket sk_register(void *sock, Plug plug)
 {
-    static struct socket_function_table fn_table = {
-       sk_tcp_plug,
-       sk_tcp_close,
-       sk_tcp_write,
-       sk_tcp_write_oob,
-       sk_tcp_flush,
-       sk_tcp_set_private_ptr,
-       sk_tcp_get_private_ptr,
-       sk_tcp_set_frozen,
-       sk_tcp_socket_error
-    };
-
     Actual_Socket ret;
 
     /*
      * Create Socket structure.
      */
     ret = smalloc(sizeof(struct Socket_tag));
-    ret->fn = &fn_table;
+    ret->fn = &tcp_fn_table;
     ret->error = NULL;
     ret->plug = plug;
     bufchain_init(&ret->output_data);
@@ -355,18 +355,6 @@ Socket sk_register(void *sock, Plug plug)
 Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
              int nodelay, Plug plug)
 {
-    static struct socket_function_table fn_table = {
-       sk_tcp_plug,
-       sk_tcp_close,
-       sk_tcp_write,
-       sk_tcp_write_oob,
-       sk_tcp_flush,
-       sk_tcp_set_private_ptr,
-       sk_tcp_get_private_ptr,
-       sk_tcp_set_frozen,
-       sk_tcp_socket_error
-    };
-
     int s;
 #ifdef IPV6
     struct sockaddr_in6 a6;
@@ -380,7 +368,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
      * Create Socket structure.
      */
     ret = smalloc(sizeof(struct Socket_tag));
-    ret->fn = &fn_table;
+    ret->fn = &tcp_fn_table;
     ret->error = NULL;
     ret->plug = plug;
     bufchain_init(&ret->output_data);
@@ -524,18 +512,6 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
 
 Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
 {
-    static struct socket_function_table fn_table = {
-       sk_tcp_plug,
-       sk_tcp_close,
-       sk_tcp_write,
-       sk_tcp_write_oob,
-       sk_tcp_flush,
-       sk_tcp_set_private_ptr,
-       sk_tcp_get_private_ptr,
-       sk_tcp_set_frozen,
-       sk_tcp_socket_error
-    };
-
     int s;
 #ifdef IPV6
     struct sockaddr_in6 a6;
@@ -550,7 +526,7 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
      * Create Socket structure.
      */
     ret = smalloc(sizeof(struct Socket_tag));
-    ret->fn = &fn_table;
+    ret->fn = &tcp_fn_table;
     ret->error = NULL;
     ret->plug = plug;
     bufchain_init(&ret->output_data);
@@ -661,6 +637,35 @@ static void sk_tcp_close(Socket sock)
     sfree(s);
 }
 
+int sk_getxdmdata(void *sock, unsigned long *ip, int *port)
+{
+    Actual_Socket s = (Actual_Socket) sock;
+    struct sockaddr_in addr;
+    socklen_t addrlen;
+
+    /*
+     * We must check that this socket really _is_ an Actual_Socket.
+     */
+    if (s->fn != &tcp_fn_table)
+       return 0;                      /* failure */
+
+    /*
+     * If we ever implement connecting to a local X server through
+     * a Unix socket, we return 0xFFFFFFFF for the IP address and
+     * our current pid for the port. Bizarre, but such is life.
+     */
+
+    addrlen = sizeof(addr);
+    if (getsockname(s->s, (struct sockaddr *)&addr, &addrlen) < 0 ||
+       addr.sin_family != AF_INET)
+       return 0;
+
+    *ip = ntohl(addr.sin_addr.s_addr);
+    *port = ntohs(addr.sin_port);
+
+    return 1;
+}
+
 /*
  * The function which tries to send on a socket once it's deemed
  * writable.
index e2d700e..e58c12e 100644 (file)
@@ -89,6 +89,15 @@ GLOBAL void *logctx;
 #define SEL_NL { 13, 10 }
 
 /*
+ * sk_getxdmdata() does not exist under Windows (not that I
+ * couldn't write it if I wanted to, but I haven't bothered), so
+ * it's a macro which always returns FALSE. With any luck this will
+ * cause the compiler to notice it can optimise away the
+ * implementation of XDM-AUTHORIZATION-1 in x11fwd.c :-)
+ */
+#define sk_getxdmdata(socket, ip, port) (0)
+
+/*
  * Exports from winctrls.c.
  */
 
index 184a330..56b6eae 100644 (file)
--- a/x11fwd.c
+++ b/x11fwd.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <time.h>
 
 #include "putty.h"
 #include "ssh.h"
@@ -52,7 +53,7 @@
   (endian=='B' ? PUT_16BIT_MSB_FIRST(cp, val) : PUT_16BIT_LSB_FIRST(cp, val))
 
 const char *const x11_authnames[] = {
-    "", "MIT-MAGIC-COOKIE-1"
+    "", "MIT-MAGIC-COOKIE-1", "XDM-AUTHORIZATION-1"
 };
 
 struct X11Auth {
@@ -381,13 +382,27 @@ int x11_send(Socket s, char *data, int len)
             char realauthdata[64];
             int realauthlen = 0;
             int authstrlen = strlen(x11_authnames[pr->auth->realproto]);
+           unsigned long ip;
+           int port;
             static const char zeroes[4] = { 0,0,0,0 };
 
             if (pr->auth->realproto == X11_MIT) {
                 assert(pr->auth->reallen <= lenof(realauthdata));
                 realauthlen = pr->auth->reallen;
                 memcpy(realauthdata, pr->auth->realdata, realauthlen);
-            }
+            } else if (pr->auth->realproto == X11_XDM &&
+                      pr->auth->reallen == 16 &&
+                      sk_getxdmdata(s, &ip, &port)) {
+               time_t t;
+                realauthlen = 24;
+               memset(realauthdata, 0, 24);
+               memcpy(realauthdata, pr->auth->realdata, 8);
+               PUT_32BIT_MSB_FIRST(realauthdata+8, ip);
+               PUT_16BIT_MSB_FIRST(realauthdata+12, port);
+               t = time(NULL);
+               PUT_32BIT_MSB_FIRST(realauthdata+14, t);
+               des_encrypt_xdmauth(pr->auth->realdata+9, realauthdata, 24);
+           }
             /* implement other auth methods here if required */
 
             PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 6, authstrlen);