diff options
author | Mattias Andrée <maandree@operamail.com> | 2015-12-05 12:23:17 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2015-12-05 12:23:17 +0100 |
commit | 25b6ad79922d739fd046e07db1996c93c567b350 (patch) | |
tree | fe1725cea7db899c0f858db84189c1b380a9f64f /src/passphrase.c | |
parent | beginning of issue #2 on github (diff) | |
download | libpassphrase-25b6ad79922d739fd046e07db1996c93c567b350.tar.gz libpassphrase-25b6ad79922d739fd046e07db1996c93c567b350.tar.bz2 libpassphrase-25b6ad79922d739fd046e07db1996c93c567b350.tar.xz |
read input from passcheck
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to '')
-rw-r--r-- | src/passphrase.c | 108 |
1 files changed, 101 insertions, 7 deletions
diff --git a/src/passphrase.c b/src/passphrase.c index 1430a47..032111b 100644 --- a/src/passphrase.c +++ b/src/passphrase.c @@ -19,8 +19,10 @@ #include <stdlib.h> #include <stdio.h> #include <unistd.h> +#include <string.h> #include <fcntl.h> #include <errno.h> +#include <limits.h> #include <sys/wait.h> #define PASSPHRASE_USE_DEPRECATED @@ -44,6 +46,9 @@ struct passcheck_state pid_t pid; int flags; }; + +static char* strength = NULL; +static size_t strength_size = 0; #endif /* PASSPHRASE_METER */ @@ -111,24 +116,28 @@ static void passcheck_start(struct passcheck_state* state, int flags) { gid_t gid = getgid(), egid = getegid(); uid_t uid = getuid(), euid = geteuid(); + int fd; if ((state->pipe_rw[0] != STDIN_FILENO) && (state->pipe_rw[1] == STDIN_FILENO)) { - pipe_rw[1] = dup(state->pipe_rw[1]); - if (pipe_rw[1] == -1) + fd = dup(state->pipe_rw[1]); + if (fd == -1) goto child_fail; - state->pipe_rw[1] = pipe_rw[1], pipe_rw[1] = -1; + state->pipe_rw[1] = fd; } for (i = 0; i <= 1; i++) if (state->pipe_rw[i] != i) { close(i); - pipe_rw[i] = dup2(state->pipe_rw[i], i); - if (pipe_rw[i] == -1) + fd = dup2(state->pipe_rw[i], i); + if (fd == -1) goto child_fail; - close(state->pipe_rw[i]), state->pipe_rw[i] = pipe_rw[i]; + close(state->pipe_rw[i]); + state->pipe_rw[i] = fd; } + close(STDERR_FILENO); + if (egid != gid) if (setregid(gid, gid) && gid) goto child_fail; @@ -168,6 +177,7 @@ static void passcheck_start(struct passcheck_state* state, int flags) state->flags = 0; } + static void passcheck_stop(struct passcheck_state* state) { int _status; @@ -178,19 +188,103 @@ static void passcheck_stop(struct passcheck_state* state) close(state->pipe_rw[0]); close(state->pipe_rw[1]); + free(strength), strength = NULL; + strength_size = 0; + rereap: if ((waitpid(state->pid, &_status, 0) == -1) && (errno == EINTR)) goto rereap; /* TODO cleanup */ + + state->flags = 0; } -static void passcheck_update(struct passcheck_state* state, char* passphrase, size_t len) + +static void passcheck_update(struct passcheck_state* state, const char* passphrase, size_t len) { + size_t strength_ptr = 0; + ssize_t n; + int i; + void* new; + char* p; + unsigned long long int value; + if (state->flags == 0) return; + for (i = 0; i < 2; i++, passphrase = "\n", len = 1) + while (len) + { + n = write(state->pipe_rw[1], passphrase, len); + if (n < 0) + { + if (errno == EINTR) + continue; + goto fail; + } + passphrase += (size_t)n; + len -= (size_t)n; + } + + again: + if (strength_ptr == strength_size) + { + strength_size = strength_size ? (strength_size << 1) : 8; + new = realloc(strength, strength_size * sizeof(char)); + if (new == NULL) + goto fail; + strength = new; + } + n = read(state->pipe_rw[0], strength + strength_ptr, strength_size - 1 - strength_ptr); + if (n <= 0) + { + if (n && (errno == EINTR)) + goto again; + goto fail; + } + strength_ptr += (size_t)n; + strength[strength_ptr] = '\0'; + p = strpbrk(strength, " \t\r\f\n\v"); + if (p == NULL) + goto again; + if (*p == '\033') + { + p = strpbrk(strength, "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm~"); + if (p == NULL) + goto fail; + p++; + } + else + p = strength; + *(strpbrk(p, " \t\r\f\n\v\033")) = '\0'; + errno = 0; + value = strtoull(p, NULL, 10); + if ((value == 0) && errno) + { + if (errno != ERANGE) + goto fail; + value = ULLONG_MAX; + } + while (memchr(strength, '\n', strength_ptr) == NULL) + { + strength_ptr = 0; + n = read(state->pipe_rw[0], strength, strength_size); + if (n <= 0) + { + if (n && (errno == EINTR)) + goto again; + goto fail; + } + strength_ptr = (size_t)n; + } + strength_ptr = 0; + /* TODO */ + + return; + fail: + passcheck_stop(state); } #endif /* PASSPHRASE_METER */ |