+/* Do-nothing "plug" implementation, used by x11_setup_display() when it
+ * creates a trial connection (and then immediately closes it).
+ * XXX: bit out of place here, could in principle live in a platform-
+ * independent network.c or something */
+static void dummy_plug_log(Plug p, int type, SockAddr addr, int port,
+ const char *error_msg, int error_code) { }
+static int dummy_plug_closing
+ (Plug p, const char *error_msg, int error_code, int calling_back)
+{ return 1; }
+static int dummy_plug_receive(Plug p, int urgent, char *data, int len)
+{ return 1; }
+static void dummy_plug_sent(Plug p, int bufsize) { }
+static int dummy_plug_accepting(Plug p, accept_fn_t constructor, accept_ctx_t ctx) { return 1; }
+static const struct plug_function_table dummy_plug = {
+ dummy_plug_log, dummy_plug_closing, dummy_plug_receive,
+ dummy_plug_sent, dummy_plug_accepting
+};
+
+struct X11FakeAuth *x11_invent_fake_auth(tree234 *authtree, int authtype)
+{
+ struct X11FakeAuth *auth = snew(struct X11FakeAuth);
+ int i;
+
+ /*
+ * This function has the job of inventing a set of X11 fake auth
+ * data, and adding it to 'authtree'. We must preserve the
+ * property that for any given actual authorisation attempt, _at
+ * most one_ thing in the tree can possibly match it.
+ *
+ * For MIT-MAGIC-COOKIE-1, that's not too difficult: the match
+ * criterion is simply that the entire cookie is correct, so we
+ * just have to make sure we don't make up two cookies the same.
+ * (Vanishingly unlikely, but we check anyway to be sure, and go
+ * round again inventing a new cookie if add234 tells us the one
+ * we thought of is already in use.)
+ *
+ * For XDM-AUTHORIZATION-1, it's a little more fiddly. The setup
+ * with XA1 is that half the cookie is used as a DES key with
+ * which to CBC-encrypt an assortment of stuff. Happily, the stuff
+ * encrypted _begins_ with the other half of the cookie, and the
+ * IV is always zero, which means that any valid XA1 authorisation
+ * attempt for a given cookie must begin with the same cipher
+ * block, consisting of the DES ECB encryption of the first half
+ * of the cookie using the second half as a key. So we compute
+ * that cipher block here and now, and use it as the sorting key
+ * for distinguishing XA1 entries in the tree.
+ */
+
+ if (authtype == X11_MIT) {
+ auth->proto = X11_MIT;
+
+ /* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
+ auth->datalen = 16;
+ auth->data = snewn(auth->datalen, unsigned char);
+ auth->xa1_firstblock = NULL;
+
+ while (1) {
+ for (i = 0; i < auth->datalen; i++)
+ auth->data[i] = random_byte();
+ if (add234(authtree, auth) == auth)
+ break;
+ }
+
+ auth->xdmseen = NULL;
+ } else {
+ assert(authtype == X11_XDM);
+ auth->proto = X11_XDM;
+
+ /* XDM-AUTHORIZATION-1. Cookie size is 16 bytes; byte 8 is zero. */
+ auth->datalen = 16;
+ auth->data = snewn(auth->datalen, unsigned char);
+ auth->xa1_firstblock = snewn(8, unsigned char);
+ memset(auth->xa1_firstblock, 0, 8);
+
+ while (1) {
+ for (i = 0; i < auth->datalen; i++)
+ auth->data[i] = (i == 8 ? 0 : random_byte());
+ memcpy(auth->xa1_firstblock, auth->data, 8);
+ des_encrypt_xdmauth(auth->data + 9, auth->xa1_firstblock, 8);
+ if (add234(authtree, auth) == auth)
+ break;
+ }
+
+ auth->xdmseen = newtree234(xdmseen_cmp);
+ }
+ auth->protoname = dupstr(x11_authnames[auth->proto]);
+ auth->datastring = snewn(auth->datalen * 2 + 1, char);
+ for (i = 0; i < auth->datalen; i++)
+ sprintf(auth->datastring + i*2, "%02x",
+ auth->data[i]);
+
+ auth->disp = NULL;
+ auth->share_cs = auth->share_chan = NULL;
+
+ return auth;
+}
+
+void x11_free_fake_auth(struct X11FakeAuth *auth)
+{
+ if (auth->data)
+ smemclr(auth->data, auth->datalen);
+ sfree(auth->data);
+ sfree(auth->protoname);
+ sfree(auth->datastring);
+ sfree(auth->xa1_firstblock);
+ if (auth->xdmseen != NULL) {
+ struct XDMSeen *seen;
+ while ((seen = delpos234(auth->xdmseen, 0)) != NULL)
+ sfree(seen);
+ freetree234(auth->xdmseen);
+ }
+ sfree(auth);
+}
+
+int x11_authcmp(void *av, void *bv)
+{
+ struct X11FakeAuth *a = (struct X11FakeAuth *)av;
+ struct X11FakeAuth *b = (struct X11FakeAuth *)bv;
+
+ if (a->proto < b->proto)
+ return -1;
+ else if (a->proto > b->proto)
+ return +1;
+
+ if (a->proto == X11_MIT) {
+ if (a->datalen < b->datalen)
+ return -1;
+ else if (a->datalen > b->datalen)
+ return +1;
+
+ return memcmp(a->data, b->data, a->datalen);
+ } else {
+ assert(a->proto == X11_XDM);
+
+ return memcmp(a->xa1_firstblock, b->xa1_firstblock, 8);
+ }
+}
+
+struct X11Display *x11_setup_display(const char *display, Conf *conf)