]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/negotiate_auth/wrapper/negotiate_wrapper.cc
2 * -----------------------------------------------------------------------------
4 * Author: Markus Moeller (markus_moeller at compuserve.com)
6 * Copyright (C) 2011 Markus Moeller. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22 * -----------------------------------------------------------------------------
25 * Hosted at http://sourceforge.net/projects/squidkerbauth
56 #if !defined(HAVE_DECL_XMALLOC) || !HAVE_DECL_XMALLOC
57 #define xmalloc malloc
59 #if !defined(HAVE_DECL_XSTRDUP) || !HAVE_DECL_XSTRDUP
60 #define xstrdup strdup
62 #if !defined(HAVE_DECL_XFREE) || !HAVE_DECL_XFREE
67 #define PROGRAM "negotiate_wrapper"
69 #define VERSION "1.0.1"
71 #ifndef MAX_AUTHTOKEN_LEN
72 #define MAX_AUTHTOKEN_LEN 65535
75 static const unsigned char ntlmProtocol
[] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};
81 static time_t last_t
= 0;
84 gettimeofday(&now
, NULL
);
85 if (now
.tv_sec
!= last_t
) {
86 time_t *tmp
= (time_t *) & now
.tv_sec
;
87 struct tm
*tm
= localtime(tmp
);
88 strftime(buf
, 127, "%Y/%m/%d %H:%M:%S", tm
);
96 fprintf(stderr
, "Usage: \n");
97 fprintf(stderr
, "negotiate_wrapper [-h] [-d] --ntlm ntlm helper + arguments --kerberos kerberos helper + arguments\n");
98 fprintf(stderr
, "-h help\n");
99 fprintf(stderr
, "-d full debug\n");
100 fprintf(stderr
, "--ntlm full ntlm helper path with arguments\n");
101 fprintf(stderr
, "--kerberos full kerberos helper path with arguments\n");
105 main(int argc
, char *const argv
[])
107 char buf
[MAX_AUTHTOKEN_LEN
];
108 char tbuff
[MAX_AUTHTOKEN_LEN
];
109 char buff
[MAX_AUTHTOKEN_LEN
+2];
114 int nstart
= 0, kstart
= 0;
115 int nend
= 0, kend
= 0;
117 char **nargs
, **kargs
;
127 setbuf(stdout
, NULL
);
130 if (argc
==1 || !strncasecmp(argv
[1],"-h",2)) {
136 if (!strncasecmp(argv
[1],"-d",2)) {
141 for (i
=j
; i
<argc
; i
++) {
142 if (!strncasecmp(argv
[i
],"--ntlm",6))
144 if (!strncasecmp(argv
[i
],"--kerberos",10))
147 if (nstart
> kstart
) {
154 if (nstart
== 0 || kstart
== 0 || kend
-kstart
<= 0 || nend
-nstart
<= 0 ) {
160 fprintf(stderr
, "%s| %s: Starting version %s\n", LogTime(), PROGRAM
,
163 if ((nargs
= (char **)xmalloc((nend
-nstart
+1)*sizeof(char *))) == NULL
) {
164 fprintf(stderr
, "%s| %s: Error allocating memory for ntlm helper\n", LogTime(), PROGRAM
);
167 memcpy(nargs
,argv
+nstart
+1,(nend
-nstart
)*sizeof(char *));
168 nargs
[nend
-nstart
]=NULL
;
170 fprintf(stderr
, "%s| %s: NTLM command: ", LogTime(), PROGRAM
);
171 for (i
=0; i
<nend
-nstart
; i
++)
172 fprintf(stderr
, "%s ", nargs
[i
]);
173 fprintf(stderr
, "\n");
175 if ((kargs
= (char **)xmalloc((kend
-kstart
+1)*sizeof(char *))) == NULL
) {
176 fprintf(stderr
, "%s| %s: Error allocating memory for kerberos helper\n", LogTime(), PROGRAM
);
179 memcpy(kargs
,argv
+kstart
+1,(kend
-kstart
)*sizeof(char *));
180 kargs
[kend
-kstart
]=NULL
;
182 fprintf(stderr
, "%s| %s: Kerberos command: ", LogTime(), PROGRAM
);
183 for (i
=0; i
<kend
-kstart
; i
++)
184 fprintf(stderr
, "%s ", kargs
[i
]);
185 fprintf(stderr
, "\n");
188 Fork Kerberos helper and NTLM helper and manage IO to send NTLM requests
189 to the right helper. squid must keep session state
192 if (pipe(pkin
) < 0) {
193 fprintf(stderr
, "%s| %s: Could not assign streams for pkin\n", LogTime(), PROGRAM
);
196 if (pipe(pkout
) < 0) {
197 fprintf(stderr
, "%s| %s: Could not assign streams for pkout\n", LogTime(), PROGRAM
);
202 if (( fpid
= vfork()) < 0 ) {
203 fprintf(stderr
, "%s| %s: Failed first fork\n", LogTime(), PROGRAM
);
208 /* First Child for Kerberos helper */
211 dup2(pkin
[0],STDIN_FILENO
);
215 dup2(pkout
[1],STDOUT_FILENO
);
219 setbuf(stdout
, NULL
);
221 execv(kargs
[0], kargs
);
222 fprintf(stderr
, "%s| %s: Failed execv for %s: %s\n", LogTime(), PROGRAM
, kargs
[0], strerror(errno
));
230 if (pipe(pnin
) < 0) {
231 fprintf(stderr
, "%s| %s: Could not assign streams for pnin\n", LogTime(), PROGRAM
);
234 if (pipe(pnout
) < 0) {
235 fprintf(stderr
, "%s| %s: Could not assign streams for pnout\n", LogTime(), PROGRAM
);
239 if (( fpid
= vfork()) < 0 ) {
240 fprintf(stderr
, "%s| %s: Failed second fork\n", LogTime(), PROGRAM
);
245 /* Second Child for NTLM helper */
248 dup2(pnin
[0],STDIN_FILENO
);
252 dup2(pnout
[1],STDOUT_FILENO
);
256 setbuf(stdout
, NULL
);
258 execv(nargs
[0], nargs
);
259 fprintf(stderr
, "%s| %s: Failed execv for %s: %s\n", LogTime(), PROGRAM
, nargs
[0], strerror(errno
));
266 FDKIN
=fdopen(pkin
[1],"w");
267 FDKOUT
=fdopen(pkout
[0],"r");
269 FDNIN
=fdopen(pnin
[1],"w");
270 FDNOUT
=fdopen(pnout
[0],"r");
272 if (!FDKIN
|| !FDKOUT
|| !FDNIN
|| !FDNOUT
) {
273 fprintf(stderr
, "%s| %s: Could not assign streams for FDKIN/FDKOUT/FDNIN/FDNOUT\n", LogTime(), PROGRAM
);
278 setbuf(FDKOUT
, NULL
);
280 setbuf(FDNOUT
, NULL
);
284 if (fgets(buf
, sizeof(buf
) - 1, stdin
) == NULL
) {
288 "%s| %s: fgets() failed! dying..... errno=%d (%s)\n",
289 LogTime(), PROGRAM
, ferror(stdin
),
290 strerror(ferror(stdin
)));
292 fprintf(stdout
, "BH input error\n");
293 return 1; /* BIIG buffer */
295 fprintf(stdout
, "BH input error\n");
298 c
= static_cast<char*>(memchr(buf
, '\n', sizeof(buf
) - 1));
307 fprintf(stderr
, "%s| %s: Oversized message\n", LogTime(),
309 fprintf(stdout
, "BH Oversized message\n");
314 fprintf(stderr
, "%s| %s: Got '%s' from squid (length: %d).\n",
315 LogTime(), PROGRAM
, buf
, length
);
317 if (buf
[0] == '\0') {
319 fprintf(stderr
, "%s| %s: Invalid request\n", LogTime(),
321 fprintf(stdout
, "BH Invalid request\n");
324 if (strlen(buf
) < 2) {
326 fprintf(stderr
, "%s| %s: Invalid request [%s]\n", LogTime(),
328 fprintf(stdout
, "BH Invalid request\n");
331 if (!strncmp(buf
, "QQ", 2)) {
332 fprintf(stdout
, "BH quit command\n");
335 if (strncmp(buf
, "YR", 2) && strncmp(buf
, "KK", 2)) {
337 fprintf(stderr
, "%s| %s: Invalid request [%s]\n", LogTime(),
339 fprintf(stdout
, "BH Invalid request\n");
342 if (strlen(buf
) <= 3) {
344 fprintf(stderr
, "%s| %s: Invalid negotiate request [%s]\n",
345 LogTime(), PROGRAM
, buf
);
346 fprintf(stdout
, "BH Invalid negotiate request\n");
349 length
= base64_decode_len(buf
+3);
351 fprintf(stderr
, "%s| %s: Decode '%s' (decoded length: %d).\n",
352 LogTime(), PROGRAM
, buf
+ 3, (int) length
);
354 if ((token
= (char *)xmalloc(length
)) == NULL
) {
355 fprintf(stderr
, "%s| %s: Error allocating memory for token\n", LogTime(), PROGRAM
);
359 length
= base64_decode(token
, length
, buf
+3);
361 if ((static_cast<size_t>(length
) >= sizeof(ntlmProtocol
) + 1) &&
362 (!memcmp(token
, ntlmProtocol
, sizeof ntlmProtocol
))) {
365 fprintf(stderr
, "%s| %s: received type %d NTLM token\n",
366 LogTime(), PROGRAM
, (int) *((unsigned char *) token
+
367 sizeof ntlmProtocol
));
368 fprintf(FDNIN
, "%s\n",buf
);
369 if (fgets(tbuff
, sizeof(tbuff
) - 1, FDNOUT
) == NULL
) {
370 if (ferror(FDNOUT
)) {
372 "fgets() failed! dying..... errno=%d (%s)\n",
373 ferror(FDNOUT
), strerror(ferror(FDNOUT
)));
376 fprintf(stderr
, "%s| %s: Error reading NTLM helper response\n",
381 Need to translate NTLM reply to Negotiate reply
382 AF user => AF blob user
383 NA reason => NA blob reason
386 if (strlen(tbuff
) >= 3 && (!strncmp(tbuff
,"AF ",3) || !strncmp(tbuff
,"NA ",3))) {
387 strncpy(buff
,tbuff
,3);
389 for (unsigned int i
=2; i
<=strlen(tbuff
); i
++)
390 buff
[i
+2] = tbuff
[i
];
397 fprintf(stderr
, "%s| %s: received Kerberos token\n",
400 fprintf(FDKIN
, "%s\n",buf
);
401 if (fgets(buff
, sizeof(buff
) - 1, FDKOUT
) == NULL
) {
402 if (ferror(FDKOUT
)) {
404 "fgets() failed! dying..... errno=%d (%s)\n",
405 ferror(FDKOUT
), strerror(ferror(FDKOUT
)));
408 fprintf(stderr
, "%s| %s: Error reading Kerberos helper response\n",
413 fprintf(stdout
,"%s",buff
);
415 fprintf(stderr
, "%s| %s: Return '%s'\n",
416 LogTime(), PROGRAM
, buff
);