dovecotpw.c revision c1252a5812eb11fcb81508b9ed37597a5bc84100
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek/* Copyright (C) 2004 Joshua Goodall */
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include "lib.h"
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include "password-scheme.h"
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include "randgen.h"
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include "safe-memset.h"
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include <ctype.h>
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include <fcntl.h>
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include <getopt.h>
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include <libgen.h>
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include <stdio.h>
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include <stdlib.h>
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#include <unistd.h>
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek#define DEFAULT_SCHEME "HMAC-MD5"
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozekstatic void
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozekusage(const char *s)
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek{
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek fprintf(stderr,
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek "usage: %s [-l] [-p plaintext] [-s scheme] [-u user] [-V]\n", s);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek " -l List known password schemes",
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek " -p plaintext New password",
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek " -s scheme Password scheme",
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek " -u user Username (if scheme uses it)",
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek " -V Internally verify the hash");
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek exit(1);
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek}
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozekint main(int argc, char *argv[] __attr_unused__)
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek{
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek extern char *optarg;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek extern int optind;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek const char *hash = NULL;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek const char *user = NULL;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek char *scheme = NULL;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek char *plaintext = NULL;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek char ch;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek int lflag = 0, Vflag = 0;
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek lib_init();
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek random_init();
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek password_schemes_init();
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek while ((ch = getopt(argc, argv, "lp:s:u:V")) != -1) {
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek switch (ch) {
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek case 'l':
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek lflag = 1;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek break;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek case 'p':
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek plaintext = i_strdup(optarg);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek safe_memset(optarg, 0, strlen(optarg));
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek break;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek case 's':
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek scheme = i_strdup(optarg);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek break;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek case 'u':
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek user = i_strdup(optarg);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek break;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek case 'V':
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek Vflag = 1;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek break;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek case '?':
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek default:
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek usage(basename(*argv));
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek }
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek }
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek if (lflag) {
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek const struct password_scheme *p = NULL;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek const char *s;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek while ((s = password_list_schemes(&p)) != NULL)
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek printf("%s ", s);
4e5e846de22407f825fe3b4040d79606818a2419Jakub Hrozek printf("\n");
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek exit(0);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek }
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek if (argc != optind)
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek usage(basename(*argv));
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek if (scheme == NULL)
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek scheme = i_strdup(DEFAULT_SCHEME);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek else {
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek char *c;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek for (c = scheme; *c != '\0'; c++)
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek *c = i_toupper(*c);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek }
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek while (plaintext == NULL) {
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek char *check;
16cb0969f0a9ea71524d852077d6a480740d4f12Jakub Hrozek static int lives = 3;
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek plaintext = i_strdup(getpass("Enter new password: "));
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek check = i_strdup(getpass("Retype new password: "));
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek if (strcmp(plaintext, check) != 0) {
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek fprintf(stderr, "Passwords don't match!\n");
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek if (--lives == 0)
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek exit(1);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek safe_memset(plaintext, 0, strlen(plaintext));
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek safe_memset(check, 0, strlen(check));
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek i_free(plaintext);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek i_free(check);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek plaintext = NULL;
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek }
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek }
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek if ((hash = password_generate(plaintext, user, scheme)) == NULL) {
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek fprintf(stderr, "error generating password hash\n");
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek exit(1);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek }
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek if (Vflag == 1) {
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek const char *checkscheme, *checkpass;
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek checkpass = t_strdup_printf("{%s}%s", scheme, hash);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek checkscheme = password_get_scheme(&checkpass);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek if (strcmp(scheme, checkscheme) != 0) {
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek fprintf(stderr, "reverse scheme lookup check failed\n");
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek exit(2);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek }
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek if (password_verify(plaintext, checkpass,
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek checkscheme, user) != 1) {
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek fprintf(stderr,
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek "reverse password verification check failed\n");
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek exit(2);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek }
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek printf("{%s}%s (verified)\n", scheme, hash);
b4f87b42b18888c396e44e7359f7aafb092221bfJakub Hrozek } else
16cb0969f0a9ea71524d852077d6a480740d4f12Jakub Hrozek printf("{%s}%s\n", scheme, hash);
16cb0969f0a9ea71524d852077d6a480740d4f12Jakub Hrozek
16cb0969f0a9ea71524d852077d6a480740d4f12Jakub Hrozek return 0;
16cb0969f0a9ea71524d852077d6a480740d4f12Jakub Hrozek}
16cb0969f0a9ea71524d852077d6a480740d4f12Jakub Hrozek