mirror of
https://github.com/samba-team/samba.git
synced 2025-02-23 09:57:40 +03:00
Merge the ntlm_auth updates (refactor, add --diagnostics) into Samba 3.0
Andrew Bartlett (This used to be commit d711a1c95c92f5a89b43bf29bba8460b870d3b3a)
This commit is contained in:
parent
0e6cba20b4
commit
6dce8c678a
@ -4,7 +4,7 @@
|
||||
Winbind status program.
|
||||
|
||||
Copyright (C) Tim Potter 2000-2002
|
||||
Copyright (C) Andrew Bartlett 2003
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
|
||||
Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -39,22 +39,17 @@ enum squid_mode {
|
||||
extern int winbindd_fd;
|
||||
|
||||
static const char *helper_protocol;
|
||||
static const char *username;
|
||||
static const char *domain;
|
||||
static const char *workstation;
|
||||
static const char *hex_challenge;
|
||||
static const char *hex_lm_response;
|
||||
static const char *hex_nt_response;
|
||||
static unsigned char *challenge;
|
||||
static size_t challenge_len;
|
||||
static unsigned char *lm_response;
|
||||
static size_t lm_response_len;
|
||||
static unsigned char *nt_response;
|
||||
static size_t nt_response_len;
|
||||
static const char *opt_username;
|
||||
static const char *opt_domain;
|
||||
static const char *opt_workstation;
|
||||
static const char *opt_password;
|
||||
static DATA_BLOB opt_challenge;
|
||||
static DATA_BLOB opt_lm_response;
|
||||
static DATA_BLOB opt_nt_response;
|
||||
static int request_lm_key;
|
||||
static int request_nt_key;
|
||||
static int diagnostics;
|
||||
|
||||
static char *password;
|
||||
|
||||
static char winbind_separator(void)
|
||||
{
|
||||
@ -162,58 +157,110 @@ static BOOL check_plaintext_auth(const char *user, const char *pass, BOOL stdout
|
||||
d_printf("Reading winbind reply failed! (0x01)\n");
|
||||
}
|
||||
|
||||
d_printf("%s (0x%x)\n",
|
||||
d_printf("%s: %s (0x%x)\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.error_string,
|
||||
response.data.auth.nt_status);
|
||||
} else {
|
||||
if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
|
||||
DEBUG(1, ("Reading winbind reply failed! (0x01)\n"));
|
||||
}
|
||||
|
||||
DEBUG(3, ("%s (0x%x)\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.nt_status));
|
||||
DEBUG(3, ("%s: %s (0x%x)\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.error_string,
|
||||
response.data.auth.nt_status));
|
||||
}
|
||||
|
||||
return (result == NSS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state)
|
||||
/* authenticate a user with an encrypted username/password */
|
||||
|
||||
static NTSTATUS contact_winbind_auth_crap(const char *username,
|
||||
const char *domain,
|
||||
const char *workstation,
|
||||
const DATA_BLOB *challenge,
|
||||
const DATA_BLOB *lm_response,
|
||||
const DATA_BLOB *nt_response,
|
||||
uint32 flags,
|
||||
uint8 lm_key[16],
|
||||
uint8 nt_key[16],
|
||||
char **error_string)
|
||||
{
|
||||
NTSTATUS nt_status;
|
||||
NSS_STATUS result;
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
/* Send off request */
|
||||
|
||||
static uint8 zeros[16];
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
fstrcpy(request.data.auth_crap.user, ntlmssp_state->user);
|
||||
request.data.auth_crap.flags = flags;
|
||||
|
||||
fstrcpy(request.data.auth_crap.domain, ntlmssp_state->domain);
|
||||
fstrcpy(request.data.auth_crap.workstation, ntlmssp_state->workstation);
|
||||
fstrcpy(request.data.auth_crap.user, username);
|
||||
|
||||
fstrcpy(request.data.auth_crap.domain, domain);
|
||||
fstrcpy(request.data.auth_crap.workstation, workstation);
|
||||
|
||||
memcpy(request.data.auth_crap.chal, challenge->data, MIN(challenge->length, 8));
|
||||
|
||||
if (lm_response && lm_response->length) {
|
||||
memcpy(request.data.auth_crap.lm_resp, lm_response->data, MIN(lm_response->length, sizeof(request.data.auth_crap.lm_resp)));
|
||||
request.data.auth_crap.lm_resp_len = lm_response->length;
|
||||
}
|
||||
|
||||
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)));
|
||||
request.data.auth_crap.nt_resp_len = nt_response->length;
|
||||
}
|
||||
|
||||
memcpy(request.data.auth_crap.chal, ntlmssp_state->chal.data,
|
||||
MIN(ntlmssp_state->chal.length, 8));
|
||||
|
||||
memcpy(request.data.auth_crap.lm_resp, ntlmssp_state->lm_resp.data,
|
||||
MIN(ntlmssp_state->lm_resp.length, sizeof(request.data.auth_crap.lm_resp)));
|
||||
|
||||
memcpy(request.data.auth_crap.nt_resp, ntlmssp_state->nt_resp.data,
|
||||
MIN(ntlmssp_state->nt_resp.length, sizeof(request.data.auth_crap.nt_resp)));
|
||||
|
||||
request.data.auth_crap.lm_resp_len = ntlmssp_state->lm_resp.length;
|
||||
request.data.auth_crap.nt_resp_len = ntlmssp_state->nt_resp.length;
|
||||
|
||||
result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
|
||||
|
||||
/* Display response */
|
||||
|
||||
if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
nt_status = NT_STATUS_UNSUCCESSFUL;
|
||||
if (error_string)
|
||||
*error_string = smb_xstrdup("Reading winbind reply failed!");
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
nt_status = (NT_STATUS(response.data.auth.nt_status));
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
if (error_string)
|
||||
*error_string = smb_xstrdup(response.data.auth.error_string);
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
return NT_STATUS(response.data.auth.nt_status);
|
||||
if ((flags & WINBIND_PAM_LMKEY) && lm_key
|
||||
&& (memcmp(zeros, response.data.auth.first_8_lm_hash,
|
||||
sizeof(response.data.auth.first_8_lm_hash)) != 0)) {
|
||||
memcpy(lm_key, response.data.auth.first_8_lm_hash,
|
||||
sizeof(response.data.auth.first_8_lm_hash));
|
||||
}
|
||||
if ((flags & WINBIND_PAM_NTKEY) && nt_key
|
||||
&& (memcmp(zeros, response.data.auth.nt_session_key,
|
||||
sizeof(response.data.auth.nt_session_key)) != 0)) {
|
||||
memcpy(nt_key, response.data.auth.nt_session_key,
|
||||
sizeof(response.data.auth.nt_session_key));
|
||||
}
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state)
|
||||
{
|
||||
return contact_winbind_auth_crap(ntlmssp_state->user, ntlmssp_state->domain,
|
||||
ntlmssp_state->workstation,
|
||||
&ntlmssp_state->chal,
|
||||
&ntlmssp_state->lm_resp,
|
||||
&ntlmssp_state->nt_resp,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void manage_squid_ntlmssp_request(enum squid_mode squid_mode,
|
||||
@ -356,72 +403,283 @@ static void squid_stream(enum squid_mode squid_mode) {
|
||||
|
||||
static BOOL check_auth_crap(void)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
char *lm_key;
|
||||
char *nt_key;
|
||||
NTSTATUS nt_status;
|
||||
uint32 flags = 0;
|
||||
char lm_key[8];
|
||||
char nt_key[16];
|
||||
char *hex_lm_key;
|
||||
char *hex_nt_key;
|
||||
char *error_string;
|
||||
|
||||
static uint8 zeros[16];
|
||||
|
||||
NSS_STATUS result;
|
||||
/* Send off request */
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
if (request_lm_key)
|
||||
request.data.auth_crap.flags |= WINBIND_PAM_LMKEY;
|
||||
flags |= WINBIND_PAM_LMKEY;
|
||||
|
||||
if (request_nt_key)
|
||||
request.data.auth_crap.flags |= WINBIND_PAM_NTKEY;
|
||||
flags |= WINBIND_PAM_NTKEY;
|
||||
|
||||
fstrcpy(request.data.auth_crap.user, username);
|
||||
nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
|
||||
opt_workstation,
|
||||
&opt_challenge,
|
||||
&opt_lm_response,
|
||||
&opt_nt_response,
|
||||
flags,
|
||||
lm_key,
|
||||
nt_key,
|
||||
&error_string);
|
||||
|
||||
fstrcpy(request.data.auth_crap.domain, domain);
|
||||
fstrcpy(request.data.auth_crap.workstation, workstation);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
d_printf("%s (0x%x)\n",
|
||||
error_string,
|
||||
NT_STATUS_V(nt_status));
|
||||
SAFE_FREE(error_string);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (request_lm_key
|
||||
&& (memcmp(zeros, lm_key,
|
||||
sizeof(lm_key)) != 0)) {
|
||||
hex_encode(lm_key,
|
||||
sizeof(lm_key),
|
||||
&hex_lm_key);
|
||||
d_printf("LM_KEY: %s\n", hex_lm_key);
|
||||
SAFE_FREE(hex_lm_key);
|
||||
}
|
||||
if (request_nt_key
|
||||
&& (memcmp(zeros, nt_key,
|
||||
sizeof(nt_key)) != 0)) {
|
||||
hex_encode(nt_key,
|
||||
sizeof(nt_key),
|
||||
&hex_nt_key);
|
||||
d_printf("NT_KEY: %s\n", hex_nt_key);
|
||||
SAFE_FREE(hex_nt_key);
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
Authenticate a user with a challenge/response, checking session key
|
||||
and valid authentication types
|
||||
*/
|
||||
|
||||
static const DATA_BLOB get_challenge(void)
|
||||
{
|
||||
static DATA_BLOB chal;
|
||||
if (opt_challenge.length)
|
||||
return opt_challenge;
|
||||
|
||||
memcpy(request.data.auth_crap.chal, challenge, MIN(challenge_len, 8));
|
||||
chal = data_blob(NULL, 8);
|
||||
|
||||
memcpy(request.data.auth_crap.lm_resp, lm_response, MIN(lm_response_len, sizeof(request.data.auth_crap.lm_resp)));
|
||||
|
||||
memcpy(request.data.auth_crap.nt_resp, nt_response, MIN(nt_response_len, sizeof(request.data.auth_crap.nt_resp)));
|
||||
|
||||
request.data.auth_crap.lm_resp_len = lm_response_len;
|
||||
request.data.auth_crap.nt_resp_len = nt_response_len;
|
||||
generate_random_buffer(chal.data, chal.length, False);
|
||||
return chal;
|
||||
}
|
||||
|
||||
result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
|
||||
static BOOL test_lm(void)
|
||||
{
|
||||
NTSTATUS nt_status;
|
||||
uint32 flags = 0;
|
||||
DATA_BLOB lm_response = data_blob(NULL, 24);
|
||||
|
||||
/* Display response */
|
||||
uchar lm_key[8];
|
||||
uchar lm_hash[16];
|
||||
DATA_BLOB chall = get_challenge();
|
||||
char *error_string;
|
||||
|
||||
flags |= WINBIND_PAM_LMKEY;
|
||||
|
||||
if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
|
||||
d_printf("Reading winbind reply failed! (0x01)\n");
|
||||
SMBencrypt(opt_password,chall.data,lm_response.data);
|
||||
E_deshash(opt_password, lm_hash);
|
||||
|
||||
nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation,
|
||||
&chall,
|
||||
&lm_response,
|
||||
NULL,
|
||||
flags,
|
||||
lm_key,
|
||||
NULL,
|
||||
&error_string);
|
||||
|
||||
data_blob_free(&lm_response);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
d_printf("%s (0x%x)\n",
|
||||
error_string,
|
||||
NT_STATUS_V(nt_status));
|
||||
return False;
|
||||
}
|
||||
|
||||
d_printf("%s (0x%x)\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.nt_status);
|
||||
if (memcmp(lm_hash, lm_key,
|
||||
sizeof(lm_key)) != 0) {
|
||||
DEBUG(1, ("LM Key does not match expectations!\n"));
|
||||
DEBUG(1, ("lm_key:\n"));
|
||||
dump_data(1, lm_key, 8);
|
||||
DEBUG(1, ("expected:\n"));
|
||||
dump_data(1, lm_hash, 8);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
if (response.data.auth.nt_status == 0) {
|
||||
if (request_lm_key
|
||||
&& (memcmp(zeros, response.data.auth.first_8_lm_hash,
|
||||
sizeof(response.data.auth.first_8_lm_hash)) != 0)) {
|
||||
hex_encode(response.data.auth.first_8_lm_hash,
|
||||
sizeof(response.data.auth.first_8_lm_hash),
|
||||
&lm_key);
|
||||
d_printf("LM_KEY: %s\n", lm_key);
|
||||
SAFE_FREE(lm_key);
|
||||
}
|
||||
if (request_nt_key
|
||||
&& (memcmp(zeros, response.data.auth.nt_session_key,
|
||||
sizeof(response.data.auth.nt_session_key)) != 0)) {
|
||||
hex_encode(response.data.auth.nt_session_key,
|
||||
sizeof(response.data.auth.nt_session_key),
|
||||
&nt_key);
|
||||
d_printf("NT_KEY: %s\n", nt_key);
|
||||
SAFE_FREE(nt_key);
|
||||
static BOOL test_lm_ntlm(void)
|
||||
{
|
||||
BOOL pass = True;
|
||||
NTSTATUS nt_status;
|
||||
uint32 flags = 0;
|
||||
DATA_BLOB lm_response = data_blob(NULL, 24);
|
||||
DATA_BLOB nt_response = data_blob(NULL, 24);
|
||||
DATA_BLOB session_key = data_blob(NULL, 16);
|
||||
|
||||
uchar lm_key[8];
|
||||
uchar nt_key[16];
|
||||
uchar lm_hash[16];
|
||||
uchar nt_hash[16];
|
||||
DATA_BLOB chall = get_challenge();
|
||||
char *error_string;
|
||||
|
||||
flags |= WINBIND_PAM_LMKEY;
|
||||
flags |= WINBIND_PAM_NTKEY;
|
||||
|
||||
SMBencrypt(opt_password,chall.data,lm_response.data);
|
||||
E_deshash(opt_password, lm_hash);
|
||||
|
||||
SMBNTencrypt(opt_password,chall.data,nt_response.data);
|
||||
|
||||
E_md4hash(opt_password, nt_hash);
|
||||
SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
|
||||
|
||||
nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
|
||||
opt_workstation,
|
||||
&chall,
|
||||
&lm_response,
|
||||
&nt_response,
|
||||
flags,
|
||||
lm_key,
|
||||
nt_key,
|
||||
&error_string);
|
||||
|
||||
data_blob_free(&lm_response);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
d_printf("%s (0x%x)\n",
|
||||
error_string,
|
||||
NT_STATUS_V(nt_status));
|
||||
SAFE_FREE(error_string);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (memcmp(lm_hash, lm_key,
|
||||
sizeof(lm_key)) != 0) {
|
||||
DEBUG(1, ("LM Key does not match expectations!\n"));
|
||||
DEBUG(1, ("lm_key:\n"));
|
||||
dump_data(1, lm_key, 8);
|
||||
DEBUG(1, ("expected:\n"));
|
||||
dump_data(1, lm_hash, 8);
|
||||
pass = False;
|
||||
}
|
||||
if (memcmp(session_key.data, nt_key,
|
||||
sizeof(nt_key)) != 0) {
|
||||
DEBUG(1, ("NT Session Key does not match expectations!\n"));
|
||||
DEBUG(1, ("nt_key:\n"));
|
||||
dump_data(1, nt_key, 16);
|
||||
DEBUG(1, ("expected:\n"));
|
||||
dump_data(1, session_key.data, session_key.length);
|
||||
pass = False;
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
static BOOL test_ntlm(void)
|
||||
{
|
||||
BOOL pass = True;
|
||||
NTSTATUS nt_status;
|
||||
uint32 flags = 0;
|
||||
DATA_BLOB nt_response = data_blob(NULL, 24);
|
||||
DATA_BLOB session_key = data_blob(NULL, 16);
|
||||
|
||||
char nt_key[16];
|
||||
char nt_hash[16];
|
||||
DATA_BLOB chall = get_challenge();
|
||||
char *error_string;
|
||||
|
||||
flags |= WINBIND_PAM_NTKEY;
|
||||
|
||||
SMBNTencrypt(opt_password,chall.data,nt_response.data);
|
||||
E_md4hash(opt_password, nt_hash);
|
||||
SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
|
||||
|
||||
nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
|
||||
opt_workstation,
|
||||
&chall,
|
||||
NULL,
|
||||
&nt_response,
|
||||
flags,
|
||||
NULL,
|
||||
nt_key,
|
||||
&error_string);
|
||||
|
||||
data_blob_free(&nt_response);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
d_printf("%s (0x%x)\n",
|
||||
error_string,
|
||||
NT_STATUS_V(nt_status));
|
||||
SAFE_FREE(error_string);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (memcmp(session_key.data, nt_key,
|
||||
sizeof(nt_key)) != 0) {
|
||||
DEBUG(1, ("NT Session Key does not match expectations!\n"));
|
||||
DEBUG(1, ("nt_key:\n"));
|
||||
dump_data(1, nt_key, 16);
|
||||
DEBUG(1, ("expected:\n"));
|
||||
dump_data(1, session_key.data, session_key.length);
|
||||
pass = False;
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
/*
|
||||
Tests:
|
||||
|
||||
- LM only
|
||||
- NT and LM
|
||||
- NT
|
||||
- NTLMv2
|
||||
- NTLMv2 and LMv2
|
||||
- LMv2
|
||||
|
||||
check we get the correct session key in each case
|
||||
check what values we get for the LM session key
|
||||
|
||||
*/
|
||||
|
||||
struct ntlm_tests {
|
||||
BOOL (*fn)();
|
||||
const char *name;
|
||||
} test_table[] = {
|
||||
{test_lm, "test LM"},
|
||||
{test_lm_ntlm, "test LM and NTLM"},
|
||||
{test_ntlm, "test NTLM"}
|
||||
/* {test_lm_ntlmv2, "test NTLMv2"}, */
|
||||
/* {test_lm_ntlmv2, "test NTLMv2 and LMv2"}, */
|
||||
/* {test_lm_ntlmv2, "test LMv2"} */
|
||||
};
|
||||
|
||||
static BOOL diagnose_ntlm_auth(void)
|
||||
{
|
||||
unsigned int i;
|
||||
BOOL pass = True;
|
||||
|
||||
for (i=0; test_table[i].fn; i++) {
|
||||
if (!test_table[i].fn()) {
|
||||
DEBUG(1, ("Test %s failed!\n", test_table[i].name));
|
||||
pass = False;
|
||||
}
|
||||
}
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
return pass;
|
||||
}
|
||||
|
||||
/* Main program */
|
||||
@ -436,31 +694,48 @@ enum {
|
||||
OPT_NT,
|
||||
OPT_PASSWORD,
|
||||
OPT_LM_KEY,
|
||||
OPT_NT_KEY
|
||||
OPT_NT_KEY,
|
||||
OPT_DIAGNOSTICS
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
int opt;
|
||||
|
||||
static const char *hex_challenge;
|
||||
static const char *hex_lm_response;
|
||||
static const char *hex_nt_response;
|
||||
char *challenge;
|
||||
char *lm_response;
|
||||
char *nt_response;
|
||||
size_t challenge_len;
|
||||
size_t lm_response_len;
|
||||
size_t nt_response_len;
|
||||
|
||||
poptContext pc;
|
||||
|
||||
/* NOTE: DO NOT change this interface without considering the implications!
|
||||
This is an external interface, which other programs will use to interact
|
||||
with this helper.
|
||||
*/
|
||||
|
||||
/* We do not use single-letter command abbreviations, because they harm future
|
||||
interface stability. */
|
||||
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
|
||||
{ "helper-protocol", 0, POPT_ARG_STRING, &helper_protocol, OPT_DOMAIN, "operate as a stdio-based helper", "helper protocol to use"},
|
||||
{ "username", 0, POPT_ARG_STRING, &username, OPT_USERNAME, "username"},
|
||||
{ "domain", 0, POPT_ARG_STRING, &domain, OPT_DOMAIN, "domain name"},
|
||||
{ "workstation", 0, POPT_ARG_STRING, &domain, OPT_WORKSTATION, "workstation"},
|
||||
{ "username", 0, POPT_ARG_STRING, &opt_username, OPT_USERNAME, "username"},
|
||||
{ "domain", 0, POPT_ARG_STRING, &opt_domain, OPT_DOMAIN, "domain name"},
|
||||
{ "workstation", 0, POPT_ARG_STRING, &opt_workstation, OPT_WORKSTATION, "workstation"},
|
||||
{ "challenge", 0, POPT_ARG_STRING, &hex_challenge, OPT_CHALLENGE, "challenge (HEX encoded)"},
|
||||
{ "lm-response", 0, POPT_ARG_STRING, &hex_lm_response, OPT_LM, "LM Response to the challenge (HEX encoded)"},
|
||||
{ "nt-response", 0, POPT_ARG_STRING, &hex_nt_response, OPT_NT, "NT or NTLMv2 Response to the challenge (HEX encoded)"},
|
||||
{ "password", 0, POPT_ARG_STRING, &password, OPT_PASSWORD, "User's plaintext password"},
|
||||
{ "password", 0, POPT_ARG_STRING, &opt_password, OPT_PASSWORD, "User's plaintext password"},
|
||||
{ "request-lm-key", 0, POPT_ARG_NONE, &request_lm_key, OPT_LM_KEY, "Retreive LM session key"},
|
||||
{ "request-nt-key", 0, POPT_ARG_NONE, &request_nt_key, OPT_NT_KEY, "Retreive NT session key"},
|
||||
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
|
||||
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
|
||||
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version},
|
||||
{ 0, 0, 0, 0 }
|
||||
{ "diagnostics", 0, POPT_ARG_NONE, &diagnostics, OPT_DIAGNOSTICS, "Perform diagnostics on the authentictaion chain"},
|
||||
{ NULL, 0, 0, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
/* Samba client initialisation */
|
||||
@ -484,29 +759,40 @@ int main(int argc, const char **argv)
|
||||
while((opt = poptGetNextOpt(pc)) != -1) {
|
||||
switch (opt) {
|
||||
case OPT_CHALLENGE:
|
||||
challenge_len = strlen(hex_challenge);
|
||||
challenge = smb_xmalloc((challenge_len+1)/2);
|
||||
if ((challenge_len = strhex_to_str(challenge, challenge_len, hex_challenge)) != 8) {
|
||||
fprintf(stderr, "hex decode of %s failed (only got %u bytes)!\n",
|
||||
challenge = smb_xmalloc((strlen(hex_challenge)+1)/2);
|
||||
if ((challenge_len = strhex_to_str(challenge,
|
||||
strlen(hex_challenge),
|
||||
hex_challenge)) != 8) {
|
||||
x_fprintf(x_stderr, "hex decode of %s failed (only got %u bytes)!\n",
|
||||
hex_challenge, challenge_len);
|
||||
exit(1);
|
||||
}
|
||||
opt_challenge = data_blob(challenge, challenge_len);
|
||||
SAFE_FREE(challenge);
|
||||
break;
|
||||
case OPT_LM:
|
||||
lm_response_len = strlen(hex_lm_response);
|
||||
lm_response = smb_xmalloc((lm_response_len+1)/2);
|
||||
if ((lm_response_len = strhex_to_str(lm_response, lm_response_len, hex_lm_response)) != 24) {
|
||||
fprintf(stderr, "hex decode of %s failed!\n", hex_lm_response);
|
||||
lm_response = smb_xmalloc((strlen(hex_lm_response)+1)/2);
|
||||
lm_response_len = strhex_to_str(lm_response,
|
||||
strlen(hex_lm_response),
|
||||
hex_lm_response);
|
||||
if (lm_response_len != 24) {
|
||||
x_fprintf(x_stderr, "hex decode of %s failed!\n", hex_lm_response);
|
||||
exit(1);
|
||||
}
|
||||
opt_lm_response = data_blob(lm_response, lm_response_len);
|
||||
SAFE_FREE(lm_response);
|
||||
break;
|
||||
case OPT_NT:
|
||||
nt_response_len = strlen(hex_nt_response);
|
||||
nt_response = smb_xmalloc((nt_response_len+1)/2);
|
||||
if ((nt_response_len = strhex_to_str(nt_response, nt_response_len, hex_nt_response)) < 24) {
|
||||
fprintf(stderr, "hex decode of %s failed!\n", hex_nt_response);
|
||||
nt_response = smb_xmalloc((strlen(hex_nt_response)+1)/2);
|
||||
nt_response_len = strhex_to_str(nt_response,
|
||||
strlen(hex_nt_response),
|
||||
hex_nt_response);
|
||||
if (nt_response_len < 24) {
|
||||
x_fprintf(x_stderr, "hex decode of %s failed!\n", hex_nt_response);
|
||||
exit(1);
|
||||
}
|
||||
opt_nt_response = data_blob(nt_response, nt_response_len);
|
||||
SAFE_FREE(nt_response);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -519,27 +805,45 @@ int main(int argc, const char **argv)
|
||||
} else if (strcmp(helper_protocol, "squid-2.4-basic")== 0) {
|
||||
squid_stream(SQUID_2_4_BASIC);
|
||||
} else {
|
||||
fprintf(stderr, "unknown helper protocol [%s]\n", helper_protocol);
|
||||
x_fprintf(x_stderr, "unknown helper protocol [%s]\n", helper_protocol);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (domain == NULL) {
|
||||
domain = get_winbind_domain();
|
||||
if (!opt_username) {
|
||||
x_fprintf(x_stderr, "username must be specified!\n\n");
|
||||
poptPrintHelp(pc, stderr, 0);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (workstation == NULL) {
|
||||
workstation = "";
|
||||
if (opt_domain == NULL) {
|
||||
opt_domain = get_winbind_domain();
|
||||
}
|
||||
|
||||
if (challenge) {
|
||||
if (opt_workstation == NULL) {
|
||||
opt_workstation = "";
|
||||
}
|
||||
|
||||
if (opt_challenge.length) {
|
||||
if (!check_auth_crap()) {
|
||||
exit(1);
|
||||
}
|
||||
} else if (password) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!opt_password) {
|
||||
opt_password = getpass("password: ");
|
||||
}
|
||||
|
||||
if (diagnostics) {
|
||||
if (!diagnose_ntlm_auth()) {
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
fstring user;
|
||||
snprintf(user, sizeof(user)-1, "%s%c%s", domain, winbind_separator(), username);
|
||||
if (!check_plaintext_auth(user, password, True)) {
|
||||
|
||||
snprintf(user, sizeof(user)-1, "%s%c%s", opt_domain, winbind_separator(), opt_username);
|
||||
if (!check_plaintext_auth(user, opt_password, True)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user