2 * SSH agent client code.
9 #include <sys/socket.h>
17 int agent_exists(void)
19 if (getenv("SSH_AUTH_SOCK") != NULL)
24 static tree234 *agent_connections;
25 struct agent_connection {
30 void (*callback)(void *, void *, int);
33 static int agent_conncmp(void *av, void *bv)
35 struct agent_connection *a = (struct agent_connection *) av;
36 struct agent_connection *b = (struct agent_connection *) bv;
43 static int agent_connfind(void *av, void *bv)
45 int afd = *(int *) av;
46 struct agent_connection *b = (struct agent_connection *) bv;
54 static int agent_select_result(int fd, int event)
57 struct agent_connection *conn;
59 assert(event == 1); /* not selecting for anything but R */
61 conn = find234(agent_connections, &fd, agent_connfind);
67 ret = read(fd, conn->retbuf+conn->retlen, conn->retsize-conn->retlen);
69 if (conn->retbuf != conn->sizebuf) sfree(conn->retbuf);
75 if (conn->retsize == 4 && conn->retlen == 4) {
76 conn->retsize = GET_32BIT(conn->retbuf);
77 if (conn->retsize <= 0) {
83 assert(conn->retbuf == conn->sizebuf);
84 conn->retbuf = snewn(conn->retsize, char);
85 memcpy(conn->retbuf, conn->sizebuf, 4);
88 if (conn->retlen < conn->retsize)
89 return 0; /* more data to come */
93 * We have now completed the agent query. Do the callback, and
94 * clean up. (Of course we don't free retbuf, since ownership
95 * of that passes to the callback.)
97 conn->callback(conn->callback_ctx, conn->retbuf, conn->retlen);
100 del234(agent_connections, conn);
105 int agent_query(void *in, int inlen, void **out, int *outlen,
106 void (*callback)(void *, void *, int), void *callback_ctx)
110 struct sockaddr_un addr;
112 struct agent_connection *conn;
114 name = getenv("SSH_AUTH_SOCK");
118 sock = socket(PF_UNIX, SOCK_STREAM, 0);
120 perror("socket(PF_UNIX)");
124 addr.sun_family = AF_UNIX;
125 strncpy(addr.sun_path, name, sizeof(addr.sun_path));
126 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
131 for (done = 0; done < inlen ;) {
132 int ret = write(sock, (char *)in + done, inlen - done);
140 if (!agent_connections)
141 agent_connections = newtree234(agent_conncmp);
143 conn = snew(struct agent_connection);
145 conn->retbuf = conn->sizebuf;
148 conn->callback = callback;
149 conn->callback_ctx = callback_ctx;
150 add234(agent_connections, conn);
152 uxsel_set(sock, 1, agent_select_result);