]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/basic_auth/NCSA/basic_ncsa_auth.cc
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 * AUTHOR: Arjan de Vet <Arjan.deVet@adv.iae.nl>
12 * Example authentication program for Squid, based on the original
13 * proxy_auth code from client_side.c, written by
14 * Jon Thackray <jrmt@uk.gdscorp.com>.
16 * Uses a NCSA httpd style password file for authentication with the
17 * following improvements suggested by various people:
19 * - comment lines are possible and should start with a '#';
20 * - empty or blank lines are possible;
21 * - extra fields in the password file are ignored; this makes it
22 * possible to use a Unix password file but I do not recommend that.
24 * MD5 without salt and magic strings - Added by Ramon de Carvalho and Rodrigo Rubira Branco
28 #include "crypt_md5.h"
29 #include "helpers/defines.h"
32 #include <unordered_map>
40 typedef std::unordered_map
<std::string
, std::string
> usermap_t
;
44 read_passwd_file(const char *passwdfile
)
47 char buf
[HELPER_INPUT_BUFFER
];
52 //TODO: change to c++ streams
53 f
= fopen(passwdfile
, "r");
55 fprintf(stderr
, "FATAL: %s: %s\n", passwdfile
, xstrerror());
58 unsigned int lineCount
= 0;
59 buf
[HELPER_INPUT_BUFFER
-1] = '\0';
60 while (fgets(buf
, sizeof(buf
)-1, f
) != NULL
) {
62 if ((buf
[0] == '#') || (buf
[0] == ' ') || (buf
[0] == '\t') ||
65 user
= strtok(buf
, ":\n\r");
67 fprintf(stderr
, "ERROR: Missing user name at %s line %d\n", passwdfile
, lineCount
);
70 passwd
= strtok(NULL
, ":\n\r");
71 if ((strlen(user
) > 0) && passwd
) {
72 usermap
[user
] = passwd
;
79 main(int argc
, char **argv
)
82 time_t change_time
= -1;
83 char buf
[HELPER_INPUT_BUFFER
];
84 char *user
, *passwd
, *p
;
87 fprintf(stderr
, "Usage: ncsa_auth <passwordfile>\n");
90 if (stat(argv
[1], &sb
) != 0) {
91 fprintf(stderr
, "FATAL: cannot stat %s\n", argv
[1]);
94 while (fgets(buf
, HELPER_INPUT_BUFFER
, stdin
) != NULL
) {
95 if ((p
= strchr(buf
, '\n')) != NULL
)
96 *p
= '\0'; /* strip \n */
97 if (stat(argv
[1], &sb
) == 0) {
98 if (sb
.st_mtime
!= change_time
) {
99 read_passwd_file(argv
[1]);
100 change_time
= sb
.st_mtime
;
103 if ((user
= strtok(buf
, " ")) == NULL
) {
107 if ((passwd
= strtok(NULL
, "")) == NULL
) {
111 rfc1738_unescape(user
);
112 rfc1738_unescape(passwd
);
113 const auto userpassIterator
= usermap
.find(user
);
114 if (userpassIterator
== usermap
.end()) {
115 SEND_ERR("No such user");
118 std::string stored_pass
= userpassIterator
->second
;
120 char *crypted
= NULL
;
122 size_t passwordLength
= strlen(passwd
);
123 // Bug 3831: given algorithms more secure than DES crypt() does not truncate, so we can ignore the bug 3107 length checks below
124 // '$1$' = MD5, '$2a$' = Blowfish, '$5$' = SHA256 (Linux), '$6$' = SHA256 (BSD) and SHA512
125 if (passwordLength
> 1 && stored_pass
[0] == '$' &&
126 (crypted
= crypt(passwd
, stored_pass
.c_str())) && stored_pass
== crypted
) {
130 // 'other' prefixes indicate DES algorithm.
131 if (passwordLength
<= 8 && (crypted
= crypt(passwd
, stored_pass
.c_str())) && stored_pass
== crypted
) {
135 if (passwordLength
> 8 && (crypted
= crypt(passwd
, stored_pass
.c_str())) && stored_pass
== crypted
) {
136 // Bug 3107: crypt() DES functionality silently truncates long passwords.
137 SEND_ERR("Password too long. Only 8 characters accepted.");
142 if ( (crypted
= crypt_md5(passwd
, stored_pass
.c_str())) && stored_pass
== crypted
) {
146 if ( (crypted
= md5sum(passwd
)) && stored_pass
== crypted
) {
150 SEND_ERR("Wrong password");