view auth/hash_password.c @ 265:056790c4fb0d

add role-aware Epi assistant prompts Add verified June knowledge, guest/member/admin Copilot profiles, profile-isolated session recovery, animated Epi greetings, and a single authoritative runtime config workflow for inference. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 10:50:30 -0700
parents 04fee26ecce0
children
line wrap: on
line source

#include "auth/auth_crypto.h"

#include <openssl/crypto.h>

#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

#define PW_MAX AUTH_CRYPTO_PASSWORD_MAX_BYTES

static int read_password(int fd, char *buf, size_t capacity)
{
  size_t len = 0;
  int too_long = 0;
  for (;;)
  {
    unsigned char c;
    int r = (int)read(fd, &c, 1);
    if (r < 0)
      return -1;
    if (r == 0)
      break;
    if (c == '\n' || c == '\r')
      break;
    if (len + 1 >= capacity)
    {
      too_long = 1;
      continue;
    }
    buf[len++] = (char)c;
  }
  buf[len] = '\0';
  return too_long ? -2 : (int)len;
}

int main(int argc, char **argv)
{
  (void)argc;
  (void)argv;

  int fd = STDIN_FILENO;
  int is_tty = isatty(fd);
  struct termios old_term;
  struct termios new_term;
  int restored = 0;

  if (is_tty)
  {
    if (tcgetattr(fd, &old_term) != 0)
    {
      fprintf(stderr, "hash_password: failed to get terminal attributes\n");
      return 1;
    }
    new_term = old_term;
    new_term.c_lflag &= (tcflag_t)~(ECHO | ECHOE | ECHOK | ECHONL);
    new_term.c_lflag |= ICANON;
    if (tcsetattr(fd, TCSAFLUSH, &new_term) != 0)
    {
      fprintf(stderr, "hash_password: failed to disable echo\n");
      return 1;
    }
    restored = 1;
    fprintf(stderr, "Password: ");
    fflush(stderr);
  }

  char pw[PW_MAX + 1];
  memset(pw, 0, sizeof(pw));
  int n = read_password(fd, pw, sizeof(pw));

  if (restored)
  {
    tcsetattr(fd, TCSAFLUSH, &old_term);
    fprintf(stderr, "\n");
  }

  if (n == -2)
  {
    fprintf(stderr, "hash_password: %s\n",
            Auth_Crypto_Result_String(AUTH_CRYPTO_PASSWORD_TOO_LONG));
    OPENSSL_cleanse(pw, sizeof(pw));
    return 1;
  }
  if (n < 0)
  {
    fprintf(stderr, "hash_password: read error\n");
    OPENSSL_cleanse(pw, sizeof(pw));
    return 1;
  }
  if (n == 0)
  {
    fprintf(stderr, "hash_password: empty password\n");
    OPENSSL_cleanse(pw, sizeof(pw));
    return 1;
  }

  char encoded_hash[AUTH_CRYPTO_PASSWORD_HASH_ENCODED_SIZE];
  Auth_Crypto_Result result =
      Auth_Crypto_Password_Hash(pw, encoded_hash, sizeof(encoded_hash));
  OPENSSL_cleanse(pw, sizeof(pw));

  if (result != AUTH_CRYPTO_OK)
  {
    fprintf(stderr, "hash_password: %s\n", Auth_Crypto_Result_String(result));
    return 1;
  }

  puts(encoded_hash);
  return 0;
}