Skip to content

Commit

Permalink
The forked agent doesn't work yet. Either I've misunderstood fork()
Browse files Browse the repository at this point in the history
or it has weird semantics on cygwin. Oh well, check it in, *then*
figure it out.
  • Loading branch information
wesleyd committed Nov 23, 2009
1 parent a782c78 commit 6283aec
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 87 deletions.
2 changes: 2 additions & 0 deletions TODO
Expand Up @@ -7,3 +7,5 @@ o Deal with partial messages from ssh - unlikely, but catastrophic!
+ Look at length at beginning, block until length arrives.
o Check open files in each process that results
o Signal handling
o Specified agent socket
o Redirect stderr (& stdout?) to log even 'pon fork
176 changes: 89 additions & 87 deletions charade.c
Expand Up @@ -22,6 +22,7 @@

#include "cmdline.h"
#include "eprintf.h"
#include "todo.h"

#define LISTEN_BACKLOG 5
#define BUFSIZE 8192
Expand Down Expand Up @@ -122,10 +123,6 @@ remove_socket(void) /* atexit handler */
void
create_socket(void)
{
#if 0
if (agentsocket == NULL) {
#endif

if (atexit(remove_socket_dir)) {
EPRINTF(0, "Can't install atexit handler to delete socket dir.\n");
exit(1);
Expand All @@ -134,9 +131,8 @@ create_socket(void)
/* Create private directory for agent socket */
strlcpy(socket_dir, "/tmp/ssh-XXXXXXXXXX", sizeof socket_dir);
if (mkdtemp(socket_dir) == NULL) {
EPRINTF(0, "Can't mkdir private socket directory: %s\n",
EPRINTF(0, "Can't mkdir socket directory: %s\n",
strerror(errno));
//perror("mkdtemp: private socket dir");
exit(1);
}

Expand All @@ -146,24 +142,14 @@ create_socket(void)
"%s/agent.%ld", socket_dir, (long)getpid());
if (ret >= sizeof(socket_name)) {
// Would have liked to print more...
fprintf(stderr, "socket_name too long (%d >= %d).\n",
EPRINTF(0, "socket_name too long (%d >= %d).\n",
ret, sizeof(socket_name));
exit(1);
}


#if 0
} else {
/* Try to use specified agent socket */
socket_dir[0] = '\0';
strlcpy(socket_name, agentsocket, sizeof socket_name);
}
#endif


listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (listen_sock < 0) {
perror("socket");
EPRINTF(0, "socket error: %s.\n", strerror(errno));
exit(1);
}

Expand All @@ -173,20 +159,20 @@ create_socket(void)
strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
int prev_mask = umask(0177);
if (bind(listen_sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) {
perror("bind");
EPRINTF(0, "bind() error: %s.\n", strerror(errno));
umask(prev_mask);
exit(1);
}

if (atexit(remove_socket)) {
fprintf(stderr, "Can't install atexit handler to delete socket '%s'. "
"Do it yourself!\n", socket_name);
EPRINTF(0, "Can't install atexit handler to delete socket '%s'; "
"do it yourself!\n", socket_name);
exit(1);
}

umask(prev_mask);
if (listen(listen_sock, LISTEN_BACKLOG) < 0) {
perror("listen");
EPRINTF(0, "listen() error: %s", strerror(errno));
exit(1);
}
}
Expand Down Expand Up @@ -250,42 +236,6 @@ print_env_stuff(int pid)
print_env_var(SSH_AGENTPID_ENV_NAME, itoa_unsafe(pid));
}

void
fork_subprocess(void)
{
if (! g_dontfork_flag) {
long pid = fork();

if (-1 == pid) {
perror("fork");
exit(1);
}

if (pid) { // Parent
printf("%s=%s; export %s\n", SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf("%s=%ld; export %s\n", SSH_AGENTPID_ENV_NAME, (long) pid,
SSH_AGENTPID_ENV_NAME);

// TODO: If argv present, fork and exec it. Only do above if no args.

remove_socket_at_exit = 0;
exit(0);
}
// Child
if (setsid() == -1) {
perror("setsid");
}
} else {
int pid = getpid();

printf("%s=%s; export %s\n", SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf("%s=%ld; export %s\n", SSH_AGENTPID_ENV_NAME, (long) pid,
SSH_AGENTPID_ENV_NAME);
}
}

int
make_poll_fds(struct pollfd **fds)
{
Expand All @@ -295,7 +245,7 @@ make_poll_fds(struct pollfd **fds)
struct pollfd *pollfds = calloc(sizeof(struct pollfd), nfds);

if (!pollfds) {
fprintf(stderr, "Can't calloc struct pollfd's for poll().\n");
EPRINTF(0, "Can't calloc() %d struct pollfd's for poll().\n", nfds);
exit(1);
}

Expand All @@ -307,14 +257,15 @@ make_poll_fds(struct pollfd **fds)
for (p = socklist.tqh_first; p != NULL; p = p->next.tqe_next) {

if (i >= nfds) {
fprintf(stderr, "Fatal: socket list changed underneath us.\n");
EPRINTF(0, "Internal error: socket list changed beneath us.\n");
exit(1);
}

// TODO: Do we want POLLOUT and the close notifications too???

pollfds[i].events = POLLIN | POLLHUP;
pollfds[i].fd = p->fd;
++i;
}

*fds = pollfds;
Expand All @@ -332,15 +283,14 @@ set_nonblock(int sock)
{
int flags = fcntl(sock, F_GETFL, 0);
if (flags < 0) {
fprintf(stderr, "fcntl(%d, F_GETFL, 0): %s.\n", sock, strerror(errno));
EPRINTF(0, "Can't fcntl(%d, F_GETFL, 0): %s.\n", sock, strerror(errno));
exit(1);
}

flags |= O_NONBLOCK;

if (fcntl(sock, F_SETFL, flags) == -1) {
fprintf(stderr, "fcntl(%d, F_SETFL, O_NONBLOCK): %s.\n",
sock, strerror(errno));
EPRINTF(0, "fcntl(%d, F_SETFL, O_NONBLOCK): %s.\n", sock, strerror(errno));
exit(1);
}
}
Expand All @@ -353,7 +303,7 @@ accept_new_socket(void)
int newsock = accept(listen_sock, (struct sockaddr *) &sunaddr, &socksize);

if (-1 == newsock) {
perror("accept");
EPRINTF(0, "accept error: %s", strerror(errno));
exit(1);
}

Expand All @@ -365,9 +315,10 @@ accept_new_socket(void)
void
fd_is_closed(int fd)
{
EPRINTF(3, "Removing fd %d from list.\n", fd);
// Remove it from the list...

// TODO: Remove the fd from the big list!
// Remove the fd from the list...
struct socklist_node_t *p;
for (p = socklist.tqh_first; p != NULL; p = p->next.tqe_next) {
if (p->fd == fd) {
Expand All @@ -385,6 +336,8 @@ fd_is_closed(int fd)
int
send_request_to_pageant(byte *buf, int numbytes, int bufsize)
{
EPRINTF(3, "Sending %d bytes to pageant.\n", numbytes);

// Now, let's just *assume* that it'll arrive in one big
// chunk and just *send* it to pageant...
HWND hwnd;
Expand All @@ -406,8 +359,8 @@ send_request_to_pageant(byte *buf, int numbytes, int bufsize)
return 0;
}

byte *p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
memcpy(p, buf, numbytes);
byte *shmem = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
memcpy(shmem, buf, numbytes);
COPYDATASTRUCT cds;
cds.dwData = AGENT_COPYDATA_ID;
cds.cbData = 1 + strlen(mapname);
Expand All @@ -416,22 +369,23 @@ send_request_to_pageant(byte *buf, int numbytes, int bufsize)
int id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
int retlen = 0;
if (id > 0) {
retlen = 4 + GET_32BIT(p);
retlen = 4 + GET_32BIT(shmem);
if (retlen > bufsize) {
EPRINTF(0, "Buffer too small to contain reply from pageant.\n");
return 0;
}

// TODO: are there miscounting errors here?

memcpy(buf, p, retlen);
memcpy(buf, shmem, retlen);
} else {
EPRINTF(0, "Couldn't SendMessage().\n");
return 0;
}
UnmapViewOfFile(p);

UnmapViewOfFile(shmem);
CloseHandle(filemap);

EPRINTF(3, "Got %d bytes back from pageant.\n", retlen);

return retlen;
}

Expand All @@ -448,38 +402,50 @@ deal_with_ready_fds(struct pollfd *fds, int nfds)
// Don't just *assume* that entry 0 is listen_sock...
if (listen_sock == fds[i].fd) {
accept_new_socket();
} else {
} else if (fds[i].revents & POLLIN) {
// Deal with data from fds[i].fd...
const size_t count = BUFSIZE;
byte buf[BUFSIZE];

ssize_t numbytes = read(fds[i].fd, buf, count);

if (0 == numbytes) {
close(fds[i].fd);
fd_is_closed(fds[i].fd);
} else if (-1 == numbytes) {
fprintf(stderr, "TODO: fd %d error, errno is %s.\n", fds[i].fd, strerror(errno));
exit(1);
// TODO: Should we handle EAGAIN/EWOULDBLOCK specially?
EPRINTF(0, "internal error: read(fd=%d) => errno=%d/%s.\n",
fds[i].fd, errno, strerror(errno));
close(fds[i].fd);
fd_is_closed(fds[i].fd);
} else {
int retlen = send_request_to_pageant(buf, numbytes, sizeof(buf));

// Now, send buf back to the socket. We should probably
// loop and retry or use poll properly since it's nonblocking...
ssize_t byteswritten = write(fds[i].fd, buf, retlen);
if (byteswritten != retlen) {
fprintf(stderr, "Tried to write %d bytes, "
"ended up writing %d. Quitting.\n",
EPRINTF(0, "Tried to write %d bytes, "
"ended up writing %d.\n",
retlen, byteswritten);
exit(1);
close(fds[i].fd);
fd_is_closed(fds[i].fd);
}
}
}
} else {
EPRINTF(0, "Don't know how to deal with revents=0x%x on fd %d.\n",
fds[i].revents, fds[i].fd);
close(fds[i].fd);
fd_is_closed(fds[i].fd);
}
}
}

void
handle_key_requests_forever(void)
{
EPRINTF(5, "entry.\n");

for (;;) {
struct pollfd *fds;
int nfds = make_poll_fds(&fds);
Expand All @@ -493,11 +459,11 @@ handle_key_requests_forever(void)
EPRINTF(3, "poll() was EINTR-ed.\n");
continue;
} else {
perror("poll error");
EPRINTF(0, "poll error: %s.\n", strerror(errno));
exit(1);
}
} else if (0 == numready) {
fprintf(stderr, "Error: poll() => 0, but no timeout was set.\n");
EPRINTF(0, "Internal error: poll() => 0, but no timeout was set.\n");
exit(1);
}

Expand All @@ -508,15 +474,49 @@ handle_key_requests_forever(void)
pid_t
fork_off_key_handler(void)
{
fprintf(stderr, "TODO: fork_off_key_handler.\n");
exit(1);
pid_t handler_pid = fork();
if (handler_pid == -1) {
EPRINTF(0, "Can't fork(): %s.\n", strerror(errno));
exit(1);
}

if (handler_pid != 0) {
return handler_pid;
}

// OK, we're the child agent process now...

FILE *f = fopen("/tmp/loggy", "w");

fprintf(f, "Hello.\n");
fflush(f);

// TODO: Do the setsid thing
/*
if (setsid() == -1) {
EPRINTF(0, "error from setsid(): %s.\n", strerror(errno));
exit(1);
}
*/

chdir("/");

// TODO: Do the filehandle thing

// TODO: Do setrlimit thing

// TODO: Do the signal thing

handle_key_requests_forever();

/* NOTREACHED */
exit(0);
}

void
exec_subprocess(void)
exec_subprocess(pid_t agent_pid)
{
fprintf(stderr, "TODO: exec_subprocess.\n");
exit(1);
TODO();
}

int
Expand Down Expand Up @@ -544,8 +544,10 @@ main(int argc, char **argv)
} else {
pid_t agent_pid = fork_off_key_handler();

close(listen_sock);

if (g_subprocess_argc) {
exec_subprocess();
exec_subprocess(agent_pid);
/* NOTREACHED */
} else {
print_env_stuff(agent_pid);
Expand Down
8 changes: 8 additions & 0 deletions todo.h
@@ -0,0 +1,8 @@
#ifndef TODO_H
#define TODO_H

#include "eprintf.h"

#define TODO() do { EPRINTF(0, "TODO.\n"); exit(1); } while (1)

#endif // #ifndef TODO_H

0 comments on commit 6283aec

Please sign in to comment.