diff options
author | Andrew Tridgell <tridge@samba.org> | 2008-01-23 13:08:14 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2008-01-23 13:08:14 +1100 |
commit | 39d172bf34d0cbb3bf3e3a04d534876097cdccb5 (patch) | |
tree | 3a32fd867e34c9a86c3a2f01308445b76bf2d50c /source3/utils/ntlm_auth.c | |
parent | 2caa0e82f5ff2f45a5c912c624e54c4a43f0c3cc (diff) | |
parent | 9051199e40dec27d3532fbec7f5744033def1874 (diff) | |
download | samba-39d172bf34d0cbb3bf3e3a04d534876097cdccb5.tar.gz samba-39d172bf34d0cbb3bf3e3a04d534876097cdccb5.tar.bz2 samba-39d172bf34d0cbb3bf3e3a04d534876097cdccb5.zip |
Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
(This used to be commit bc2973df8504850a40cb0a1172689dc0bdafa323)
Diffstat (limited to 'source3/utils/ntlm_auth.c')
-rw-r--r-- | source3/utils/ntlm_auth.c | 397 |
1 files changed, 243 insertions, 154 deletions
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 6a702fc0cf..3e2093a194 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -1,23 +1,24 @@ -/* +/* Unix SMB/CIFS implementation. Winbind status program. Copyright (C) Tim Potter 2000-2003 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004 - Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000 + Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000 Copyright (C) Robert O'Callahan 2006 (added cached credential code). + Copyright (C) Kai Blin <kai@samba.org> 2008 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 3 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, see <http://www.gnu.org/licenses/>. */ @@ -28,7 +29,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -#define SQUID_BUFFER_SIZE 2010 +#define INITIAL_BUFFER_SIZE 300 +#define MAX_BUFFER_SIZE 630000 enum stdio_helper_mode { SQUID_2_4_BASIC, @@ -42,28 +44,56 @@ enum stdio_helper_mode { NUM_HELPER_MODES }; -typedef void (*stdio_helper_function)(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); +enum ntlm_auth_cli_state { + CLIENT_INITIAL = 0, + CLIENT_RESPONSE, + CLIENT_FINISHED, + CLIENT_ERROR +}; + +enum ntlm_auth_svr_state { + SERVER_INITIAL = 0, + SERVER_CHALLENGE, + SERVER_FINISHED, + SERVER_ERROR +}; + +struct ntlm_auth_state { + TALLOC_CTX *mem_ctx; + enum stdio_helper_mode helper_mode; + enum ntlm_auth_cli_state cli_state; + enum ntlm_auth_svr_state svr_state; + struct ntlmssp_state *ntlmssp_state; + uint32_t neg_flags; + char *want_feature_list; + bool have_session_key; + DATA_BLOB session_key; + DATA_BLOB initial_message; +}; + +typedef void (*stdio_helper_function)(struct ntlm_auth_state *state, char *buf, + int length); -static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode, +static void manage_squid_basic_request (struct ntlm_auth_state *state, char *buf, int length); -static void manage_squid_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); +static void manage_squid_ntlmssp_request (struct ntlm_auth_state *state, + char *buf, int length); -static void manage_client_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); +static void manage_client_ntlmssp_request (struct ntlm_auth_state *state, + char *buf, int length); -static void manage_gss_spnego_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); +static void manage_gss_spnego_request (struct ntlm_auth_state *state, + char *buf, int length); -static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); +static void manage_gss_spnego_client_request (struct ntlm_auth_state *state, + char *buf, int length); -static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode, - char *buf, int length); +static void manage_ntlm_server_1_request (struct ntlm_auth_state *state, + char *buf, int length); -static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length); +static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, + char *buf, int length); static const struct { enum stdio_helper_mode mode; @@ -123,7 +153,7 @@ static char winbind_separator(void) d_printf("winbind separator was NULL!\n"); return *lp_winbind_separator(); } - + return sep; } @@ -679,14 +709,9 @@ static NTSTATUS do_ccache_ntlm_auth(DATA_BLOB initial_msg, DATA_BLOB challenge_m return NT_STATUS_MORE_PROCESSING_REQUIRED; } -static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) +static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, + char *buf, int length) { - static NTLMSSP_STATE *ntlmssp_state = NULL; - static char* want_feature_list = NULL; - static uint32 neg_flags = 0; - static bool have_session_key = False; - static DATA_BLOB session_key; DATA_BLOB request, reply; NTSTATUS nt_status; @@ -699,8 +724,9 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod if (strlen(buf) > 3) { if(strncmp(buf, "SF ", 3) == 0){ DEBUG(10, ("Setting flags to negotioate\n")); - SAFE_FREE(want_feature_list); - want_feature_list = SMB_STRNDUP(buf+3, strlen(buf)-3); + TALLOC_FREE(state->want_feature_list); + state->want_feature_list = talloc_strdup(state->mem_ctx, + buf+3); x_fprintf(x_stdout, "OK\n"); return; } @@ -710,9 +736,11 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod } if ((strncmp(buf, "PW ", 3) == 0)) { - /* The calling application wants us to use a local password (rather than winbindd) */ + /* The calling application wants us to use a local password + * (rather than winbindd) */ - opt_password = SMB_STRNDUP((const char *)request.data, request.length); + opt_password = SMB_STRNDUP((const char *)request.data, + request.length); if (opt_password == NULL) { DEBUG(1, ("Out of memory\n")); @@ -727,25 +755,33 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod } if (strncmp(buf, "YR", 2) == 0) { - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); + if (state->ntlmssp_state) + ntlmssp_end(&state->ntlmssp_state); + state->svr_state = SERVER_INITIAL; } else if (strncmp(buf, "KK", 2) == 0) { - + /* No special preprocessing required */ } else if (strncmp(buf, "GF", 2) == 0) { DEBUG(10, ("Requested negotiated NTLMSSP flags\n")); - x_fprintf(x_stdout, "GF 0x%08lx\n", have_session_key?neg_flags:0l); + + if (state->svr_state == SERVER_FINISHED) { + x_fprintf(x_stdout, "GF 0x%08x\n", state->neg_flags); + } + else { + x_fprintf(x_stdout, "BH\n"); + } data_blob_free(&request); return; } else if (strncmp(buf, "GK", 2) == 0) { DEBUG(10, ("Requested NTLMSSP session key\n")); - if(have_session_key) { - char *key64 = base64_encode_data_blob(session_key); + if(state->have_session_key) { + char *key64 = base64_encode_data_blob(state->mem_ctx, + state->session_key); x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>"); TALLOC_FREE(key64); } else { x_fprintf(x_stdout, "BH\n"); } - + data_blob_free(&request); return; } else { @@ -754,65 +790,62 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod return; } - if (!ntlmssp_state) { - if (!NT_STATUS_IS_OK(nt_status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) { + if (!state->ntlmssp_state) { + nt_status = ntlm_auth_start_ntlmssp_server( + &state->ntlmssp_state); + if (!NT_STATUS_IS_OK(nt_status)) { x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); return; } - ntlmssp_want_feature_list(ntlmssp_state, want_feature_list); + ntlmssp_want_feature_list(state->ntlmssp_state, + state->want_feature_list); } DEBUG(10, ("got NTLMSSP packet:\n")); dump_data(10, request.data, request.length); - nt_status = ntlmssp_update(ntlmssp_state, request, &reply); - + nt_status = ntlmssp_update(state->ntlmssp_state, request, &reply); + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - char *reply_base64 = base64_encode_data_blob(reply); + char *reply_base64 = base64_encode_data_blob(state->mem_ctx, + reply); x_fprintf(x_stdout, "TT %s\n", reply_base64); TALLOC_FREE(reply_base64); data_blob_free(&reply); + state->svr_state = SERVER_CHALLENGE; DEBUG(10, ("NTLMSSP challenge\n")); } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) { x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status))); - ntlmssp_end(&ntlmssp_state); + ntlmssp_end(&state->ntlmssp_state); } else if (!NT_STATUS_IS_OK(nt_status)) { x_fprintf(x_stdout, "NA %s\n", nt_errstr(nt_status)); DEBUG(10, ("NTLMSSP %s\n", nt_errstr(nt_status))); } else { - x_fprintf(x_stdout, "AF %s\n", (char *)ntlmssp_state->auth_context); + x_fprintf(x_stdout, "AF %s\n", + (char *)state->ntlmssp_state->auth_context); DEBUG(10, ("NTLMSSP OK!\n")); - - if(have_session_key) - data_blob_free(&session_key); - session_key = data_blob(ntlmssp_state->session_key.data, - ntlmssp_state->session_key.length); - neg_flags = ntlmssp_state->neg_flags; - have_session_key = True; + + if(state->have_session_key) + data_blob_free(&state->session_key); + state->session_key = data_blob( + state->ntlmssp_state->session_key.data, + state->ntlmssp_state->session_key.length); + state->neg_flags = state->ntlmssp_state->neg_flags; + state->have_session_key = true; + state->svr_state = SERVER_FINISHED; } data_blob_free(&request); } -static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) +static void manage_client_ntlmssp_request(struct ntlm_auth_state *state, + char *buf, int length) { - /* The statics here are *HORRIBLE* and this entire concept - needs to be rewritten. Essentially it's using these statics - as the state in a state machine. BLEEEGH ! JRA. */ - - static NTLMSSP_STATE *ntlmssp_state = NULL; - static DATA_BLOB initial_message; - static char* want_feature_list = NULL; - static uint32 neg_flags = 0; - static bool have_session_key = False; - static DATA_BLOB session_key; DATA_BLOB request, reply; NTSTATUS nt_status; - bool first = False; - + if (!opt_username || !*opt_username) { x_fprintf(x_stderr, "username must be specified!\n\n"); exit(1); @@ -827,8 +860,9 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo if (strlen(buf) > 3) { if(strncmp(buf, "SF ", 3) == 0) { DEBUG(10, ("Looking for flags to negotiate\n")); - SAFE_FREE(want_feature_list); - want_feature_list = SMB_STRNDUP(buf+3, strlen(buf)-3); + talloc_free(state->want_feature_list); + state->want_feature_list = talloc_strdup(state->mem_ctx, + buf+3); x_fprintf(x_stdout, "OK\n"); return; } @@ -840,7 +874,8 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo if (strncmp(buf, "PW ", 3) == 0) { /* We asked for a password and obviously got it :-) */ - opt_password = SMB_STRNDUP((const char *)request.data, request.length); + opt_password = SMB_STRNDUP((const char *)request.data, + request.length); if (opt_password == NULL) { DEBUG(1, ("Out of memory\n")); @@ -854,8 +889,8 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo return; } - if (!ntlmssp_state && use_cached_creds) { - /* check whether credentials are usable. */ + if (!state->ntlmssp_state && use_cached_creds) { + /* check whether cached credentials are usable. */ DATA_BLOB empty_blob = data_blob_null; nt_status = do_ccache_ntlm_auth(empty_blob, empty_blob, NULL); @@ -866,30 +901,39 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo } if (opt_password == NULL && !use_cached_creds) { - /* Request a password from the calling process. After - sending it, the calling process should retry asking for the negotiate. */ - + sending it, the calling process should retry asking for the + negotiate. */ + DEBUG(10, ("Requesting password\n")); x_fprintf(x_stdout, "PW\n"); return; } if (strncmp(buf, "YR", 2) == 0) { - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); + if (state->ntlmssp_state) + ntlmssp_end(&state->ntlmssp_state); + state->cli_state = CLIENT_INITIAL; } else if (strncmp(buf, "TT", 2) == 0) { - + /* No special preprocessing required */ } else if (strncmp(buf, "GF", 2) == 0) { DEBUG(10, ("Requested negotiated NTLMSSP flags\n")); - x_fprintf(x_stdout, "GF 0x%08lx\n", have_session_key?neg_flags:0l); + + if(state->cli_state == CLIENT_FINISHED) { + x_fprintf(x_stdout, "GF 0x%08x\n", state->neg_flags); + } + else { + x_fprintf(x_stdout, "BH\n"); + } + data_blob_free(&request); return; } else if (strncmp(buf, "GK", 2) == 0 ) { DEBUG(10, ("Requested session key\n")); - if(have_session_key) { - char *key64 = base64_encode_data_blob(session_key); + if(state->cli_state == CLIENT_FINISHED) { + char *key64 = base64_encode_data_blob(state->mem_ctx, + state->session_key); x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>"); TALLOC_FREE(key64); } @@ -905,67 +949,75 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo return; } - if (!ntlmssp_state) { - if (!NT_STATUS_IS_OK(nt_status = ntlm_auth_start_ntlmssp_client(&ntlmssp_state))) { + if (!state->ntlmssp_state) { + nt_status = ntlm_auth_start_ntlmssp_client( + &state->ntlmssp_state); + if (!NT_STATUS_IS_OK(nt_status)) { x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); return; } - ntlmssp_want_feature_list(ntlmssp_state, want_feature_list); - first = True; - initial_message = data_blob_null; + ntlmssp_want_feature_list(state->ntlmssp_state, + state->want_feature_list); + state->initial_message = data_blob_null; } DEBUG(10, ("got NTLMSSP packet:\n")); dump_data(10, request.data, request.length); - if (use_cached_creds && !opt_password && !first) { - nt_status = do_ccache_ntlm_auth(initial_message, request, &reply); + if (use_cached_creds && !opt_password && + (state->cli_state == CLIENT_RESPONSE)) { + nt_status = do_ccache_ntlm_auth(state->initial_message, request, + &reply); } else { - nt_status = ntlmssp_update(ntlmssp_state, request, &reply); + nt_status = ntlmssp_update(state->ntlmssp_state, request, + &reply); } - + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - char *reply_base64 = base64_encode_data_blob(reply); - if (first) { + char *reply_base64 = base64_encode_data_blob(state->mem_ctx, + reply); + if (state->cli_state == CLIENT_INITIAL) { x_fprintf(x_stdout, "YR %s\n", reply_base64); - } else { - x_fprintf(x_stdout, "KK %s\n", reply_base64); - } - TALLOC_FREE(reply_base64); - if (first) { - initial_message = reply; + state->initial_message = reply; + state->cli_state = CLIENT_RESPONSE; } else { + x_fprintf(x_stdout, "KK %s\n", reply_base64); data_blob_free(&reply); } + TALLOC_FREE(reply_base64); DEBUG(10, ("NTLMSSP challenge\n")); } else if (NT_STATUS_IS_OK(nt_status)) { - char *reply_base64 = base64_encode_data_blob(reply); + char *reply_base64 = base64_encode_data_blob(talloc_tos(), + reply); x_fprintf(x_stdout, "AF %s\n", reply_base64); TALLOC_FREE(reply_base64); - if(have_session_key) - data_blob_free(&session_key); + if(state->have_session_key) + data_blob_free(&state->session_key); - session_key = data_blob(ntlmssp_state->session_key.data, - ntlmssp_state->session_key.length); - neg_flags = ntlmssp_state->neg_flags; - have_session_key = True; + state->session_key = data_blob( + state->ntlmssp_state->session_key.data, + state->ntlmssp_state->session_key.length); + state->neg_flags = state->ntlmssp_state->neg_flags; + state->have_session_key = true; DEBUG(10, ("NTLMSSP OK!\n")); - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); + state->cli_state = CLIENT_FINISHED; + if (state->ntlmssp_state) + ntlmssp_end(&state->ntlmssp_state); } else { x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status))); - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); + state->cli_state = CLIENT_ERROR; + if (state->ntlmssp_state) + ntlmssp_end(&state->ntlmssp_state); } data_blob_free(&request); } -static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) +static void manage_squid_basic_request(struct ntlm_auth_state *state, + char *buf, int length) { char *user, *pass; user=buf; @@ -979,7 +1031,7 @@ static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, *pass='\0'; pass++; - if (stdio_helper_mode == SQUID_2_5_BASIC) { + if (state->helper_mode == SQUID_2_5_BASIC) { rfc1738_unescape(user); rfc1738_unescape(pass); } @@ -1039,7 +1091,7 @@ static void offer_gss_spnego_mechs(void) { return; } - reply_base64 = base64_encode_data_blob(token); + reply_base64 = base64_encode_data_blob(talloc_tos(), token); x_fprintf(x_stdout, "TT %s *\n", reply_base64); TALLOC_FREE(reply_base64); @@ -1048,8 +1100,8 @@ static void offer_gss_spnego_mechs(void) { return; } -static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) +static void manage_gss_spnego_request(struct ntlm_auth_state *state, + char *buf, int length) { static NTLMSSP_STATE *ntlmssp_state = NULL; SPNEGO_DATA request, response; @@ -1276,7 +1328,7 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, return; } - reply_base64 = base64_encode_data_blob(token); + reply_base64 = base64_encode_data_blob(talloc_tos(), token); x_fprintf(x_stdout, "%s %s %s\n", reply_code, reply_base64, reply_argument); @@ -1343,7 +1395,7 @@ static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego) write_spnego_data(&to_server, &spnego); data_blob_free(&spnego.negTokenInit.mechToken); - to_server_base64 = base64_encode_data_blob(to_server); + to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server); data_blob_free(&to_server); x_fprintf(x_stdout, "KK %s\n", to_server_base64); TALLOC_FREE(to_server_base64); @@ -1401,7 +1453,7 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) write_spnego_data(&to_server, &spnego); data_blob_free(&request); - to_server_base64 = base64_encode_data_blob(to_server); + to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server); data_blob_free(&to_server); x_fprintf(x_stdout, "KK %s\n", to_server_base64); TALLOC_FREE(to_server_base64); @@ -1490,7 +1542,7 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego) return False; } - reply_base64 = base64_encode_data_blob(to_server); + reply_base64 = base64_encode_data_blob(talloc_tos(), to_server); x_fprintf(x_stdout, "KK %s *\n", reply_base64); TALLOC_FREE(reply_base64); @@ -1522,8 +1574,8 @@ static void manage_client_krb5_targ(SPNEGO_DATA spnego) #endif -static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) +static void manage_gss_spnego_client_request(struct ntlm_auth_state *state, + char *buf, int length) { DATA_BLOB request; SPNEGO_DATA spnego; @@ -1660,8 +1712,8 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper return; } -static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode, - char *buf, int length) +static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, + char *buf, int length) { char *request, *parameter; static DATA_BLOB challenge; @@ -1853,7 +1905,8 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod } } -static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length) +static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, + char *buf, int length) { char *request, *parameter; static DATA_BLOB new_nt_pswd; @@ -2063,57 +2116,93 @@ static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_ } } -static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helper_function fn) +static void manage_squid_request(struct ntlm_auth_state *state, + stdio_helper_function fn) { - char buf[SQUID_BUFFER_SIZE+1]; - int length; + char *buf; + char tmp[INITIAL_BUFFER_SIZE+1]; + int length, buf_size = 0; char *c; - static bool err; - /* this is not a typo - x_fgets doesn't work too well under squid */ - if (fgets(buf, sizeof(buf)-1, stdin) == NULL) { - if (ferror(stdin)) { - DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", ferror(stdin), - strerror(ferror(stdin)))); - - exit(1); /* BIIG buffer */ - } - exit(0); - } - - c=(char *)memchr(buf,'\n',sizeof(buf)-1); - if (c) { - *c = '\0'; - length = c-buf; - } else { - err = 1; - return; - } - if (err) { - DEBUG(2, ("Oversized message\n")); + buf = talloc_strdup(state->mem_ctx, ""); + if (!buf) { + DEBUG(0, ("Failed to allocate input buffer.\n")); x_fprintf(x_stderr, "ERR\n"); - err = 0; - return; + exit(1); } + do { + + /* this is not a typo - x_fgets doesn't work too well under + * squid */ + if (fgets(tmp, sizeof(tmp)-1, stdin) == NULL) { + if (ferror(stdin)) { + DEBUG(1, ("fgets() failed! dying..... errno=%d " + "(%s)\n", ferror(stdin), + strerror(ferror(stdin)))); + + exit(1); + } + exit(0); + } + + buf = talloc_strdup_append_buffer(buf, tmp); + buf_size += INITIAL_BUFFER_SIZE; + + if (buf_size > MAX_BUFFER_SIZE) { + DEBUG(2, ("Oversized message\n")); + x_fprintf(x_stderr, "ERR\n"); + talloc_free(buf); + return; + } + + c = strchr(buf, '\n'); + } while (c == NULL); + + *c = '\0'; + length = c-buf; + DEBUG(10, ("Got '%s' from squid (length: %d).\n",buf,length)); if (buf[0] == '\0') { DEBUG(2, ("Invalid Request\n")); x_fprintf(x_stderr, "ERR\n"); + talloc_free(buf); return; } - - fn(helper_mode, buf, length); + + fn(state, buf, length); + talloc_free(buf); } static void squid_stream(enum stdio_helper_mode stdio_mode, stdio_helper_function fn) { + TALLOC_CTX *mem_ctx; + struct ntlm_auth_state *state; + /* initialize FDescs */ x_setbuf(x_stdout, NULL); x_setbuf(x_stderr, NULL); + + mem_ctx = talloc_init("ntlm_auth"); + if (!mem_ctx) { + DEBUG(0, ("squid_stream: Failed to create talloc context\n")); + x_fprintf(x_stderr, "ERR\n"); + exit(1); + } + + state = talloc_zero(mem_ctx, struct ntlm_auth_state); + if (!state) { + DEBUG(0, ("squid_stream: Failed to talloc ntlm_auth_state\n")); + x_fprintf(x_stderr, "ERR\n"); + exit(1); + } + + state->mem_ctx = mem_ctx; + state->helper_mode = stdio_mode; + while(1) { - manage_squid_request(stdio_mode, fn); + manage_squid_request(state, fn); } } |