--------------------- PatchSet 25 Date: 2000/02/05 20:14:18 Author: hno Branch: ntlm Tag: (none) Log: Imported NTLM proxy_auth patch from Andy Doran Members: include/util.h:1.1.1.3->1.1.1.3.10.1 lib/base64.c:1.1.1.1->1.1.1.1.14.1 src/acl.c:1.1.1.3->1.1.1.3.12.1 src/authenticate.c:1.1.1.3->1.1.1.3.12.1 src/cf.data.pre:1.1.1.3.4.1->1.1.1.3.4.1.2.1 src/client_side.c:1.1.1.3.4.1->1.1.1.3.4.1.2.1 src/errorpage.c:1.1.1.3->1.1.1.3.10.1 src/ntlm.h:1.1->1.1.2.1 src/protos.h:1.1.1.3->1.1.1.3.12.1 src/structs.h:1.1.1.3.4.1->1.1.1.3.4.1.2.1 Index: squid/include/util.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/util.h,v retrieving revision 1.1.1.3 retrieving revision 1.1.1.3.10.1 diff -u -r1.1.1.3 -r1.1.1.3.10.1 --- squid/include/util.h 26 Jan 2000 03:25:00 -0000 1.1.1.3 +++ squid/include/util.h 5 Feb 2000 20:14:18 -0000 1.1.1.3.10.1 @@ -1,5 +1,5 @@ /* - * $Id: util.h,v 1.1.1.3 2000/01/26 03:25:00 hno Exp $ + * $Id: util.h,v 1.1.1.3.10.1 2000/02/05 20:14:18 hno Exp $ * * AUTHOR: Harvest Derived * @@ -108,6 +108,7 @@ extern time_t parse_iso3307_time(const char *buf); extern char *base64_decode(const char *coded); extern const char *base64_encode(const char *decoded); +extern const char *base64_encode_bin(const char *data, int len); extern double xpercent(double part, double whole); extern int xpercentInt(double part, double whole); Index: squid/lib/base64.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/base64.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.14.1 diff -u -r1.1.1.1 -r1.1.1.1.14.1 --- squid/lib/base64.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/base64.c 5 Feb 2000 20:14:18 -0000 1.1.1.1.14.1 @@ -1,5 +1,5 @@ /* - * $Id: base64.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: base64.c,v 1.1.1.1.14.1 2000/02/05 20:14:18 hno Exp $ */ #include "config.h" @@ -111,3 +111,50 @@ result[out_cnt] = '\0'; /* terminate */ return result; } + +/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */ +const char * +base64_encode_bin(const char * data, int len) +{ + static char result[BASE64_RESULT_SZ]; + int bits = 0; + int char_count = 0; + int out_cnt = 0; + int c; + + if (!data) + return data; + + if (!base64_initialized) + base64_init(); + + while (len-- && out_cnt < sizeof(result) - 1) { + c = (unsigned char)*data++; + bits += c; + char_count++; + if (char_count == 3) { + result[out_cnt++] = base64_code[bits >> 18]; + result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; + result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; + result[out_cnt++] = base64_code[bits & 0x3f]; + bits = 0; + char_count = 0; + } else { + bits <<= 8; + } + } + if (char_count != 0) { + bits <<= 16 - (8 * char_count); + result[out_cnt++] = base64_code[bits >> 18]; + result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; + if (char_count == 1) { + result[out_cnt++] = '='; + result[out_cnt++] = '='; + } else { + result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; + result[out_cnt++] = '='; + } + } + result[out_cnt] = '\0'; /* terminate */ + return result; +} Index: squid/src/acl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/acl.c,v retrieving revision 1.1.1.3 retrieving revision 1.1.1.3.12.1 diff -u -r1.1.1.3 -r1.1.1.3.12.1 --- squid/src/acl.c 26 Jan 2000 03:25:01 -0000 1.1.1.3 +++ squid/src/acl.c 5 Feb 2000 20:14:18 -0000 1.1.1.3.12.1 @@ -1,6 +1,6 @@ /* - * $Id: acl.c,v 1.1.1.3 2000/01/26 03:25:01 hno Exp $ + * $Id: acl.c,v 1.1.1.3.12.1 2000/02/05 20:14:18 hno Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -35,6 +35,7 @@ #include "squid.h" #include "splay.h" +#include "ntlm.h" static int aclFromFile = 0; static FILE *aclFile; @@ -1003,14 +1004,26 @@ { char *sent_auth; char *cleartext; +#if USE_NTLM + int ntlm = 0; +#endif + if (proxy_auth == NULL) return 0; debug(28, 6) ("aclDecodeProxyAuth: header = '%s'\n", proxy_auth); - if (strncasecmp(proxy_auth, "Basic ", 6) != 0) { + + if (strncasecmp(proxy_auth, "Basic ", 6) == 0) { + proxy_auth += 6; +#if USE_NTLM + } else if (strncmp("NTLM ", proxy_auth, 5) == 0) { + ntlm = 1; + proxy_auth += 5; +#endif + } else { debug(28, 1) ("aclDecodeProxyAuth: Unsupported proxy-auth sheme, '%s'\n", proxy_auth); return 0; } - proxy_auth += 6; /* "Basic " */ + /* Trim leading whitespace before decoding */ while (xisspace(*proxy_auth)) proxy_auth++; @@ -1026,8 +1039,30 @@ strtok(cleartext, "\r\n"); debug(28, 6) ("aclDecodeProxyAuth: cleartext = '%s'\n", cleartext); xstrncpy(buf, cleartext, bufsize); + +#ifdef USE_NTLM + if (ntlm) { + if (ntlmCheckHeader((struct ntlmhdr *)cleartext, NTLM_NEGOTIATE)) { + /* Assume this is the authentication request */ + ntlmDecodeAuth((struct ntlm_authenticate *)cleartext, buf, + bufsize, user, password); + xfree(cleartext); + + if (*user == NULL || *password == NULL) { + debug(28, 1) ("aclDecodeProxyAuth: no NT response in NTLM authorization header\n"); + return 0; + } + return 1; + } + + /* Otherwise assume it's the negotiation request */ + return 2; + } +#endif + xfree(cleartext); *user = buf; + if ((*password = strchr(*user, ':')) != NULL) *(*password)++ = '\0'; if (*password == NULL) { @@ -1046,7 +1081,7 @@ * 0 : user denied access * 1 : user validated OK * -1 : check the password for this user via an external authenticator - * -2 : invalid Proxy-authorization: header; + * -2 : invalid Proxy-Authorization: header; * ask for Proxy-Authorization: header */ @@ -1055,11 +1090,23 @@ { /* checklist is used to register user name when identified, nothing else */ LOCAL_ARRAY(char, login_buf, USER_IDENT_SZ); - char *user, *password; + char *user, *password, rv; - if (!aclDecodeProxyAuth(proxy_auth, &user, &password, login_buf, sizeof(login_buf))) - /* No or invalid Proxy-Auth header */ - return -2; +#if USE_NTLM + /* For NTLM we only ask for authentication on the first request */ + if (checklist->conn && checklist->conn->authenticated) + return 1; +#endif + + switch (aclDecodeProxyAuth(proxy_auth, &user, &password, login_buf, sizeof(login_buf))) { +#if USE_NTLM + case 2: /* Send an NTLM challenge */ + checklist->ntlm_challenge = 1; + /* FALLTHROUGH */ +#endif + case 0: /* User denied access */ + return -2; + } debug(28, 5) ("aclMatchProxyAuth: checking user '%s'\n", user); @@ -1101,7 +1148,6 @@ } /* see if we already know this user */ auth_user = hash_lookup(proxy_auth_cache, user); - if (!auth_user) { /* user not yet known, ask external authenticator */ debug(28, 4) ("aclMatchProxyAuth: user '%s' not yet known\n", user); @@ -1118,7 +1164,15 @@ auth_user->ipaddr = checklist->src_addr; /* copy username to request for logging on client-side */ xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); - return aclMatchUser(data, user); + rv = aclMatchUser(data, user); +#if USE_NTLM + /* Copy the username from the NTLM header */ + if (checklist->conn) { + checklist->conn->authenticated = rv; /* XXX THIS IS NOT SAFE */ + xstrncpy(checklist->conn->ident, user, USER_IDENT_SZ); + } +#endif + return rv; } else { /* user has switched to another IP addr */ debug(28, 1) ("aclMatchProxyAuth: user '%s' has changed IP address\n", user); @@ -1140,7 +1194,6 @@ return -1; } /* NOTREACHED */ - } static void @@ -1751,6 +1804,10 @@ if (ident) xstrncpy(checklist->ident, ident, USER_IDENT_SZ); #endif +#ifdef USE_NTLM + /* Initially we don't have to issue a challenge */ + checklist->ntlm_challenge = 0; +#endif checklist->auth_user = NULL; /* init to NULL */ return checklist; } Index: squid/src/authenticate.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/authenticate.c,v retrieving revision 1.1.1.3 retrieving revision 1.1.1.3.12.1 diff -u -r1.1.1.3 -r1.1.1.3.12.1 --- squid/src/authenticate.c 26 Jan 2000 03:25:01 -0000 1.1.1.3 +++ squid/src/authenticate.c 5 Feb 2000 20:14:18 -0000 1.1.1.3.12.1 @@ -1,6 +1,6 @@ /* - * $Id: authenticate.c,v 1.1.1.3 2000/01/26 03:25:01 hno Exp $ + * $Id: authenticate.c,v 1.1.1.3.12.1 2000/02/05 20:14:18 hno Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Duane Wessels @@ -34,6 +34,11 @@ */ #include "squid.h" +#ifdef USE_NTLM +#include "ntlm.h" +#endif + +#define NTLM_STATIC_CHALLENGE "deadbeef" typedef struct { void *data; @@ -100,7 +105,28 @@ cbdataLock(data); r->data = data; r->auth_user = auth_user; - snprintf(buf, 8192, "%s %s\n", r->auth_user->user, r->auth_user->passwd); + +#ifdef USE_NTLM + if (Config.authenticate_ntlm_domain != NULL) { + /* These fields can be NULL ... */ + if (auth_user->user == NULL || auth_user->user[0] == '\0') + auth_user->user = "-"; + if (auth_user->domain == NULL || auth_user->domain[0] == '\0') + auth_user->domain = "-"; + if (auth_user->workstation == NULL || auth_user->workstation[0] == '\0') + auth_user->workstation = "-"; + if (auth_user->lmresponse == NULL || auth_user->lmresponse[0] == '\0') + auth_user->lmresponse = "-"; + if (auth_user->ntresponse == NULL || auth_user->ntresponse[0] == '\0') + auth_user->ntresponse = "-"; + + snprintf(buf, 8192, "%s %s %s %s %s %s\n", + auth_user->user, auth_user->domain, + auth_user->workstation, NTLM_STATIC_CHALLENGE, + auth_user->lmresponse, auth_user->ntresponse); + } else +#endif + snprintf(buf, 8192, "%s %s\n", auth_user->user, auth_user->passwd); helperSubmit(authenticators, buf, authenticateHandleReply, r); } @@ -135,3 +161,217 @@ helperFree(authenticators); authenticators = NULL; } + +void +authenticateFixErrorHeader(HttpReply * rep, int type, int ntlm_challenge) +{ + char *fmt, *data; +#ifdef USE_NTLM + int len; + + if (Config.authenticate_ntlm_domain != NULL) { + struct ntlm_challenge chal; + + if (ntlm_challenge) { + ntlmMakeChallenge(&chal); + fmt = "NTLM %s"; + len = sizeof(chal) - sizeof(chal.pad) + SSWAP(chal.target.maxlen); + debug(29, 5) ("authenticateFixErrorHeader: len: %d\n", len); + data = (char *)base64_encode_bin((char *)&chal, len); + } else + fmt = "NTLM"; + } else +#endif + { + fmt = "Basic realm=\"%s\""; + data = Config.proxyAuthRealm; + } + + httpHeaderPutStrf(&rep->header, type, fmt, data); +} + +#ifdef USE_NTLM +/* NTLM authentication by ad@netbsd.org - 07/1999 */ +/* XXX this is not done cleanly... */ + +/* + * Generates a challenge request. The randomness of the 8 byte + * challenge strings can be guarenteed to be poor at best. + */ +void +ntlmMakeChallenge(struct ntlm_challenge *chal) +{ +#ifndef NTLM_STATIC_CHALLENGE + static unsigned hash; + int r; +#endif + char *d; + int i; + + memset(chal, 0, sizeof(*chal)); + memcpy(chal->hdr.signature, "NTLMSSP", 8); + chal->flags = WSWAP(0x00018206); + chal->hdr.type = WSWAP(NTLM_CHALLENGE); + chal->unknown[6] = SSWAP(0x003a); + + d = (char *)chal + 48; + i = 0; + + while (Config.authenticate_ntlm_domain[i]) + *d++ = toupper(Config.authenticate_ntlm_domain[i++]); + + chal->target.offset = WSWAP(48); + chal->target.maxlen = SSWAP(i); + chal->target.len = chal->target.maxlen; + +#ifdef NTLM_STATIC_CHALLENGE + memcpy(chal->challenge, NTLM_STATIC_CHALLENGE, 8); +#else + r = (int)rand(); + r = (hash ^ r) + r; + + for (i = 0; i < 8; i++) { + chal->challenge[i] = r; + r = (r >> 2) ^ r; + } + + hash = r; +#endif +} + +/* + * Check the vailidity of a request header. Return -1 on error. + */ +int +ntlmCheckHeader(struct ntlmhdr *hdr, int type) +{ + /* + * Must be the correct security package and request type. The + * 8 bytes compared includes the ASCII 'NUL'. + */ + if (memcmp(hdr->signature, "NTLMSSP", 8) != 0) { + debug(29, 5) ("ntlmCheckHeader: bad header signature\n"); + return (-1); + } + + if (WSWAP(hdr->type) != type) { + debug(29, 5) ("ntlmCheckHeader: type is %d, wanted %d\n", WSWAP(hdr->type), type); + return (-1); + } + + return (0); +} + +/* + * Extract a string from an NTLM request and return as ASCII. + */ +char * +ntlmGetString(ntlmhdr *hdr, strhdr *str, int flags) +{ + static char buf[512]; + u_short *s, c; + char *d, *sc; + int l, o; + + l = SSWAP(str->len); + o = WSWAP(str->offset); + + /* Sanity checks. XXX values arbitrarialy chosen */ + if (l <= 0 || l >= 32 || o >= 256) + return (NULL); + + if ((flags & 2) == 0) { + /* UNICODE string */ + s = (u_short *)((char *)hdr + o); + d = buf; + + for (l >>= 1; l; s++, l--) { + c = SSWAP(*s); + if (c > 254 || c == '\0' || !isprint(c)) { + debug(29, 5) ("ntlmGetString: bad uni: %04x\n", c); + return (NULL); + } + *d++ = c; + debug(29, 5) ("ntlmGetString: conv: '%c'\n", c); + } + + *d = 0; + } else { + /* ASCII string */ + sc = (char *)hdr + o; + d = buf; + + for (; l; l--) { + if (*sc == '\0' || !isprint(*sc)) { + debug(29, 5) ("ntlmGetString: bad ascii: %04x\n", c); + return (NULL); + } + *d++ = *sc++; + } + + *d = 0; + } + + return (buf); +} + +/* + * Decode the strings in an NTLM authentication request + */ +int ntlmDecodeAuth(struct ntlm_authenticate *auth, char *buf, size_t size, + char **user, char **pass) +{ + char *p; + int s; + + if (ntlmCheckHeader(&auth->hdr, NTLM_AUTHENTICATE)) { + debug(29, 5) ("ntlmDecodeAuth: header check fails\n"); + return -1; + } + + debug(29, 5) ("ntlmDecodeAuth: size of %d\n", size); + debug(29, 5) ("ntlmDecodeAuth: flg %08x\n", auth->flags); + debug(29, 5) ("ntlmDecodeAuth: usr o(%d) l(%d)\n", auth->user.offset, + auth->user.len); + + if (user) { + *user = buf; + + if ((p = ntlmGetString(&auth->hdr, &auth->domain, 2)) == NULL) + p = Config.authenticate_ntlm_domain; + if ((s = strlen(p) + 1) >= size) + return 0; + strcpy(buf, p); + size -= s; + buf += (s - 1); + *buf++ = '.'; + + p = ntlmGetString(&auth->hdr, &auth->user, 2); + if ((s = strlen(p) + 1) >= size) + return 0; + while (*p) + *buf++ = tolower(*p++); + *buf++ = '\0'; + size -= s; + + debug(29, 5) ("ntlmDecodeAuth: user: %s\n", *user); + } + + if (pass) { +#ifdef notdef /* XXX */ + p = ntlmGetString(&auth->hdr, &auth->ntresponse, 2); +#endif + p = "PASSWORD"; + if ((s = strlen(p) + 1) >= size) + return 0; + strcpy(buf, p); + *pass = buf; + size -= s; + buf += s; + debug(29, 5) ("ntlmDecodeAuth: ntresponse: %s\n", *pass); + } + + return 1; +} + +#endif /* USE_NTLM */ Index: squid/src/cf.data.pre =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v retrieving revision 1.1.1.3.4.1 retrieving revision 1.1.1.3.4.1.2.1 diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.2.1 --- squid/src/cf.data.pre 4 Feb 2000 19:39:40 -0000 1.1.1.3.4.1 +++ squid/src/cf.data.pre 5 Feb 2000 20:14:18 -0000 1.1.1.3.4.1.2.1 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.1.1.3.4.1 2000/02/04 19:39:40 hno Exp $ +# $Id: cf.data.pre,v 1.1.1.3.4.1.2.1 2000/02/05 20:14:18 hno Exp $ # # # SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -1075,6 +1075,16 @@ authenticate_ip_ttl 0 DOC_END +NAME: authenticate_ntlm_domain +TYPE: string +DEFAULT: none +LOC: Config.authenticate_ntlm_domain +DOC_START + XXX insert description here + +authenticate_ntlm_domain MYDOMAIN +DOC_END + COMMENT_START OPTIONS FOR TUNING THE CACHE ----------------------------------------------------------------------------- Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.1.1.3.4.1 retrieving revision 1.1.1.3.4.1.2.1 diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.2.1 --- squid/src/client_side.c 4 Feb 2000 19:39:40 -0000 1.1.1.3.4.1 +++ squid/src/client_side.c 5 Feb 2000 20:14:18 -0000 1.1.1.3.4.1.2.1 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.1.1.3.4.1 2000/02/04 19:39:40 hno Exp $ + * $Id: client_side.c,v 1.1.1.3.4.1.2.1 2000/02/05 20:14:18 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -198,6 +198,9 @@ int page_id = -1; http_status status; ErrorState *err = NULL; +#ifdef USE_NTLM + int ntlm_challenge http->acl_checklist->ntlm_challenge; +#endif debug(33, 2) ("The request %s %s is %s, because it matched '%s'\n", RequestMethodStr[http->request->method], http->uri, answer == ACCESS_ALLOWED ? "ALLOWED" : "DENIED", @@ -241,6 +244,9 @@ err = errorCon(page_id, status); err->request = requestLink(http->request); err->src_addr = http->conn->peer.sin_addr; +#ifdef USE_NTLM + err->ntlm_challenge = ntlm_challenge; +#endif errorAppendEntry(http->entry, err); } } @@ -2053,6 +2059,10 @@ return http; } +#if USE_NTLM +#define NTLM_WORKAROUND 1 +#endif + /* * parseHttpRequest() * @@ -2083,6 +2093,11 @@ struct natlookup natLookup; static int natfd = -1; #endif +#if NTLM_WORKAROUND + char *mlist[] = { "GET", "POST", "PUT", "HEAD", "CONNECT", "TRACE", "PURGE", NULL }; + int lastcr, i, getout, ncr; + char *pinbuf; +#endif if ((req_sz = headersEnd(conn->in.buf, conn->in.offset)) == 0) { debug(33, 5) ("Incomplete request, waiting for end of headers\n"); @@ -2107,6 +2122,35 @@ debug(33, 1) ("parseHttpRequest: Requestheader contains NULL characters\n"); return parseHttpRequestAbort(conn, "error:invalid-request"); } + +#if NTLM_WORKAROUND + /* This is a UGLY hack to work around some problems with POST and + * NTLM authentication. It is CERTAINLY not the correct way to + * solve this + */ + pinbuf = inbuf; + for (lastcr = 1, getout = 0, ncr = 0; *inbuf != '\0'; inbuf++) { + if (lastcr) { + for (i = 0; mlist[i]; i++) { + if (strncmp(inbuf, mlist[i], strlen(mlist[i])) == 0) { + getout = 1; + break; + } + } + } + if (getout) + break; + + if ((lastcr = (*inbuf == '\n')) != 0) { + if (ncr++ == 1) + break; + } + } + + if (getout == 0) + inbuf = pinbuf; +#endif /* NTLM_WORKAROUND */ + /* Look for request method */ if ((mstr = strtok(inbuf, "\t ")) == NULL) { debug(33, 1) ("parseHttpRequest: Can't get request method\n"); Index: squid/src/errorpage.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/errorpage.c,v retrieving revision 1.1.1.3 retrieving revision 1.1.1.3.10.1 diff -u -r1.1.1.3 -r1.1.1.3.10.1 --- squid/src/errorpage.c 26 Jan 2000 03:25:01 -0000 1.1.1.3 +++ squid/src/errorpage.c 5 Feb 2000 20:14:18 -0000 1.1.1.3.10.1 @@ -1,6 +1,6 @@ /* - * $Id: errorpage.c,v 1.1.1.3 2000/01/26 03:25:01 hno Exp $ + * $Id: errorpage.c,v 1.1.1.3.10.1 2000/02/05 20:14:18 hno Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels @@ -52,8 +52,6 @@ /* local constant and vars */ -static const char *const proxy_auth_challenge_fmt = "Basic realm=\"%s\""; - /* * note: hard coded error messages are not appended with %S automagically * to give you more control on the format @@ -282,22 +280,22 @@ switch (err->http_status) { case HTTP_PROXY_AUTHENTICATION_REQUIRED: /* Proxy authorisation needed */ - httpHeaderPutStrf(&rep->header, HDR_PROXY_AUTHENTICATE, - proxy_auth_challenge_fmt, Config.proxyAuthRealm); +#ifdef USE_NTLM + authenticateFixErrorHeader(rep, HDR_PROXY_AUTHENTICATE, err->ntlm_challenge); +#else + authenticateFixErrorHeader(rep, HDR_PROXY_AUTHENTICATE, 0); +#endif break; case HTTP_UNAUTHORIZED: /* WWW Authorisation needed */ - httpHeaderPutStrf(&rep->header, HDR_WWW_AUTHENTICATE, - proxy_auth_challenge_fmt, Config.proxyAuthRealm); + authenticateFixErrorHeader(rep, HDR_WWW_AUTHENTICATE, 0); break; default: /* Keep GCC happy */ break; } httpReplySwapOut(rep, entry); - httpReplyDestroy(rep); - mem->reply->sline.status = err->http_status; - mem->reply->content_length = -1; + httpReplyAbsorb(mem->reply, rep); EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); storeBufferFlush(entry); storeComplete(entry); @@ -361,10 +359,13 @@ ErrorState *err = data; debug(4, 3) ("errorSendComplete: FD %d, size=%d\n", fd, size); if (errflag != COMM_ERR_CLOSING) { - if (err->callback) + if (err->callback) { + debug(4, 3) ("errorSendComplete: callback\n"); err->callback(fd, err->callback_data, size); - else + } else { comm_close(fd); + debug(4, 3) ("errorSendComplete: comm_close\n"); + } } errorStateFree(err); } --- /dev/null Wed Feb 14 00:42:24 2007 +++ squid/src/ntlm.h Wed Feb 14 00:43:09 2007 @@ -0,0 +1,72 @@ +#ifndef _NTLM_H_ +#define _NTLM_H_ 1 + +/* All of this cruft is little endian */ +#ifdef WORDS_BIGENDIAN +#define SSWAP(x) (bswap16((x))) +#define WSWAP(x) (bswap32((x))) +#else +#define SSWAP(x) (x) +#define WSWAP(x) (x) +#endif + +/* NTLM request types that we know about */ +#define NTLM_NEGOTIATE 1 +#define NTLM_CHALLENGE 2 +#define NTLM_AUTHENTICATE 3 + +/* Header proceeding each request */ +typedef struct ntlmhdr { + char signature[8]; /* NTLMSSP */ + int32_t type; /* One of NTLM_* from above */ +} ntlmhdr; + +/* String header. String data resides at the end of the request */ +typedef struct strhdr { + int16_t len; /* Length in bytes */ + int16_t maxlen; /* Allocated space in bytes */ + int32_t offset; /* Offset from start of request */ +} strhdr; + +/* Negotiation request sent by client */ +struct ntlm_negotiate { + ntlmhdr hdr; /* NTLM header */ + int32_t flags; /* Request flags */ + strhdr domain; /* Domain we wish to authenticate in */ + strhdr workstation; /* Client workstation name */ + char pad[256]; /* String data */ +}; + +/* Challenge request sent by server. */ +struct ntlm_challenge { + ntlmhdr hdr; /* NTLM header */ + strhdr target; /* Authentication target (domain/server ...) */ + int32_t flags; /* Request flags */ + u_char challenge[8]; /* Challenge string */ + int16_t unknown[8]; /* Some sort of context data */ + char pad[256]; /* String data */ +}; + +/* Authentication request sent by client in response to challenge */ +struct ntlm_authenticate { + ntlmhdr hdr; /* NTLM header */ + strhdr lmresponse; /* LANMAN challenge response */ + strhdr ntresponse; /* NT challenge response */ + strhdr domain; /* Domain to authenticate against */ + strhdr user; /* Username */ + strhdr workstation; /* Workstation name */ + strhdr sessionkey; /* Session key for server's use */ + int32_t flags; /* Request flags */ + char pad[256*6]; /* String data */ +}; + +char *ntlmGetString(ntlmhdr *hdr, strhdr *str, int flags); +void ntlmMakeChallenge(struct ntlm_challenge *chal); +int ntlmCheckHeader(struct ntlmhdr *hdr, int type); +int ntlmCheckNegotiation(struct ntlm_negotiate *neg); +int ntlmAuthenticate(struct ntlm_authenticate *neg); +void ntlmDumpChallenge(struct ntlm_challenge *chal); +int ntlmDecodeAuth(struct ntlm_authenticate *neg, char *buf, size_t size, + char **user, char **pass); + +#endif /* !defined _NTLM_H_ */ Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.1.1.3 retrieving revision 1.1.1.3.12.1 diff -u -r1.1.1.3 -r1.1.1.3.12.1 --- squid/src/protos.h 26 Jan 2000 03:25:01 -0000 1.1.1.3 +++ squid/src/protos.h 5 Feb 2000 20:14:19 -0000 1.1.1.3.12.1 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.1.1.3 2000/01/26 03:25:01 hno Exp $ + * $Id: protos.h,v 1.1.1.3.12.1 2000/02/05 20:14:19 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -693,6 +693,7 @@ extern void authenticateStart(acl_proxy_auth_user *, RH *, void *); extern void authenticateInit(void); extern void authenticateShutdown(void); +extern void authenticateFixErrorHeader(HttpReply *, int, int); extern void refreshAddToList(const char *, int, time_t, int, time_t); extern int refreshIsCachable(const StoreEntry *); Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.1.1.3.4.1 retrieving revision 1.1.1.3.4.1.2.1 diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.2.1 --- squid/src/structs.h 4 Feb 2000 19:39:41 -0000 1.1.1.3.4.1 +++ squid/src/structs.h 5 Feb 2000 20:14:19 -0000 1.1.1.3.4.1.2.1 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.1.1.3.4.1 2000/02/04 19:39:41 hno Exp $ + * $Id: structs.h,v 1.1.1.3.4.1.2.1 2000/02/05 20:14:19 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -73,6 +73,12 @@ acl_proxy_auth_user *next; /* extra fields for proxy_auth */ char *passwd; +#ifdef USE_NTLM + char *lmresponse; + char *ntresponse; + char *domain; + char *workstation; +#endif int passwd_ok; /* 1 = passwd checked OK */ long expiretime; struct in_addr ipaddr; /* IP addr this user authenticated from */ @@ -150,6 +156,9 @@ ConnStateData *conn; /* hack for ident */ char ident[USER_IDENT_SZ]; #endif +#if USE_NTLM + int ntlm_challenge; /* need to issue NTLM challenge */ +#endif acl_proxy_auth_user *auth_user; acl_lookup_state state[ACL_ENUM_MAX]; #if SQUID_SNMP @@ -323,6 +332,9 @@ int authenticateChildren; int authenticateTTL; int authenticateIpTTL; +#ifdef USE_NTLM + char *authenticate_ntlm_domain; +#endif struct { char *host; u_short port; @@ -887,6 +899,9 @@ char ident[USER_IDENT_SZ]; int nrequests; int persistent; +#if USE_NTLM + int authenticated; +#endif struct { int n; time_t until; @@ -1484,6 +1499,9 @@ err_type type; int page_id; http_status http_status; +#ifdef USE_NTLM + int ntlm_challenge; /* NTLM: got negotiation, send challenge */ +#endif request_t *request; char *url; int xerrno;