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