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
);