Re: Transferring ownership of SSH connection from process A to B, letting A quit nicely?
On Wednesday, August 11th, 2021 at 7:57 AM, m brandenberg wrote: > Check msg.msg_flags here. I think you will receive a hint. msg_flags is always zero. Seems okay, after all, the FDs are received correctly.
Re: Transferring ownership of SSH connection from process A to B, letting A quit nicely?
On Tue, Aug 10, 2021 at 12:13 PM mid wrote: > On Monday, August 9th, 2021 at 5:36 AM, Philip Guenther < > guent...@gmail.com> wrote: > > > If you're 100% sure you have it right, then it should be easy to provide > a > > program that demonstrates > > 1. passing an fd between processes > > 2. using it successfully in the receiving process > > 3. the sending process exiting > > 4. attempts to us it failing the receiving process > > Not 100%, but I'm out of ideas, so here goes nothing. > > client.c (process A): > ... > Compiled with: > cc -std=c99 -o server server.c > cc -std=c99 -o client client.c > > `client` is also the shell of the user, but the results are the same if > I call it from within a "real" shell, too. > > The server receives the correct FDs, and prints > "Hello from the Server\n" correctly, too. But as soon as `client` > exits, the SSH connection goes with it, instead of staying (as in, > I get "Connection to localhost closed"). > Your problems have nothing to do with fd passing but rather are around not understanding how session management works. The client is passing its stdin/stdout, which are either pipes or a pseudo-tty connected to the ssh server and NOT the actual TCP socket carrying the ssh connection. When the session leader process exits the kernel will perform various cleanup operations (block tty access, send some signals). If you _really_ want to hack around in this area, you need to do a bunch of reading and research. I recommend buying/borrowing a copy of _Advanced_Programming_in_the_UNIX_Environment_ by W. Richard Stevens. Philip Guenther
Re: Transferring ownership of SSH connection from process A to B, letting A quit nicely?
On Tue, 10 Aug 2021, mid wrote: len = recvmsg(socket, &msg, 0); if(len <= 0) { return -1; } Check msg.msg_flags here. I think you will receive a hint. -- Monty Brandenberg
Re: Transferring ownership of SSH connection from process A to B, letting A quit nicely?
On Monday, August 9th, 2021 at 5:36 AM, Philip Guenther wrote: > If you're 100% sure you have it right, then it should be easy to provide a > program that demonstrates > 1. passing an fd between processes > 2. using it successfully in the receiving process > 3. the sending process exiting > 4. attempts to us it failing the receiving process Not 100%, but I'm out of ideas, so here goes nothing. client.c (process A): #include #include #include #include #include int sendfd(int sock, int fd) { struct msghdr msg; struct iovec iov[1]; struct cmsghdr *cmsg = NULL; char ctrl_buf[CMSG_SPACE(sizeof(int))]; char data[1]; memset(&msg, 0, sizeof(struct msghdr)); memset(ctrl_buf, 0, CMSG_SPACE(sizeof(int))); data[0] = ' '; iov[0].iov_base = data; iov[0].iov_len = sizeof(data); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_controllen = CMSG_SPACE(sizeof(int)); msg.msg_control = ctrl_buf; cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); *((int*) CMSG_DATA(cmsg)) = fd; return sendmsg(sock, &msg, 0); } int main(int argc, char **argv) { int c = socket(AF_UNIX, SOCK_STREAM, 0); assert(c != -1); struct sockaddr_un a; a.sun_family = AF_UNIX; strcpy(a.sun_path, "/service/sock"); assert(connect(c, (struct sockaddr*) &a, sizeof(a)) != -1); sendfd(c, 0); sendfd(c, 1); close(c); /* The SSH conn should stay after returning, but it doesn't. */ } server.c (process B): #include #include #include #include #include #include #include int recvfd(int socket) { int len; int fd; char buf[1]; struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; char cms[CMSG_SPACE(sizeof(int))]; iov.iov_base = buf; iov.iov_len = sizeof(buf); msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = (caddr_t) cms; msg.msg_controllen = sizeof(cms); len = recvmsg(socket, &msg, 0); if(len <= 0) { return -1; } cmsg = CMSG_FIRSTHDR(&msg); memmove(&fd, CMSG_DATA(cmsg), sizeof(int)); return fd; } int main(int argc, char **argv) { unlink("/service/sock"); int s = socket(AF_UNIX, SOCK_STREAM, 0); assert(s != -1); struct sockaddr_un a; a.sun_family = AF_UNIX; strcpy(a.sun_path, "/service/sock"); assert(bind(s, (struct sockaddr*) &a, sizeof(a)) != -1); assert(chmod("/service/sock", 0777) != -1); /* Quick workaround. */ assert(listen(s, 20) != -1); while(1) { puts("Waiting.."); int c = accept(s, NULL, NULL); assert(c != -1); puts("Accepted"); int in = recvfd(c); int out = recvfd(c); printf("Received: in=%i out=%i\n", in, out); char *outstr = "Hello from the Server\n"; assert(write(out, outstr, strlen(outstr)) != -1); assert(close(c) != -1); /* Intentionally leaking SSH FDs */ } } Compiled with: cc -std=c99 -o server server.c cc -std=c99 -o client client.c `client` is also the shell of the user, but the results are the same if I call it from within a "real" shell, too. The server receives the correct FDs, and prints "Hello from the Server\n" correctly, too. But as soon as `client` exits, the SSH connection goes with it, instead of staying (as in, I get "Connection to localhost closed").
Re: Transferring ownership of SSH connection from process A to B, letting A quit nicely?
On Sun, Aug 8, 2021 at 10:13 AM mid wrote: ... > I have tried sending the file descriptors associated with the connection > to process B via sendmsg, thinking that maybe the > file descriptors are reference-counted. It's a logical > assumption, but it didn't work - the connection closed with > process A. > File descriptors sent via sendmsg() on a unix domain socket of SCM_RIGHTS control messages *are* reference-counted. If you think you've done that and it's not behaving as expected, then first check and report errors on *all* the system calls, and that the returned data fields on things like recvmsg() have the values you expect. If sendmsg() is failing or you're accidentally discarding the fds in the recvmsg() by not providing the space needed then yeah, the fds will be closed because the last reference is gone. If you're 100% sure you have it right, then it should be easy to provide a program that demonstrates 1) passing an fd between processes 2) using it *successfully* in the receiving process 3) the sending process exiting 3) attempts to us it failing the receiving process No? Philip (Replies not on the list will be deleted)
Transferring ownership of SSH connection from process A to B, letting A quit nicely?
Hello. I have an interesting conundrum I'm dealing with, and would like some ideas on getting it to work. I'm making a useless service for recreational purposes, and it involves holding many SSH connections at once. Ideally said service should be composed of only one process, accepting multiple clients, since they interact with each other in (mostly) real-time, unlike a typical web server. But because of how SSH works, each connection sits behind yet another process. I'd have to employ some IPC for it to work, but would end up making it a lot less scalable. What I wanted was so that each connection would invoke the SSH shell (process A), and said shell would somehow pass ownership of the connection to the main server process (process B). Afterwards, process A could safely exit, leaving the SSH connection intact. This would mean process B would be in charge of multiple SSH connections. I have tried sending the file descriptors associated with the connection to process B via sendmsg, thinking that maybe the file descriptors are reference-counted. It's a logical assumption, but it didn't work - the connection closed with process A. I have also tried opening a /dev/ttyp* file corresponding to the connection, but that didn't work either. So is this not possible under OpenBSD's semantics? Scalability is not a real issue, but having IPC adds a load of complexity I'd rather not get involved with. Thanks.