-/*
+/*
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/>.
*/
#include "includes.h"
#include "utils/ntlm_auth.h"
+#include "../libcli/auth/libcli_auth.h"
#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,
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
+};
-static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode,
+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 (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;
{ NUM_HELPER_MODES, NULL, NULL}
};
-extern int winbindd_fd;
-
const char *opt_username;
const char *opt_domain;
const char *opt_workstation;
d_printf("winbind separator was NULL!\n");
return *lp_winbind_separator();
}
-
+
return sep;
}
}
if (nt_response && nt_response->length) {
- memcpy(request.data.auth_crap.nt_resp,
- nt_response->data,
- MIN(nt_response->length, sizeof(request.data.auth_crap.nt_resp)));
+ if (nt_response->length > sizeof(request.data.auth_crap.nt_resp)) {
+ request.flags = request.flags | WBFLAG_BIG_NTLMV2_BLOB;
+ request.extra_len = nt_response->length;
+ request.extra_data.data = SMB_MALLOC_ARRAY(char, request.extra_len);
+ if (request.extra_data.data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ memcpy(request.extra_data.data, nt_response->data,
+ nt_response->length);
+
+ } else {
+ memcpy(request.data.auth_crap.nt_resp,
+ nt_response->data, nt_response->length);
+ }
request.data.auth_crap.nt_resp_len = nt_response->length;
}
result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
+ SAFE_FREE(request.extra_data.data);
/* Display response */
}
if (flags & WBFLAG_PAM_UNIX_NAME) {
- *unix_name = SMB_STRDUP((char *)response.extra_data.data);
+ *unix_name = SMB_STRDUP(response.data.auth.unix_username);
if (!*unix_name) {
winbindd_free_response(&response);
return NT_STATUS_NO_MEMORY;
{
static const char zeros[16] = { 0, };
NTSTATUS nt_status;
- char *error_string;
+ char *error_string = NULL;
uint8 lm_key[8];
uint8 user_sess_key[16];
- char *unix_name;
+ char *unix_name = NULL;
nt_status = contact_winbind_auth_crap(ntlmssp_state->user, ntlmssp_state->domain,
ntlmssp_state->workstation,
if (memcmp(user_sess_key, zeros, 16) != 0) {
*user_session_key = data_blob(user_sess_key, 16);
}
- ntlmssp_state->auth_context = talloc_strdup(ntlmssp_state->mem_ctx, unix_name);
- SAFE_FREE(unix_name);
+ ntlmssp_state->auth_context = talloc_strdup(ntlmssp_state,
+ unix_name);
} else {
DEBUG(NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED) ? 0 : 3,
("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n",
error_string ? error_string : "unknown error (NULL)"));
ntlmssp_state->auth_context = NULL;
}
+
+ SAFE_FREE(error_string);
+ SAFE_FREE(unix_name);
return nt_status;
}
static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
{
NTSTATUS nt_status;
- uint8 lm_pw[16], nt_pw[16];
+ struct samr_Password lm_pw, nt_pw;
- nt_lm_owf_gen (opt_password, nt_pw, lm_pw);
+ nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash);
- nt_status = ntlm_password_check(ntlmssp_state->mem_ctx,
+ nt_status = ntlm_password_check(ntlmssp_state,
+ true, true, 0,
&ntlmssp_state->chal,
&ntlmssp_state->lm_resp,
&ntlmssp_state->nt_resp,
- NULL, NULL,
ntlmssp_state->user,
ntlmssp_state->user,
ntlmssp_state->domain,
- lm_pw, nt_pw, user_session_key, lm_session_key);
+ &lm_pw, &nt_pw, user_session_key, lm_session_key);
if (NT_STATUS_IS_OK(nt_status)) {
- ntlmssp_state->auth_context = talloc_asprintf(ntlmssp_state->mem_ctx,
+ ntlmssp_state->auth_context = talloc_asprintf(ntlmssp_state,
"%s%c%s", ntlmssp_state->domain,
*lp_winbind_separator(),
ntlmssp_state->user);
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;
if (strlen(buf) < 2) {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH NTLMSSP query invalid\n");
return;
}
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;
}
}
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"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Out of memory\n");
data_blob_free(&request);
return;
}
}
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(talloc_tos(),
- 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 {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH NTLMSSP query invalid\n");
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(talloc_tos(),
+ 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);
if (strlen(buf) < 2) {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH NTLMSSP query invalid\n");
return;
}
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;
}
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"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Out of memory\n");
data_blob_free(&request);
return;
}
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);
}
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(talloc_tos(),
- 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);
}
return;
} else {
DEBUG(1, ("NTLMSSP query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH NTLMSSP query invalid\n");
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(talloc_tos(),
+ char *reply_base64 = base64_encode_data_blob(state->mem_ctx,
reply);
- if (first) {
+ 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(talloc_tos(),
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;
*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);
}
if (len == -1) {
DEBUG(1, ("Could not write SPNEGO data blob\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Could not write SPNEGO data blob\n");
return;
}
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;
if (strlen(buf) < 2) {
DEBUG(1, ("SPENGO query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH SPENGO query invalid\n");
return;
}
;
} else {
DEBUG(1, ("SPENGO query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH SPENGO query invalid\n");
return;
}
if (strlen(buf) <= 3) {
DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH GSS-SPNEGO query invalid\n");
return;
}
if (len == -1) {
DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH GSS-SPNEGO query invalid\n");
return;
}
if ( (request.negTokenInit.mechTypes == NULL) ||
(request.negTokenInit.mechTypes[0] == NULL) ) {
DEBUG(1, ("Client did not offer any mechanism"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Client did not offer any "
+ "mechanism\n");
return;
}
if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) {
if ( request.negTokenInit.mechToken.data == NULL ) {
- DEBUG(1, ("Client did not provide NTLMSSP data\n"));
- x_fprintf(x_stdout, "BH\n");
+ DEBUG(1, ("Client did not provide NTLMSSP data\n"));
+ x_fprintf(x_stdout, "BH Client did not provide "
+ "NTLMSSP data\n");
return;
}
if ( ntlmssp_state != NULL ) {
DEBUG(1, ("Client wants a new NTLMSSP challenge, but "
"already got one\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Client wants a new "
+ "NTLMSSP challenge, but "
+ "already got one\n");
ntlmssp_end(&ntlmssp_state);
return;
}
char *principal;
DATA_BLOB ap_rep;
DATA_BLOB session_key;
- PAC_DATA *pac_data = NULL;
+ struct PAC_DATA *pac_data = NULL;
if ( request.negTokenInit.mechToken.data == NULL ) {
DEBUG(1, ("Client did not provide Kerberos data\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Client did not provide "
+ "Kerberos data\n");
return;
}
&principal, &pac_data, &ap_rep,
&session_key, True);
- talloc_destroy(mem_ctx);
-
/* Now in "principal" we have the name we are
authenticated as. */
if (domain == NULL) {
DEBUG(1, ("Did not get a valid principal "
"from ads_verify_ticket\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Did not get a "
+ "valid principal from "
+ "ads_verify_ticket\n");
return;
}
user = SMB_STRDUP(principal);
data_blob_free(&ap_rep);
-
- SAFE_FREE(principal);
}
+
+ TALLOC_FREE(mem_ctx);
}
#endif
is the only one we support that sends this stuff */
DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n",
request.negTokenTarg.supportedMech));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Got a negTokenTarg for "
+ "something non-NTLMSSP\n");
return;
}
if (request.negTokenTarg.responseToken.data == NULL) {
DEBUG(1, ("Got a negTokenTarg without a responseToken!\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Got a negTokenTarg without a "
+ "responseToken!\n");
return;
}
if (!reply_argument) {
DEBUG(1, ("Could not write SPNEGO data blob\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Could not write SPNEGO data blob\n");
return;
}
if (len == -1) {
DEBUG(1, ("Could not write SPNEGO data blob\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Could not write SPNEGO data blob\n");
return;
}
if (client_ntlmssp_state == NULL) {
DEBUG(1, ("Got NTLMSSP tArg without a client state\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Got NTLMSSP tArg without a client state\n");
return;
}
DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED from "
"ntlmssp_client_update, got: %s\n",
nt_errstr(status)));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Expected MORE_PROCESSING_REQUIRED from "
+ "ntlmssp_client_update\n");
data_blob_free(&request);
ntlmssp_end(&client_ntlmssp_state);
return;
switch (spnego.negTokenTarg.negResult) {
case SPNEGO_ACCEPT_INCOMPLETE:
DEBUG(1, ("Got a Kerberos negTokenTarg with ACCEPT_INCOMPLETE\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Got a Kerberos negTokenTarg with "
+ "ACCEPT_INCOMPLETE\n");
break;
case SPNEGO_ACCEPT_COMPLETED:
DEBUG(10, ("Accept completed\n"));
#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;
if (strlen(buf) <= 3) {
DEBUG(1, ("SPNEGO query [%s] too short\n", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH SPNEGO query too short\n");
return;
}
if (opt_password == NULL) {
DEBUG(1, ("Out of memory\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Out of memory\n");
data_blob_free(&request);
return;
}
(strncmp(buf, "AF ", 3) != 0) &&
(strncmp(buf, "NA ", 3) != 0) ) {
DEBUG(1, ("SPNEGO request [%s] invalid\n", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH SPNEGO request invalid\n");
data_blob_free(&request);
return;
}
if (len == -1) {
DEBUG(1, ("Could not read SPNEGO data for [%s]\n", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Could not read SPNEGO data\n");
return;
}
}
DEBUG(1, ("Server offered no compatible mechanism\n"));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Server offered no compatible mechanism\n");
return;
}
DEBUG(1, ("Got a negTokenTarg with no mech and an "
"unknown negResult: %d\n",
spnego.negTokenTarg.negResult));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Got a negTokenTarg with"
+ " no mech and an unknown "
+ "negResult\n");
}
ntlmssp_end(&client_ntlmssp_state);
}
DEBUG(1, ("Got an SPNEGO token I could not handle [%s]!\n", buf));
- x_fprintf(x_stdout, "BH\n");
+ x_fprintf(x_stdout, "BH Got an SPNEGO token I could not handle\n");
return;
out:
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;
x_fprintf(x_stdout, "Authenticated: No\n");
x_fprintf(x_stdout, "Authentication-Error: %s\n.\n", error_string);
- SAFE_FREE(error_string);
} else {
static char zeros[16];
char *hex_lm_key;
if (ntlm_server_1_lm_session_key
&& (memcmp(zeros, lm_key,
sizeof(lm_key)) != 0)) {
- hex_lm_key = hex_encode(NULL,
+ hex_lm_key = hex_encode_talloc(NULL,
(const unsigned char *)lm_key,
sizeof(lm_key));
x_fprintf(x_stdout, "LANMAN-Session-Key: %s\n", hex_lm_key);
if (ntlm_server_1_user_session_key
&& (memcmp(zeros, user_session_key,
sizeof(user_session_key)) != 0)) {
- hex_user_session_key = hex_encode(NULL,
+ hex_user_session_key = hex_encode_talloc(NULL,
(const unsigned char *)user_session_key,
sizeof(user_session_key));
x_fprintf(x_stdout, "User-Session-Key: %s\n", hex_user_session_key);
TALLOC_FREE(hex_user_session_key);
}
}
+ SAFE_FREE(error_string);
}
/* clear out the state */
challenge = data_blob_null;
}
}
-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;
encode_pw_buffer(new_lm_pswd.data, newpswd,
STR_UNICODE);
- SamOEMhash(new_lm_pswd.data, old_nt_hash, 516);
+ arcfour_crypt(new_lm_pswd.data, old_nt_hash, 516);
E_old_pw_hash(new_nt_hash, old_lm_hash,
old_lm_hash_enc.data);
} else {
encode_pw_buffer(new_nt_pswd.data, newpswd,
STR_UNICODE);
- SamOEMhash(new_nt_pswd.data, old_nt_hash, 516);
+ arcfour_crypt(new_nt_pswd.data, old_nt_hash, 516);
E_old_pw_hash(new_nt_hash, old_nt_hash,
old_nt_hash_enc.data);
}
}
}
-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);
}
}
if (request_lm_key
&& (memcmp(zeros, lm_key,
sizeof(lm_key)) != 0)) {
- hex_lm_key = hex_encode(NULL, (const unsigned char *)lm_key,
+ hex_lm_key = hex_encode_talloc(talloc_tos(), (const unsigned char *)lm_key,
sizeof(lm_key));
x_fprintf(x_stdout, "LM_KEY: %s\n", hex_lm_key);
TALLOC_FREE(hex_lm_key);
if (request_user_session_key
&& (memcmp(zeros, user_session_key,
sizeof(user_session_key)) != 0)) {
- hex_user_session_key = hex_encode(NULL, (const unsigned char *)user_session_key,
+ hex_user_session_key = hex_encode_talloc(talloc_tos(), (const unsigned char *)user_session_key,
sizeof(user_session_key));
x_fprintf(x_stdout, "NT_KEY: %s\n", hex_user_session_key);
TALLOC_FREE(hex_user_session_key);
{ "use-cached-creds", 0, POPT_ARG_NONE, &use_cached_creds, OPT_USE_CACHED_CREDS, "Use cached credentials if no password is given"},
{ "diagnostics", 0, POPT_ARG_NONE, &diagnostics, OPT_DIAGNOSTICS, "Perform diagnostics on the authentictaion chain"},
{ "require-membership-of", 0, POPT_ARG_STRING, &require_membership_of, OPT_REQUIRE_MEMBERSHIP, "Require that a user be a member of this group (either name or SID) for authentication to succeed" },
- POPT_COMMON_SAMBA
+ POPT_COMMON_CONFIGFILE
+ POPT_COMMON_VERSION
POPT_TABLEEND
};
load_case_tables();
dbf = x_stderr;
-
- /* Samba client initialisation */
-
- if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, True)) {
- d_fprintf(stderr, "ntlm_auth: error opening config file %s. Error was %s\n",
- get_dyn_CONFIGFILE(), strerror(errno));
- exit(1);
- }
/* Parse options */
return 1;
}
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ /* Get generic config options like --configfile */
+ }
+
+ poptFreeContext(pc);
+
+ if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, True)) {
+ d_fprintf(stderr, "ntlm_auth: error opening config file %s. Error was %s\n",
+ get_dyn_CONFIGFILE(), strerror(errno));
+ exit(1);
+ }
+
pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
POPT_CONTEXT_KEEP_FIRST);