diff options
Diffstat (limited to '')
-rw-r--r-- | src/passphrase.c | 108 | ||||
-rw-r--r-- | src/passphrase.h | 2 |
2 files changed, 102 insertions, 8 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 */ diff --git a/src/passphrase.h b/src/passphrase.h index 24ee71b..dd9dfb6 100644 --- a/src/passphrase.h +++ b/src/passphrase.h @@ -39,7 +39,7 @@ /** * `passphrase_read2` shall draw a pasphrase - * strenght meter if such capability is + * strength meter if such capability is * available. This should be used when create * a new passphrase. * Should not be combined with `PASSPHRASE_READ_EXISTING`. |