2 * SSH agent client code.
9 #include <sys/socket.h>
17 #define GET_32BIT(cp) \
18 (((unsigned long)(unsigned char)(cp)[0] << 24) | \
19 ((unsigned long)(unsigned char)(cp)[1] << 16) | \
20 ((unsigned long)(unsigned char)(cp)[2] << 8) | \
21 ((unsigned long)(unsigned char)(cp)[3]))
23 int agent_exists(void)
25 if (getenv("SSH_AUTH_SOCK") != NULL)
30 static tree234 *agent_connections;
31 struct agent_connection {
36 void (*callback)(void *, void *, int);
39 static int agent_conncmp(void *av, void *bv)
41 struct agent_connection *a = (struct agent_connection *) av;
42 struct agent_connection *b = (struct agent_connection *) bv;
49 static int agent_connfind(void *av, void *bv)
51 int afd = *(int *) av;
52 struct agent_connection *b = (struct agent_connection *) bv;
60 static int agent_select_result(int fd, int event)
63 struct agent_connection *conn;
65 assert(event == 1); /* not selecting for anything but R */
67 conn = find234(agent_connections, &fd, agent_connfind);
73 ret = read(fd, conn->retbuf+conn->retlen, conn->retsize-conn->retlen);
75 if (conn->retbuf != conn->sizebuf) sfree(conn->retbuf);
81 if (conn->retsize == 4 && conn->retlen == 4) {
82 conn->retsize = GET_32BIT(conn->retbuf);
83 if (conn->retsize <= 0) {
89 assert(conn->retbuf == conn->sizebuf);
90 conn->retbuf = snewn(conn->retsize, char);
91 memcpy(conn->retbuf, conn->sizebuf, 4);
94 if (conn->retlen < conn->retsize)
95 return 0; /* more data to come */
99 * We have now completed the agent query. Do the callback, and
100 * clean up. (Of course we don't free retbuf, since ownership
101 * of that passes to the callback.)
103 conn->callback(conn->callback_ctx, conn->retbuf, conn->retlen);
106 del234(agent_connections, conn);
111 int agent_query(void *in, int inlen, void **out, int *outlen,
112 void (*callback)(void *, void *, int), void *callback_ctx)
116 struct sockaddr_un addr;
118 struct agent_connection *conn;
120 name = getenv("SSH_AUTH_SOCK");
124 sock = socket(PF_UNIX, SOCK_STREAM, 0);
126 perror("socket(PF_UNIX)");
130 addr.sun_family = AF_UNIX;
131 strncpy(addr.sun_path, name, sizeof(addr.sun_path));
132 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
137 for (done = 0; done < inlen ;) {
138 int ret = write(sock, (char *)in + done, inlen - done);
146 if (!agent_connections)
147 agent_connections = newtree234(agent_conncmp);
149 conn = snew(struct agent_connection);
151 conn->retbuf = conn->sizebuf;
154 conn->callback = callback;
155 conn->callback_ctx = callback_ctx;
156 add234(agent_connections, conn);
158 uxsel_set(sock, 1, agent_select_result);