#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>
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 */
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.
*/
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,
*/
int init_ucs(int font_charset);
+/*
+ * Spare function exported directly from uxnet.c.
+ */
+int sk_getxdmdata(void *sock, unsigned long *ip, int *port);
+
#endif
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);
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;
* 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);
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;
* 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);
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.
#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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <time.h>
#include "putty.h"
#include "ssh.h"
(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 {
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);