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