diff options
Diffstat (limited to 'src')
| -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`. | 
