diff options
-rw-r--r-- | src/pwgui/main.cpp | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/src/pwgui/main.cpp b/src/pwgui/main.cpp index 2c8123b..264f0df 100644 --- a/src/pwgui/main.cpp +++ b/src/pwgui/main.cpp @@ -19,6 +19,8 @@ #include <pwd.h> #include <grp.h> #include <errno.h> +#include <sys/socket.h> +#include <sys/un.h> #include "../x11workaround.h" @@ -60,7 +62,8 @@ static char *helper_urlencode(char *s, char *enc); static int helper_cupsError(const int code); static void helper_messageBox(const char *caption, const char *text, const bool error = false); -static void demo(); +static void query_pwdaemon(int pfd, char *creds); + /* * Note to the next HiWi who wants to refactor this to use something like boost::program_options: * Don't do it unless you are certain that you understood the behaviour described here: @@ -203,6 +206,7 @@ int main(int argc, char *argv[]) // Seems we need the dialog int status; char *pass = NULL; + int numRun = 0; do { @@ -219,6 +223,11 @@ int main(int argc, char *argv[]) close(pfd[0]); helper_dropprivs(); helper_copyenv(NULL); + // .... but first, try pwdaemon + if (numRun == 0) { + query_pwdaemon(pfd[1], creds); + // if the function returned, nothing was queried and we should show the gui + } QApplication a(argc, argv); Backdrop *bg = new Backdrop; bg->show(); @@ -232,6 +241,7 @@ int main(int argc, char *argv[]) exit(a.exec()); return CUPS_BACKEND_CANCEL; } + numRun++; // Main (Parent) close(pfd[1]); // Read from pipe @@ -670,3 +680,65 @@ static void helper_messageBox(const char *caption, const char *text, const bool // Wait for child to die waitpid(pid, NULL, 0); } + +static void query_pwdaemon(int pfd, char *creds) +{ + char homedir[NAMELEN]; + char daemon_data[NAMELEN]; + char *e = getenv("HOME"); + if (e == NULL) { + struct passwd *p = getpwuid(getuid()); + if (p != nullptr) { + e = p->pw_dir; + } + } + if (e == nullptr) { + return; + } + snprintf(homedir, NAMELEN, "%s/.pwsocket", e); + // KONNEKT + struct sockaddr_un remote; + struct timeval tv; + int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd == -1) { + perror("Cannot create unix socket"); + return; + } + memset(&remote, 0, sizeof(remote)); + remote.sun_family = AF_UNIX; + strncpy(remote.sun_path, homedir, sizeof(remote.sun_path)-1); + tv.tv_sec = 2; + tv.tv_usec = 0; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + if (connect(fd, (struct sockaddr*)&remote, sizeof(remote)) == -1) { + perror("Cannot connect to pw daemon"); + close(fd); + return; + } + write(fd, "PW", 2); + ssize_t ret = read(fd, daemon_data, NAMELEN - 5); + if (ret == -1) { + perror("Cannot read reply from pwdaemon"); + close(fd); + return; + } + if (ret == 0) { + fprintf(stderr, "pwdaemon is configured to not reveal pw\n"); + close(fd); + return; + } + daemon_data[ret] = '\0'; + char *ptr = daemon_data; + int i = strlen(creds); + while (++i < NAMELEN - 5) { + creds[i] = *ptr++; + if (creds[i] == '\0') + break; + } + creds[NAMELEN-1] = '\0'; + close(fd); + ::write(pfd, creds, qMin(i+1, NAMELEN)); + ::close(pfd); + exit(0); +} |