]>
git.ipfire.org Git - thirdparty/squid.git/blob - helpers/ntlm_auth/SMB/ntlm_auth.c
2 * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>
3 * Distributed freely under the terms of the GNU General Public License,
4 * version 2. See the file COPYING for licensing details
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
15 * Warning! We MIGHT be open to buffer overflows caused by malformed headers
18 * use hashtable to cache authentications. Yummy performance-boost, security
19 * loss should be negligible for two reasons:
20 * - if they-re using NT, there's no security to speak of anyways
21 * - it can't get worse than basic authentication.
23 * challenge hash expiry and renewal.
24 * PDC disconnect, after X minutes of inactivity
27 * change syntax from options-driven to args-driven, with args domain
28 * or domain[/\]server, and an arbitrary number of backup Domain Controllers
29 * we don't really need the "status" management, it's more for debugging
30 * purposes. Remove it.
31 * Maybe we can cache the created challenge, saving more time?
41 #define BUFFER_SIZE 10240
61 char load_balance
= 0, failover_enabled
= 0, protocol_pedantic
= 0;
63 dc
*controllers
= NULL
;
64 int numcontrollers
= 0;
67 /* housekeeping cycle and periodic operations */
68 static unsigned char need_dc_resurrection
= 0;
75 need_dc_resurrection
= 0;
76 for (j
= 0; j
< numcontrollers
; j
++)
77 if (c
->status
!= DC_OK
&& is_dc_ok(c
->domain
, c
->controller
))
81 /* makes a null-terminated string upper-case. Changes CONTENTS! */
92 /* makes a null-terminated string lower-case. Changes CONTENTS! */
105 * -b try load-balancing the domain-controllers
106 * -f fail-over to another DC if DC connection fails.
107 * domain\controller ...
110 process_options(int argc
, char *argv
[])
112 int opt
, j
, had_error
= 0;
113 dc
*new_dc
= NULL
, *last_dc
= NULL
;
114 while (-1 != (opt
= getopt(argc
, argv
, "bf"))) {
120 failover_enabled
= 1;
123 fprintf(stderr
, "unknown option: -%c. Exiting\n", opt
);
129 /* Okay, now begin filling controllers up */
130 /* we can avoid memcpy-ing, and just reuse argv[] */
131 for (j
= optind
; j
< argc
; j
++) {
134 if (NULL
== (c
= strchr(d
, '\\')) && NULL
== (c
= strchr(d
, '/'))) {
135 fprintf(stderr
, "Couldn't grok domain-controller %s\n", d
);
139 new_dc
= (dc
*) malloc(sizeof(dc
));
141 fprintf(stderr
, "Malloc error while parsing DC options\n");
149 new_dc
->controller
= c
;
150 new_dc
->status
= DC_OK
;
151 if (controllers
== NULL
) { /* first controller */
152 controllers
= new_dc
;
155 last_dc
->next
= new_dc
; /* can't be null */
159 if (numcontrollers
== 0) {
160 fprintf(stderr
, "You must specify at least one domain-controller!\n");
163 last_dc
->next
= controllers
; /* close the queue, now it's circular */
166 /* tries connecting to the domain controllers in the "controllers" ring,
167 * with failover if the adequate option is specified.
174 for (j
= 0; j
< numcontrollers
; j
++) {
175 if (current_dc
->status
== DC_OK
) {
176 ch
= make_challenge(current_dc
->domain
, current_dc
->controller
);
178 return ch
; /* All went OK, returning */
179 /* Huston, we've got a problem. Take this DC out of the loop */
180 current_dc
->status
= DC_DEAD
;
181 need_dc_resurrection
= 1;
183 if (failover_enabled
== 0) /* No failover. Just return */
185 /* Try with the next */
186 current_dc
= current_dc
->next
;
194 ntlmhdr
*fast_header
;
197 char *ch2
, *decoded
, *cred
;
200 if (fgets(buf
, BUFFER_SIZE
, stdin
) == NULL
)
201 exit(0); /* BIIG buffer */
202 ch2
= memchr(buf
, '\n', BUFFER_SIZE
); /* safer against overrun than strchr */
204 *ch2
= '\0'; /* terminate the string at newline. */
207 debug("ntlm authenticator. Got '%s' from Squid\n", buf
);
209 if (memcmp(buf
, "KK ", 3) == 0) { /* authenticate-request */
210 /* figure out what we got */
211 decoded
= base64_decode(buf
+ 3);
212 /* Note: we don't need to manage memory at this point, since
213 * base64_decode returns a pointer to static storage.
216 if (!decoded
) { /* decoding failure, return error */
217 SEND("NA Packet format error, couldn't base64-decode");
220 /* fast-track-decode request type. */
221 fast_header
= (struct _ntlmhdr
*) decoded
;
223 /* sanity-check: it IS a NTLMSSP packet, isn't it? */
224 if (memcmp(fast_header
->signature
, "NTLMSSP", 8) != 0) {
225 SEND("NA Broken authentication packet");
228 switch (fast_header
->type
) {
230 SEND("NA Invalid negotiation request received");
234 SEND("NA Got a challenge. We refuse to have our authority disputed");
237 case NTLM_AUTHENTICATE
:
238 /* check against the DC */
239 plen
= strlen(buf
) * 3 / 4; /* we only need it here. Optimization */
240 cred
= ntlm_check_auth((ntlm_authenticate
*) decoded
, plen
);
242 switch (ntlm_errno
) {
243 case NTLM_LOGON_ERROR
:
244 SEND("NA authentication failure");
246 current_dc
= current_dc
->next
;
248 case NTLM_SERVER_ERROR
:
249 SEND("BH Domain Controller Error");
251 current_dc
= current_dc
->next
;
253 case NTLM_PROTOCOL_ERROR
:
254 SEND("BH Domain Controller communication error");
256 current_dc
= current_dc
->next
;
258 case NTLM_NOT_CONNECTED
:
259 SEND("BH Domain Controller (or network) died on us");
261 current_dc
= current_dc
->next
;
263 case NTLM_BAD_PROTOCOL
:
264 SEND("BH Domain controller failure");
266 current_dc
= current_dc
->next
;
269 SEND("BH Unhandled error while talking to Domain Controller");
271 current_dc
= current_dc
->next
;
275 lc(cred
); /* let's lowercase them for our convenience */
276 SEND2("AF %s", cred
);
279 SEND("BH unknown authentication packet type");
286 if (memcmp(buf
, "YR", 2) == 0) { /* refresh-request */
288 ch
= obtain_challenge();
291 ch
= obtain_challenge();
294 if (need_dc_resurrection
) /* looks like a good moment... */
298 SEND("BH Helper detected protocol error");
300 /********* END ********/
306 main(int argc
, char *argv
[])
309 debug("starting up...\n");
311 process_options(argc
, argv
);
313 debug("options processed OK\n");
315 /* initialize FDescs */
316 setbuf(stdout
, NULL
);
317 setbuf(stderr
, NULL
);
319 /* select the first domain controller we're going to use */
320 current_dc
= controllers
;
321 if (load_balance
!= 0 && numcontrollers
> 1) {
323 pid_t pid
= getpid();
324 n
= pid
% numcontrollers
;
325 debug("load balancing. Selected controller #%d\n", n
);
327 current_dc
= current_dc
->next
;
332 debug("managing request\n");