]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/uxagentc.c
af56f1b8a839483d32da0a374f7cdcb9357a67e4
[PuTTY.git] / unix / uxagentc.c
1 /*
2  * SSH agent client code.
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <assert.h>
8 #include <unistd.h>
9 #include <sys/socket.h>
10 #include <sys/un.h>
11
12 #include "misc.h"
13 #include "puttymem.h"
14
15 #define GET_32BIT(cp) \
16     (((unsigned long)(unsigned char)(cp)[0] << 24) | \
17     ((unsigned long)(unsigned char)(cp)[1] << 16) | \
18     ((unsigned long)(unsigned char)(cp)[2] << 8) | \
19     ((unsigned long)(unsigned char)(cp)[3]))
20
21 int agent_exists(void)
22 {
23     if (getenv("SSH_AUTH_SOCK") != NULL)
24         return TRUE;
25     return FALSE;
26 }
27
28 void agent_query(void *in, int inlen, void **out, int *outlen)
29 {
30     char *name;
31     int sock;
32     struct sockaddr_un addr;
33     int done;
34     int retsize, retlen;
35     char sizebuf[4], *retbuf;
36
37     name = getenv("SSH_AUTH_SOCK");
38     if (!name)
39         goto failure;
40
41     sock = socket(PF_UNIX, SOCK_STREAM, 0);
42     if (sock < 0) {
43         perror("socket(PF_UNIX)");
44         exit(1);
45     }
46
47     addr.sun_family = AF_UNIX;
48     strncpy(addr.sun_path, name, sizeof(addr.sun_path));
49     if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
50         close(sock);
51         goto failure;
52     }
53
54     for (done = 0; done < inlen ;) {
55         int ret = write(sock, (char *)in + done, inlen - done);
56         if (ret <= 0) {
57             close(sock);
58             goto failure;
59         }
60         done += ret;
61     }
62
63     retbuf = sizebuf;
64     retsize = 4;
65     retlen = 0;
66
67     while (retlen < retsize) {
68         int ret = read(sock, retbuf + retlen, retsize - retlen);
69         if (ret <= 0) {
70             close(sock);
71             if (retbuf != sizebuf) sfree(retbuf);
72             goto failure;
73         }
74         retlen += ret;
75         if (retsize == 4 && retlen == 4) {
76             retsize = GET_32BIT(retbuf);
77             if (retsize <= 0) {
78                 close(sock);
79                 goto failure;
80             }
81             retsize += 4;
82             assert(retbuf == sizebuf);
83             retbuf = smalloc(retsize);
84             memcpy(retbuf, sizebuf, 4);
85         }
86     }
87
88     assert(retbuf != sizebuf);
89     *out = retbuf;
90     *outlen = retlen;
91     return;
92
93     failure:
94     *out = NULL;
95     *outlen = 0;
96 }