]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/negotiate_auth/mswin_sspi/negotiate_auth.c
Silence rm -v again
[thirdparty/squid.git] / helpers / negotiate_auth / mswin_sspi / negotiate_auth.c
CommitLineData
766743af 1
6e785d85 2/*
2f127098 3 * mswin_negotiate_auth: helper for Negotiate Authentication for Squid Cache
6e785d85 4 *
5 * (C)2005 Guido Serassio - Acme Consulting S.r.l.
6 *
7 * Authors:
8 * Guido Serassio <guido.serassio@acmeconsulting.it>
9 * Acme Consulting S.r.l., Italy <http://www.acmeconsulting.it>
10 *
11 * With contributions from others mentioned in the change history section
12 * below.
13 *
14 * Based on previous work of Francesco Chemolli and Robert Collins.
15 *
9af66127 16 * Dependencies: Windows 2000 and later.
6e785d85 17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
31 *
32 * History:
33 *
34 * Version 1.0
35 * 29-10-2005 Guido Serassio
36 * First release.
37 *
38 *
39 */
40
41#include "util.h"
42#if HAVE_GETOPT_H
43#include <getopt.h>
44#endif
45#include "negotiate.h"
46#if HAVE_CTYPE_H
47#include <ctype.h>
48#endif
49
50#define BUFFER_SIZE 10240
51
52int debug_enabled = 0;
53int Negotiate_packet_debug_enabled = 0;
54
55static int have_serverblob;
56
57/* makes a null-terminated string upper-case. Changes CONTENTS! */
58void
59uc(char *string)
60{
61 char *p = string, c;
62 while ((c = *p)) {
766743af
GS
63 *p = xtoupper(c);
64 p++;
6e785d85 65 }
66}
67
68/* makes a null-terminated string lower-case. Changes CONTENTS! */
69static void
70lc(char *string)
71{
72 char *p = string, c;
73 while ((c = *p)) {
766743af
GS
74 *p = xtolower(c);
75 p++;
6e785d85 76 }
77}
78
79void
80helperfail(const char *reason)
81{
82#if FAIL_DEBUG
766743af 83 fail_debug_enabled = 1;
6e785d85 84#endif
85 SEND2("BH %s", reason);
86}
87
88/*
766743af
GS
89 * options:
90 * -d enable debugging.
91 * -v enable verbose Negotiate packet debugging.
6e785d85 92 */
93char *my_program_name = NULL;
94
95void
96usage()
97{
98 fprintf(stderr,
766743af
GS
99 "Usage: %s [-d] [-v] [-h]\n"
100 " -d enable debugging.\n"
101 " -v enable verbose Negotiate packet debugging.\n"
102 " -h this message\n\n",
103 my_program_name);
6e785d85 104}
105
106
107void
108process_options(int argc, char *argv[])
109{
110 int opt, had_error = 0;
111
766743af 112 opterr = 0;
6e785d85 113 while (-1 != (opt = getopt(argc, argv, "hdv"))) {
766743af
GS
114 switch (opt) {
115 case 'd':
116 debug_enabled = 1;
117 break;
118 case 'v':
119 debug_enabled = 1;
120 Negotiate_packet_debug_enabled = 1;
121 break;
122 case 'h':
123 usage();
124 exit(0);
125 case '?':
126 opt = optopt;
127 /* fall thru to default */
128 default:
129 fprintf(stderr, "unknown option: -%c. Exiting\n", opt);
130 usage();
131 had_error = 1;
132 }
6e785d85 133 }
134 if (had_error)
766743af 135 exit(1);
6e785d85 136}
137
138int
139manage_request()
140{
141 char buf[BUFFER_SIZE];
142 char helper_command[3];
143 char *c, *decoded;
144 int plen, status;
145 int oversized = 0;
766743af
GS
146 char *ErrorMessage;
147 static char cred[SSP_MAX_CRED_LEN + 1];
6e785d85 148 BOOL Done = FALSE;
149
766743af 150 try_again:
26ac0430 151 if (fgets(buf, BUFFER_SIZE, stdin) == NULL)
766743af 152 return 0;
6e785d85 153
766743af 154 c = memchr(buf, '\n', BUFFER_SIZE); /* safer against overrun than strchr */
6e785d85 155 if (c) {
766743af
GS
156 if (oversized) {
157 helperfail("illegal request received");
158 fprintf(stderr, "Illegal request received: '%s'\n", buf);
159 return 1;
160 }
161 *c = '\0';
6e785d85 162 } else {
766743af
GS
163 fprintf(stderr, "No newline in '%s'\n", buf);
164 oversized = 1;
165 goto try_again;
6e785d85 166 }
167
168 if ((strlen(buf) > 3) && Negotiate_packet_debug_enabled) {
766743af
GS
169 decoded = base64_decode(buf + 3);
170 strncpy(helper_command, buf, 2);
171 debug("Got '%s' from Squid with data:\n", helper_command);
172 hex_dump(decoded, ((strlen(buf) - 3) * 3) / 4);
6e785d85 173 } else
766743af 174 debug("Got '%s' from Squid\n", buf);
6e785d85 175
176 if (memcmp(buf, "YR ", 3) == 0) { /* refresh-request */
766743af
GS
177 /* figure out what we got */
178 decoded = base64_decode(buf + 3);
179 /* Note: we don't need to manage memory at this point, since
180 * base64_decode returns a pointer to static storage.
181 */
182 if (!decoded) { /* decoding failure, return error */
183 SEND("NA * Packet format error, couldn't base64-decode");
184 return 1;
185 }
186 /* Obtain server blob against SSPI */
187 plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */
188 c = (char *) SSP_MakeNegotiateBlob(decoded, plen, &Done, &status, cred);
6e785d85 189
766743af
GS
190 if (status == SSP_OK) {
191 if (Done) {
192 lc(cred); /* let's lowercase them for our convenience */
193 have_serverblob = 0;
194 Done = FALSE;
195 if (Negotiate_packet_debug_enabled) {
196 decoded = base64_decode(c);
197 debug("sending 'AF' %s to squid with data:\n", cred);
198 if (c != NULL)
199 hex_dump(decoded, (strlen(c) * 3) / 4);
200 else
201 fprintf(stderr, "No data available.\n");
202 printf("AF %s %s\n", c, cred);
203 } else
204 SEND3("AF %s %s", c, cred);
205 } else {
206 if (Negotiate_packet_debug_enabled) {
207 decoded = base64_decode(c);
208 debug("sending 'TT' to squid with data:\n");
209 hex_dump(decoded, (strlen(c) * 3) / 4);
210 printf("TT %s\n", c);
211 } else {
212 SEND2("TT %s", c);
213 }
214 have_serverblob = 1;
215 }
216 } else
217 helperfail("can't obtain server blob");
218 return 1;
6e785d85 219 }
6e785d85 220 if (memcmp(buf, "KK ", 3) == 0) { /* authenticate-request */
766743af
GS
221 if (!have_serverblob) {
222 helperfail("invalid server blob");
223 return 1;
224 }
225 /* figure out what we got */
226 decoded = base64_decode(buf + 3);
227 /* Note: we don't need to manage memory at this point, since
228 * base64_decode returns a pointer to static storage.
229 */
230 if (!decoded) { /* decoding failure, return error */
231 SEND("NA * Packet format error, couldn't base64-decode");
232 return 1;
233 }
234 /* check against SSPI */
235 plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */
236 c = (char *) SSP_ValidateNegotiateCredentials(decoded, plen, &Done, &status, cred);
6e785d85 237
766743af 238 if (status == SSP_ERROR) {
6e785d85 239#if FAIL_DEBUG
766743af 240 fail_debug_enabled = 1;
6e785d85 241#endif
766743af
GS
242 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
243 FORMAT_MESSAGE_IGNORE_INSERTS,
244 NULL,
245 GetLastError(),
246 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
247 (LPTSTR) & ErrorMessage,
248 0,
249 NULL);
250 if (ErrorMessage[strlen(ErrorMessage) - 1] == '\n')
251 ErrorMessage[strlen(ErrorMessage) - 1] = '\0';
252 if (ErrorMessage[strlen(ErrorMessage) - 1] == '\r')
253 ErrorMessage[strlen(ErrorMessage) - 1] = '\0';
254 SEND2("NA * %s", ErrorMessage);
255 LocalFree(ErrorMessage);
256 return 1;
257 }
258 if (Done) {
259 lc(cred); /* let's lowercase them for our convenience */
260 have_serverblob = 0;
261 Done = FALSE;
262 if (Negotiate_packet_debug_enabled) {
263 decoded = base64_decode(c);
264 debug("sending 'AF' %s to squid with data:\n", cred);
265 if (c != NULL)
266 hex_dump(decoded, (strlen(c) * 3) / 4);
267 else
268 fprintf(stderr, "No data available.\n");
269 printf("AF %s %s\n", c, cred);
270 } else {
271 SEND3("AF %s %s", c, cred);
272 }
273 return 1;
274 } else {
275 if (Negotiate_packet_debug_enabled) {
276 decoded = base64_decode(c);
277 debug("sending 'TT' to squid with data:\n");
278 hex_dump(decoded, (strlen(c) * 3) / 4);
279 printf("TT %s\n", c);
280 } else
281 SEND2("TT %s", c);
282 return 1;
283 }
6e785d85 284
766743af
GS
285 } else { /* not an auth-request */
286 helperfail("illegal request received");
287 fprintf(stderr, "Illegal request received: '%s'\n", buf);
288 return 1;
6e785d85 289 }
290 helperfail("detected protocol error");
291 return 1;
766743af 292/********* END ********/
6e785d85 293}
294
295int
296main(int argc, char *argv[])
297{
298 my_program_name = argv[0];
299
300 process_options(argc, argv);
301
302 debug("%s build " __DATE__ ", " __TIME__ " starting up...\n", my_program_name);
26ac0430 303
6e785d85 304 if (LoadSecurityDll(SSP_NTLM, NEGOTIATE_PACKAGE_NAME) == NULL) {
766743af
GS
305 fprintf(stderr, "FATAL, can't initialize SSPI, exiting.\n");
306 exit(1);
6e785d85 307 }
308 debug("SSPI initialized OK\n");
309
310 atexit(UnloadSecurityDll);
311
312 /* initialize FDescs */
313 setbuf(stdout, NULL);
314 setbuf(stderr, NULL);
315
316 while (manage_request()) {
766743af 317 /* everything is done within manage_request */
6e785d85 318 }
319 exit(0);
320}