📄 auth_ntlm.c
字号:
/* * $Id: auth_ntlm.c,v 1.35 2006/07/30 23:27:04 hno Exp $ * * DEBUG: section 29 NTLM Authenticator * AUTHOR: Robert Collins * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from * the Internet community; see the CONTRIBUTORS file for full * details. Many organizations have provided support for Squid's * development; see the SPONSORS file for full details. Squid is * Copyrighted (C) 2001 by the Regents of the University of * California; see the COPYRIGHT file for full details. Squid * incorporates software developed and/or copyrighted by other * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * *//* The functions in this file handle authentication. * They DO NOT perform access control or auditing. * See acl.c for access control and client_side.c for auditing */#include "squid.h"#include "auth_ntlm.h"extern AUTHSSETUP authSchemeSetup_ntlm;static voidauthenticateStateFree(authenticateStateData * r){ authenticateAuthUserRequestUnlock(r->auth_user_request); r->auth_user_request = NULL; cbdataFree(r);}/* NTLM Scheme */static HLPSCB authenticateNTLMHandleReply;static AUTHSACTIVE authenticateNTLMActive;static AUTHSAUTHED authNTLMAuthenticated;static AUTHSAUTHUSER authenticateNTLMAuthenticateUser;static AUTHSCONFIGURED authNTLMConfigured;static AUTHSFIXERR authenticateNTLMFixErrorHeader;static AUTHSFREE authenticateNTLMFreeUser;static AUTHSDIRECTION authenticateNTLMDirection;static AUTHSDECODE authenticateDecodeNTLMAuth;static AUTHSDUMP authNTLMCfgDump;static AUTHSFREECONFIG authNTLMFreeConfig;static AUTHSINIT authNTLMInit;static AUTHSONCLOSEC authenticateNTLMOnCloseConnection;static AUTHSUSERNAME authenticateNTLMUsername;static AUTHSREQFREE authNTLMAURequestFree;static AUTHSPARSE authNTLMParse;static AUTHSCHECKCONFIG authNTLMCheckConfig;static AUTHSSTART authenticateNTLMStart;static AUTHSSTATS authenticateNTLMStats;static AUTHSSHUTDOWN authNTLMDone;static statefulhelper *ntlmauthenticators = NULL;CBDATA_TYPE(authenticateStateData);static int authntlm_initialised = 0;static MemPool *ntlm_user_pool = NULL;static MemPool *ntlm_request_pool = NULL;static auth_ntlm_config *ntlmConfig = NULL;static void authenticateNTLMReleaseServer(ntlm_request_t * ntlm_request);/* * * Private Functions * */static voidauthNTLMDone(void){ debug(29, 2) ("authNTLMDone: shutting down NTLM authentication.\n"); if (ntlmauthenticators) helperStatefulShutdown(ntlmauthenticators); authntlm_initialised = 0; if (!shutting_down) return; if (ntlmauthenticators) helperStatefulFree(ntlmauthenticators); ntlmauthenticators = NULL; if (ntlm_request_pool) { memPoolDestroy(ntlm_request_pool); ntlm_request_pool = NULL; } if (ntlm_user_pool) { memPoolDestroy(ntlm_user_pool); ntlm_user_pool = NULL; } debug(29, 2) ("authNTLMDone: NTLM authentication Shutdown.\n");}/* free any allocated configuration details */static voidauthNTLMFreeConfig(authScheme * scheme){ if (ntlmConfig == NULL) return; assert(ntlmConfig == scheme->scheme_data); if (ntlmConfig->authenticate) wordlistDestroy(&ntlmConfig->authenticate); safe_free(ntlmConfig); scheme->scheme_data = NULL;}static voidauthNTLMCfgDump(StoreEntry * entry, const char *name, authScheme * scheme){ auth_ntlm_config *config = scheme->scheme_data; wordlist *list = config->authenticate; storeAppendPrintf(entry, "%s %s program", name, "ntlm"); while (list != NULL) { storeAppendPrintf(entry, " %s", list->key); list = list->next; } storeAppendPrintf(entry, "\n"); storeAppendPrintf(entry, "%s %s children %d\n", name, "ntlm", config->authenticateChildren); storeAppendPrintf(entry, "%s %s keep_alive %s\n", name, "ntlm", config->keep_alive ? "on" : "off");}static voidauthNTLMParse(authScheme * scheme, int n_configured, char *param_str){ if (scheme->scheme_data == NULL) { assert(ntlmConfig == NULL); /* this is the first param to be found */ scheme->scheme_data = xmalloc(sizeof(auth_ntlm_config)); memset(scheme->scheme_data, 0, sizeof(auth_ntlm_config)); ntlmConfig = scheme->scheme_data; ntlmConfig->authenticateChildren = 5; ntlmConfig->keep_alive = 1; } ntlmConfig = scheme->scheme_data; if (strcasecmp(param_str, "program") == 0) { if (ntlmConfig->authenticate) wordlistDestroy(&ntlmConfig->authenticate); parse_wordlist(&ntlmConfig->authenticate); } else if (strcasecmp(param_str, "children") == 0) { parse_int(&ntlmConfig->authenticateChildren); } else if (strcasecmp(param_str, "keep_alive") == 0) { parse_onoff(&ntlmConfig->keep_alive); } else { debug(29, 0) ("unrecognised ntlm auth scheme parameter '%s'\n", param_str); }}static voidauthNTLMCheckConfig(authScheme * scheme){ auth_ntlm_config *config = scheme->scheme_data; requirePathnameExists("authparam ntlm program", config->authenticate->key);}voidauthSchemeSetup_ntlm(authscheme_entry_t * authscheme){ assert(!authntlm_initialised); authscheme->Active = authenticateNTLMActive; authscheme->configured = authNTLMConfigured; authscheme->parse = authNTLMParse; authscheme->checkconfig = authNTLMCheckConfig; authscheme->dump = authNTLMCfgDump; authscheme->requestFree = authNTLMAURequestFree; authscheme->freeconfig = authNTLMFreeConfig; authscheme->init = authNTLMInit; authscheme->authAuthenticate = authenticateNTLMAuthenticateUser; authscheme->authenticated = authNTLMAuthenticated; authscheme->authFixHeader = authenticateNTLMFixErrorHeader; authscheme->FreeUser = authenticateNTLMFreeUser; authscheme->authStart = authenticateNTLMStart; authscheme->authStats = authenticateNTLMStats; authscheme->authUserUsername = authenticateNTLMUsername; authscheme->getdirection = authenticateNTLMDirection; authscheme->decodeauth = authenticateDecodeNTLMAuth; authscheme->donefunc = authNTLMDone; authscheme->oncloseconnection = authenticateNTLMOnCloseConnection;}/* Initialize helpers and the like for this auth scheme. Called AFTER parsing the * config file */static voidauthNTLMInit(authScheme * scheme){ static int ntlminit = 0; if (ntlmConfig->authenticate) { /* * disable client side request pipelining. There is a race with * NTLM when the client sends a second request on an NTLM * connection before the authenticate challenge is sent. With * this patch, the client may fail to authenticate, but squid's * state will be preserved. */ if (ntlmConfig->authenticate && Config.onoff.pipeline_prefetch != 0) { debug(29, 1) ("pipeline prefetching incompatile with NTLM authentication. Disabling pipeline_prefetch\n"); Config.onoff.pipeline_prefetch = 0; } if (!ntlm_user_pool) ntlm_user_pool = memPoolCreate("NTLM Scheme User Data", sizeof(ntlm_user_t)); if (!ntlm_request_pool) ntlm_request_pool = memPoolCreate("NTLM Scheme Request Data", sizeof(ntlm_request_t)); authntlm_initialised = 1; if (ntlmauthenticators == NULL) ntlmauthenticators = helperStatefulCreate("ntlmauthenticator"); ntlmauthenticators->cmdline = ntlmConfig->authenticate; ntlmauthenticators->n_to_start = ntlmConfig->authenticateChildren; ntlmauthenticators->ipc_type = IPC_STREAM; helperStatefulOpenServers(ntlmauthenticators); if (!ntlminit) { cachemgrRegister("ntlmauthenticator", "NTLM User Authenticator Stats", authenticateNTLMStats, 0, 1); ntlminit++; } CBDATA_INIT_TYPE(authenticateStateData); }}static intauthenticateNTLMActive(){ return (authntlm_initialised == 1) ? 1 : 0;}static intauthNTLMConfigured(){ if (ntlmConfig == NULL) { debug(29, 9) ("authNTLMConfigured: not configured\n"); return 0; } if (ntlmConfig->authenticate == NULL) { debug(29, 9) ("authNTLMConfigured: no helper\n"); return 0; } if (ntlmConfig->authenticateChildren == 0) { debug(29, 9) ("authNTLMConfigured: no helper children\n"); return 0; } debug(29, 9) ("authNTLMConfigured: returning configured\n"); return 1;}/* NTLM Scheme */static intauthenticateNTLMDirection(auth_user_request_t * auth_user_request){ ntlm_request_t *ntlm_request = auth_user_request->scheme_data; /* null auth_user is checked for by authenticateDirection */ if (ntlm_request->waiting || ntlm_request->client_blob) return -1; /* Need helper response to continue */ switch (ntlm_request->auth_state) { case AUTHENTICATE_STATE_NONE: /* no progress at all. */ debug(29, 1) ("authenticateNTLMDirection: called before NTLM Authenticate!. Report a bug to squid-dev. au %p\n", auth_user_request); return -2; case AUTHENTICATE_STATE_NEGOTIATE: /* send to client */ assert(ntlm_request->server_blob); return 1; case AUTHENTICATE_STATE_FAILED: return -2; case AUTHENTICATE_STATE_FINISHED: /* do nothing.. */ case AUTHENTICATE_STATE_DONE: /* do nothing.. */ return 0; case AUTHENTICATE_STATE_INITIAL: debug(29, 1) ("authenticateNTLMDirection: Unexpected AUTHENTICATE_STATE_INITIAL\n"); return -2; } return -2;}/* * Send the authenticate error header(s). Note: IE has a bug and the NTLM header * must be first. To ensure that, the configure use --enable-auth=ntlm, anything * else. */static voidauthenticateNTLMFixErrorHeader(auth_user_request_t * auth_user_request, HttpReply * rep, http_hdr_type type, request_t * request){ ntlm_request_t *ntlm_request; if (!ntlmConfig->authenticate) return; /* New request, no user details */ if (auth_user_request == NULL) { debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM'\n", type); httpHeaderPutStrf(&rep->header, type, "NTLM"); if (!ntlmConfig->keep_alive) { /* drop the connection */ httpHeaderDelByName(&rep->header, "keep-alive"); request->flags.proxy_keepalive = 0; } return; } ntlm_request = auth_user_request->scheme_data; switch (ntlm_request->auth_state) { case AUTHENTICATE_STATE_NONE: case AUTHENTICATE_STATE_FAILED: debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM'\n", type); httpHeaderPutStrf(&rep->header, type, "NTLM"); /* drop the connection */ httpHeaderDelByName(&rep->header, "keep-alive"); request->flags.proxy_keepalive = 0; break; case AUTHENTICATE_STATE_NEGOTIATE: /* we are 'waiting' for a response from the client */ /* pass the blob to the client */ debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM %s'\n", type, ntlm_request->server_blob); httpHeaderPutStrf(&rep->header, type, "NTLM %s", ntlm_request->server_blob); safe_free(ntlm_request->server_blob); request->flags.must_keepalive = 1; break; case AUTHENTICATE_STATE_FINISHED: /* Special case when authentication finished, but not allowed by ACL */ debug(29, 9) ("authenticateNTLMFixErrorHeader: Sending type:%d header: 'NTLM'\n", type); httpHeaderPutStrf(&rep->header, type, "NTLM"); break; default: debug(29, 0) ("authenticateNTLMFixErrorHeader: state %d.\n", ntlm_request->auth_state); fatal("unexpected state in AuthenticateNTLMFixErrorHeader.\n"); }}static voidauthNTLMRequestFree(ntlm_request_t * ntlm_request){ if (!ntlm_request) return; safe_free(ntlm_request->server_blob); safe_free(ntlm_request->client_blob); if (ntlm_request->authserver != NULL) { debug(29, 9) ("authenticateNTLMRequestFree: releasing server '%p'\n", ntlm_request->authserver); authenticateNTLMReleaseServer(ntlm_request); } memPoolFree(ntlm_request_pool, ntlm_request);}static voidauthNTLMAURequestFree(auth_user_request_t * auth_user_request){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -