]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Summary: Merge in digest helper refactoring.
authorrobertc <>
Tue, 1 Apr 2003 17:39:38 +0000 (17:39 +0000)
committerrobertc <>
Tue, 1 Apr 2003 17:39:38 +0000 (17:39 +0000)
Keywords:

Patches applied:

  * robertc@squid-cache.org--squid/squid--digest-auth--3.0--patch-6
     Merge from HEAD.

  * robertc@squid-cache.org--squid/squid--digest-auth--3.0--patch-5
     Tweak digest helper.

  * robertc@squid-cache.org--squid/squid--digest-auth--3.0--patch-4
     Factor digest password helper for easy extension.

  * robertc@squid-cache.org--squid/squid--digest-auth--3.0--patch-3
     merge from HEAD.

helpers/digest_auth/password/Makefile.am
helpers/digest_auth/password/digest_common.h [new file with mode: 0644]
helpers/digest_auth/password/digest_pw_auth.c
helpers/digest_auth/password/text_backend.c [new file with mode: 0644]
helpers/digest_auth/password/text_backend.h [new file with mode: 0644]

index 72ab19aab468ff373ea5d532d45cb95d535c83dc..652410c8a48014178f2779b225198d2271972f46 100644 (file)
@@ -1,12 +1,16 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.am,v 1.2 2003/01/23 00:35:54 robertc Exp $
+#  $Id: Makefile.am,v 1.3 2003/04/01 10:39:38 robertc Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
 
 libexec_PROGRAMS = digest_pw_auth
+digest_pw_auth_SOURCES = digest_pw_auth.c \
+       digest_common.h \
+       text_backend.c \
+       text_backend.h
 INCLUDES      = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \
                -I$(top_srcdir)/src/
 
diff --git a/helpers/digest_auth/password/digest_common.h b/helpers/digest_auth/password/digest_common.h
new file mode 100644 (file)
index 0000000..e69f9fa
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * digest_common.h
+ *
+ * AUTHOR: Robert Collins.
+ *
+ * Digest helper API details.
+ *
+ * Copyright (c) 2003  Robert Collins  <robertc@squid-cache.org>
+ */
+
+#ifndef   _SQUID_DIGEST_COMMON_H_
+#define   _SQUID_DIGEST_COMMON_H_
+
+#include "config.h"
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#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
+#if HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+#include "util.h"
+#include "hash.h"
+#include "rfc2617.h"
+
+typedef struct _request_data {
+    char *user;
+    char *realm;
+    char *password;
+    HASHHEX HHA1;
+    int parsed;
+    int error;
+} RequestData;
+
+/* to use a backend, include your backend.h file 
+ * and define thusly: 
+ * #define ProcessArguments(A, B) MyHandleArguments(A,B)
+ * #define GetHHA1(A) MyGetHHA1(A)
+ */
+typedef void HandleArguments (int, char **);
+typedef void HHA1Creator(RequestData *);
+#endif /* _SQUID_DIGEST_COMMON_H_ */
index f5854b929c719d2069e1e5e4c5c2ec40679421ce..1e42d7da739052b7ad7198c12df22a88c9aaf143 100644 (file)
  * they allow the user access. Password syncronisation is not tackled
  * by digest - just preventing on the wire compromise.
  *
+ * Copyright (c) 2003  Robert Collins  <robertc@squid-cache.org>
  */
 
-#include "config.h"
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#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
-#if HAVE_CRYPT_H
-#include <crypt.h>
-#endif
-
-#include "util.h"
-#include "hash.h"
-#include "rfc2617.h"
-
-static hash_table *hash = NULL;
-static HASHFREE my_free;
-
-typedef struct _user_data {
-    hash_link hash;
-    char *passwd;
-    char *realm;
-} user_data;
+#include "digest_common.h"
+#include "text_backend.h"
 
 static void
-my_free(void *p)
+ParseBuffer(char *buf, RequestData *requestData)
 {
-    user_data *u = p;
-    xfree(u->hash.key);
-    xfree(u->passwd);
-    xfree(u);
+    char *p;
+    requestData->parsed = 0;
+    if ((p = strchr(buf, '\n')) != NULL)
+       *p = '\0';              /* strip \n */
+    if ((requestData->user = strtok(buf, "\"")) == NULL)
+       return;
+    if ((requestData->realm = strtok(NULL, "\"")) == NULL)
+       return;
+    if ((requestData->realm = strtok(NULL, "\"")) == NULL)
+       return;
+    requestData->parsed = -1;
 }
 
 static void
-read_passwd_file(const char *passwdfile, int ha1mode)
+OutputHHA1(RequestData *requestData)
 {
-    FILE *f;
-    char buf[8192];
-    user_data *u;
-    char *user;
-    char *passwd;
-    int passwdha1;
-
-    if (hash != NULL) {
-       hashFreeItems(hash, my_free);
+    requestData->error = 0;
+    GetHHA1(requestData);
+    if (requestData->error) {    
+       printf("ERR\n");
+       return;
     }
-    /* initial setup */
-    hash = hash_create((HASHCMP *) strcmp, 7921, hash_string);
-    if (NULL == hash) {
-       fprintf(stderr, "digest_pw_auth: cannot create hash table\n");
-       exit(1);
-    }
-    f = fopen(passwdfile, "r");
-    while (fgets(buf, 8192, f) != NULL) {
-       if ((buf[0] == '#') || (buf[0] == ' ') || (buf[0] == '\t') ||
-           (buf[0] == '\n'))
-           continue;
-       user = strtok(buf, ":\n");
-       passwd = strtok(NULL, ":\n");
-       if ((strlen(user) > 0) && passwd) {
-           passwdha1 = (strncmp("{HHA1}", passwd, 6))?0:1;
-           if (!ha1mode || passwdha1) {
-               u = xmalloc(sizeof(*u));
-               u->hash.key = xstrdup(user);
-               u->passwd = xstrdup(passwd);
-               hash_join(hash, &u->hash);
-           } else {
-               /* We cannot accept plaintext passwords when using HA1 encoding,
-                * as the passwords may be output to cache.log if debugging is on.
-                */
-               fprintf(stderr, "digest_pw_auth: ignoring %s password for %s\n",
-                       "plaintext", user);
-           }
-       }
+    printf("%s\n", requestData->HHA1);
+}
+
+static void
+DoOneRequest(char *buf)
+{
+    RequestData requestData;
+    ParseBuffer (buf, &requestData);
+    if (!requestData.parsed) {
+       printf ("ERR\n");
+       return;
     }
-    fclose(f);
+    OutputHHA1(&requestData);
 }
 
 int
 main(int argc, char **argv)
 {
-    struct stat sb;
-    time_t change_time = 0;
     char buf[256];
-    char *user, *realm, *p, *passwdfile=NULL;
-    user_data *u;
-    HASH HA1;
-    HASHHEX HHA1;
-    int ha1mode=0;
-
     setbuf(stdout, NULL);
-    if(argc == 2){
-        passwdfile = argv[1];
-    }
-    if((argc == 3) && !strcmp("-c", argv[1])){
-        ha1mode=1;
-        passwdfile = argv[2];
-    }
-    if (!passwdfile) {
-        fprintf(stderr, "Usage: digest_pw_auth [OPTIONS] <passwordfile>\n");
-        fprintf(stderr, "  -c   accept HHA1 passwords rather than plaintext in passwordfile\n");
-       exit(1);
-    }
-    if (stat(passwdfile, &sb) != 0) {
-       fprintf(stderr, "cannot stat %s\n", passwdfile);
-       exit(1);
-    }
-    while (fgets(buf, 256, stdin) != NULL) {
-       if ((p = strchr(buf, '\n')) != NULL)
-           *p = '\0';          /* strip \n */
-       if (stat(passwdfile, &sb) == 0) {
-           if (sb.st_mtime != change_time) {
-               read_passwd_file(passwdfile, ha1mode);
-               change_time = sb.st_mtime;
-           }
-       }
-       if (!hash) {
-           printf("ERR\n");
-           continue;
-       }
-       if ((user = strtok(buf, "\"")) == NULL) {
-           printf("ERR\n");
-           continue;
-       }
-       if ((realm = strtok(NULL, "\"")) == NULL) {
-           printf("ERR\n");
-           continue;
-       }
-       if ((realm = strtok(NULL, "\"")) == NULL) {
-           printf("ERR\n");
-           continue;
-       }
-       u = (user_data *)hash_lookup(hash, user);
-       if (u == NULL) {
-           printf("ERR\n");
-       } else {
-
-           if(! ha1mode )
-            {
-                DigestCalcHA1("md5", user, realm, u->passwd, NULL, NULL, HA1, HHA1);
-                printf("%s\n", HHA1);
-                /* fprintf(stderr, "digest_pw_auth: %s:{HHA1}%s\n", user, HHA1); */
-            }
-            else
-            {
-               printf("%s\n", &u->passwd[6]);
-            }
-       }
-    }
+    ProcessArguments (argc, argv);
+    while (fgets(buf, 256, stdin) != NULL)
+       DoOneRequest (buf);
     exit(0);
 }
diff --git a/helpers/digest_auth/password/text_backend.c b/helpers/digest_auth/password/text_backend.c
new file mode 100644 (file)
index 0000000..ee6fa34
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * text_backend.c
+ *
+ * AUTHOR: Robert Collins. Based on ncsa_auth.c by Arjan de Vet
+ * <Arjan.deVet@adv.iae.nl>
+ *
+ * Example digest auth text backend for Squid, based on the original
+ * proxy_auth code from client_side.c, written by
+ * Jon Thackray <jrmt@uk.gdscorp.com>.
+ *
+ * - comment lines are possible and should start with a '#';
+ * - empty or blank lines are possible;
+ * - file format is username:password
+ * 
+ * To build a directory integrated backend, you need to be able to
+ * calculate the HA1 returned to squid. To avoid storing a plaintext
+ * password you can calculate MD5(username:realm:password) when the
+ * user changes their password, and store the tuple username:realm:HA1.
+ * then find the matching username:realm when squid asks for the
+ * HA1.
+ *
+ * This implementation could be improved by using such a triple for
+ * the file format.  However storing such a triple does little to
+ * improve security: If compromised the username:realm:HA1 combination
+ * is "plaintext equivalent" - for the purposes of digest authentication
+ * they allow the user access. Password syncronisation is not tackled
+ * by digest - just preventing on the wire compromise.
+ *
+ * Copyright (c) 2003  Robert Collins  <robertc@squid-cache.org>
+ */
+
+#include "text_backend.h"
+
+static hash_table *hash = NULL;
+static HASHFREE my_free;
+static char *passwdfile = NULL;
+static int ha1mode=0;
+static time_t change_time = 0;
+
+typedef struct _user_data {
+    hash_link hash;
+    char *passwd;
+} user_data;
+
+static void
+my_free(void *p)
+{
+    user_data *u = p;
+    xfree(u->hash.key);
+    xfree(u->passwd);
+    xfree(u);
+}
+
+static void
+read_passwd_file(const char *passwdfile, int ha1mode)
+{
+    FILE *f;
+    char buf[8192];
+    user_data *u;
+    char *user;
+    char *passwd;
+    int passwdha1;
+
+    if (hash != NULL) {
+       hashFreeItems(hash, my_free);
+    }
+    /* initial setup */
+    hash = hash_create((HASHCMP *) strcmp, 7921, hash_string);
+    if (NULL == hash) {
+       fprintf(stderr, "digest_pw_auth: cannot create hash table\n");
+       exit(1);
+    }
+    f = fopen(passwdfile, "r");
+    while (fgets(buf, 8192, f) != NULL) {
+       if ((buf[0] == '#') || (buf[0] == ' ') || (buf[0] == '\t') ||
+           (buf[0] == '\n'))
+           continue;
+       user = strtok(buf, ":\n");
+       passwd = strtok(NULL, ":\n");
+       if ((strlen(user) > 0) && passwd) {
+           passwdha1 = (strncmp("{HHA1}", passwd, 6))?0:1;
+           if (!ha1mode || passwdha1) {
+               u = xmalloc(sizeof(*u));
+               u->hash.key = xstrdup(user);
+               u->passwd = xstrdup(passwd);
+               hash_join(hash, &u->hash);
+           } else {
+               /* We cannot accept plaintext passwords when using HA1 encoding,
+                * as the passwords may be output to cache.log if debugging is on.
+                */
+               fprintf(stderr, "digest_pw_auth: ignoring %s password for %s\n",
+                       "plaintext", user);
+           }
+       }
+    }
+    fclose(f);
+}
+
+/* replace when changing the backend */
+void
+TextArguments (int argc, char **argv)
+{
+    struct stat sb;
+    if(argc == 2)
+        passwdfile = argv[1];
+    if((argc == 3) && !strcmp("-c", argv[1])){
+        ha1mode=1;
+        passwdfile = argv[2];
+    }
+    if (!passwdfile) {
+        fprintf(stderr, "Usage: digest_pw_auth [OPTIONS] <passwordfile>\n");
+        fprintf(stderr, "  -c   accept HHA1 passwords rather than plaintext in passwordfile\n");
+       exit(1);
+    }
+    if (stat(passwdfile, &sb) != 0) {
+       fprintf(stderr, "cannot stat %s\n", passwdfile);
+       exit(1);
+    }
+}
+
+static void
+GetPassword (RequestData *requestData)
+{
+    user_data *u;
+    struct stat sb;
+    if (stat(passwdfile, &sb) == 0) {
+       if (sb.st_mtime != change_time) {
+           read_passwd_file(passwdfile, ha1mode);
+           change_time = sb.st_mtime;
+       }
+    }
+    requestData->password = NULL;
+    if (!hash)
+       return;
+    u = (user_data *)hash_lookup(hash, requestData->user);
+    if (u != NULL)
+       requestData->password = u->passwd;
+}
+
+void
+TextHHA1(RequestData *requestData)
+{
+    GetPassword (requestData);
+    if (requestData->password == NULL) {
+       requestData->error = -1;
+       return;
+    }
+    if(!ha1mode) {
+       HASH HA1;
+       DigestCalcHA1("md5", requestData->user, requestData->realm, requestData->password, NULL, NULL, HA1, requestData->HHA1);
+       
+       /* fprintf(stderr, "digest_pw_auth: %s:{HHA1}%s\n", requestData.user, HHA1); */
+    } else
+       xstrncpy (requestData->HHA1, &requestData->password[6], sizeof (requestData->HHA1));
+}
diff --git a/helpers/digest_auth/password/text_backend.h b/helpers/digest_auth/password/text_backend.h
new file mode 100644 (file)
index 0000000..ec52f1c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * text_backend.h
+ *
+ * AUTHOR: Robert Collins.
+ *
+ * Example digest authentication backend for Squid,
+ *
+ * - comment lines are possible and should start with a '#';
+ * - empty or blank lines are possible;
+ * - file format is username:password
+ * 
+ * This implementation could be improved by using such a triple for
+ * the file format.  However storing such a triple does little to
+ * improve security: If compromised the username:realm:HA1 combination
+ * is "plaintext equivalent" - for the purposes of digest authentication
+ * they allow the user access. Password syncronisation is not tackled
+ * by digest - just preventing on the wire compromise.
+ *
+ * Copyright (c) 2003  Robert Collins  <robertc@squid-cache.org>
+ */
+
+#include "digest_common.h"
+
+extern void TextArguments (int argc, char **argv);
+#define ProcessArguments(A, B) TextArguments(A,B)
+extern void TextHHA1(RequestData *requestData);
+#define GetHHA1(A) TextHHA1(A)