2 * SSH agent client code.
\r
9 #include <sys/socket.h>
\r
15 #include "tree234.h"
\r
16 #include "puttymem.h"
\r
18 int agent_exists(void)
\r
20 const char *p = getenv("SSH_AUTH_SOCK");
\r
26 static tree234 *agent_connections;
\r
27 struct agent_connection {
\r
31 int retsize, retlen;
\r
32 void (*callback)(void *, void *, int);
\r
35 static int agent_conncmp(void *av, void *bv)
\r
37 struct agent_connection *a = (struct agent_connection *) av;
\r
38 struct agent_connection *b = (struct agent_connection *) bv;
\r
45 static int agent_connfind(void *av, void *bv)
\r
47 int afd = *(int *) av;
\r
48 struct agent_connection *b = (struct agent_connection *) bv;
\r
56 static int agent_select_result(int fd, int event)
\r
59 struct agent_connection *conn;
\r
61 assert(event == 1); /* not selecting for anything but R */
\r
63 conn = find234(agent_connections, &fd, agent_connfind);
\r
69 ret = read(fd, conn->retbuf+conn->retlen, conn->retsize-conn->retlen);
\r
71 if (conn->retbuf != conn->sizebuf) sfree(conn->retbuf);
\r
72 conn->retbuf = NULL;
\r
76 conn->retlen += ret;
\r
77 if (conn->retsize == 4 && conn->retlen == 4) {
\r
78 conn->retsize = toint(GET_32BIT(conn->retbuf) + 4);
\r
79 if (conn->retsize <= 0) {
\r
80 conn->retbuf = NULL;
\r
84 assert(conn->retbuf == conn->sizebuf);
\r
85 conn->retbuf = snewn(conn->retsize, char);
\r
86 memcpy(conn->retbuf, conn->sizebuf, 4);
\r
89 if (conn->retlen < conn->retsize)
\r
90 return 0; /* more data to come */
\r
94 * We have now completed the agent query. Do the callback, and
\r
95 * clean up. (Of course we don't free retbuf, since ownership
\r
96 * of that passes to the callback.)
\r
98 conn->callback(conn->callback_ctx, conn->retbuf, conn->retlen);
\r
101 del234(agent_connections, conn);
\r
106 int agent_query(void *in, int inlen, void **out, int *outlen,
\r
107 void (*callback)(void *, void *, int), void *callback_ctx)
\r
111 struct sockaddr_un addr;
\r
113 struct agent_connection *conn;
\r
115 name = getenv("SSH_AUTH_SOCK");
\r
119 sock = socket(PF_UNIX, SOCK_STREAM, 0);
\r
121 perror("socket(PF_UNIX)");
\r
127 addr.sun_family = AF_UNIX;
\r
128 strncpy(addr.sun_path, name, sizeof(addr.sun_path));
\r
129 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
\r
134 for (done = 0; done < inlen ;) {
\r
135 int ret = write(sock, (char *)in + done, inlen - done);
\r
143 if (!agent_connections)
\r
144 agent_connections = newtree234(agent_conncmp);
\r
146 conn = snew(struct agent_connection);
\r
148 conn->retbuf = conn->sizebuf;
\r
151 conn->callback = callback;
\r
152 conn->callback_ctx = callback_ctx;
\r
153 add234(agent_connections, conn);
\r
155 uxsel_set(sock, 1, agent_select_result);
\r