putty/unix/uxagentc.c

97 строки
1.9 KiB
C

/*
* SSH agent client code.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "misc.h"
#include "puttymem.h"
#define GET_32BIT(cp) \
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
((unsigned long)(unsigned char)(cp)[1] << 16) | \
((unsigned long)(unsigned char)(cp)[2] << 8) | \
((unsigned long)(unsigned char)(cp)[3]))
int agent_exists(void)
{
if (getenv("SSH_AUTH_SOCK") != NULL)
return TRUE;
return FALSE;
}
void agent_query(void *in, int inlen, void **out, int *outlen)
{
char *name;
int sock;
struct sockaddr_un addr;
int done;
int retsize, retlen;
char sizebuf[4], *retbuf;
name = getenv("SSH_AUTH_SOCK");
if (!name)
goto failure;
sock = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket(PF_UNIX)");
exit(1);
}
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, name, sizeof(addr.sun_path));
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(sock);
goto failure;
}
for (done = 0; done < inlen ;) {
int ret = write(sock, (char *)in + done, inlen - done);
if (ret <= 0) {
close(sock);
goto failure;
}
done += ret;
}
retbuf = sizebuf;
retsize = 4;
retlen = 0;
while (retlen < retsize) {
int ret = read(sock, retbuf + retlen, retsize - retlen);
if (ret <= 0) {
close(sock);
if (retbuf != sizebuf) sfree(retbuf);
goto failure;
}
retlen += ret;
if (retsize == 4 && retlen == 4) {
retsize = GET_32BIT(retbuf);
if (retsize <= 0) {
close(sock);
goto failure;
}
retsize += 4;
assert(retbuf == sizebuf);
retbuf = smalloc(retsize);
memcpy(retbuf, sizebuf, 4);
}
}
assert(retbuf != sizebuf);
*out = retbuf;
*outlen = retlen;
return;
failure:
*out = NULL;
*outlen = 0;
}