]> granicus.if.org Git - apache/blobdiff - support/htdbm.c
Follow up to r1715876: core directives are ASCII.
[apache] / support / htdbm.c
index 69c0d2db82db40120311a69f09bb41cfbd7dbcdf..40a3d232938a28030881135d5e084a0e53ce4100 100644 (file)
@@ -1,9 +1,9 @@
-/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
- * applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -22,9 +22,7 @@
  * 12 Oct 2001
  */
 
-#include "apr.h"
-#include "apr_lib.h"
-#include "apr_strings.h"
+#include "passwd_common.h"
 #include "apr_file_io.h"
 #include "apr_file_info.h"
 #include "apr_pools.h"
@@ -32,6 +30,7 @@
 #include "apr_md5.h"
 #include "apr_sha1.h"
 #include "apr_dbm.h"
+#include "apr_getopt.h"
 
 #if APR_HAVE_STDLIB_H
 #include <stdlib.h>
 #include "apr_xlate.h"
 #endif /*APR_CHARSET_EBCDIC*/
 
-#if APR_HAVE_CRYPT_H
-#include <crypt.h>
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
 #endif
-
-
-#if !APR_CHARSET_EBCDIC
-#define LF 10
-#define CR 13
-#else /*APR_CHARSET_EBCDIC*/
-#define LF '\n'
-#define CR '\r'
-#endif /*APR_CHARSET_EBCDIC*/
-
-#define MAX_STRING_LEN 256
-#define ALG_PLAIN 0
-#define ALG_APMD5 1
-#define ALG_APSHA 2
 #if APR_HAVE_CRYPT_H
-#define ALG_CRYPT 3
+#include <crypt.h>
 #endif
 
 
-#define ERR_FILEPERM    1
-#define ERR_SYNTAX      2
-#define ERR_PWMISMATCH  3
-#define ERR_INTERRUPTED 4
-#define ERR_OVERFLOW    5
-#define ERR_BADUSER     6
-#define ERR_EMPTY       7
-
-
 typedef struct htdbm_t htdbm_t;
 
 struct htdbm_t {
     apr_dbm_t               *dbm;
-    apr_pool_t              *pool;
+    struct passwd_ctx       ctx;
 #if APR_CHARSET_EBCDIC
     apr_xlate_t             *to_ascii;
 #endif
     char                    *filename;
     char                    *username;
-    char                    *userpass;
     char                    *comment;
     char                    *type;
     int                     create;
     int                     rdonly;
-    int                     alg;
 };
 
 
@@ -104,7 +77,6 @@ struct htdbm_t {
 #define HTDBM_VERIFY 2
 #define HTDBM_LIST   3
 #define HTDBM_NOFILE 4
-#define HTDBM_STDIN  5
 
 static void terminate(void)
 {
@@ -114,7 +86,7 @@ static void terminate(void)
 #endif
 }
 
-static void htdbm_terminate(htdbm_t *htdbm) 
+static void htdbm_terminate(htdbm_t *htdbm)
 {
     if (htdbm->dbm)
         apr_dbm_close(htdbm->dbm);
@@ -122,15 +94,15 @@ static void htdbm_terminate(htdbm_t *htdbm)
 }
 
 static htdbm_t *h;
-  
-static void htdbm_interrupted(void) 
+
+static void htdbm_interrupted(void)
 {
     htdbm_terminate(h);
     fprintf(stderr, "htdbm Interrupted !\n");
     exit(ERR_INTERRUPTED);
 }
 
-static apr_status_t htdbm_init(apr_pool_t **pool, htdbm_t **hdbm) 
+static apr_status_t htdbm_init(apr_pool_t **pool, htdbm_t **hdbm)
 {
 
 #if APR_CHARSET_EBCDIC
@@ -138,13 +110,15 @@ static apr_status_t htdbm_init(apr_pool_t **pool, htdbm_t **hdbm)
 #endif
 
     apr_pool_create( pool, NULL);
+    apr_pool_abort_set(abort_on_oom, *pool);
+    apr_file_open_stderr(&errfile, *pool);
     apr_signal(SIGINT, (void (*)(int)) htdbm_interrupted);
 
     (*hdbm) = (htdbm_t *)apr_pcalloc(*pool, sizeof(htdbm_t));
-    (*hdbm)->pool = *pool;
+    (*hdbm)->ctx.pool = *pool;
 
 #if APR_CHARSET_EBCDIC
-    rv = apr_xlate_open(&((*hdbm)->to_ascii), "ISO-8859-1", APR_DEFAULT_CHARSET, (*hdbm)->pool);
+    rv = apr_xlate_open(&((*hdbm)->to_ascii), "ISO-8859-1", APR_DEFAULT_CHARSET, (*hdbm)->ctx.pool);
     if (rv) {
         fprintf(stderr, "apr_xlate_open(to ASCII)->%d\n", rv);
         return APR_EGENERAL;
@@ -162,23 +136,23 @@ static apr_status_t htdbm_init(apr_pool_t **pool, htdbm_t **hdbm)
 #endif /*APR_CHARSET_EBCDIC*/
 
     /* Set MD5 as default */
-    (*hdbm)->alg = ALG_APMD5;
+    (*hdbm)->ctx.alg = ALG_APMD5;
     (*hdbm)->type = "default";
     return APR_SUCCESS;
 }
 
-static apr_status_t htdbm_open(htdbm_t *htdbm) 
+static apr_status_t htdbm_open(htdbm_t *htdbm)
 {
     if (htdbm->create)
-        return apr_dbm_open_ex(&htdbm->dbm, htdbm->type, htdbm->filename, APR_DBM_RWCREATE, 
-                            APR_OS_DEFAULT, htdbm->pool);
+        return apr_dbm_open_ex(&htdbm->dbm, htdbm->type, htdbm->filename, APR_DBM_RWCREATE,
+                            APR_OS_DEFAULT, htdbm->ctx.pool);
     else
-        return apr_dbm_open_ex(&htdbm->dbm, htdbm->type, htdbm->filename, 
-                            htdbm->rdonly ? APR_DBM_READONLY : APR_DBM_READWRITE, 
-                            APR_OS_DEFAULT, htdbm->pool);
+        return apr_dbm_open_ex(&htdbm->dbm, htdbm->type, htdbm->filename,
+                            htdbm->rdonly ? APR_DBM_READONLY : APR_DBM_READWRITE,
+                            APR_OS_DEFAULT, htdbm->ctx.pool);
 }
 
-static apr_status_t htdbm_save(htdbm_t *htdbm, int *changed) 
+static apr_status_t htdbm_save(htdbm_t *htdbm, int *changed)
 {
     apr_datum_t key, val;
 
@@ -190,18 +164,18 @@ static apr_status_t htdbm_save(htdbm_t *htdbm, int *changed)
     if (apr_dbm_exists(htdbm->dbm, key))
         *changed = 1;
 
-    val.dsize = strlen(htdbm->userpass);
+    val.dsize = strlen(htdbm->ctx.passwd);
     if (!htdbm->comment)
-        val.dptr  = htdbm->userpass;
+        val.dptr  = htdbm->ctx.passwd;
     else {
-        val.dptr = apr_pstrcat(htdbm->pool, htdbm->userpass, ":",
+        val.dptr = apr_pstrcat(htdbm->ctx.pool, htdbm->ctx.passwd, ":",
                                htdbm->comment, NULL);
         val.dsize += (strlen(htdbm->comment) + 1);
     }
     return apr_dbm_store(htdbm->dbm, key, val);
 }
 
-static apr_status_t htdbm_del(htdbm_t *htdbm) 
+static apr_status_t htdbm_del(htdbm_t *htdbm)
 {
     apr_datum_t key;
 
@@ -213,58 +187,52 @@ static apr_status_t htdbm_del(htdbm_t *htdbm)
     return apr_dbm_delete(htdbm->dbm, key);
 }
 
-static apr_status_t htdbm_verify(htdbm_t *htdbm) 
+static apr_status_t htdbm_verify(htdbm_t *htdbm)
 {
     apr_datum_t key, val;
-    char pwd[MAX_STRING_LEN] = {0};
+    char *pwd;
     char *rec, *cmnt;
 
     key.dptr = htdbm->username;
     key.dsize = strlen(htdbm->username);
     if (!apr_dbm_exists(htdbm->dbm, key))
-        return APR_ENOENT;    
+        return APR_ENOENT;
     if (apr_dbm_fetch(htdbm->dbm, key, &val) != APR_SUCCESS)
         return APR_ENOENT;
-    rec = apr_pstrndup(htdbm->pool, val.dptr, val.dsize);
-    cmnt = strchr(rec, ';');
+    rec = apr_pstrndup(htdbm->ctx.pool, val.dptr, val.dsize);
+    cmnt = strchr(rec, ':');
     if (cmnt)
-        strncpy(pwd, rec, cmnt - rec);
+        pwd = apr_pstrndup(htdbm->ctx.pool, rec, cmnt - rec);
     else
-        strcpy(pwd, rec);
-    return apr_password_validate(htdbm->userpass, pwd);
+        pwd = apr_pstrdup(htdbm->ctx.pool, rec);
+    return apr_password_validate(htdbm->ctx.passwd, pwd);
 }
 
-static apr_status_t htdbm_list(htdbm_t *htdbm) 
+static apr_status_t htdbm_list(htdbm_t *htdbm)
 {
     apr_status_t rv;
     apr_datum_t key, val;
-    char *rec, *cmnt;
-    char kb[MAX_STRING_LEN];
+    char *cmnt;
     int i = 0;
 
     rv = apr_dbm_firstkey(htdbm->dbm, &key);
     if (rv != APR_SUCCESS) {
-        fprintf(stderr, "Empty database -- %s\n", htdbm->filename); 
+        fprintf(stderr, "Empty database -- %s\n", htdbm->filename);
         return APR_ENOENT;
     }
-    rec = apr_pcalloc(htdbm->pool, HUGE_STRING_LEN);
-
-    fprintf(stderr, "Dumping records from database -- %s\n", htdbm->filename); 
-    fprintf(stderr, "    %-32sComment\n", "Username");    
+    fprintf(stderr, "Dumping records from database -- %s\n", htdbm->filename);
+    fprintf(stderr, "    %-32s Comment\n", "Username");
     while (key.dptr != NULL) {
         rv = apr_dbm_fetch(htdbm->dbm, key, &val);
         if (rv != APR_SUCCESS) {
             fprintf(stderr, "Failed getting data from %s\n", htdbm->filename);
             return APR_EGENERAL;
         }
-        strncpy(kb, key.dptr, key.dsize);
-        kb[key.dsize] = '\0';
-        fprintf(stderr, "    %-32s", kb);
-        strncpy(rec, val.dptr, val.dsize);
-        rec[val.dsize] = '\0';
-        cmnt = strchr(rec, ':');
+        /* Note: we don't store \0-terminators on our dbm data */
+        fprintf(stderr, "    %-32.*s", (int)key.dsize, key.dptr);
+        cmnt = memchr(val.dptr, ':', val.dsize);
         if (cmnt)
-            fprintf(stderr, "%s", cmnt + 1);
+            fprintf(stderr, " %.*s", (int)(val.dptr+val.dsize - (cmnt+1)), cmnt + 1);
         fprintf(stderr, "\n");
         rv = apr_dbm_nextkey(htdbm->dbm, &key);
         if (rv != APR_SUCCESS)
@@ -276,52 +244,20 @@ static apr_status_t htdbm_list(htdbm_t *htdbm)
     return APR_SUCCESS;
 }
 
-static void to64(char *s, unsigned long v, int n)
-{
-    static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
-    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-    while (--n >= 0) {
-        *s++ = itoa64[v&0x3f];
-        v >>= 6;
-    }
-}
-
-static apr_status_t htdbm_make(htdbm_t *htdbm) 
+static int htdbm_make(htdbm_t *htdbm)
 {
     char cpw[MAX_STRING_LEN];
-    char salt[9];
-
-    switch (htdbm->alg) {
-        case ALG_APSHA:
-            /* XXX cpw >= 28 + strlen(sha1) chars - fixed len SHA */
-            apr_sha1_base64(htdbm->userpass,strlen(htdbm->userpass),cpw);
-        break;
-
-        case ALG_APMD5: 
-            (void) srand((int) time((time_t *) NULL));
-            to64(&salt[0], rand(), 8);
-            salt[8] = '\0';
-            apr_md5_encode((const char *)htdbm->userpass, (const char *)salt,
-                            cpw, sizeof(cpw));
-        break;
-        case ALG_PLAIN:
-            /* XXX this len limitation is not in sync with any HTTPd len. */
-            apr_cpystrn(cpw,htdbm->userpass,sizeof(cpw));
-        break;
-#if APR_HAVE_CRYPT_H
-        case ALG_CRYPT:
-            (void) srand((int) time((time_t *) NULL));
-            to64(&salt[0], rand(), 8);
-            salt[8] = '\0';
-            apr_cpystrn(cpw, (char *)crypt(htdbm->userpass, salt), sizeof(cpw) - 1);
-            fprintf(stderr, "CRYPT is now deprecated, use MD5 instead!\n");
-#endif
-        default:
-        break;
+    int ret;
+
+    htdbm->ctx.out = cpw;
+    htdbm->ctx.out_len = sizeof(cpw);
+    ret = mkhash(&htdbm->ctx);
+    if (ret != 0) {
+        fprintf(stderr, "Error: %s\n", htdbm->ctx.errstr);
+        return ret;
     }
-    htdbm->userpass = apr_pstrdup(htdbm->pool, cpw);
-    return APR_SUCCESS;
+    htdbm->ctx.passwd = apr_pstrdup(htdbm->ctx.pool, cpw);
+    return 0;
 }
 
 static apr_status_t htdbm_valid_username(htdbm_t *htdbm)
@@ -339,60 +275,54 @@ static apr_status_t htdbm_valid_username(htdbm_t *htdbm)
 
 static void htdbm_usage(void)
 {
-
-#if APR_HAVE_CRYPT_H
-#define CRYPT_OPTION "d"
-#else
-#define CRYPT_OPTION ""
-#endif
-    fprintf(stderr, "htdbm -- program for manipulating DBM password databases.\n\n");
-    fprintf(stderr, "Usage: htdbm    [-cm"CRYPT_OPTION"pstvx] [-TDBTYPE] database username\n");
-    fprintf(stderr, "                -b[cm"CRYPT_OPTION"ptsv] [-TDBTYPE] database username password\n");
-    fprintf(stderr, "                -n[m"CRYPT_OPTION"pst]   username\n");
-    fprintf(stderr, "                -nb[m"CRYPT_OPTION"pst]  username password\n");
-    fprintf(stderr, "                -v[m"CRYPT_OPTION"ps]    [-TDBTYPE] database username\n");
-    fprintf(stderr, "                -vb[m"CRYPT_OPTION"ps]   [-TDBTYPE] database username password\n");
-    fprintf(stderr, "                -x[m"CRYPT_OPTION"ps]    [-TDBTYPE] database username\n");
-    fprintf(stderr, "                -l                       [-TDBTYPE] database\n");
-    fprintf(stderr, "Options:\n");
-    fprintf(stderr, "   -b   Use the password from the command line rather "
-                    "than prompting for it.\n");
-    fprintf(stderr, "   -c   Create a new database.\n");
-    fprintf(stderr, "   -n   Don't update database; display results on stdout.\n");
-    fprintf(stderr, "   -m   Force MD5 encryption of the password (default).\n");
-#if APR_HAVE_CRYPT_H
-    fprintf(stderr, "   -d   Force CRYPT encryption of the password (now deprecated).\n");
-#endif
-    fprintf(stderr, "   -p   Do not encrypt the password (plaintext).\n");
-    fprintf(stderr, "   -s   Force SHA encryption of the password.\n");
-    fprintf(stderr, "   -T   DBM Type (SDBM|GDBM|DB|default).\n");
-    fprintf(stderr, "   -l   Display usernames from database on stdout.\n");
-    fprintf(stderr, "   -t   The last param is username comment.\n");
-    fprintf(stderr, "   -v   Verify the username/password.\n");
-    fprintf(stderr, "   -x   Remove the username record from database.\n");
+    fprintf(stderr,
+        "htdbm -- program for manipulating DBM password databases.\n\n"
+        "Usage: htdbm   [-cimBdpstvx] [-C cost] [-TDBTYPE] database username\n"
+        "                -b[cmBdptsv] [-C cost] [-TDBTYPE] database username password\n"
+        "                -n[imBdpst]  [-C cost] username\n"
+        "                -nb[mBdpst]  [-C cost] username password\n"
+        "                -v[imBdps]   [-C cost] [-TDBTYPE] database username\n"
+        "                -vb[mBdps]   [-C cost] [-TDBTYPE] database username password\n"
+        "                -x                     [-TDBTYPE] database username\n"
+        "                -l                     [-TDBTYPE] database\n"
+        "Options:\n"
+        "   -c   Create a new database.\n"
+        "   -n   Don't update database; display results on stdout.\n"
+        "   -b   Use the password from the command line rather than prompting for it.\n"
+        "   -i   Read password from stdin without verification (for script usage).\n"
+        "   -m   Force MD5 encryption of the password (default).\n"
+        "   -B   Force BCRYPT encryption of the password (very secure).\n"
+        "   -C   Set the computing time used for the bcrypt algorithm\n"
+        "        (higher is more secure but slower, default: %d, valid: 4 to 31).\n"
+        "   -d   Force CRYPT encryption of the password (8 chars max, insecure).\n"
+        "   -s   Force SHA encryption of the password (insecure).\n"
+        "   -p   Do not encrypt the password (plaintext, insecure).\n"
+        "   -T   DBM Type (SDBM|GDBM|DB|default).\n"
+        "   -l   Display usernames from database on stdout.\n"
+        "   -v   Verify the username/password.\n"
+        "   -x   Remove the username record from database.\n"
+        "   -t   The last param is username comment.\n"
+        "The SHA algorithm does not use a salt and is less secure than the "
+        "MD5 algorithm.\n",
+        BCRYPT_DEFAULT_COST);
     exit(ERR_SYNTAX);
-
 }
 
-
 int main(int argc, const char * const argv[])
 {
     apr_pool_t *pool;
     apr_status_t rv;
-    apr_size_t l;
-    char pwi[MAX_STRING_LEN];
-    char pwc[MAX_STRING_LEN];
     char errbuf[MAX_STRING_LEN];
-    const char *arg;
     int  need_file = 1;
     int  need_user = 1;
     int  need_pwd  = 1;
     int  need_cmnt = 0;
-    int  pwd_supplied = 0;
-    int  changed;
+    int  changed = 0;
     int  cmd = HTDBM_MAKE;
-    int  i;
-    int args_left = 2;
+    int  i, ret, args_left = 2;
+    apr_getopt_t *state;
+    char opt;
+    const char *opt_arg;
 
     apr_app_initialize(&argc, &argv, NULL);
     atexit(terminate);
@@ -402,136 +332,95 @@ int main(int argc, const char * const argv[])
         apr_strerror(rv, errbuf, sizeof(errbuf));
         exit(1);
     }
-    /*
-     * Preliminary check to make sure they provided at least
-     * three arguments, we'll do better argument checking as 
-     * we parse the command line.
-     */
-    if (argc < 3)
-       htdbm_usage();
-    /*
-     * Go through the argument list and pick out any options.  They
-     * have to precede any other arguments.
-     */
-    for (i = 1; i < argc; i++) {
-        arg = argv[i];
-        if (*arg != '-')
+
+    rv = apr_getopt_init(&state, pool, argc, argv);
+    if (rv != APR_SUCCESS)
+        exit(ERR_SYNTAX);
+
+    while ((rv = apr_getopt(state, "cnmspdBbtivxlC:T:", &opt, &opt_arg)) == APR_SUCCESS) {
+        switch (opt) {
+        case 'c':
+            h->create = 1;
             break;
-        
-        while (*++arg != '\0') {
-            switch (*arg) {
-            case 'b':
-                pwd_supplied = 1;
-                need_pwd = 0;
-                args_left++;
-                break;
-            case 'c':
-                h->create = 1;
-                break;
-            case 'n':
-                need_file = 0;
-                cmd = HTDBM_NOFILE;
-                    args_left--;
-                break;
-            case 'l':
-                need_pwd = 0;
-                need_user = 0;
-                cmd = HTDBM_LIST;
-                h->rdonly = 1;
-                args_left--;
-                break;
-            case 't':
-                need_cmnt = 1;
-                args_left++;
-                break;
-            case 'T':
-                h->type = apr_pstrdup(h->pool, ++arg);
-                while (*arg != '\0')
-                    ++arg;
-                --arg; /* so incrementing this in the loop with find a null */
-                break;
-            case 'v':
-                h->rdonly = 1;
-                cmd = HTDBM_VERIFY;
-                break;
-            case 'x':
-                need_pwd = 0;
-                cmd = HTDBM_DELETE;
-                break;
-            case 'm':
-                h->alg = ALG_APMD5;
-                break;
-            case 'p':
-                h->alg = ALG_PLAIN;
-                break;
-            case 's':
-                h->alg = ALG_APSHA;
-                break;
-#if APR_HAVE_CRYPT_H
-            case 'd':
-                h->alg = ALG_CRYPT;
-                break;
-#endif
-            default:
-                htdbm_usage();
-                break;
+        case 'n':
+            need_file = 0;
+            cmd = HTDBM_NOFILE;
+            args_left--;
+            break;
+        case 'l':
+            need_pwd = 0;
+            need_user = 0;
+            cmd = HTDBM_LIST;
+            h->rdonly = 1;
+            args_left--;
+            break;
+        case 't':
+            need_cmnt = 1;
+            args_left++;
+            break;
+        case 'T':
+            h->type = apr_pstrdup(h->ctx.pool, opt_arg);
+            break;
+        case 'v':
+            h->rdonly = 1;
+            cmd = HTDBM_VERIFY;
+            break;
+        case 'x':
+            need_pwd = 0;
+            cmd = HTDBM_DELETE;
+            break;
+        default:
+            ret = parse_common_options(&h->ctx, opt, opt_arg);
+            if (ret) {
+                fprintf(stderr, "Error: %s\n", h->ctx.errstr);
+                exit(ret);
             }
         }
     }
+    if (h->ctx.passwd_src == PW_ARG) {
+            need_pwd = 0;
+            args_left++;
+    }
     /*
      * Make sure we still have exactly the right number of arguments left
      * (the filename, the username, and possibly the password if -b was
      * specified).
      */
-    if ((argc - i) != args_left)
+    i = state->ind;
+    if (rv != APR_EOF || argc - i != args_left)
         htdbm_usage();
 
-    if (!need_file)
-        i--;
-    else {
-        h->filename = apr_pstrdup(h->pool, argv[i]);
-            if ((rv = htdbm_open(h)) != APR_SUCCESS) {
-            fprintf(stderr, "Error opening database %s\n", argv[i]);
+    if (need_file) {
+        h->filename = apr_pstrdup(h->ctx.pool, argv[i++]);
+        if ((rv = htdbm_open(h)) != APR_SUCCESS) {
+            fprintf(stderr, "Error opening database %s\n", h->filename);
             apr_strerror(rv, errbuf, sizeof(errbuf));
             fprintf(stderr,"%s\n",errbuf);
             exit(ERR_FILEPERM);
         }
     }
     if (need_user) {
-        h->username = apr_pstrdup(pool, argv[i+1]);
+        h->username = apr_pstrdup(pool, argv[i++]);
         if (htdbm_valid_username(h) != APR_SUCCESS)
             exit(ERR_BADUSER);
     }
-    if (pwd_supplied)
-        h->userpass = apr_pstrdup(pool, argv[i+2]);
+    if (h->ctx.passwd_src == PW_ARG)
+        h->ctx.passwd = apr_pstrdup(pool, argv[i++]);
 
     if (need_pwd) {
-        l = sizeof(pwc);
-        if (apr_password_get("Enter password        : ", pwi, &l) != APR_SUCCESS) {
-            fprintf(stderr, "Password too long\n");
-            exit(ERR_OVERFLOW);
-        }
-        l = sizeof(pwc);
-        if (apr_password_get("Re-type password      : ", pwc, &l) != APR_SUCCESS) {
-            fprintf(stderr, "Password too long\n");
-            exit(ERR_OVERFLOW);
-        }
-        if (strcmp(pwi, pwc) != 0) {
-            fprintf(stderr, "Password verification error\n");
-            exit(ERR_PWMISMATCH);
+        ret = get_password(&h->ctx);
+        if (ret) {
+            fprintf(stderr, "Error: %s\n", h->ctx.errstr);
+            exit(ret);
         }
-            
-        h->userpass = apr_pstrdup(pool,  pwi);
     }
-    if (need_cmnt && pwd_supplied)
-        h->comment = apr_pstrdup(pool, argv[i+3]);
-    else if (need_cmnt)
-        h->comment = apr_pstrdup(pool, argv[i+2]);
+    if (need_cmnt)
+        h->comment = apr_pstrdup(pool, argv[i++]);
 
     switch (cmd) {
         case HTDBM_VERIFY:
             if ((rv = htdbm_verify(h)) != APR_SUCCESS) {
-                if(rv == APR_ENOENT) {
+                if (APR_STATUS_IS_ENOENT(rv)) {
                     fprintf(stderr, "The user '%s' could not be found in database\n", h->username);
                     exit(ERR_BADUSER);
                 }
@@ -555,28 +444,29 @@ int main(int argc, const char * const argv[])
             htdbm_list(h);
             break;
         default:
-            htdbm_make(h);
+            ret = htdbm_make(h);
+            if (ret)
+                exit(ret);
             break;
-
-    }    
+    }
     if (need_file && !h->rdonly) {
         if ((rv = htdbm_save(h, &changed)) != APR_SUCCESS) {
             apr_strerror(rv, errbuf, sizeof(errbuf));
             exit(ERR_FILEPERM);
         }
-        fprintf(stdout, "Database %s %s.\n", h->filename, 
+        fprintf(stdout, "Database %s %s.\n", h->filename,
                 h->create ? "created" : (changed ? "modified" : "updated"));
     }
     if (cmd == HTDBM_NOFILE) {
         if (!need_cmnt) {
-            fprintf(stderr, "%s:%s\n", h->username, h->userpass);
+            fprintf(stderr, "%s:%s\n", h->username, h->ctx.passwd);
         }
         else {
-            fprintf(stderr, "%s:%s:%s\n", h->username, h->userpass,
+            fprintf(stderr, "%s:%s:%s\n", h->username, h->ctx.passwd,
                     h->comment);
         }
     }
     htdbm_terminate(h);
-    
+
     return 0; /* Suppress compiler warning. */
 }