]> granicus.if.org Git - apache/blobdiff - support/htdbm.c
Fix integer overflow in ap_pregsub. This can be triggered e.g.
[apache] / support / htdbm.c
index 3272181ff0738ce9ac57a4c2f79aaa9b3dd76e9f..f9a02bd49cd323bf9dda642cd1b5410ae5c52ebf 100644 (file)
@@ -1,8 +1,9 @@
-/* Copyright 2001-2004 Apache Software Foundation
- *
- * 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
  *
@@ -47,6 +48,9 @@
 #include "apr_xlate.h"
 #endif /*APR_CHARSET_EBCDIC*/
 
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #if APR_HAVE_CRYPT_H
 #include <crypt.h>
 #endif
@@ -64,8 +68,8 @@
 #define ALG_PLAIN 0
 #define ALG_APMD5 1
 #define ALG_APSHA 2
-#if APR_HAVE_CRYPT_H
+
+#if (!(defined(WIN32) || defined(NETWARE)))
 #define ALG_CRYPT 3
 #endif
 
@@ -105,24 +109,31 @@ struct htdbm_t {
 #define HTDBM_NOFILE 4
 #define HTDBM_STDIN  5
 
-static void htdbm_terminate(htdbm_t *htdbm) 
+static void terminate(void)
+{
+    apr_terminate();
+#ifdef NETWARE
+    pressanykey();
+#endif
+}
+
+static void htdbm_terminate(htdbm_t *htdbm)
 {
-    
     if (htdbm->dbm)
         apr_dbm_close(htdbm->dbm);
     htdbm->dbm = NULL;
 }
 
 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
@@ -136,7 +147,7 @@ static apr_status_t htdbm_init(apr_pool_t **pool, htdbm_t **hdbm)
     (*hdbm)->pool = *pool;
 
 #if APR_CHARSET_EBCDIC
-    rv = apr_xlate_open(&((*hdbm)->to_ascii), "ISO8859-1", APR_DEFAULT_CHARSET, (*hdbm)->pool);
+    rv = apr_xlate_open(&((*hdbm)->to_ascii), "ISO-8859-1", APR_DEFAULT_CHARSET, (*hdbm)->pool);
     if (rv) {
         fprintf(stderr, "apr_xlate_open(to ASCII)->%d\n", rv);
         return APR_EGENERAL;
@@ -159,18 +170,18 @@ static apr_status_t htdbm_init(apr_pool_t **pool, htdbm_t **hdbm)
     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, 
+        return apr_dbm_open_ex(&htdbm->dbm, htdbm->type, htdbm->filename, APR_DBM_RWCREATE,
                             APR_OS_DEFAULT, htdbm->pool);
     else
-        return apr_dbm_open_ex(&htdbm->dbm, htdbm->type, htdbm->filename, 
-                            htdbm->rdonly ? APR_DBM_READONLY : APR_DBM_READWRITE, 
+        return apr_dbm_open_ex(&htdbm->dbm, htdbm->type, htdbm->filename,
+                            htdbm->rdonly ? APR_DBM_READONLY : APR_DBM_READWRITE,
                             APR_OS_DEFAULT, htdbm->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;
 
@@ -193,7 +204,7 @@ static apr_status_t htdbm_save(htdbm_t *htdbm, int *changed)
     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;
 
@@ -205,58 +216,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, ';');
+    cmnt = strchr(rec, ':');
     if (cmnt)
-        strncpy(pwd, rec, cmnt - rec);
+        pwd = apr_pstrndup(htdbm->pool, rec, cmnt - rec);
     else
-        strcpy(pwd, rec);
+        pwd = apr_pstrdup(htdbm->pool, rec);
     return apr_password_validate(htdbm->userpass, 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, 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)
@@ -279,7 +284,7 @@ static void to64(char *s, unsigned long v, int n)
     }
 }
 
-static apr_status_t htdbm_make(htdbm_t *htdbm) 
+static apr_status_t htdbm_make(htdbm_t *htdbm)
 {
     char cpw[MAX_STRING_LEN];
     char salt[9];
@@ -290,7 +295,7 @@ static apr_status_t htdbm_make(htdbm_t *htdbm)
             apr_sha1_base64(htdbm->userpass,strlen(htdbm->userpass),cpw);
         break;
 
-        case ALG_APMD5: 
+        case ALG_APMD5:
             (void) srand((int) time((time_t *) NULL));
             to64(&salt[0], rand(), 8);
             salt[8] = '\0';
@@ -300,13 +305,17 @@ static apr_status_t htdbm_make(htdbm_t *htdbm)
         case ALG_PLAIN:
             /* XXX this len limitation is not in sync with any HTTPd len. */
             apr_cpystrn(cpw,htdbm->userpass,sizeof(cpw));
+#if (!(defined(WIN32) || defined(NETWARE)))
+            fprintf(stderr, "Warning: Plain text passwords aren't supported by the "
+                    "server on this platform!\n");
+#endif
         break;
-#if APR_HAVE_CRYPT_H
+#if (!(defined(WIN32) || defined(NETWARE)))
         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);
+            apr_cpystrn(cpw, crypt(htdbm->userpass, salt), sizeof(cpw) - 1);
             fprintf(stderr, "CRYPT is now deprecated, use MD5 instead!\n");
 #endif
         default:
@@ -332,7 +341,7 @@ static apr_status_t htdbm_valid_username(htdbm_t *htdbm)
 static void htdbm_usage(void)
 {
 
-#if APR_HAVE_CRYPT_H
+#if (!(defined(WIN32) || defined(NETWARE)))
 #define CRYPT_OPTION "d"
 #else
 #define CRYPT_OPTION ""
@@ -352,7 +361,7 @@ static void htdbm_usage(void)
     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
+#if (!(defined(WIN32) || defined(NETWARE)))
     fprintf(stderr, "   -d   Force CRYPT encryption of the password (now deprecated).\n");
 #endif
     fprintf(stderr, "   -p   Do not encrypt the password (plaintext).\n");
@@ -381,13 +390,13 @@ int main(int argc, const char * const argv[])
     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;
 
     apr_app_initialize(&argc, &argv, NULL);
-    atexit(apr_terminate);
+    atexit(terminate);
 
     if ((rv = htdbm_init(&pool, &h)) != APR_SUCCESS) {
         fprintf(stderr, "Unable to initialize htdbm terminating!\n");
@@ -396,7 +405,7 @@ int main(int argc, const char * const argv[])
     }
     /*
      * Preliminary check to make sure they provided at least
-     * three arguments, we'll do better argument checking as 
+     * three arguments, we'll do better argument checking as
      * we parse the command line.
      */
     if (argc < 3)
@@ -409,7 +418,7 @@ int main(int argc, const char * const argv[])
         arg = argv[i];
         if (*arg != '-')
             break;
-        
+
         while (*++arg != '\0') {
             switch (*arg) {
             case 'b':
@@ -459,7 +468,7 @@ int main(int argc, const char * const argv[])
             case 's':
                 h->alg = ALG_APSHA;
                 break;
-#if APR_HAVE_CRYPT_H
+#if (!(defined(WIN32) || defined(NETWARE)))
             case 'd':
                 h->alg = ALG_CRYPT;
                 break;
@@ -512,7 +521,7 @@ int main(int argc, const char * const argv[])
             fprintf(stderr, "Password verification error\n");
             exit(ERR_PWMISMATCH);
         }
-            
+
         h->userpass = apr_pstrdup(pool,  pwi);
     }
     if (need_cmnt && pwd_supplied)
@@ -523,7 +532,7 @@ int main(int argc, const char * const argv[])
     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);
                 }
@@ -550,13 +559,13 @@ int main(int argc, const char * const argv[])
             htdbm_make(h);
             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) {
@@ -569,7 +578,6 @@ int main(int argc, const char * const argv[])
         }
     }
     htdbm_terminate(h);
-    apr_terminate();
-    
+
     return 0; /* Suppress compiler warning. */
 }