# Miscellaneous objects appearing in all the network utilities (not
# Pageant or PuTTYgen).
WINMISC = misc version winstore settings tree234 winnet proxy cmdline
- + windefs
+ + windefs winmisc
UXMISC = misc version uxstore settings tree234 uxnet proxy cmdline
MACMISC = misc version macstore settings tree234 mtcpnet proxy
pterm : [X] pterm terminal wcwidth uxucs uxmisc tree234 misc ldisc ldiscucs
+ logging uxprint settings pty be_none uxstore signal CHARSET
-plink : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal
+plink : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal ux_x11
PuTTY : [M] terminal wcwidth ldiscucs logging be_all mac macdlg
+ macterm macucs mac_res.rsrc testback NONSSH MACSSH MACMISC CHARSET
-/* $Id: mac.c,v 1.22 2003/01/09 22:39:47 ben Exp $ */
+/* $Id: mac.c,v 1.23 2003/01/10 18:33:35 simon Exp $ */
/*
* Copyright (c) 1999 Ben Harris
* All rights reserved.
return def;
}
+void platform_get_x11_auth(char *display, int *proto,
+ unsigned char *data, int *datalen)
+{
+ /* SGT: I have no idea whether Mac X servers need anything here. */
+}
+
/*
* Local Variables:
* c-file-style: "simon"
return ch->buffersize;
}
-void bufchain_add(bufchain *ch, void *data, int len)
+void bufchain_add(bufchain *ch, const void *data, int len)
{
- char *buf = (char *)data;
+ const char *buf = (const char *)data;
ch->buffersize += len;
void bufchain_init(bufchain *ch);
void bufchain_clear(bufchain *ch);
int bufchain_size(bufchain *ch);
-void bufchain_add(bufchain *ch, void *data, int len);
+void bufchain_add(bufchain *ch, const void *data, int len);
void bufchain_prefix(bufchain *ch, void **data, int *len);
void bufchain_consume(bufchain *ch, int len);
void bufchain_fetch(bufchain *ch, void *data, int len);
/* if p is NULL, it doesn't change the plug */
/* but it does return the one it's using */
void (*close) (Socket s);
- int (*write) (Socket s, char *data, int len);
- int (*write_oob) (Socket s, char *data, int len);
+ int (*write) (Socket s, const char *data, int len);
+ int (*write_oob) (Socket s, const char *data, int len);
void (*flush) (Socket s);
void (*set_private_ptr) (Socket s, void *ptr);
void *(*get_private_ptr) (Socket s);
sfree(ps);
}
-static int sk_proxy_write (Socket s, char *data, int len)
+static int sk_proxy_write (Socket s, const char *data, int len)
{
Proxy_Socket ps = (Proxy_Socket) s;
return sk_write(ps->sub_socket, data, len);
}
-static int sk_proxy_write_oob (Socket s, char *data, int len)
+static int sk_proxy_write_oob (Socket s, const char *data, int len)
{
Proxy_Socket ps = (Proxy_Socket) s;
void cmdline_error(char *, ...);
+/*
+ * X11 auth mechanisms we know about.
+ */
+enum {
+ X11_NO_AUTH,
+ X11_MIT, /* MIT-MAGIC-COOKIE-1 */
+ X11_NAUTHS
+};
+extern const char *const x11_authnames[]; /* declared in x11fwd.c */
+
#endif
logevent("Requesting X11 forwarding");
ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
data, sizeof(data));
+ x11_get_real_auth(ssh->x11auth, cfg.x11_display);
if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
PKT_STR, proto, PKT_STR, data,
logevent("Requesting X11 forwarding");
ssh->x11auth = x11_invent_auth(proto, sizeof(proto),
data, sizeof(data));
+ x11_get_real_auth(ssh->x11auth, cfg.x11_display);
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid);
ssh2_pkt_addstring(ssh, "x11-req");
extern void x11_unthrottle(Socket s);
extern void x11_override_throttle(Socket s, int enable);
extern int x11_get_screen_number(char *display);
+void x11_get_real_auth(void *authv, char *display);
Bignum copybn(Bignum b);
Bignum bn_power_2(int n);
--- /dev/null
+/*
+ * ux_x11.c: fetch local auth data for X forwarding.
+ */
+
+#include <ctype.h>
+#include <unistd.h>
+#include "putty.h"
+
+void platform_get_x11_auth(char *display, int *protocol,
+ unsigned char *data, int *datalen)
+{
+ FILE *fp;
+ char *command;
+ int maxsize = *datalen;
+ char *localbuf;
+
+ command = dupprintf("xauth list %s 2>/dev/null", display);
+ fp = popen(command, "r");
+ sfree(command);
+
+ if (!fp)
+ return; /* assume no auth */
+
+ localbuf = smalloc(maxsize);
+
+ while (1) {
+ /*
+ * Read a line from stdin, and attempt to parse it into a
+ * display name (ignored), auth protocol, and auth string.
+ */
+ int c, i, hexdigit, proto;
+ char protoname[64];
+
+ /* Skip the display name. */
+ while (c = getc(fp), c != EOF && c != '\n' && !isspace(c));
+ if (c == EOF) break;
+ if (c == '\n') continue;
+
+ /* Skip white space. */
+ while (c != EOF && c != '\n' && isspace(c))
+ c = getc(fp);
+ if (c == EOF) break;
+ if (c == '\n') continue;
+
+ /* Read the auth protocol name, and see if it matches any we
+ * know about. */
+ i = 0;
+ while (c != EOF && c != '\n' && !isspace(c)) {
+ if (i < lenof(protoname)-1) protoname[i++] = c;
+ c = getc(fp);
+ }
+ protoname[i] = '\0';
+
+ for (i = X11_NO_AUTH; ++i < X11_NAUTHS ;) {
+ if (!strcmp(protoname, x11_authnames[i]))
+ break;
+ }
+ if (i >= X11_NAUTHS || i <= proto) {
+ /* Unrecognised protocol name, or a worse one than we already have.
+ * Skip this line. */
+ while (c != EOF && c != '\n')
+ c = getc(fp);
+ if (c == EOF) break;
+ }
+ proto = i;
+
+ /* Skip white space. */
+ while (c != EOF && c != '\n' && isspace(c))
+ c = getc(fp);
+ if (c == EOF) break;
+ if (c == '\n') continue;
+
+ /*
+ * Now grab pairs of hex digits and shove them into `data'.
+ */
+ i = 0;
+ hexdigit = -1;
+ while (c != EOF && c != '\n') {
+ int hexval = -1;
+ if (c >= 'A' && c <= 'F')
+ hexval = c + 10 - 'A';
+ if (c >= 'a' && c <= 'f')
+ hexval = c + 10 - 'a';
+ if (c >= '0' && c <= '9')
+ hexval = c - '0';
+ if (hexval >= 0) {
+ if (hexdigit >= 0) {
+ hexdigit = (hexdigit << 4) + hexval;
+ if (i < maxsize)
+ localbuf[i++] = hexdigit;
+ hexdigit = -1;
+ } else
+ hexdigit = hexval;
+ }
+ c = getc(fp);
+ }
+
+ *datalen = i;
+ *protocol = proto;
+ memcpy(data, localbuf, i);
+
+ /* Nonetheless, continue looping round; we might find a better one. */
+ }
+ pclose(fp);
+ sfree(localbuf);
+}
}
static void sk_tcp_close(Socket s);
-static int sk_tcp_write(Socket s, char *data, int len);
-static int sk_tcp_write_oob(Socket s, char *data, int len);
+static int sk_tcp_write(Socket s, const char *data, int len);
+static int sk_tcp_write_oob(Socket s, const char *data, int len);
static void sk_tcp_set_private_ptr(Socket s, void *ptr);
static void *sk_tcp_get_private_ptr(Socket s);
static void sk_tcp_set_frozen(Socket s, int is_frozen);
}
}
-static int sk_tcp_write(Socket sock, char *buf, int len)
+static int sk_tcp_write(Socket sock, const char *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
return bufchain_size(&s->output_data);
}
-static int sk_tcp_write_oob(Socket sock, char *buf, int len)
+static int sk_tcp_write_oob(Socket sock, const char *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
--- /dev/null
+/*
+ * winmisc.c: miscellaneous Windows-specific things.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "putty.h"
+
+void platform_get_x11_auth(char *display, int *proto,
+ unsigned char *data, int *datalen)
+{
+ /* We don't support this at all under Windows. */
+}
}
static void sk_tcp_close(Socket s);
-static int sk_tcp_write(Socket s, char *data, int len);
-static int sk_tcp_write_oob(Socket s, char *data, int len);
+static int sk_tcp_write(Socket s, const char *data, int len);
+static int sk_tcp_write_oob(Socket s, const char *data, int len);
static void sk_tcp_set_private_ptr(Socket s, void *ptr);
static void *sk_tcp_get_private_ptr(Socket s);
static void sk_tcp_set_frozen(Socket s, int is_frozen);
}
}
-static int sk_tcp_write(Socket sock, char *buf, int len)
+static int sk_tcp_write(Socket sock, const char *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
return bufchain_size(&s->output_data);
}
-static int sk_tcp_write_oob(Socket sock, char *buf, int len)
+static int sk_tcp_write_oob(Socket sock, const char *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
#include <stdio.h>
#include <stdlib.h>
+#include <assert.h>
#include "putty.h"
#include "ssh.h"
#define PUT_16BIT(endian, cp, val) \
(endian=='B' ? PUT_16BIT_MSB_FIRST(cp, val) : PUT_16BIT_LSB_FIRST(cp, val))
+const char *const x11_authnames[] = {
+ "", "MIT-MAGIC-COOKIE-1"
+};
+
struct X11Auth {
- unsigned char data[64];
- int len;
+ unsigned char fakedata[64], realdata[64];
+ int fakeproto, realproto;
+ int fakelen, reallen;
};
+extern void platform_get_x11_auth(char *display, int *proto,
+ unsigned char *data, int *datalen);
+
struct X11Private {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
char ourdata[64];
int i;
+ auth->fakeproto = X11_MIT;
+
/* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
- auth->len = 16;
+ auth->fakelen = 16;
for (i = 0; i < 16; i++)
- auth->data[i] = random_byte();
+ auth->fakedata[i] = random_byte();
/* Now format for the recipient. */
- strncpy(proto, "MIT-MAGIC-COOKIE-1", protomaxlen);
+ strncpy(proto, x11_authnames[auth->fakeproto], protomaxlen);
ourdata[0] = '\0';
- for (i = 0; i < auth->len; i++)
- sprintf(ourdata + strlen(ourdata), "%02x", auth->data[i]);
+ for (i = 0; i < auth->fakelen; i++)
+ sprintf(ourdata + strlen(ourdata), "%02x", auth->fakedata[i]);
strncpy(data, ourdata, datamaxlen);
return auth;
}
+/*
+ * Fetch the real auth data for a given display string, and store
+ * it in an X11Auth structure. Returns NULL on success, or an error
+ * string.
+ */
+void x11_get_real_auth(void *authv, char *display)
+{
+ struct X11Auth *auth = (struct X11Auth *)authv;
+
+ auth->realproto = X11_NO_AUTH; /* in case next call does nothing */
+
+ auth->reallen = sizeof(auth->realdata);
+ platform_get_x11_auth(display, &auth->realproto,
+ auth->realdata, &auth->reallen);
+}
+
static int x11_verify(struct X11Auth *auth,
char *proto, unsigned char *data, int dlen)
{
- if (strcmp(proto, "MIT-MAGIC-COOKIE-1") != 0)
+ if (strcmp(proto, x11_authnames[auth->fakeproto]) != 0)
return 0; /* wrong protocol attempted */
- if (dlen != auth->len)
- return 0; /* cookie was wrong length */
- if (memcmp(auth->data, data, dlen) != 0)
- return 0; /* cookie was wrong cookie! */
+ if (auth->fakeproto == X11_MIT) {
+ if (dlen != auth->fakelen)
+ return 0; /* cookie was wrong length */
+ if (memcmp(auth->fakedata, data, dlen) != 0)
+ return 0; /* cookie was wrong cookie! */
+ }
+ /* implement other protocols here if ever required */
return 1;
}
/*
* Now we know we're going to accept the connection. Strip
- * the auth data. (TODO: if we ever work out how, we should
- * replace some real auth data in here.)
+ * the fake auth data, and optionally put real auth data in
+ * instead.
*/
- PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 6, 0); /* auth proto */
- PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 8, 0); /* auth data */
- sk_write(s, (char *)pr->firstpkt, 12);
+ {
+ char realauthdata[64];
+ int realauthlen = 0;
+ int authstrlen = strlen(x11_authnames[pr->auth->realproto]);
+ 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);
+ }
+ /* implement other auth methods here if required */
+
+ PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 6, authstrlen);
+ PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 8, realauthlen);
+
+ sk_write(s, (char *)pr->firstpkt, 12);
+
+ if (authstrlen) {
+ sk_write(s, x11_authnames[pr->auth->realproto], authstrlen);
+ sk_write(s, zeroes, 3 & (-authstrlen));
+ }
+ if (realauthlen) {
+ sk_write(s, realauthdata, realauthlen);
+ sk_write(s, zeroes, 3 & (-realauthlen));
+ }
+ }
pr->verified = 1;
}