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