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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors