diff options
Diffstat (limited to 'source3/utils')
-rw-r--r-- | source3/utils/net_domain.c | 8 | ||||
-rw-r--r-- | source3/utils/net_rpc.c | 20 | ||||
-rw-r--r-- | source3/utils/net_rpc_join.c | 12 | ||||
-rw-r--r-- | source3/utils/net_rpc_samsync.c | 8 | ||||
-rw-r--r-- | source3/utils/ntlm_auth.c | 397 |
5 files changed, 276 insertions, 169 deletions
diff --git a/source3/utils/net_domain.c b/source3/utils/net_domain.c index da5e61caf0..a98f090e62 100644 --- a/source3/utils/net_domain.c +++ b/source3/utils/net_domain.c @@ -208,6 +208,7 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, uint32 num_rids, *name_types, *user_rids; uint32 flags = 0x3e8; uint32 acb_info = ACB_WSTRUST; + uint32 acct_flags; uint32 fields_present; uchar pwbuf[532]; SAM_USERINFO_CTR ctr; @@ -245,8 +246,13 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, /* Don't try to set any acb_info flags other than ACB_WSTRUST */ + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, - acct_name, acb_info, 0xe005000b, &user_pol, &user_rid); + acct_name, acb_info, acct_flags, &user_pol, &user_rid); if ( !NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 677924649c..b08a93627d 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -588,7 +588,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; const char *acct_name; uint32 acb_info; - uint32 access_mask, user_rid; + uint32 acct_flags, user_rid; if (argc < 1) { d_printf("User must be specified\n"); @@ -618,10 +618,13 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, /* Create domain user */ acb_info = ACB_NORMAL; - access_mask = 0xe005000b; + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, - acct_name, acb_info, access_mask, + acct_name, acb_info, acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -5341,7 +5344,8 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; char *acct_name; uint32 acb_info; - uint32 unknown, user_rid; + uint32 acct_flags=0; + uint32 user_rid; if (argc != 2) { d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n"); @@ -5375,11 +5379,13 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, /* Create trusting domain's account */ acb_info = ACB_NORMAL; - unknown = 0xe00500b0; /* No idea what this is - a permission mask? - mimir: yes, most probably it is */ + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, - acct_name, acb_info, unknown, + acct_name, acb_info, acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) { goto done; diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 6e37f3c84c..5c3fb2b2ff 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -45,7 +45,7 @@ NTSTATUS net_rpc_join_ok(const char *domain, const char *server, { enum security_types sec; unsigned int conn_flags = NET_FLAGS_PDC; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; struct cli_state *cli = NULL; struct rpc_pipe_client *pipe_hnd = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; @@ -132,7 +132,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) struct cli_state *cli; TALLOC_CTX *mem_ctx; uint32 acb_info = ACB_WSTRUST; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0); + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0); uint32 sec_channel_type; struct rpc_pipe_client *pipe_hnd = NULL; @@ -160,6 +160,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) uint32 flags = 0x3e8; char *acct_name; const char *const_acct_name; + uint32 acct_flags=0; /* check what type of join */ if (argc >= 0) { @@ -249,9 +250,14 @@ int net_rpc_join_newstyle(int argc, const char **argv) strlower_m(acct_name); const_acct_name = acct_name; + acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | + SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | + SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | + SAMR_USER_SETATTR; + DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, acct_name, acb_info, - 0xe005000b, &user_pol, + acct_flags, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result) && diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 779006884d..e1f0cd3751 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -237,7 +237,7 @@ NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid, NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uchar trust_password[16]; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint32 sec_channel_type = 0; if (!secrets_fetch_trust_account_password(domain_name, @@ -365,7 +365,8 @@ static NTSTATUS sam_account_from_delta(struct samu *account, SAM_ACCOUNT_INFO *d old_string = pdb_get_munged_dial(account); mung.length = delta->hdr_parameters.uni_str_len; mung.data = (uint8 *) delta->uni_parameters.buffer; - newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(mung); + newstr = (mung.length == 0) ? NULL : + base64_encode_data_blob(talloc_tos(), mung); if (STRING_CHANGED_NC(old_string, newstr)) pdb_set_munged_dial(account, newstr, PDB_CHANGED); @@ -1422,12 +1423,11 @@ static int fprintf_attr(FILE *add_fd, const char *attr_name, base64_blob.data = (unsigned char *)value; base64_blob.length = strlen(value); - base64 = base64_encode_data_blob(base64_blob); + base64 = base64_encode_data_blob(value, base64_blob); SMB_ASSERT(base64 != NULL); res = fprintf(add_fd, "%s:: %s\n", attr_name, base64); TALLOC_FREE(value); - TALLOC_FREE(base64); return res; } 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); } } |