]> git.ipfire.org Git - thirdparty/squid.git/blob - helpers/basic_auth/NCSA/basic_ncsa_auth.cc
Bug 3038: Detatch libmisc from libcompat
[thirdparty/squid.git] / helpers / basic_auth / NCSA / basic_ncsa_auth.cc
1 /*
2 * AUTHOR: Arjan de Vet <Arjan.deVet@adv.iae.nl>
3 *
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>.
7 *
8 * Uses a NCSA httpd style password file for authentication with the
9 * following improvements suggested by various people:
10 *
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.
15 *
16 */
17
18 #include "config.h"
19 #include "crypt_md5.h"
20 #include "hash.h"
21 #include "helpers/defines.h"
22 #include "rfc1738.h"
23 #include "util.h"
24
25 #if HAVE_STDIO_H
26 #include <stdio.h>
27 #endif
28 #if HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #if HAVE_STRING_H
32 #include <string.h>
33 #endif
34 #if HAVE_SYS_STAT_H
35 #include <sys/stat.h>
36 #endif
37 #if HAVE_CRYPT_H
38 #include <crypt.h>
39 #endif
40 #if HAVE_ERRNO_H
41 #include <errno.h>
42 #endif
43
44 static hash_table *hash = NULL;
45 static HASHFREE my_free;
46
47 typedef struct _user_data {
48 /* first two items must be same as hash_link */
49 char *user;
50 struct _user_data *next;
51 char *passwd;
52 } user_data;
53
54 static void
55 my_free(void *p)
56 {
57 user_data *u = static_cast<user_data*>(p);
58 xfree(u->user);
59 xfree(u->passwd);
60 xfree(u);
61 }
62
63 static void
64 read_passwd_file(const char *passwdfile)
65 {
66 FILE *f;
67 char buf[8192];
68 user_data *u;
69 char *user;
70 char *passwd;
71 if (hash != NULL) {
72 hashFreeItems(hash, my_free);
73 hashFreeMemory(hash);
74 }
75 /* initial setup */
76 hash = hash_create((HASHCMP *) strcmp, 7921, hash_string);
77 if (NULL == hash) {
78 fprintf(stderr, "FATAL: Cannot create hash table\n");
79 exit(1);
80 }
81 f = fopen(passwdfile, "r");
82 if (NULL == f) {
83 fprintf(stderr, "FATAL: %s: %s\n", passwdfile, xstrerror());
84 exit(1);
85 }
86 while (fgets(buf, 8192, f) != NULL) {
87 if ((buf[0] == '#') || (buf[0] == ' ') || (buf[0] == '\t') ||
88 (buf[0] == '\n'))
89 continue;
90 user = strtok(buf, ":\n\r");
91 passwd = strtok(NULL, ":\n\r");
92 if ((strlen(user) > 0) && passwd) {
93 u = static_cast<user_data*>(xmalloc(sizeof(*u)));
94 u->user = xstrdup(user);
95 u->passwd = xstrdup(passwd);
96 hash_join(hash, (hash_link *) u);
97 }
98 }
99 fclose(f);
100 }
101
102 int
103 main(int argc, char **argv)
104 {
105 struct stat sb;
106 time_t change_time = -1;
107 char buf[HELPER_INPUT_BUFFER];
108 char *user, *passwd, *p;
109 user_data *u;
110 setbuf(stdout, NULL);
111 if (argc != 2) {
112 fprintf(stderr, "Usage: ncsa_auth <passwordfile>\n");
113 exit(1);
114 }
115 if (stat(argv[1], &sb) != 0) {
116 fprintf(stderr, "FATAL: cannot stat %s\n", argv[1]);
117 exit(1);
118 }
119 while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != NULL) {
120 if ((p = strchr(buf, '\n')) != NULL)
121 *p = '\0'; /* strip \n */
122 if (stat(argv[1], &sb) == 0) {
123 if (sb.st_mtime != change_time) {
124 read_passwd_file(argv[1]);
125 change_time = sb.st_mtime;
126 }
127 }
128 if ((user = strtok(buf, " ")) == NULL) {
129 SEND_ERR("");
130 continue;
131 }
132 if ((passwd = strtok(NULL, "")) == NULL) {
133 SEND_ERR("");
134 continue;
135 }
136 rfc1738_unescape(user);
137 rfc1738_unescape(passwd);
138 u = (user_data *) hash_lookup(hash, user);
139 if (u == NULL) {
140 SEND_ERR("No such user");
141 #if HAVE_CRYPT
142 } else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd)) == 0) {
143 SEND_OK("");
144 #endif
145 } else if (strcmp(u->passwd, (char *) crypt_md5(passwd, u->passwd)) == 0) {
146 SEND_OK("");
147 } else if (strcmp(u->passwd, (char *) md5sum(passwd)) == 0) { /* md5 without salt and magic strings - Added by Ramon de Carvalho and Rodrigo Rubira Branco */
148 SEND_OK("");
149 } else {
150 SEND_ERR("Wrong password");
151 }
152 }
153 if (hash != NULL) {
154 hashFreeItems(hash, my_free);
155 hashFreeMemory(hash);
156 }
157 exit(0);
158 }