1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

Introduce framework for authenticating with the local X server.

Windows and Mac backends have acquired auth-finding functions which
do nothing; Unix backend has acquired one which actually works, so
Plink can now do X forwarding believably.
(This checkin stretches into some unlikely parts of the code because
there have been one or two knock-on effects involving `const'. Bah.)

[originally from svn r2536]
This commit is contained in:
Simon Tatham 2003-01-10 18:33:35 +00:00
parent 2e8b94c8d4
commit 86977efa81
14 changed files with 229 additions and 36 deletions

4
Recipe
View File

@ -109,7 +109,7 @@ SFTP = sftp int64 logging
# 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
@ -145,7 +145,7 @@ puttygen : [G] puttygen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version
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

View File

@ -1,4 +1,4 @@
/* $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.
@ -740,6 +740,12 @@ int platform_default_i(char *name, int def)
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"

4
misc.c
View File

@ -174,9 +174,9 @@ int bufchain_size(bufchain *ch)
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;

2
misc.h
View File

@ -28,7 +28,7 @@ typedef struct bufchain_tag {
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);

View File

@ -24,8 +24,8 @@ struct socket_function_table {
/* 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);

View File

@ -91,7 +91,7 @@ static void sk_proxy_close (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;
@ -102,7 +102,7 @@ static int sk_proxy_write (Socket s, char *data, int len)
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;

10
putty.h
View File

@ -691,4 +691,14 @@ extern int cmdline_tooltype;
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

2
ssh.c
View File

@ -3019,6 +3019,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
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,
@ -5068,6 +5069,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
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");

1
ssh.h
View File

@ -273,6 +273,7 @@ extern void *x11_invent_auth(char *, int, char *, int);
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);

106
unix/ux_x11.c Normal file
View File

@ -0,0 +1,106 @@
/*
* 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);
}

View File

@ -298,8 +298,8 @@ static void sk_tcp_flush(Socket s)
}
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);
@ -726,7 +726,7 @@ void try_send(Actual_Socket s)
}
}
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;
@ -744,7 +744,7 @@ static int sk_tcp_write(Socket sock, char *buf, int len)
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;

14
winmisc.c Normal file
View File

@ -0,0 +1,14 @@
/*
* 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. */
}

View File

@ -460,8 +460,8 @@ static void sk_tcp_flush(Socket s)
}
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);
@ -924,7 +924,7 @@ void try_send(Actual_Socket s)
}
}
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;
@ -942,7 +942,7 @@ static int sk_tcp_write(Socket sock, char *buf, int len)
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;

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "putty.h"
#include "ssh.h"
@ -50,11 +51,19 @@
#define PUT_16BIT(endian, cp, val) \
(endian=='B' ? PUT_16BIT_MSB_FIRST(cp, val) : PUT_16BIT_LSB_FIRST(cp, val))
struct X11Auth {
unsigned char data[64];
int len;
const char *const x11_authnames[] = {
"", "MIT-MAGIC-COOKIE-1"
};
struct X11Auth {
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 */
@ -76,30 +85,51 @@ void *x11_invent_auth(char *proto, int protomaxlen,
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;
}
@ -344,12 +374,36 @@ int x11_send(Socket s, char *data, int len)
/*
* 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;
}