]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - helpers/basic_auth/NCSA/basic_ncsa_auth.cc
SourceFormat Enforcement
[thirdparty/squid.git] / helpers / basic_auth / NCSA / basic_ncsa_auth.cc
index a7f3de977a00487846fddb44d38a279a58bcdbe1..8f910b96ca5a47cb26127975cb496fd77586eff6 100644 (file)
@@ -1,6 +1,12 @@
 /*
- * ncsa_auth.c
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/*
  * AUTHOR: Arjan de Vet <Arjan.deVet@adv.iae.nl>
  *
  * Example authentication program for Squid, based on the original
  * - extra fields in the password file are ignored; this makes it
  *   possible to use a Unix password file but I do not recommend that.
  *
+ *  MD5 without salt and magic strings - Added by Ramon de Carvalho and Rodrigo Rubira Branco
  */
 
-#include "config.h"
+#include "squid.h"
+#include "crypt_md5.h"
+#include "hash.h"
+#include "helpers/defines.h"
+#include "rfc1738.h"
+#include "util.h"
 
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include <cerrno>
+#include <cstring>
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
 #if HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
 #include <crypt.h>
 #endif
 
-#include "util.h"
-#include "hash.h"
-#include "crypt_md5.h"
-
 static hash_table *hash = NULL;
 static HASHFREE my_free;
 
@@ -68,7 +66,7 @@ static void
 read_passwd_file(const char *passwdfile)
 {
     FILE *f;
-    char buf[8192];
+    char buf[HELPER_INPUT_BUFFER];
     user_data *u;
     char *user;
     char *passwd;
@@ -79,19 +77,26 @@ read_passwd_file(const char *passwdfile)
     /* initial setup */
     hash = hash_create((HASHCMP *) strcmp, 7921, hash_string);
     if (NULL == hash) {
-        fprintf(stderr, "ncsa_auth: cannot create hash table\n");
+        fprintf(stderr, "FATAL: Cannot create hash table\n");
         exit(1);
     }
     f = fopen(passwdfile, "r");
     if (NULL == f) {
-        fprintf(stderr, "%s: %s\n", passwdfile, xstrerror());
+        fprintf(stderr, "FATAL: %s: %s\n", passwdfile, xstrerror());
         exit(1);
     }
-    while (fgets(buf, 8192, f) != NULL) {
+    unsigned int lineCount = 0;
+    buf[HELPER_INPUT_BUFFER-1] = '\0';
+    while (fgets(buf, sizeof(buf)-1, f) != NULL) {
+        ++lineCount;
         if ((buf[0] == '#') || (buf[0] == ' ') || (buf[0] == '\t') ||
                 (buf[0] == '\n'))
             continue;
         user = strtok(buf, ":\n\r");
+        if (user == NULL) {
+            fprintf(stderr, "ERROR: Missing user name at %s line %d\n", passwdfile, lineCount);
+            continue;
+        }
         passwd = strtok(NULL, ":\n\r");
         if ((strlen(user) > 0) && passwd) {
             u = static_cast<user_data*>(xmalloc(sizeof(*u)));
@@ -108,7 +113,7 @@ main(int argc, char **argv)
 {
     struct stat sb;
     time_t change_time = -1;
-    char buf[256];
+    char buf[HELPER_INPUT_BUFFER];
     char *user, *passwd, *p;
     user_data *u;
     setbuf(stdout, NULL);
@@ -117,12 +122,12 @@ main(int argc, char **argv)
         exit(1);
     }
     if (stat(argv[1], &sb) != 0) {
-        fprintf(stderr, "cannot stat %s\n", argv[1]);
+        fprintf(stderr, "FATAL: cannot stat %s\n", argv[1]);
         exit(1);
     }
-    while (fgets(buf, 256, stdin) != NULL) {
+    while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != NULL) {
         if ((p = strchr(buf, '\n')) != NULL)
-            *p = '\0';         /* strip \n */
+            *p = '\0';      /* strip \n */
         if (stat(argv[1], &sb) == 0) {
             if (sb.st_mtime != change_time) {
                 read_passwd_file(argv[1]);
@@ -130,29 +135,51 @@ main(int argc, char **argv)
             }
         }
         if ((user = strtok(buf, " ")) == NULL) {
-            printf("ERR\n");
+            SEND_ERR("");
             continue;
         }
         if ((passwd = strtok(NULL, "")) == NULL) {
-            printf("ERR\n");
+            SEND_ERR("");
             continue;
         }
         rfc1738_unescape(user);
         rfc1738_unescape(passwd);
         u = (user_data *) hash_lookup(hash, user);
         if (u == NULL) {
-            printf("ERR No such user\n");
+            SEND_ERR("No such user");
+            continue;
+        }
+        char *crypted = NULL;
 #if HAVE_CRYPT
-        } else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd)) == 0) {
-            printf("OK\n");
+        size_t passwordLength = strlen(passwd);
+        // Bug 3831: given algorithms more secure than DES crypt() does not truncate, so we can ignore the bug 3107 length checks below
+        // '$1$' = MD5, '$2a$' = Blowfish, '$5$' = SHA256 (Linux), '$6$' = SHA256 (BSD) and SHA512
+        if (passwordLength > 1 && u->passwd[0] == '$' &&
+                (crypted = crypt(passwd, u->passwd)) && strcmp(u->passwd, crypted) == 0) {
+            SEND_OK("");
+            continue;
+        }
+        // 'other' prefixes indicate DES algorithm.
+        if (passwordLength <= 8 && (crypted = crypt(passwd, u->passwd)) && (strcmp(u->passwd, crypted) == 0)) {
+            SEND_OK("");
+            continue;
+        }
+        if (passwordLength > 8 && (crypted = crypt(passwd, u->passwd)) && (strcmp(u->passwd, crypted) == 0)) {
+            // Bug 3107: crypt() DES functionality silently truncates long passwords.
+            SEND_ERR("Password too long. Only 8 characters accepted.");
+            continue;
+        }
+
 #endif
-        } else if (strcmp(u->passwd, (char *) crypt_md5(passwd, u->passwd)) == 0) {
-            printf("OK\n");
-        } else if (strcmp(u->passwd, (char *) md5sum(passwd)) == 0) {  /* md5 without salt and magic strings - Added by Ramon de Carvalho and Rodrigo Rubira Branco */
-            printf("OK\n");
-        } else {
-            printf("ERR Wrong password\n");
+        if ( (crypted = crypt_md5(passwd, u->passwd)) && strcmp(u->passwd, crypted) == 0) {
+            SEND_OK("");
+            continue;
         }
+        if ( (crypted = md5sum(passwd)) && strcmp(u->passwd, crypted) == 0) {
+            SEND_OK("");
+            continue;
+        }
+        SEND_ERR("Wrong password");
     }
     if (hash != NULL) {
         hashFreeItems(hash, my_free);
@@ -160,3 +187,4 @@ main(int argc, char **argv)
     }
     exit(0);
 }
+