From: Miklos S. <mi...@sz...> - 2008-03-20 10:03:46
|
> I've attached a patch that adds a prompt_password option to sshfs. > It works like this: > * password is read on stdin (enabling sshfs to work with pam_mount) > * in start_ssh: > * a pipe is created, and the password written to it > * export SSHFS_ASKPASS_FD = stdin of pipe > * export SSH_ASKPASS = LIBEXECDIR/sshfs_askpass_fd > * before execvp(), setsid() is called (otherwise ssh won't use > $SSH_ASKPASS) > * ssh calls $SSH_ASKPASS to get the password. sshfs_askpass_fd is a > shell script that simply reads the password from $SSHFS_ASKPASS_FD and > then writes it to stdout. > > This is the same way in which the python version of LDM (LTSP Display > Manager) passes the password to ssh. > > It's possible to achieve almost the same (no sshfs changes needed) by > using a shell script wrapper, but that has the downside of not working > with -o reconnect. I've also attached the script in case anyone's > interested. Interesting approach, it has a strongly hackish feel though. A better approach would be to run ssh in a pseudo terminal, and proxy I/O to stdin/out. This makes ssh believe that it's connected to a terminal and asks the password normally. I've attached a little utility that does this. If it works for you it could be integrated into sshfs. Thanks, Miklos ===File ~/cc/ptypipe.c====================================== #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <stropts.h> #include <poll.h> static int pty_master(char **pty_name) { int master_fd; master_fd = open("/dev/ptmx", O_RDWR); if(master_fd < 0) return -1; grantpt(master_fd); unlockpt(master_fd); *pty_name = ptsname(master_fd); return master_fd; } static int start_child(char *argv[]) { char *pty_name; int mfd, sfd, pid; int ctrlp[2]; char c; mfd = pty_master(&pty_name); if(mfd < 0) { fprintf(stderr, "Could not open pseudo-tty\n"); exit(1); } if(pipe(ctrlp) < 0) { fprintf(stderr, "Could not open control pipe\n"); exit(1); } pid = fork(); if(pid < 0) { fprintf(stderr, "Could not fork\n"); exit(1); } if(pid == 0) { /* Child */ close(ctrlp[0]); setsid(); sfd = open(pty_name, O_RDWR); if(sfd < 0) { write(ctrlp[1], "f", 1); exit(1); } ioctl(sfd, I_PUSH, "ptem"); /* push ptem */ ioctl(sfd, I_PUSH, "ldterm"); /* push ldterm */ write(ctrlp[1], "s", 1); close(ctrlp[1]); dup2(sfd, 0); dup2(sfd, 1); dup2(sfd, 2); close(mfd); execv(argv[0], argv); fprintf(stderr, "Could not exec %s!\n", argv[0]); exit(1); } close(ctrlp[1]); read(ctrlp[0], &c, 1); if(c == 'f') { fprintf(stderr, "Failed to open slave pty\n"); exit(1); } close(ctrlp[0]); fcntl(mfd, F_SETFL, O_NONBLOCK); return mfd; } int main(int argc, char *argv[]) { int fd; char buf[4096]; int res; if(argc < 2) { fprintf(stderr, "usage: %s program [args]\n", argv[0]); exit(1); } fd = start_child(argv + 1); while(1) { struct pollfd pfds[2]; pfds[0].fd = fd; pfds[0].events = POLLIN; pfds[1].fd = 0; pfds[1].events = POLLIN; poll(pfds, 2, -1); if(pfds[0].revents) { res = read(fd, buf, sizeof(buf)); if(res > 0) write(1, buf, res); else if(res < 0) { perror("read from pty"); exit(1); } else break; } if(pfds[1].revents) { res = read(0, buf, sizeof(buf)); if(res > 0) write(fd, buf, res); else if(res < 0) { perror("read from stdin"); exit(1); } } } return 0; } ============================================================ |