changeset 10002:d9cb9d03e50e HEAD

dovecotpw binary is now accessed via "doveadm pw".
author Timo Sirainen <tss@iki.fi>
date Thu, 08 Oct 2009 18:24:24 -0400
parents a02c1d9df1bf
children 3721ae3917fc
files .hgignore src/doveadm/Makefile.am src/doveadm/doveadm-mail.c src/doveadm/doveadm-pw.c src/doveadm/doveadm.c src/doveadm/doveadm.h src/util/Makefile.am src/util/dovecotpw.c
diffstat 8 files changed, 200 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu Oct 08 17:58:38 2009 -0400
+++ b/.hgignore	Thu Oct 08 18:24:24 2009 -0400
@@ -79,7 +79,6 @@
 src/pop3-login/pop3-login
 src/pop3/pop3
 src/util/authtest
-src/util/dovecotpw
 src/util/gdbhelper
 src/util/idxview
 src/util/imap-utf7
--- a/src/doveadm/Makefile.am	Thu Oct 08 17:58:38 2009 -0400
+++ b/src/doveadm/Makefile.am	Thu Oct 08 18:24:24 2009 -0400
@@ -12,13 +12,24 @@
 	-I$(top_srcdir)/src/auth \
 	-DPKG_RUNDIR=\""$(rundir)"\"
 
+cmd_pw_libs = \
+	../auth/libpassword.a \
+	../lib-ntlm/libntlm.a \
+	../lib-otp/libotp.a
+
 doveadm_LDADD = \
+	$(cmd_pw_libs) $(AUTH_LIBS) \
 	$(LIBDOVECOT_STORAGE) \
 	$(LIBDOVECOT) \
 	$(MODULE_LIBS)
-doveadm_DEPENDENCIES = $(LIBDOVECOT_STORAGE) $(LIBDOVECOT)
+doveadm_DEPENDENCIES = \
+	$(cmd_pw_libs) \
+	$(LIBDOVECOT_STORAGE) \
+	$(LIBDOVECOT)
+
 doveadm_SOURCES = \
 	doveadm.c \
+	doveadm-pw.c \
 	doveadm-mail.c
 
 noinst_HEADERS = \
--- a/src/doveadm/doveadm-mail.c	Thu Oct 08 17:58:38 2009 -0400
+++ b/src/doveadm/doveadm-mail.c	Thu Oct 08 18:24:24 2009 -0400
@@ -211,9 +211,7 @@
 			service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
 			break;
 		default:
-			if (!master_service_parse_option(master_service,
-							 c, optarg))
-				usage();
+			usage();
 		}
 	}
 	if (!all_users) {
@@ -253,7 +251,7 @@
 	const struct doveadm_mail_cmd *cmd;
 
 	array_foreach(&doveadm_mail_cmds, cmd) {
-		fprintf(stderr, "  %s <user>|-a", cmd->name);
+		fprintf(stderr, USAGE_CMDNAME_FMT" <user>|-a", cmd->name);
 		if (cmd->usage_args != NULL)
 			fprintf(stderr, " %s", cmd->usage_args);
 		fputc('\n', stderr);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-pw.c	Thu Oct 08 18:24:24 2009 -0400
@@ -0,0 +1,112 @@
+/* Copyright (C) 2004 Joshua Goodall */
+
+#include "lib.h"
+#include "array.h"
+#include "password-scheme.h"
+#include "randgen.h"
+#include "doveadm.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define DEFAULT_SCHEME "CRAM-MD5"
+
+static void cmd_pw(int argc, char *argv[])
+{
+	const char *hash = NULL;
+	const char *user = NULL;
+	const char *scheme = NULL;
+	const char *plaintext = NULL;
+	int ch, lflag = 0, Vflag = 0;
+
+	random_init();
+	password_schemes_init();
+	
+	while ((ch = getopt(argc, argv, "lp:s:u:V")) != -1) {
+		switch (ch) {
+		case 'l':
+			lflag = 1;
+			break;
+		case 'p':
+			plaintext = optarg;
+			break;
+		case 's':
+			scheme = optarg;
+			break;
+		case 'u':
+			user = optarg;
+			break;
+		case 'V':
+			Vflag = 1;
+			break;
+		case '?':
+		default:
+			help(&doveadm_cmd_pw);
+		}
+	}
+
+	if (lflag) {
+		const struct password_scheme *const *schemes;
+		unsigned int i, count;
+
+		schemes = array_get(&password_schemes, &count);
+		for (i = 0; i < count; i++)
+			printf("%s ", schemes[i]->name);
+		printf("\n");
+		exit(0);
+	}
+
+	if (argc != optind)
+		help(&doveadm_cmd_pw);
+
+	scheme = scheme == NULL ? DEFAULT_SCHEME : t_str_ucase(scheme);
+	while (plaintext == NULL) {
+		const char *check;
+		static int lives = 3;
+
+		plaintext = t_strdup(getpass("Enter new password: "));
+		check = t_strdup(getpass("Retype new password: "));
+		if (strcmp(plaintext, check) != 0) {
+			fprintf(stderr, "Passwords don't match!\n");
+			if (--lives == 0)
+				exit(1);
+			plaintext = NULL;
+		}
+	}
+
+	if (!password_generate_encoded(plaintext, user, scheme, &hash)) {
+		fprintf(stderr, "Unknown scheme: %s\n", scheme);
+		exit(1);
+	}
+	if (Vflag == 1) {
+		const unsigned char *raw_password;
+		size_t size;
+
+		if (password_decode(hash, scheme, &raw_password, &size) <= 0) {
+			fprintf(stderr, "reverse decode check failed\n");
+			exit(2);
+		}
+
+		if (password_verify(plaintext, user, scheme,
+				    raw_password, size) != 1) {
+			fprintf(stderr,
+				"reverse password verification check failed\n");
+			exit(2);
+		}
+
+		printf("{%s}%s (verified)\n", scheme, hash);
+	} else
+		printf("{%s}%s\n", scheme, hash);
+}
+
+struct doveadm_cmd doveadm_cmd_pw = {
+	cmd_pw, "pw", "[-l] [-p plaintext] [-s scheme] [-u user] [-V]",
+"  -l            List known password schemes\n"
+"  -p plaintext  New password\n"
+"  -s scheme     Password scheme\n"
+"  -u user       Username (if scheme uses it)\n"
+"  -V            Internally verify the hash\n"
+};
--- a/src/doveadm/doveadm.c	Thu Oct 08 17:58:38 2009 -0400
+++ b/src/doveadm/doveadm.c	Thu Oct 08 18:24:24 2009 -0400
@@ -1,6 +1,7 @@
 /* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "array.h"
 #include "master-service.h"
 #include "doveadm-mail.h"
 #include "doveadm.h"
@@ -9,13 +10,64 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+static ARRAY_DEFINE(doveadm_cmds, struct doveadm_cmd);
+
+void doveadm_register_cmd(const struct doveadm_cmd *cmd)
+{
+	array_append(&doveadm_cmds, cmd, 1);
+}
+
 void usage(void)
 {
+	const struct doveadm_cmd *cmd;
+
 	fprintf(stderr, "usage: doveadm\n");
+
+	array_foreach(&doveadm_cmds, cmd) {
+		fprintf(stderr, USAGE_CMDNAME_FMT" %s\n",
+			cmd->name, cmd->short_usage);
+	}
 	doveadm_mail_usage();
 	exit(1);
 }
 
+void help(const struct doveadm_cmd *cmd)
+{
+	fprintf(stderr, "doveadm %s %s\n", cmd->name, cmd->short_usage);
+	if (cmd->long_usage != NULL)
+		fprintf(stderr, "%s", cmd->long_usage);
+	exit(0);
+}
+
+static void cmd_help(int argc ATTR_UNUSED, char *argv[])
+{
+	const struct doveadm_cmd *cmd;
+
+	if (argv[1] == NULL)
+		usage();
+	array_foreach(&doveadm_cmds, cmd) {
+		if (strcmp(cmd->name, argv[1]) == 0)
+			help(cmd);
+	}
+	usage();
+}
+static struct doveadm_cmd doveadm_cmd_help = {
+	cmd_help, "help", "<cmd>", NULL
+};
+
+static bool doveadm_try_run(const char *cmd_name, int argc, char *argv[])
+{
+	const struct doveadm_cmd *cmd;
+
+	array_foreach(&doveadm_cmds, cmd) {
+		if (strcmp(cmd_name, cmd->name) == 0) {
+			cmd->cmd(argc, argv);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
 int main(int argc, char *argv[])
 {
 	const char *cmd_name, *getopt_str;
@@ -24,7 +76,10 @@
 	master_service = master_service_init("doveadm",
 					     MASTER_SERVICE_FLAG_STANDALONE,
 					     argc, argv);
+	i_array_init(&doveadm_cmds, 32);
 	doveadm_mail_init();
+	doveadm_register_cmd(&doveadm_cmd_help);
+	doveadm_register_cmd(&doveadm_cmd_pw);
 
 	/* "+" is GNU extension to stop at the first non-option.
 	   others just accept -+ option. */
@@ -40,10 +95,12 @@
 	argc -= optind;
 	argv += optind;
 
-	if (!doveadm_mail_try_run(cmd_name, argc, argv))
+	if (!doveadm_try_run(cmd_name, argc, argv) &&
+	    doveadm_mail_try_run(cmd_name, argc, argv))
 		usage();
 
 	master_service_deinit(&master_service);
 	doveadm_mail_deinit();
+	array_free(&doveadm_cmds);
 	return 0;
 }
--- a/src/doveadm/doveadm.h	Thu Oct 08 17:58:38 2009 -0400
+++ b/src/doveadm/doveadm.h	Thu Oct 08 18:24:24 2009 -0400
@@ -1,6 +1,22 @@
 #ifndef DOVEADM_H
 #define DOVEADM_H
 
+#define USAGE_CMDNAME_FMT "  %-12s"
+
+typedef void doveadm_command_t(int argc, char *argv[]);
+
+struct doveadm_cmd {
+	doveadm_command_t *cmd;
+	const char *name;
+	const char *short_usage;
+	const char *long_usage;
+};
+
+extern struct doveadm_cmd doveadm_cmd_pw;
+
+void doveadm_register_cmd(const struct doveadm_cmd *cmd);
+
 void usage(void);
+void help(const struct doveadm_cmd *cmd);
 
 #endif
--- a/src/util/Makefile.am	Thu Oct 08 17:58:38 2009 -0400
+++ b/src/util/Makefile.am	Thu Oct 08 18:24:24 2009 -0400
@@ -12,8 +12,6 @@
 	maildirlock \
 	threadview
 
-sbin_PROGRAMS = dovecotpw
-
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-auth \
@@ -75,17 +73,3 @@
 threadview_DEPENDENCIES = $(LIBDOVECOT)
 threadview_SOURCES = \
 	threadview.c
-
-dovecotpw_libs = \
-	../auth/libpassword.a \
-	../lib-ntlm/libntlm.a \
-	../lib-otp/libotp.a \
-	$(LIBDOVECOT)
-
-dovecotpw_LDADD = \
-	$(dovecotpw_libs) \
-	$(AUTH_LIBS)
-dovecotpw_DEPENDENCIES = $(dovecotpw_libs)
-
-dovecotpw_SOURCES = \
-	dovecotpw.c
--- a/src/util/dovecotpw.c	Thu Oct 08 17:58:38 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/* Copyright (C) 2004 Joshua Goodall */
-
-#include "lib.h"
-#include "array.h"
-#include "password-scheme.h"
-#include "randgen.h"
-#include "safe-memset.h"
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef HAVE_LIBGEN_H
-#  include <libgen.h>
-#endif
-
-#define DEFAULT_SCHEME "CRAM-MD5"
-
-static void ATTR_NORETURN
-usage(const char *s)
-{
-	fprintf(stderr,
-	    "usage: %s [-l] [-p plaintext] [-s scheme] [-u user] [-V]\n", s);
-	fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
-	    "    -l            List known password schemes",
-	    "    -p plaintext  New password",
-	    "    -s scheme     Password scheme",
-	    "    -u user       Username (if scheme uses it)",
-	    "    -V            Internally verify the hash");
-
-	exit(1);
-}
-
-int main(int argc, char *argv[])
-{
-	const char *hash = NULL;
-	const char *user = NULL;
-	char *scheme = NULL;
-	char *plaintext = NULL;
-	int ch, lflag = 0, Vflag = 0;
-
-	lib_init();
-	random_init();
-	password_schemes_init();
-	
-	while ((ch = getopt(argc, argv, "lp:s:u:V")) != -1) {
-		switch (ch) {
-		case 'l':
-			lflag = 1;
-			break;
-		case 'p':
-			plaintext = i_strdup(optarg);
-			safe_memset(optarg, 0, strlen(optarg));
-			break;
-		case 's':
-			scheme = i_strdup(optarg);
-			break;
-		case 'u':
-			user = i_strdup(optarg);
-			break;
-		case 'V':
-			Vflag = 1;
-			break;
-		case '?':
-		default:
-			usage(basename(*argv));
-		}
-	}
-
-	if (lflag) {
-		const struct password_scheme *const *schemes;
-		unsigned int i, count;
-
-		schemes = array_get(&password_schemes, &count);
-		for (i = 0; i < count; i++)
-			printf("%s ", schemes[i]->name);
-		printf("\n");
-		exit(0);
-	}
-
-	if (argc != optind)
-		usage(basename(*argv));
-
-	if (scheme == NULL)
-		scheme = i_strdup(DEFAULT_SCHEME);
-	else {
-		char *c;
-		for (c = scheme; *c != '\0'; c++)
-			*c = i_toupper(*c);
-	}
-
-
-	while (plaintext == NULL) {
-		char *check;
-		static int lives = 3;
-
-		plaintext = i_strdup(getpass("Enter new password: "));
-		check = i_strdup(getpass("Retype new password: "));
-		if (strcmp(plaintext, check) != 0) {
-			fprintf(stderr, "Passwords don't match!\n");
-			if (--lives == 0)
-				exit(1);
-			safe_memset(plaintext, 0, strlen(plaintext));
-			safe_memset(check, 0, strlen(check));
-			i_free(plaintext);
-			i_free(check);
-			plaintext = NULL;
-		}
-	}
-
-	if (!password_generate_encoded(plaintext, user, scheme, &hash)) {
-		fprintf(stderr, "Unknown scheme: %s\n", scheme);
-		exit(1);
-	}
-	if (Vflag == 1) {
-		const unsigned char *raw_password;
-		size_t size;
-
-		if (password_decode(hash, scheme, &raw_password, &size) <= 0) {
-			fprintf(stderr, "reverse decode check failed\n");
-			exit(2);
-		}
-
-		if (password_verify(plaintext, user, scheme,
-				    raw_password, size) != 1) {
-			fprintf(stderr,
-				"reverse password verification check failed\n");
-			exit(2);
-		}
-
-		printf("{%s}%s (verified)\n", scheme, hash);
-	} else
-		printf("{%s}%s\n", scheme, hash);
-
-        return 0;
-}