From 2f92b7170f74a58d1e33d7913e154f9f47852683 Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 11 Jan 2003 09:31:54 +0000 Subject: [PATCH] Support XDM-AUTHORIZATION-1 for connecting to local X servers. If 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 | 7 +++++ putty.h | 1 + ssh.h | 2 ++ sshdes.c | 26 ++++++++++++++++++ unix/unix.h | 5 ++++ unix/uxnet.c | 83 +++++++++++++++++++++++++++++++--------------------------- winstuff.h | 9 +++++++ x11fwd.c | 19 ++++++++++++-- 8 files changed, 111 insertions(+), 41 deletions(-) diff --git a/mac/macstuff.h b/mac/macstuff.h index 6dc3df2b..ce3b58fe 100644 --- a/mac/macstuff.h +++ b/mac/macstuff.h @@ -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 diff --git a/putty.h b/putty.h index 6f32be3b..e4d8d1f3 100644 --- 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 0a38e949..4ad0543a 100644 --- 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. */ diff --git a/sshdes.c b/sshdes.c index fa8e53ce..ce4bdfe3 100644 --- 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, diff --git a/unix/unix.h b/unix/unix.h index ecacebda..4e006eb6 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -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 diff --git a/unix/uxnet.c b/unix/uxnet.c index 722ab474..6b8729e3 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -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. diff --git a/winstuff.h b/winstuff.h index e2d700ee..e58c12ef 100644 --- a/winstuff.h +++ b/winstuff.h @@ -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. */ diff --git a/x11fwd.c b/x11fwd.c index 184a3302..56b6eae2 100644 --- a/x11fwd.c +++ b/x11fwd.c @@ -1,6 +1,7 @@ #include #include #include +#include #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); -- 2.11.0