]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/basic_auth/NCSA/basic_ncsa_auth.cc
2 * AUTHOR: Arjan de Vet <Arjan.deVet@adv.iae.nl>
4 * Example authentication program for Squid, based on the original
5 * proxy_auth code from client_side.c, written by
6 * Jon Thackray <jrmt@uk.gdscorp.com>.
8 * Uses a NCSA httpd style password file for authentication with the
9 * following improvements suggested by various people:
11 * - comment lines are possible and should start with a '#';
12 * - empty or blank lines are possible;
13 * - extra fields in the password file are ignored; this makes it
14 * possible to use a Unix password file but I do not recommend that.
16 * MD5 without salt and magic strings - Added by Ramon de Carvalho and Rodrigo Rubira Branco
20 #include "crypt_md5.h"
22 #include "helpers/defines.h"
38 static hash_table
*hash
= NULL
;
39 static HASHFREE my_free
;
41 typedef struct _user_data
{
42 /* first two items must be same as hash_link */
44 struct _user_data
*next
;
51 user_data
*u
= static_cast<user_data
*>(p
);
58 read_passwd_file(const char *passwdfile
)
61 char buf
[HELPER_INPUT_BUFFER
];
66 hashFreeItems(hash
, my_free
);
70 hash
= hash_create((HASHCMP
*) strcmp
, 7921, hash_string
);
72 fprintf(stderr
, "FATAL: Cannot create hash table\n");
75 f
= fopen(passwdfile
, "r");
77 fprintf(stderr
, "FATAL: %s: %s\n", passwdfile
, xstrerror());
80 unsigned int lineCount
= 0;
81 buf
[HELPER_INPUT_BUFFER
-1] = '\0';
82 while (fgets(buf
, sizeof(buf
)-1, f
) != NULL
) {
84 if ((buf
[0] == '#') || (buf
[0] == ' ') || (buf
[0] == '\t') ||
87 user
= strtok(buf
, ":\n\r");
89 fprintf(stderr
, "ERROR: Missing user name at %s line %d\n", passwdfile
, lineCount
);
92 passwd
= strtok(NULL
, ":\n\r");
93 if ((strlen(user
) > 0) && passwd
) {
94 u
= static_cast<user_data
*>(xmalloc(sizeof(*u
)));
95 u
->user
= xstrdup(user
);
96 u
->passwd
= xstrdup(passwd
);
97 hash_join(hash
, (hash_link
*) u
);
104 main(int argc
, char **argv
)
107 time_t change_time
= -1;
108 char buf
[HELPER_INPUT_BUFFER
];
109 char *user
, *passwd
, *p
;
111 setbuf(stdout
, NULL
);
113 fprintf(stderr
, "Usage: ncsa_auth <passwordfile>\n");
116 if (stat(argv
[1], &sb
) != 0) {
117 fprintf(stderr
, "FATAL: cannot stat %s\n", argv
[1]);
120 while (fgets(buf
, HELPER_INPUT_BUFFER
, stdin
) != NULL
) {
121 if ((p
= strchr(buf
, '\n')) != NULL
)
122 *p
= '\0'; /* strip \n */
123 if (stat(argv
[1], &sb
) == 0) {
124 if (sb
.st_mtime
!= change_time
) {
125 read_passwd_file(argv
[1]);
126 change_time
= sb
.st_mtime
;
129 if ((user
= strtok(buf
, " ")) == NULL
) {
133 if ((passwd
= strtok(NULL
, "")) == NULL
) {
137 rfc1738_unescape(user
);
138 rfc1738_unescape(passwd
);
139 u
= (user_data
*) hash_lookup(hash
, user
);
141 SEND_ERR("No such user");
144 char *crypted
= NULL
;
146 size_t passwordLength
= strlen(passwd
);
147 // Bug 3831: given algorithms more secure than DES crypt() does not truncate, so we can ignore the bug 3107 length checks below
148 // '$1$' = MD5, '$2a$' = Blowfish, '$5$' = SHA256 (Linux), '$6$' = SHA256 (BSD) and SHA512
149 if (passwordLength
> 1 && u
->passwd
[0] == '$' &&
150 (crypted
= crypt(passwd
, u
->passwd
)) && strcmp(u
->passwd
, crypted
) == 0) {
154 // 'other' prefixes indicate DES algorithm.
155 if (passwordLength
<= 8 && (crypted
= crypt(passwd
, u
->passwd
)) && (strcmp(u
->passwd
, crypted
) == 0)) {
159 if (passwordLength
> 8 && (crypted
= crypt(passwd
, u
->passwd
)) && (strcmp(u
->passwd
, crypted
) == 0)) {
160 // Bug 3107: crypt() DES functionality silently truncates long passwords.
161 SEND_ERR("Password too long. Only 8 characters accepted.");
166 if ( (crypted
= crypt_md5(passwd
, u
->passwd
)) && strcmp(u
->passwd
, crypted
) == 0) {
170 if ( (crypted
= md5sum(passwd
)) && strcmp(u
->passwd
, crypted
) == 0) {
174 SEND_ERR("Wrong password");
177 hashFreeItems(hash
, my_free
);
178 hashFreeMemory(hash
);