]> git.ipfire.org Git - thirdparty/squid.git/blob - helpers/ntlm_auth/fake/ntlm_fake_auth.cc
merge from trunk
[thirdparty/squid.git] / helpers / ntlm_auth / fake / ntlm_fake_auth.cc
1 /*
2 * AUTHOR: Andrew Doran <ad@interlude.eu.org>
3 * AUTHOR: Robert Collins <rbtcollins@hotmail.com>
4 * AUTHOR: Guido Serassio: <guido.serassio@acmeconsulting.it>
5 *
6 * SQUID Web Proxy Cache http://www.squid-cache.org/
7 * ----------------------------------------------------------
8 *
9 * Squid is the result of efforts by numerous individuals from
10 * the Internet community; see the CONTRIBUTORS file for full
11 * details. Many organizations have provided support for Squid's
12 * development; see the SPONSORS file for full details. Squid is
13 * Copyrighted (C) 2001 by the Regents of the University of
14 * California; see the COPYRIGHT file for full details. Squid
15 * incorporates software developed and/or copyrighted by other
16 * sources; see the CREDITS file for full details.
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 */
33 /*
34 * Example ntlm authentication program for Squid, based on the
35 * original proxy_auth code from client_side.c, written by
36 * Jon Thackray <jrmt@uk.gdscorp.com>. Initial ntlm code by
37 * Andrew Doran <ad@interlude.eu.org>.
38 *
39 * This code gets the username and returns it. No validation is done.
40 * and by the way: it is a complete patch-up. Use the "real thing" NTLMSSP
41 * if you can.
42 *
43 * Revised by Guido Serassio: <guido.serassio@acmeconsulting.it>
44 *
45 * - Added negotiation of UNICODE char support
46 * - More detailed debugging info
47 *
48 */
49
50 /* undefine this to have strict protocol adherence. You don't really need
51 * that though */
52 #define IGNORANCE_IS_BLISS
53
54 #include "squid.h"
55 #include "base64.h"
56 #include "helpers/defines.h"
57 #include "ntlmauth/ntlmauth.h"
58 #include "ntlmauth/support_bits.cci"
59
60 #include <cctype>
61 #include <cstring>
62 #if HAVE_CRYPT_H
63 #include <crypt.h>
64 #endif
65 #if HAVE_PWD_H
66 #include <pwd.h>
67 #endif
68 #if HAVE_GETOPT_H
69 #include <getopt.h>
70 #endif
71 #if HAVE_STDINT_H
72 #include <stdint.h>
73 #endif
74 #if HAVE_INTTYPES_H
75 #include <inttypes.h>
76 #endif
77
78 /* A couple of harmless helper macros */
79 #define SEND(X) {debug("sending '%s' to squid\n",X); printf(X "\n");}
80 #ifdef __GNUC__
81 #define SEND2(X,Y...) {debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);}
82 #define SEND4(X,Y...) {debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);}
83 #else
84 /* no gcc, no debugging. varargs macros are a gcc extension */
85 #define SEND2(X,Y) {debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);}
86 #define SEND4(X,Y,Z,W) {debug("sending '" X "' to squid\n",Y,Z,W); printf(X "\n",Y,Z,W);}
87 #endif
88
89 const char *authenticate_ntlm_domain = "WORKGROUP";
90 int strip_domain_enabled = 0;
91 int NTLM_packet_debug_enabled = 0;
92
93 /*
94 * options:
95 * -d enable debugging.
96 * -v enable verbose NTLM packet debugging.
97 * -l if specified, changes behavior on failures to last-ditch.
98 */
99 char *my_program_name = NULL;
100
101 static void
102 usage(void)
103 {
104 fprintf(stderr,
105 "Usage: %s [-d] [-v] [-h]\n"
106 " -d enable debugging.\n"
107 " -S strip domain from username.\n"
108 " -v enable verbose NTLM packet debugging.\n"
109 " -h this message\n\n",
110 my_program_name);
111 }
112
113 static void
114 process_options(int argc, char *argv[])
115 {
116 int opt, had_error = 0;
117
118 opterr = 0;
119 while (-1 != (opt = getopt(argc, argv, "hdvS"))) {
120 switch (opt) {
121 case 'd':
122 debug_enabled = 1;
123 break;
124 case 'v':
125 debug_enabled = 1;
126 NTLM_packet_debug_enabled = 1;
127 break;
128 case 'S':
129 strip_domain_enabled = 1;
130 break;
131 case 'h':
132 usage();
133 exit(0);
134 case '?':
135 opt = optopt;
136 /* fall thru to default */
137 default:
138 fprintf(stderr, "unknown option: -%c. Exiting\n", opt);
139 usage();
140 had_error = 1;
141 }
142 }
143 if (had_error)
144 exit(1);
145 }
146
147 int
148 main(int argc, char *argv[])
149 {
150 char buf[HELPER_INPUT_BUFFER];
151 int buflen = 0;
152 char decodedBuf[HELPER_INPUT_BUFFER];
153 int decodedLen;
154 char user[NTLM_MAX_FIELD_LENGTH], domain[NTLM_MAX_FIELD_LENGTH];
155 char *p;
156 ntlmhdr *packet = NULL;
157 char helper_command[3];
158 int len;
159 char *data = NULL;
160
161 setbuf(stdout, NULL);
162 setbuf(stderr, NULL);
163
164 my_program_name = argv[0];
165
166 process_options(argc, argv);
167
168 debug("%s build " __DATE__ ", " __TIME__ " starting up...\n", my_program_name);
169
170 while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != NULL) {
171 user[0] = '\0'; /*no user code */
172 domain[0] = '\0'; /*no domain code */
173
174 if ((p = strchr(buf, '\n')) != NULL)
175 *p = '\0'; /* strip \n */
176 buflen = strlen(buf); /* keep this so we only scan the buffer for \0 once per loop */
177 if (buflen > 3) {
178 decodedLen = base64_decode(decodedBuf, sizeof(decodedBuf), buf+3);
179 packet = (ntlmhdr*)decodedBuf;
180 } else {
181 packet = NULL;
182 decodedLen = 0;
183 }
184 if (buflen > 3 && NTLM_packet_debug_enabled) {
185 strncpy(helper_command, buf, 2);
186 helper_command[2] = '\0';
187 debug("Got '%s' from Squid with data:\n", helper_command);
188 hex_dump((unsigned char *)decodedBuf, decodedLen);
189 } else
190 debug("Got '%s' from Squid\n", buf);
191
192 if (strncmp(buf, "YR", 2) == 0) {
193 char nonce[NTLM_NONCE_LEN];
194 ntlm_challenge chal;
195 ntlm_make_nonce(nonce);
196 if (buflen > 3) {
197 ntlm_negotiate *nego = (ntlm_negotiate *)packet;
198 ntlm_make_challenge(&chal, authenticate_ntlm_domain, NULL, nonce, NTLM_NONCE_LEN, nego->flags);
199 } else {
200 ntlm_make_challenge(&chal, authenticate_ntlm_domain, NULL, nonce, NTLM_NONCE_LEN, NTLM_NEGOTIATE_ASCII);
201 }
202 // TODO: find out what this context means, and why only the fake auth helper contains it.
203 chal.context_high = htole32(0x003a<<16);
204
205 len = sizeof(chal) - sizeof(chal.payload) + le16toh(chal.target.maxlen);
206 data = (char *) base64_encode_bin((char *) &chal, len);
207 if (NTLM_packet_debug_enabled) {
208 printf("TT %s\n", data);
209 debug("sending 'TT' to squid with data:\n");
210 hex_dump((unsigned char *)&chal, len);
211 } else
212 SEND2("TT %s", data);
213 } else if (strncmp(buf, "KK ", 3) == 0) {
214 if (!packet) {
215 SEND("BH received KK with no data! user=");
216 } else if (ntlm_validate_packet(packet, NTLM_AUTHENTICATE) == NTLM_ERR_NONE) {
217 if (ntlm_unpack_auth((ntlm_authenticate *)packet, user, domain, decodedLen) == NTLM_ERR_NONE) {
218 lc(user);
219 if (strip_domain_enabled) {
220 SEND2("AF %s", user);
221 } else {
222 SEND4("AF %s%s%s", domain, (*domain?"\\":""), user);
223 }
224 } else {
225 lc(user);
226 SEND4("NA invalid credentials, user=%s%s%s", domain, (*domain?"\\":""), user);
227 }
228 } else {
229 SEND("BH wrong packet type! user=");
230 }
231 }
232 }
233 exit(0);
234 }