#include "includes.h"
#include "lib/param/param.h"
-#include "popt_common.h"
+#include "lib/cmdline/cmdline.h"
#include "libcli/security/security.h"
#include "utils/ntlm_auth.h"
#include "../libcli/auth/libcli_auth.h"
#include "librpc/crypto/gse.h"
#include "smb_krb5.h"
#include "lib/util/tiniparser.h"
-#include "../lib/crypto/arcfour.h"
-#include "nsswitch/winbind_client.h"
#include "librpc/gen_ndr/krb5pac.h"
-#include "../lib/util/asn1.h"
#include "auth/common_auth.h"
#include "source3/include/auth.h"
#include "source3/auth/proto.h"
#include "nsswitch/libwbclient/wbclient.h"
+#include "nsswitch/winbind_struct_protocol.h"
+#include "nsswitch/libwbclient/wbclient_internal.h"
#include "lib/param/loadparm.h"
#include "lib/util/base64.h"
+#include "cmdline_contexts.h"
+#include "lib/util/tevent_ntstatus.h"
+#include "lib/util/string_wrappers.h"
-#if HAVE_KRB5
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
+#ifdef HAVE_KRB5
#include "auth/kerberos/pac_utils.h"
#endif
{
DATA_BLOB in;
if (strlen(buf) < 2) {
- DEBUG(1, ("query [%s] invalid", buf));
+ DEBUG(1, ("query [%s] invalid\n", buf));
printf("BH Query invalid\n");
return;
}
const char *get_winbind_domain(void)
{
- struct winbindd_response response;
+ struct wbcInterfaceDetails *details;
+ wbcErr ret;
static fstring winbind_domain;
if (*winbind_domain) {
return winbind_domain;
}
- ZERO_STRUCT(response);
-
/* Send off request */
- if (winbindd_request_response(NULL, WINBINDD_DOMAIN_NAME, NULL, &response) !=
- NSS_STATUS_SUCCESS) {
+ ret = wbcInterfaceDetails(&details);
+ if (!WBC_ERROR_IS_OK(ret)) {
DEBUG(1, ("could not obtain winbind domain name!\n"));
return lp_workgroup();
}
- fstrcpy(winbind_domain, response.data.domain_name);
+ fstrcpy(winbind_domain, details->netbios_domain);
+
+ wbcFreeMemory(details);
return winbind_domain;
const char *get_winbind_netbios_name(void)
{
- struct winbindd_response response;
+ struct wbcInterfaceDetails *details;
+ wbcErr ret;
static fstring winbind_netbios_name;
return winbind_netbios_name;
}
- ZERO_STRUCT(response);
-
/* Send off request */
- if (winbindd_request_response(NULL, WINBINDD_NETBIOS_NAME, NULL, &response) !=
- NSS_STATUS_SUCCESS) {
+ ret = wbcInterfaceDetails(&details);
+ if (!WBC_ERROR_IS_OK(ret)) {
DEBUG(1, ("could not obtain winbind netbios name!\n"));
return lp_netbios_name();
}
- fstrcpy(winbind_netbios_name, response.data.netbios_name);
+ fstrcpy(winbind_netbios_name, details->netbios_name);
+
+ wbcFreeMemory(details);
return winbind_netbios_name;
}
-DATA_BLOB get_challenge(void)
+DATA_BLOB get_challenge(void)
{
static DATA_BLOB chal;
if (opt_challenge.length)
/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
form DOMAIN/user into a domain and a user */
-static bool parse_ntlm_auth_domain_user(const char *domuser, fstring domain,
+static bool parse_ntlm_auth_domain_user(const char *domuser, fstring domain,
fstring user)
{
}
static bool get_require_membership_sid(void) {
- struct winbindd_request request;
- struct winbindd_response response;
+ fstring domain, name, sidbuf;
+ struct wbcDomainSid sid;
+ enum wbcSidType type;
+ wbcErr ret;
if (!require_membership_of) {
return True;
/* Otherwise, ask winbindd for the name->sid request */
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- if (!parse_ntlm_auth_domain_user(require_membership_of,
- request.data.name.dom_name,
- request.data.name.name)) {
+ if (!parse_ntlm_auth_domain_user(require_membership_of,
+ domain, name)) {
DEBUG(0, ("Could not parse %s into separate domain/name parts!\n",
require_membership_of));
return False;
}
- if (winbindd_request_response(NULL, WINBINDD_LOOKUPNAME, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- DEBUG(0, ("Winbindd lookupname failed to resolve %s into a SID!\n",
+ ret = wbcLookupName(domain, name, &sid, &type);
+ if (!WBC_ERROR_IS_OK(ret)) {
+ DEBUG(0, ("Winbindd lookupname failed to resolve %s into a SID!\n",
require_membership_of));
return False;
}
- require_membership_of_sid = SMB_STRDUP(response.data.sid.sid);
+ wbcSidToStringBuf(&sid, sidbuf, sizeof(sidbuf));
+
+ require_membership_of_sid = SMB_STRDUP(sidbuf);
if (require_membership_of_sid)
return True;
return False;
}
-/*
- * Get some configuration from pam_winbind.conf to see if we
+/*
+ * Get some configuration from pam_winbind.conf to see if we
* need to contact trusted domain
*/
-int get_pam_winbind_config()
+int get_pam_winbind_config(void)
{
int ctrl = 0;
struct tiniparser_dictionary *d = NULL;
{
struct winbindd_request request;
struct winbindd_response response;
- NSS_STATUS result;
+ wbcErr ret;
if (!get_require_membership_sid()) {
return False;
request.flags |= WBFLAG_PAM_CACHED_LOGIN;
}
- result = winbindd_request_response(NULL, WINBINDD_PAM_AUTH, &request, &response);
+ ret = wbcRequestResponse(NULL, WINBINDD_PAM_AUTH,
+ &request, &response);
/* Display response */
if (stdout_diagnostics) {
- if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
+ if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0)) {
d_fprintf(stderr, "Reading winbind reply failed! (0x01)\n");
}
response.data.auth.error_string,
response.data.auth.nt_status);
} else {
- if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
+ if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0)) {
DEBUG(1, ("Reading winbind reply failed! (0x01)\n"));
}
response.data.auth.nt_status));
}
- return (result == NSS_STATUS_SUCCESS);
+ return WBC_ERROR_IS_OK(ret);
}
/* authenticate a user with an encrypted username/password */
char **unix_name)
{
NTSTATUS nt_status;
- NSS_STATUS result;
+ wbcErr ret;
struct winbindd_request request;
struct winbindd_response response;
fstrcpy(request.data.auth_crap.user, username);
fstrcpy(request.data.auth_crap.domain, domain);
- fstrcpy(request.data.auth_crap.workstation,
+ 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;
+ size_t capped_lm_response_len = MIN(
+ lm_response->length,
+ sizeof(request.data.auth_crap.lm_resp));
+
+ memcpy(request.data.auth_crap.lm_resp,
+ lm_response->data,
+ capped_lm_response_len);
+ request.data.auth_crap.lm_resp_len = capped_lm_response_len;
}
if (nt_response && nt_response->length) {
request.data.auth_crap.nt_resp_len = nt_response->length;
}
- result = winbindd_request_response(NULL, WINBINDD_PAM_AUTH_CRAP, &request, &response);
+ ret = wbcRequestResponsePriv(
+ NULL,
+ WINBINDD_PAM_AUTH_CRAP,
+ &request,
+ &response);
SAFE_FREE(request.extra_data.data);
/* Display response */
- if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
+ if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0)) {
nt_status = NT_STATUS_UNSUCCESSFUL;
if (error_string)
*error_string = smb_xstrdup("Reading winbind reply failed!");
nt_status = (NT_STATUS(response.data.auth.nt_status));
if (!NT_STATUS_IS_OK(nt_status)) {
- if (error_string)
+ if (error_string)
*error_string = smb_xstrdup(response.data.auth.error_string);
*pauthoritative = response.data.auth.authoritative;
winbindd_free_response(&response);
}
if ((flags & WBFLAG_PAM_LMKEY) && lm_key) {
- memcpy(lm_key, response.data.auth.first_8_lm_hash,
+ memcpy(lm_key, response.data.auth.first_8_lm_hash,
sizeof(response.data.auth.first_8_lm_hash));
}
if ((flags & WBFLAG_PAM_USER_SESSION_KEY) && user_session_key) {
- memcpy(user_session_key, response.data.auth.user_session_key,
+ memcpy(user_session_key, response.data.auth.user_session_key,
sizeof(response.data.auth.user_session_key));
}
char **error_string)
{
NTSTATUS nt_status;
- NSS_STATUS result;
+ wbcErr ret;
struct winbindd_request request;
struct winbindd_response response;
request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = old_lm_hash_enc.length;
}
- result = winbindd_request_response(NULL, WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, &request, &response);
+ ret = wbcRequestResponse(NULL, WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,
+ &request, &response);
/* Display response */
- if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0))
+ if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0))
{
nt_status = NT_STATUS_UNSUCCESSFUL;
if (error_string)
nt_status = (NT_STATUS(response.data.auth.nt_status));
if (!NT_STATUS_IS_OK(nt_status))
{
- if (error_string)
+ if (error_string)
*error_string = smb_xstrdup(response.data.auth.error_string);
winbindd_free_response(&response);
return nt_status;
return nt_status;
}
+/*
+ * This function does not create a full auth_session_info, just enough
+ * for the caller to get the "unix" username
+ */
static NTSTATUS ntlm_auth_generate_session_info(struct auth4_context *auth_context,
TALLOC_CTX *mem_ctx,
void *server_returned_info,
struct auth_session_info **session_info_out)
{
const char *unix_username = (const char *)server_returned_info;
- bool ok;
struct dom_sid *sids = NULL;
struct auth_session_info *session_info = NULL;
return NT_STATUS_NO_MEMORY;
}
- session_info->security_token = talloc_zero(session_info, struct security_token);
+ /*
+ * This is not a full session_info - it is not created
+ * correctly and misses any claims etc, because all we
+ * actually use in the caller is the unix username.
+ *
+ * Therefore so no claims need to be added and
+ * se_access_check() will never run.
+ */
+ session_info->security_token
+ = security_token_initialise(talloc_tos(),
+ CLAIMS_EVALUATION_INVALID_STATE);
if (session_info->security_token == NULL) {
TALLOC_FREE(session_info);
return NT_STATUS_NO_MEMORY;
TALLOC_FREE(session_info);
return NT_STATUS_NO_MEMORY;
}
- ok = dom_sid_parse(SID_WORLD, &sids[0]);
- if (!ok) {
- TALLOC_FREE(session_info);
- return NT_STATUS_INTERNAL_ERROR;
- }
- ok = dom_sid_parse(SID_NT_NETWORK, &sids[1]);
- if (!ok) {
- TALLOC_FREE(session_info);
- return NT_STATUS_INTERNAL_ERROR;
- }
- ok = dom_sid_parse(SID_NT_AUTHENTICATED_USERS, &sids[2]);
- if (!ok) {
- TALLOC_FREE(session_info);
- return NT_STATUS_INTERNAL_ERROR;
- }
+ sid_copy(&sids[0], &global_sid_World);
+ sid_copy(&sids[1], &global_sid_Network);
+ sid_copy(&sids[2], &global_sid_Authenticated_Users);
session_info->security_token->num_sids = talloc_array_length(sids);
session_info->security_token->sids = sids;
struct PAC_LOGON_INFO *logon_info = NULL;
char *unixuser;
NTSTATUS status;
- char *domain = NULL;
- char *realm = NULL;
- char *user = NULL;
- char *p;
+ const char *domain = "";
+ const char *user = "";
tmp_ctx = talloc_new(mem_ctx);
if (!tmp_ctx) {
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
+ } else {
+ status = NT_STATUS_ACCESS_DENIED;
+ DBG_WARNING("Kerberos ticket for[%s] has no PAC: %s\n",
+ princ_name, nt_errstr(status));
+ goto done;
}
- DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
-
- p = strchr_m(princ_name, '@');
- if (!p) {
- DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
- princ_name));
- return NT_STATUS_LOGON_FAILURE;
- }
-
- user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
- if (!user) {
- return NT_STATUS_NO_MEMORY;
+ if (logon_info->info3.base.account_name.string != NULL) {
+ user = logon_info->info3.base.account_name.string;
+ } else {
+ user = "";
}
-
- realm = talloc_strdup(talloc_tos(), p + 1);
- if (!realm) {
- return NT_STATUS_NO_MEMORY;
+ if (logon_info->info3.base.logon_domain.string != NULL) {
+ domain = logon_info->info3.base.logon_domain.string;
+ } else {
+ domain = "";
}
- if (!strequal(realm, lp_realm())) {
- DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
- if (!lp_allow_trusted_domains()) {
- return NT_STATUS_LOGON_FAILURE;
- }
+ if (strlen(user) == 0 || strlen(domain) == 0) {
+ status = NT_STATUS_ACCESS_DENIED;
+ DBG_WARNING("Kerberos ticket for[%s] has invalid "
+ "account_name[%s]/logon_domain[%s]: %s\n",
+ princ_name,
+ logon_info->info3.base.account_name.string,
+ logon_info->info3.base.logon_domain.string,
+ nt_errstr(status));
+ goto done;
}
- if (logon_info && logon_info->info3.base.logon_domain.string) {
- domain = talloc_strdup(mem_ctx,
- logon_info->info3.base.logon_domain.string);
- if (!domain) {
- return NT_STATUS_NO_MEMORY;
- }
- DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
- } else {
-
- /* If we have winbind running, we can (and must) shorten the
- username by using the short netbios name. Otherwise we will
- have inconsistent user names. With Kerberos, we get the
- fully qualified realm, with ntlmssp we get the short
- name. And even w2k3 does use ntlmssp if you for example
- connect to an ip address. */
-
- wbcErr wbc_status;
- struct wbcDomainInfo *info = NULL;
-
- DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
- realm));
+ DBG_NOTICE("Kerberos ticket principal name is [%s] "
+ "account_name[%s]/logon_domain[%s]\n",
+ princ_name, user, domain);
- wbc_status = wbcDomainInfo(realm, &info);
-
- if (WBC_ERROR_IS_OK(wbc_status)) {
- domain = talloc_strdup(mem_ctx,
- info->short_name);
- wbcFreeMemory(info);
- } else {
- DEBUG(3, ("Could not find short name: %s\n",
- wbcErrorString(wbc_status)));
- domain = talloc_strdup(mem_ctx, realm);
- }
- if (!domain) {
- return NT_STATUS_NO_MEMORY;
+ if (!strequal(domain, lp_workgroup())) {
+ if (!lp_allow_trusted_domains()) {
+ status = NT_STATUS_LOGON_FAILURE;
+ goto done;
}
- DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
}
unixuser = talloc_asprintf(tmp_ctx, "%s%c%s", domain, winbind_separator(), user);
/**
- * Return the challenge as determined by the authentication subsystem
+ * Return the challenge as determined by the authentication subsystem
* @return an 8 byte random challenge
*/
uint8_t chal[8])
{
if (auth_ctx->challenge.data.length == 8) {
- DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
+ DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
auth_ctx->challenge.set_by));
memcpy(chal, auth_ctx->challenge.data.data, 8);
return NT_STATUS_OK;
}
/**
- * NTLM2 authentication modifies the effective challenge,
+ * NTLM2 authentication modifies the effective challenge,
* @param challenge The new challenge value
*/
-static NTSTATUS ntlm_auth_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by)
+static NTSTATUS ntlm_auth_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by)
{
auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
}
/**
- * Check the password on an NTLMSSP login.
+ * Check the password on an NTLMSSP login.
*
* Return the session keys used on the connection.
*/
-static NTSTATUS winbind_pw_check(struct auth4_context *auth4_context,
- TALLOC_CTX *mem_ctx,
- const struct auth_usersupplied_info *user_info,
- uint8_t *pauthoritative,
- void **server_returned_info,
- DATA_BLOB *session_key, DATA_BLOB *lm_session_key)
+struct winbind_pw_check_state {
+ uint8_t authoritative;
+ void *server_info;
+ DATA_BLOB nt_session_key;
+ DATA_BLOB lm_session_key;
+};
+
+static struct tevent_req *winbind_pw_check_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct auth4_context *auth4_context,
+ const struct auth_usersupplied_info *user_info)
{
+ struct tevent_req *req = NULL;
+ struct winbind_pw_check_state *state = NULL;
NTSTATUS nt_status;
char *error_string = NULL;
- uint8_t lm_key[8];
- uint8_t user_sess_key[16];
+ uint8_t lm_key[8];
+ uint8_t user_sess_key[16];
char *unix_name = NULL;
- nt_status = contact_winbind_auth_crap(user_info->client.account_name, user_info->client.domain_name,
- user_info->workstation_name,
- &auth4_context->challenge.data,
- &user_info->password.response.lanman,
- &user_info->password.response.nt,
- WBFLAG_PAM_LMKEY | WBFLAG_PAM_USER_SESSION_KEY | WBFLAG_PAM_UNIX_NAME,
- 0,
- lm_key, user_sess_key,
- pauthoritative,
- &error_string, &unix_name);
-
- if (NT_STATUS_IS_OK(nt_status)) {
- if (!all_zero(lm_key, 8)) {
- *lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
- memcpy(lm_session_key->data, lm_key, 8);
- memset(lm_session_key->data+8, '\0', 8);
+ req = tevent_req_create(
+ mem_ctx, &state, struct winbind_pw_check_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ nt_status = contact_winbind_auth_crap(
+ user_info->client.account_name,
+ user_info->client.domain_name,
+ user_info->workstation_name,
+ &auth4_context->challenge.data,
+ &user_info->password.response.lanman,
+ &user_info->password.response.nt,
+ WBFLAG_PAM_LMKEY |
+ WBFLAG_PAM_USER_SESSION_KEY |
+ WBFLAG_PAM_UNIX_NAME,
+ 0,
+ lm_key, user_sess_key,
+ &state->authoritative,
+ &error_string,
+ &unix_name);
+
+ if (tevent_req_nterror(req, nt_status)) {
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
+ DBG_ERR("Login for user [%s]\\[%s]@[%s] failed due "
+ "to [%s]\n",
+ user_info->client.domain_name,
+ user_info->client.account_name,
+ user_info->workstation_name,
+ error_string ?
+ error_string :
+ "unknown error (NULL)");
+ } else {
+ DBG_NOTICE("Login for user [%s]\\[%s]@[%s] failed due "
+ "to [%s]\n",
+ user_info->client.domain_name,
+ user_info->client.account_name,
+ user_info->workstation_name,
+ error_string ?
+ error_string :
+ "unknown error (NULL)");
}
+ goto done;
+ }
- if (!all_zero(user_sess_key, 16)) {
- *session_key = data_blob_talloc(mem_ctx, user_sess_key, 16);
+ if (!all_zero(lm_key, 8)) {
+ state->lm_session_key = data_blob_talloc(state, NULL, 16);
+ if (tevent_req_nomem(state->lm_session_key.data, req)) {
+ goto done;
+ }
+ memcpy(state->lm_session_key.data, lm_key, 8);
+ memset(state->lm_session_key.data+8, '\0', 8);
+ }
+ if (!all_zero(user_sess_key, 16)) {
+ state->nt_session_key = data_blob_talloc(
+ state, user_sess_key, 16);
+ if (tevent_req_nomem(state->nt_session_key.data, req)) {
+ goto done;
}
- *server_returned_info = talloc_strdup(mem_ctx,
- 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",
- user_info->client.domain_name, user_info->client.account_name,
- user_info->workstation_name,
- error_string ? error_string : "unknown error (NULL)"));
}
+ state->server_info = talloc_strdup(state, unix_name);
+ if (tevent_req_nomem(state->server_info, req)) {
+ goto done;
+ }
+ tevent_req_done(req);
+done:
SAFE_FREE(error_string);
SAFE_FREE(unix_name);
- return nt_status;
+ return tevent_req_post(req, ev);
}
-static NTSTATUS local_pw_check(struct auth4_context *auth4_context,
- TALLOC_CTX *mem_ctx,
- const struct auth_usersupplied_info *user_info,
- uint8_t *pauthoritative,
- void **server_returned_info,
- DATA_BLOB *session_key, DATA_BLOB *lm_session_key)
+static NTSTATUS winbind_pw_check_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ uint8_t *pauthoritative,
+ void **server_returned_info,
+ DATA_BLOB *nt_session_key,
+ DATA_BLOB *lm_session_key)
{
- NTSTATUS nt_status;
+ struct winbind_pw_check_state *state = tevent_req_data(
+ req, struct winbind_pw_check_state);
+ NTSTATUS status;
+
+ if (pauthoritative != NULL) {
+ *pauthoritative = state->authoritative;
+ }
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ if (server_returned_info != NULL) {
+ *server_returned_info = talloc_move(
+ mem_ctx, &state->server_info);
+ }
+ if (nt_session_key != NULL) {
+ *nt_session_key = (DATA_BLOB) {
+ .data = talloc_move(
+ mem_ctx, &state->nt_session_key.data),
+ .length = state->nt_session_key.length,
+ };
+ }
+ if (lm_session_key != NULL) {
+ *lm_session_key = (DATA_BLOB) {
+ .data = talloc_move(
+ mem_ctx, &state->lm_session_key.data),
+ .length = state->lm_session_key.length,
+ };
+ }
+
+ return NT_STATUS_OK;
+}
+
+struct local_pw_check_state {
+ uint8_t authoritative;
+ void *server_info;
+ DATA_BLOB nt_session_key;
+ DATA_BLOB lm_session_key;
+};
+
+static struct tevent_req *local_pw_check_send(
+ TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct auth4_context *auth4_context,
+ const struct auth_usersupplied_info *user_info)
+{
+ struct tevent_req *req = NULL;
+ struct local_pw_check_state *state = NULL;
struct samr_Password lm_pw, nt_pw;
+ NTSTATUS nt_status;
+
+ req = tevent_req_create(
+ mem_ctx, &state, struct local_pw_check_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->authoritative = 1;
nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash);
- *pauthoritative = 1;
+ nt_status = ntlm_password_check(
+ state,
+ true,
+ NTLM_AUTH_ON,
+ 0,
+ &auth4_context->challenge.data,
+ &user_info->password.response.lanman,
+ &user_info->password.response.nt,
+ user_info->client.account_name,
+ user_info->client.account_name,
+ user_info->client.domain_name,
+ &lm_pw,
+ &nt_pw,
+ &state->nt_session_key,
+ &state->lm_session_key);
+
+ if (tevent_req_nterror(req, nt_status)) {
+ DBG_NOTICE("Login for user [%s]\\[%s]@[%s] failed due to "
+ "[%s]\n",
+ user_info->client.domain_name,
+ user_info->client.account_name,
+ user_info->workstation_name,
+ nt_errstr(nt_status));
+ return tevent_req_post(req, ev);
+ }
+
+ state->server_info = talloc_asprintf(
+ state,
+ "%s%c%s",
+ user_info->client.domain_name,
+ *lp_winbind_separator(),
+ user_info->client.account_name);
+ if (tevent_req_nomem(state->server_info, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+}
- nt_status = ntlm_password_check(mem_ctx,
- true, true, 0,
- &auth4_context->challenge.data,
- &user_info->password.response.lanman,
- &user_info->password.response.nt,
- user_info->client.account_name,
- user_info->client.account_name,
- user_info->client.domain_name,
- &lm_pw, &nt_pw, session_key, lm_session_key);
-
- if (NT_STATUS_IS_OK(nt_status)) {
- *server_returned_info = talloc_asprintf(mem_ctx,
- "%s%c%s", user_info->client.domain_name,
- *lp_winbind_separator(),
- user_info->client.account_name);
- } else {
- DEBUG(3, ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n",
- user_info->client.domain_name, user_info->client.account_name,
- user_info->workstation_name,
- nt_errstr(nt_status)));
+static NTSTATUS local_pw_check_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ uint8_t *pauthoritative,
+ void **server_returned_info,
+ DATA_BLOB *nt_session_key,
+ DATA_BLOB *lm_session_key)
+{
+ struct local_pw_check_state *state = tevent_req_data(
+ req, struct local_pw_check_state);
+ NTSTATUS status;
+
+ if (pauthoritative != NULL) {
+ *pauthoritative = state->authoritative;
}
- return nt_status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ if (server_returned_info != NULL) {
+ *server_returned_info = talloc_move(
+ mem_ctx, &state->server_info);
+ }
+ if (nt_session_key != NULL) {
+ *nt_session_key = (DATA_BLOB) {
+ .data = talloc_move(
+ mem_ctx, &state->nt_session_key.data),
+ .length = state->nt_session_key.length,
+ };
+ }
+ if (lm_session_key != NULL) {
+ *lm_session_key = (DATA_BLOB) {
+ .data = talloc_move(
+ mem_ctx, &state->lm_session_key.data),
+ .length = state->lm_session_key.length,
+ };
+ }
+
+ return NT_STATUS_OK;
}
static NTSTATUS ntlm_auth_prepare_gensec_client(TALLOC_CTX *mem_ctx,
/* These need to be in priority order, krb5 before NTLMSSP */
#if defined(HAVE_KRB5)
- backends[idx++] = &gensec_gse_krb5_security_ops;
+ backends[idx++] = gensec_gse_security_by_oid(GENSEC_OID_KERBEROS5);
#endif
backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP);
{
struct auth4_context *auth4_context = talloc_zero(mem_ctx, struct auth4_context);
if (auth4_context == NULL) {
- DEBUG(10, ("failed to allocate auth4_context failed\n"));
+ DEBUG(10, ("failed to allocate auth4_context\n"));
return NULL;
}
auth4_context->generate_session_info = ntlm_auth_generate_session_info;
auth4_context->get_ntlm_challenge = ntlm_auth_get_challenge;
auth4_context->set_ntlm_challenge = ntlm_auth_set_challenge;
if (local_pw) {
- auth4_context->check_ntlm_password = local_pw_check;
+ auth4_context->check_ntlm_password_send = local_pw_check_send;
+ auth4_context->check_ntlm_password_recv = local_pw_check_recv;
} else {
- auth4_context->check_ntlm_password = winbind_pw_check;
+ auth4_context->check_ntlm_password_send =
+ winbind_pw_check_send;
+ auth4_context->check_ntlm_password_recv =
+ winbind_pw_check_recv;
}
auth4_context->private_data = NULL;
return auth4_context;
struct gensec_settings *gensec_settings;
size_t idx = 0;
struct cli_credentials *server_credentials;
-
+
struct auth4_context *auth4_context;
tmp_ctx = talloc_new(mem_ctx);
TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
-
+
gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
if (lp_ctx == NULL) {
DEBUG(10, ("lpcfg_gensec_settings failed\n"));
TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
-
- /*
+
+ /*
* This should be a 'netbios domain -> DNS domain'
* mapping, and can currently validly return NULL on
* poorly configured systems.
gensec_settings->server_netbios_name = get_winbind_netbios_name();
gensec_settings->server_netbios_domain = get_winbind_domain();
}
-
+
gensec_settings->server_dns_domain = strlower_talloc(gensec_settings,
get_mydnsdomname(talloc_tos()));
gensec_settings->server_dns_name = strlower_talloc(gensec_settings,
get_mydnsfullname());
-
+
backends = talloc_zero_array(gensec_settings,
const struct gensec_security_ops *, 4);
-
+
if (backends == NULL) {
TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
gensec_settings->backends = backends;
gensec_init();
-
+
/* These need to be in priority order, krb5 before NTLMSSP */
#if defined(HAVE_KRB5)
- backends[idx++] = &gensec_gse_krb5_security_ops;
+ backends[idx++] = gensec_gse_security_by_oid(GENSEC_OID_KERBEROS5);
#endif
backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP);
*/
server_credentials = cli_credentials_init_anon(tmp_ctx);
if (!server_credentials) {
- DEBUG(0, ("auth_generic_prepare: Failed to init server credentials\n"));
+ DBG_ERR("Failed to init server credentials\n");
return NT_STATUS_NO_MEMORY;
}
-
+
cli_credentials_set_conf(server_credentials, lp_ctx);
-
+
if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC || lp_security() == SEC_ADS || USE_KERBEROS_KEYTAB) {
- cli_credentials_set_kerberos_state(server_credentials, CRED_AUTO_USE_KERBEROS);
+ cli_credentials_set_kerberos_state(server_credentials,
+ CRED_USE_KERBEROS_DESIRED,
+ CRED_SPECIFIED);
} else {
- cli_credentials_set_kerberos_state(server_credentials, CRED_DONT_USE_KERBEROS);
+ cli_credentials_set_kerberos_state(server_credentials,
+ CRED_USE_KERBEROS_DISABLED,
+ CRED_SPECIFIED);
}
-
+
nt_status = gensec_server_start(tmp_ctx, gensec_settings,
auth4_context, &gensec_security);
-
+
if (!NT_STATUS_IS_OK(nt_status)) {
TALLOC_FREE(tmp_ctx);
return nt_status;
}
-
+
gensec_set_credentials(gensec_security, server_credentials);
/*
struct ntlm_auth_state *state,
char *buf, int length, void **private2)
{
- char *user, *pass;
+ char *user, *pass;
user=buf;
pass=(char *)memchr(buf,' ',length);
pass++;
if (state->helper_mode == SQUID_2_5_BASIC) {
- rfc1738_unescape(user);
- rfc1738_unescape(pass);
+ char *end = rfc1738_unescape(user);
+ if (end == NULL || (end - user) != strlen(user)) {
+ DEBUG(2, ("Badly rfc1738 encoded username: %s; "
+ "denying access\n", user));
+ printf("ERR\n");
+ return;
+ }
+ end = rfc1738_unescape(pass);
+ if (end == NULL || (end - pass) != strlen(pass)) {
+ DEBUG(2, ("Badly encoded password for %s; "
+ "denying access\n", user));
+ printf("ERR\n");
+ return;
+ }
}
if (check_plaintext_auth(user, pass, False)) {
static char *want_feature_list = NULL;
static DATA_BLOB session_key;
-
+ bool include_krb5_default_ccache = false;
TALLOC_CTX *mem_ctx;
mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx");
+ if (mem_ctx == NULL) {
+ printf("BH No Memory\n");
+ exit(1);
+ }
if (*private1) {
- state = (struct gensec_ntlm_state *)*private1;
+ state = talloc_get_type(*private1, struct gensec_ntlm_state);
+ if (state == NULL) {
+ DBG_WARNING("*private1 is of type %s\n",
+ talloc_get_name(*private1));
+ printf("BH *private1 is of type %s\n",
+ talloc_get_name(*private1));
+ exit(1);
+ }
} else {
state = talloc_zero(NULL, struct gensec_ntlm_state);
if (!state) {
}
if (strlen(buf) < 2) {
- DEBUG(1, ("query [%s] invalid", buf));
+ DEBUG(1, ("query [%s] invalid\n", buf));
printf("BH Query invalid\n");
talloc_free(mem_ctx);
return;
* NTLMSSP_CLIENT_1 for now.
*/
use_cached_creds = false;
- /* fall through */
+ if (opt_username == NULL && state->set_password == NULL) {
+ include_krb5_default_ccache = true;
+ }
+ FALL_THROUGH;
case NTLMSSP_CLIENT_1:
/* setup the client side */
GENSEC_FEATURE_NTLM_CCACHE);
} else if (state->set_password) {
cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED);
+ } else if (include_krb5_default_ccache) {
+ const char *error_string = NULL;
+ int rc;
+
+ rc = cli_credentials_set_ccache(creds,
+ lp_ctx,
+ NULL,
+ CRED_SPECIFIED,
+ &error_string);
+ if (rc != 0) {
+ fprintf(stderr,
+ "Warning reading default "
+ "krb5 credentials cache: %s\n",
+ error_string);
+ }
} else {
cli_credentials_set_password_callback(creds, get_password);
}
if (!in.length) {
first = true;
}
- /* fall through */
+ FALL_THROUGH;
case SQUID_2_5_NTLMSSP:
nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_NTLMSSP);
break;
nt_status = gensec_session_info(state->gensec_state, mem_ctx, &session_info);
if (!NT_STATUS_IS_OK(nt_status)) {
- reply_code = "BH Failed to retrive session info";
+ reply_code = "BH Failed to retrieve session info";
reply_arg = nt_errstr(nt_status);
DEBUG(1, ("GENSEC failed to retrieve the session info: %s\n", nt_errstr(nt_status)));
} else {
struct ntlm_auth_state *state,
char *buf, int length, void **private2)
{
- char *request, *parameter;
+ char *request, *parameter;
static DATA_BLOB challenge;
static DATA_BLOB lm_response;
static DATA_BLOB nt_response;
static bool ntlm_server_1_lm_session_key;
if (strequal(buf, ".")) {
- if (!full_username && !username) {
+ if (!full_username && !username) {
printf("Error: No username supplied!\n");
} else if (plaintext_password) {
/* handle this request as plaintext */
}
} else if (!lm_response.data && !nt_response.data) {
printf("Error: No password supplied!\n");
- } else if (!challenge.data) {
+ } else if (!challenge.data) {
printf("Error: No lanman-challenge supplied!\n");
} else {
char *error_string = NULL;
nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash);
nt_status = ntlm_password_check(mem_ctx,
- true, true, 0,
+ true,
+ NTLM_AUTH_ON,
+ 0,
&challenge,
&lm_response,
&nt_response,
TALLOC_FREE(mem_ctx);
} else {
- uint8_t authoritative = 0;
+ uint8_t authoritative = 1;
if (!domain) {
domain = smb_xstrdup(get_winbind_domain());
printf("Authenticated: Yes\n");
- if (ntlm_server_1_lm_session_key
+ if (ntlm_server_1_lm_session_key
&& (!all_zero(lm_key,
sizeof(lm_key)))) {
hex_lm_key = hex_encode_talloc(NULL,
TALLOC_FREE(hex_lm_key);
}
- if (ntlm_server_1_user_session_key
+ if (ntlm_server_1_user_session_key
&& (!all_zero(user_session_key,
sizeof(user_session_key)))) {
hex_user_session_key = hex_encode_talloc(NULL,
- (const unsigned char *)user_session_key,
+ (const unsigned char *)user_session_key,
sizeof(user_session_key));
printf("User-Session-Key: %s\n",
hex_user_session_key);
struct ntlm_auth_state *state,
char *buf, int length, void **private2)
{
- char *request, *parameter;
+ char *request, *parameter;
static DATA_BLOB new_nt_pswd;
static DATA_BLOB old_nt_hash_enc;
static DATA_BLOB new_lm_pswd;
uchar new_nt_hash[16];
uchar new_lm_hash[16];
+ gnutls_cipher_hd_t cipher_hnd = NULL;
+ gnutls_datum_t old_nt_key = {
+ .data = old_nt_hash,
+ .size = sizeof(old_nt_hash),
+ };
+ int rc;
+
new_nt_pswd = data_blob(NULL, 516);
old_nt_hash_enc = data_blob(NULL, 16);
E_md4hash(newpswd, new_nt_hash);
/* E_deshash returns false for 'long'
- passwords (> 14 DOS chars).
+ passwords (> 14 DOS chars).
Therefore, don't send a buffer
encrypted with the truncated hash
Likewise, obey the admin's restriction
*/
+ rc = gnutls_cipher_init(&cipher_hnd,
+ GNUTLS_CIPHER_ARCFOUR_128,
+ &old_nt_key,
+ NULL);
+ if (rc < 0) {
+ DBG_ERR("gnutls_cipher_init failed: %s\n",
+ gnutls_strerror(rc));
+ if (rc == GNUTLS_E_UNWANTED_ALGORITHM) {
+ DBG_ERR("Running in FIPS mode, NTLM blocked\n");
+ }
+ return;
+ }
+
if (lp_client_lanman_auth() &&
E_deshash(newpswd, new_lm_hash) &&
E_deshash(oldpswd, old_lm_hash)) {
encode_pw_buffer(new_lm_pswd.data, newpswd,
STR_UNICODE);
- arcfour_crypt(new_lm_pswd.data, old_nt_hash, 516);
- E_old_pw_hash(new_nt_hash, old_lm_hash,
+ rc = gnutls_cipher_encrypt(cipher_hnd,
+ new_lm_pswd.data,
+ 516);
+ if (rc < 0) {
+ gnutls_cipher_deinit(cipher_hnd);
+ return;
+ }
+ rc = E_old_pw_hash(new_nt_hash, old_lm_hash,
old_lm_hash_enc.data);
+ if (rc != 0) {
+ DBG_ERR("E_old_pw_hash failed: %s\n",
+ gnutls_strerror(rc));
+ return;
+ }
} else {
new_lm_pswd.data = NULL;
new_lm_pswd.length = 0;
encode_pw_buffer(new_nt_pswd.data, newpswd,
STR_UNICODE);
- arcfour_crypt(new_nt_pswd.data, old_nt_hash, 516);
- E_old_pw_hash(new_nt_hash, old_nt_hash,
+ rc = gnutls_cipher_encrypt(cipher_hnd,
+ new_nt_pswd.data,
+ 516);
+ gnutls_cipher_deinit(cipher_hnd);
+ if (rc < 0) {
+ return;
+ }
+ rc = E_old_pw_hash(new_nt_hash, old_nt_hash,
old_nt_hash_enc.data);
+ if (rc != 0) {
+ DBG_ERR("E_old_pw_hash failed: %s\n",
+ gnutls_strerror(rc));
+ return;
+ }
+
+ ZERO_ARRAY(old_nt_hash);
+ ZERO_ARRAY(old_lm_hash);
+ ZERO_ARRAY(new_nt_hash);
+ ZERO_ARRAY(new_lm_hash);
}
- if (!full_username && !username) {
+ if (!full_username && !username) {
printf("Error: No username supplied!\n");
} else if ((!new_nt_pswd.data || !old_nt_hash_enc.data) &&
(!new_lm_pswd.data || old_lm_hash_enc.data) ) {
char *hex_lm_key;
char *hex_user_session_key;
char *error_string;
- uint8_t authoritative = 0;
+ uint8_t authoritative = 1;
setbuf(stdout, NULL);
- if (request_lm_key)
+ if (request_lm_key)
flags |= WBFLAG_PAM_LMKEY;
- if (request_user_session_key)
+ if (request_user_session_key)
flags |= WBFLAG_PAM_USER_SESSION_KEY;
flags |= WBFLAG_PAM_NT_STATUS_SQUASH;
- nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
+ nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
opt_workstation,
- &opt_challenge,
- &opt_lm_response,
- &opt_nt_response,
+ &opt_challenge,
+ &opt_lm_response,
+ &opt_nt_response,
flags, 0,
- (unsigned char *)lm_key,
- (unsigned char *)user_session_key,
+ (unsigned char *)lm_key,
+ (unsigned char *)user_session_key,
&authoritative,
&error_string, NULL);
return False;
}
- if (request_lm_key
+ if (request_lm_key
&& (!all_zero((uint8_t *)lm_key, sizeof(lm_key)))) {
hex_lm_key = hex_encode_talloc(talloc_tos(), (const unsigned char *)lm_key,
sizeof(lm_key));
printf("LM_KEY: %s\n", hex_lm_key);
TALLOC_FREE(hex_lm_key);
}
- if (request_user_session_key
+ if (request_user_session_key
&& (!all_zero((uint8_t *)user_session_key,
sizeof(user_session_key)))) {
- hex_user_session_key = hex_encode_talloc(talloc_tos(), (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));
printf("NT_KEY: %s\n", hex_user_session_key);
TALLOC_FREE(hex_user_session_key);
const char *hex_nt_response = NULL;
struct loadparm_context *lp_ctx;
poptContext pc;
+ bool ok;
/* NOTE: DO NOT change this interface without considering the implications!
- This is an external interface, which other programs will use to interact
+ 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
+ /* 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, &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, &opt_password, OPT_PASSWORD, "User's plaintext password"},
- { "request-lm-key", 0, POPT_ARG_NONE, &request_lm_key, OPT_LM_KEY, "Retrieve LM session key"},
- { "request-nt-key", 0, POPT_ARG_NONE, &request_user_session_key, OPT_USER_SESSION_KEY, "Retrieve User (NT) session key"},
- { "use-cached-creds", 0, POPT_ARG_NONE, &use_cached_creds, OPT_USE_CACHED_CREDS, "Use cached credentials if no password is given"},
- { "allow-mschapv2", 0, POPT_ARG_NONE, &opt_allow_mschapv2, OPT_ALLOW_MSCHAPV2, "Explicitly allow MSCHAPv2" },
- { "offline-logon", 0, POPT_ARG_NONE, &offline_logon,
- OPT_OFFLINE_LOGON,
- "Use cached passwords when DC is offline"},
- { "diagnostics", 0, POPT_ARG_NONE, &diagnostics,
- OPT_DIAGNOSTICS,
- "Perform diagnostics on the authentication 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" },
- { "pam-winbind-conf", 0, POPT_ARG_STRING, &opt_pam_winbind_conf, OPT_PAM_WINBIND_CONF, "Require that request must set WBFLAG_PAM_CONTACT_TRUSTDOM when krb5 auth is required" },
- { "target-service", 0, POPT_ARG_STRING, &opt_target_service, OPT_TARGET_SERVICE, "Target service (eg http)" },
- { "target-hostname", 0, POPT_ARG_STRING, &opt_target_hostname, OPT_TARGET_HOSTNAME, "Target hostname" },
- POPT_COMMON_CONFIGFILE
+ {
+ .longName = "helper-protocol",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &helper_protocol,
+ .val = OPT_DOMAIN,
+ .descrip = "operate as a stdio-based helper",
+ .argDescrip = "helper protocol to use"
+ },
+ {
+ .longName = "username",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_username,
+ .val = OPT_USERNAME,
+ .descrip = "username"
+ },
+ {
+ .longName = "domain",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_domain,
+ .val = OPT_DOMAIN,
+ .descrip = "domain name"
+ },
+ {
+ .longName = "workstation",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_workstation,
+ .val = OPT_WORKSTATION,
+ .descrip = "workstation"
+ },
+ {
+ .longName = "challenge",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &hex_challenge,
+ .val = OPT_CHALLENGE,
+ .descrip = "challenge (HEX encoded)"
+ },
+ {
+ .longName = "lm-response",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &hex_lm_response,
+ .val = OPT_LM,
+ .descrip = "LM Response to the challenge (HEX encoded)"
+ },
+ {
+ .longName = "nt-response",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &hex_nt_response,
+ .val = OPT_NT,
+ .descrip = "NT or NTLMv2 Response to the challenge (HEX encoded)"
+ },
+ {
+ .longName = "password",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_password,
+ .val = OPT_PASSWORD,
+ .descrip = "User's plaintext password"
+ },
+ {
+ .longName = "request-lm-key",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &request_lm_key,
+ .val = OPT_LM_KEY,
+ .descrip = "Retrieve LM session key (or, with --diagnostics, expect LM support)"
+ },
+ {
+ .longName = "request-nt-key",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &request_user_session_key,
+ .val = OPT_USER_SESSION_KEY,
+ .descrip = "Retrieve User (NT) session key"
+ },
+ {
+ .longName = "use-cached-creds",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &use_cached_creds,
+ .val = OPT_USE_CACHED_CREDS,
+ .descrip = "Use cached credentials if no password is given"
+ },
+ {
+ .longName = "allow-mschapv2",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &opt_allow_mschapv2,
+ .val = OPT_ALLOW_MSCHAPV2,
+ .descrip = "Explicitly allow MSCHAPv2",
+ },
+ {
+ .longName = "offline-logon",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &offline_logon,
+ .val = OPT_OFFLINE_LOGON,
+ .descrip = "Use cached passwords when DC is offline"
+ },
+ {
+ .longName = "diagnostics",
+ .shortName = 0,
+ .argInfo = POPT_ARG_NONE,
+ .arg = &diagnostics,
+ .val = OPT_DIAGNOSTICS,
+ .descrip = "Perform diagnostics on the authentication chain"
+ },
+ {
+ .longName = "require-membership-of",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &require_membership_of,
+ .val = OPT_REQUIRE_MEMBERSHIP,
+ .descrip = "Require that a user be a member of this group (either name or SID) for authentication to succeed",
+ },
+ {
+ .longName = "pam-winbind-conf",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_pam_winbind_conf,
+ .val = OPT_PAM_WINBIND_CONF,
+ .descrip = "Require that request must set WBFLAG_PAM_CONTACT_TRUSTDOM when krb5 auth is required",
+ },
+ {
+ .longName = "target-service",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_target_service,
+ .val = OPT_TARGET_SERVICE,
+ .descrip = "Target service (eg http)",
+ },
+ {
+ .longName = "target-hostname",
+ .shortName = 0,
+ .argInfo = POPT_ARG_STRING,
+ .arg = &opt_target_hostname,
+ .val = OPT_TARGET_HOSTNAME,
+ .descrip = "Target hostname",
+ },
+ POPT_COMMON_DEBUG_ONLY
+ POPT_COMMON_CONFIG_ONLY
+ POPT_COMMON_OPTION_ONLY
POPT_COMMON_VERSION
- POPT_COMMON_OPTION
POPT_TABLEEND
};
/* Samba client initialisation */
smb_init_locale();
- setup_logging("ntlm_auth", DEBUG_STDERR);
- fault_setup();
-
- /* Parse options */
-
- pc = poptGetContext("ntlm_auth", argc, argv, long_options, 0);
-
- /* Parse command line options */
-
- if (argc == 1) {
- poptPrintHelp(pc, stderr, 0);
- return 1;
- }
-
- while((opt = poptGetNextOpt(pc)) != -1) {
- /* Get generic config options like --configfile */
+ ok = samba_cmdline_init(frame,
+ SAMBA_CMDLINE_CONFIG_CLIENT,
+ false /* require_smbconf */);
+ if (!ok) {
+ DBG_ERR("Failed to init cmdline parser!\n");
+ TALLOC_FREE(frame);
+ exit(1);
}
- poptFreeContext(pc);
-
- if (!lp_load_global(get_dyn_CONFIGFILE())) {
- d_fprintf(stderr, "ntlm_auth: error opening config file %s. Error was %s\n",
- get_dyn_CONFIGFILE(), strerror(errno));
+ pc = samba_popt_get_context(getprogname(),
+ argc,
+ argv,
+ long_options,
+ POPT_CONTEXT_KEEP_FIRST);
+ if (pc == NULL) {
+ DBG_ERR("Failed to setup popt context!\n");
+ TALLOC_FREE(frame);
exit(1);
}
- pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
- POPT_CONTEXT_KEEP_FIRST);
-
while((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
case OPT_CHALLENGE:
opt_challenge = strhex_to_data_blob(NULL, hex_challenge);
if (opt_challenge.length != 8) {
fprintf(stderr, "hex decode of %s failed! "
- "(only got %d bytes)\n",
+ "(got %d bytes, expected 8)\n",
hex_challenge,
(int)opt_challenge.length);
exit(1);
}
break;
- case OPT_LM:
+ case OPT_LM:
opt_lm_response = strhex_to_data_blob(NULL, hex_lm_response);
if (opt_lm_response.length != 24) {
fprintf(stderr, "hex decode of %s failed! "
- "(only got %d bytes)\n",
+ "(got %d bytes, expected 24)\n",
hex_lm_response,
(int)opt_lm_response.length);
exit(1);
}
break;
- case OPT_NT:
+ case OPT_NT:
opt_nt_response = strhex_to_data_blob(NULL, hex_nt_response);
if (opt_nt_response.length < 24) {
fprintf(stderr, "hex decode of %s failed! "
- "(only got %d bytes)\n",
+ "(only got %d bytes, needed at least 24)\n",
hex_nt_response,
(int)opt_nt_response.length);
exit(1);
require_membership_of_sid = require_membership_of;
}
break;
+
+ case POPT_ERROR_BADOPT:
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(opt));
+ poptPrintUsage(pc, stderr, 0);
+ exit(1);
}
}
exit(1);
}
exit(0);
- }
+ }
if (!opt_password) {
char pwd[256] = {0};
}
if (diagnostics) {
- if (!diagnose_ntlm_auth()) {
+ if (!diagnose_ntlm_auth(request_lm_key)) {
+ poptFreeContext(pc);
return 1;
}
} else {
fstr_sprintf(user, "%s%c%s", opt_domain, winbind_separator(), opt_username);
if (!check_plaintext_auth(user, opt_password, True)) {
+ poptFreeContext(pc);
return 1;
}
}
/* Exit code */
-
+ gfree_all();
poptFreeContext(pc);
TALLOC_FREE(frame);
return 0;