2 * SSH agent client code.
9 #include <sys/socket.h>
18 int agent_exists(void)
20 const char *p
= getenv("SSH_AUTH_SOCK");
26 static tree234
*agent_connections
;
27 struct agent_connection
{
32 void (*callback
)(void *, void *, int);
35 static int agent_conncmp(void *av
, void *bv
)
37 struct agent_connection
*a
= (struct agent_connection
*) av
;
38 struct agent_connection
*b
= (struct agent_connection
*) bv
;
45 static int agent_connfind(void *av
, void *bv
)
47 int afd
= *(int *) av
;
48 struct agent_connection
*b
= (struct agent_connection
*) bv
;
56 static int agent_select_result(int fd
, int event
)
59 struct agent_connection
*conn
;
61 assert(event
== 1); /* not selecting for anything but R */
63 conn
= find234(agent_connections
, &fd
, agent_connfind
);
69 ret
= read(fd
, conn
->retbuf
+conn
->retlen
, conn
->retsize
-conn
->retlen
);
71 if (conn
->retbuf
!= conn
->sizebuf
) sfree(conn
->retbuf
);
77 if (conn
->retsize
== 4 && conn
->retlen
== 4) {
78 conn
->retsize
= GET_32BIT(conn
->retbuf
);
79 if (conn
->retsize
<= 0) {
85 assert(conn
->retbuf
== conn
->sizebuf
);
86 conn
->retbuf
= snewn(conn
->retsize
, char);
87 memcpy(conn
->retbuf
, conn
->sizebuf
, 4);
90 if (conn
->retlen
< conn
->retsize
)
91 return 0; /* more data to come */
95 * We have now completed the agent query. Do the callback, and
96 * clean up. (Of course we don't free retbuf, since ownership
97 * of that passes to the callback.)
99 conn
->callback(conn
->callback_ctx
, conn
->retbuf
, conn
->retlen
);
102 del234(agent_connections
, conn
);
107 int agent_query(void *in
, int inlen
, void **out
, int *outlen
,
108 void (*callback
)(void *, void *, int), void *callback_ctx
)
112 struct sockaddr_un addr
;
114 struct agent_connection
*conn
;
116 name
= getenv("SSH_AUTH_SOCK");
120 sock
= socket(PF_UNIX
, SOCK_STREAM
, 0);
122 perror("socket(PF_UNIX)");
128 addr
.sun_family
= AF_UNIX
;
129 strncpy(addr
.sun_path
, name
, sizeof(addr
.sun_path
));
130 if (connect(sock
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
135 for (done
= 0; done
< inlen
;) {
136 int ret
= write(sock
, (char *)in
+ done
, inlen
- done
);
144 if (!agent_connections
)
145 agent_connections
= newtree234(agent_conncmp
);
147 conn
= snew(struct agent_connection
);
149 conn
->retbuf
= conn
->sizebuf
;
152 conn
->callback
= callback
;
153 conn
->callback_ctx
= callback_ctx
;
154 add234(agent_connections
, conn
);
156 uxsel_set(sock
, 1, agent_select_result
);