#include "librpc/crypto/gse_krb5.h"
#include "lib/afs/afs_funcs.h"
#include "libsmb/samlogon_cache.h"
+#include "rpc_client/util_netlogon.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
struct winbindd_response *resp,
- struct netr_SamInfo3 *info3)
+ uint16_t validation_level,
+ union netr_Validation *validation)
{
- char *ex;
+ struct netr_SamInfo3 *info3 = NULL;
+ char *ex = NULL;
uint32_t i;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ status = map_validation_to_info3(frame,
+ validation_level,
+ validation,
+ &info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
resp->data.auth.info3.logon_time =
nt_time_to_unix(info3->base.logon_time);
fstrcpy(resp->data.auth.info3.logon_dom,
info3->base.logon_domain.string);
- ex = talloc_strdup(mem_ctx, "");
- NT_STATUS_HAVE_NO_MEMORY(ex);
+ resp->data.auth.validation_level = validation_level;
+ if (validation_level == 6) {
+ fstrcpy(resp->data.auth.info6.dns_domainname,
+ validation->sam6->dns_domainname.string);
+ fstrcpy(resp->data.auth.info6.principal_name,
+ validation->sam6->principal_name.string);
+ }
+
+ ex = talloc_strdup(frame, "");
+ if (ex == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
for (i=0; i < info3->base.groups.count; i++) {
ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
info3->base.groups.rids[i].rid,
info3->base.groups.rids[i].attributes);
- NT_STATUS_HAVE_NO_MEMORY(ex);
+ if (ex == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
}
for (i=0; i < info3->sidcount; i++) {
char *sid;
- sid = dom_sid_string(mem_ctx, info3->sids[i].sid);
- NT_STATUS_HAVE_NO_MEMORY(sid);
+ sid = dom_sid_string(frame, info3->sids[i].sid);
+ if (sid == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n",
sid,
info3->sids[i].attributes);
- NT_STATUS_HAVE_NO_MEMORY(ex);
-
- talloc_free(sid);
+ if (ex == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
}
- resp->extra_data.data = ex;
resp->length += talloc_get_size(ex);
+ resp->extra_data.data = talloc_move(mem_ctx, &ex);
- return NT_STATUS_OK;
+ status = NT_STATUS_OK;
+out:
+ TALLOC_FREE(frame);
+ return status;
}
static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
DEBUG(3, ("Authentication for domain [%s] refused "
"as it is not a trusted domain\n",
domain_name));
+ return NULL;
+ }
+
+ if (domain->secure_channel_type != SEC_CHAN_NULL) {
+ return domain;
}
- return domain;
+
+ return domain->routing_domain;
}
if (strequal(domain_name, get_global_sam_name())) {
return find_our_domain();
}
+static void fake_password_policy(struct winbindd_response *r,
+ const struct netr_SamBaseInfo *bi)
+{
+ NTTIME min_password_age;
+ NTTIME max_password_age;
+
+ if (bi->allow_password_change > bi->last_password_change) {
+ min_password_age = bi->allow_password_change -
+ bi->last_password_change;
+ } else {
+ min_password_age = 0;
+ }
+
+ if (bi->force_password_change > bi->last_password_change) {
+ max_password_age = bi->force_password_change -
+ bi->last_password_change;
+ } else {
+ max_password_age = 0;
+ }
+
+ r->data.auth.policy.min_length_password = 0;
+ r->data.auth.policy.password_history = 0;
+ r->data.auth.policy.password_properties = 0;
+ r->data.auth.policy.expire =
+ nt_time_to_unix_abs(&max_password_age);
+ r->data.auth.policy.min_passwordage =
+ nt_time_to_unix_abs(&min_password_age);
+}
+
static void fill_in_password_policy(struct winbindd_response *r,
const struct samr_DomInfo1 *p)
{
struct PAC_DATA *pac_data = NULL;
struct PAC_DATA_CTR *pac_data_ctr = NULL;
const char *local_service;
- int i;
+ uint32_t i;
struct netr_SamInfo3 *info3_copy = NULL;
*info3 = NULL;
NTSTATUS append_auth_data(TALLOC_CTX *mem_ctx,
struct winbindd_response *resp,
uint32_t request_flags,
- struct netr_SamInfo3 *info3,
+ uint16_t validation_level,
+ union netr_Validation *validation,
const char *name_domain,
const char *name_user)
{
- NTSTATUS result;
+ struct netr_SamInfo3 *info3 = NULL;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ result = map_validation_to_info3(talloc_tos(),
+ validation_level,
+ validation,
+ &info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
if (request_flags & WBFLAG_PAM_USER_SESSION_KEY) {
memcpy(resp->data.auth.user_session_key,
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("Failed to append Unix Username: %s\n",
nt_errstr(result)));
- return result;
+ goto out;
}
}
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("Failed to append INFO3 (NDR): %s\n",
nt_errstr(result)));
- return result;
+ goto out;
}
}
if (request_flags & WBFLAG_PAM_INFO3_TEXT) {
- result = append_info3_as_txt(mem_ctx, resp, info3);
+ result = append_info3_as_txt(mem_ctx, resp,
+ validation_level,
+ validation);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
nt_errstr(result)));
- return result;
+ goto out;
}
}
if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("Failed to append AFS token: %s\n",
nt_errstr(result)));
- return result;
+ goto out;
}
}
- return NT_STATUS_OK;
+ result = NT_STATUS_OK;
+out:
+ TALLOC_FREE(info3);
+ return result;
}
static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
TALLOC_FREE(frame);
return NT_STATUS_NO_MEMORY;
}
+
+ /*
+ * TODO: We should get the service description passed in from
+ * the winbind client, so we can have "smb2", "squid" or "samr" logged
+ * here.
+ */
status = make_user_info(frame, &user_info, user, user, domain, domain,
- lp_netbios_name(), local, lm_resp, nt_resp, NULL, NULL,
+ lp_netbios_name(), local, local,
+ "winbind",
+ lm_resp, nt_resp, NULL, NULL,
NULL, AUTH_PASSWORD_RESPONSE);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("make_user_info failed: %s\n", nt_errstr(status)));
bool interactive,
uint8_t *authoritative,
uint32_t *flags,
- struct netr_SamInfo3 **info3)
+ uint16_t *_validation_level,
+ union netr_Validation **_validation)
{
int attempts = 0;
int netr_attempts = 0;
bool retry = false;
NTSTATUS result;
+ enum netr_LogonInfoClass logon_type_i;
+ enum netr_LogonInfoClass logon_type_n;
+ uint16_t validation_level = UINT16_MAX;
+ union netr_Validation *validation = NULL;
do {
struct rpc_pipe_client *netlogon_pipe;
- ZERO_STRUCTP(info3);
retry = false;
result = cm_connect_netlogon(domain, &netlogon_pipe);
*/
DEBUG(3, ("This is the third problem for this "
"particular call, adding DC to the "
- "negative cache list\n"));
+ "negative cache list: %s %s\n", domain->name, domain->dcname));
add_failed_connection_entry(domain->name,
domain->dcname,
result);
}
return result;
}
+
+ logon_type_i = NetlogonInteractiveInformation;
+ logon_type_n = NetlogonNetworkInformation;
+ if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
+ logon_type_i = NetlogonInteractiveTransitiveInformation;
+ logon_type_n = NetlogonNetworkTransitiveInformation;
+ }
+
+ if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
+ logon_type_i = NetlogonInteractiveTransitiveInformation;
+ logon_type_n = NetlogonNetworkTransitiveInformation;
+ }
+
+ if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
+ logon_type_i = NetlogonInteractiveInformation;
+ logon_type_n = NetlogonNetworkInformation;
+ }
+
+ if (domain->domain_trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
+ logon_type_i = NetlogonInteractiveInformation;
+ logon_type_n = NetlogonNetworkInformation;
+ }
+
netr_attempts = 0;
- if (domain->conn.netlogon_creds == NULL) {
+ if (domain->conn.netlogon_creds_ctx == NULL) {
DBG_NOTICE("No security credentials available for "
"domain [%s]\n", domainname);
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- } else if (interactive && username != NULL && password != NULL) {
- result = rpccli_netlogon_password_logon(domain->conn.netlogon_creds,
- netlogon_pipe->binding_handle,
- mem_ctx,
- logon_parameters,
- domainname,
- username,
- password,
- workstation,
- NetlogonInteractiveInformation,
- authoritative,
- flags,
- info3);
+ } else if (interactive) {
+ result = rpccli_netlogon_password_logon(
+ domain->conn.netlogon_creds_ctx,
+ netlogon_pipe->binding_handle,
+ mem_ctx,
+ logon_parameters,
+ domainname,
+ username,
+ password,
+ workstation,
+ logon_type_i,
+ authoritative,
+ flags,
+ &validation_level,
+ &validation);
} else {
- result = rpccli_netlogon_network_logon(domain->conn.netlogon_creds,
- netlogon_pipe->binding_handle,
- mem_ctx,
- logon_parameters,
- username,
- domainname,
- workstation,
- chal,
- lm_response,
- nt_response,
- authoritative,
- flags,
- info3);
+ result = rpccli_netlogon_network_logon(
+ domain->conn.netlogon_creds_ctx,
+ netlogon_pipe->binding_handle,
+ mem_ctx,
+ logon_parameters,
+ username,
+ domainname,
+ workstation,
+ chal,
+ lm_response,
+ nt_response,
+ logon_type_n,
+ authoritative,
+ flags,
+ &validation_level,
+ &validation);
}
/*
if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT)) {
DEBUG(3,("winbind_samlogon_retry_loop: sam_network_logon(ex) "
- "returned NT_STATUS_IO_TIMEOUT after the retry."
+ "returned NT_STATUS_IO_TIMEOUT after the retry. "
"Killing connections to domain %s\n",
domainname));
invalidate_cm_connection(domain);
}
- return result;
+
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ *_validation_level = validation_level;
+ *_validation = validation;
+ return NT_STATUS_OK;
}
-static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx,
- struct winbindd_domain *domain,
- const char *user,
- const char *pass,
- uint32_t request_flags,
- struct netr_SamInfo3 **info3)
+static NTSTATUS winbindd_dual_pam_auth_samlogon(
+ TALLOC_CTX *mem_ctx,
+ struct winbindd_domain *domain,
+ const char *user,
+ const char *pass,
+ uint32_t request_flags,
+ uint16_t *_validation_level,
+ union netr_Validation **_validation)
{
uchar chal[8];
unsigned char local_nt_response[24];
fstring name_domain, name_user;
NTSTATUS result;
- struct netr_SamInfo3 *my_info3 = NULL;
uint8_t authoritative = 0;
uint32_t flags = 0;
-
- *info3 = NULL;
+ uint16_t validation_level;
+ union netr_Validation *validation = NULL;
+ struct netr_SamBaseInfo *base_info = NULL;
DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
parse_domain_user(user, name_domain, name_user);
- /* do password magic */
-
- generate_random_buffer(chal, sizeof(chal));
-
- if (lp_client_ntlmv2_auth()) {
- DATA_BLOB server_chal;
- DATA_BLOB names_blob;
- server_chal = data_blob_const(chal, 8);
-
- /* note that the 'workgroup' here is for the local
- machine. The 'server name' must match the
- 'workstation' passed to the actual SamLogon call.
- */
- names_blob = NTLMv2_generate_names_blob(
- mem_ctx, lp_netbios_name(), lp_workgroup());
-
- if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain,
- pass,
- &server_chal,
- &names_blob,
- &lm_resp, &nt_resp, NULL, NULL)) {
+ /*
+ * We check against domain->name instead of
+ * name_domain, as find_auth_domain() ->
+ * find_domain_from_name_noinit() already decided
+ * that we are in a child for the correct domain.
+ *
+ * name_domain can also be lp_realm()
+ * we need to check against domain->name.
+ */
+ if (strequal(domain->name, get_global_sam_name())) {
+ DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal));
+ struct netr_SamInfo3 *info3 = NULL;
+
+ /* do password magic */
+
+ generate_random_buffer(chal, sizeof(chal));
+
+ if (lp_client_ntlmv2_auth()) {
+ DATA_BLOB server_chal;
+ DATA_BLOB names_blob;
+ server_chal = data_blob_const(chal, 8);
+
+ /* note that the 'workgroup' here is for the local
+ machine. The 'server name' must match the
+ 'workstation' passed to the actual SamLogon call.
+ */
+ names_blob = NTLMv2_generate_names_blob(
+ mem_ctx, lp_netbios_name(), lp_workgroup());
+
+ if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain,
+ pass,
+ &server_chal,
+ &names_blob,
+ &lm_resp, &nt_resp, NULL, NULL)) {
+ data_blob_free(&names_blob);
+ DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
data_blob_free(&names_blob);
- DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n"));
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
- data_blob_free(&names_blob);
- } else {
- lm_resp = data_blob_null;
- SMBNTencrypt(pass, chal, local_nt_response);
-
- nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
- sizeof(local_nt_response));
- }
+ } else {
+ lm_resp = data_blob_null;
+ SMBNTencrypt(pass, chal, local_nt_response);
- if (strequal(name_domain, get_global_sam_name())) {
- DATA_BLOB chal_blob = data_blob_const(chal, sizeof(chal));
+ nt_resp = data_blob_talloc(mem_ctx, local_nt_response,
+ sizeof(local_nt_response));
+ }
result = winbindd_dual_auth_passdb(
- mem_ctx, 0, name_domain, name_user,
+ talloc_tos(), 0, name_domain, name_user,
&chal_blob, &lm_resp, &nt_resp,
true, /* interactive */
&authoritative,
- info3);
+ &info3);
- /*
+ /*
* We need to try the remote NETLOGON server if this is
- * not authoritative.
+ * not authoritative (for example on the RODC).
*/
if (authoritative != 0) {
+ if (NT_STATUS_IS_OK(result)) {
+ result = map_info3_to_validation(
+ mem_ctx,
+ info3,
+ &validation_level,
+ &validation);
+ TALLOC_FREE(info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+ }
+
goto done;
}
}
pass,
name_domain,
lp_netbios_name(),
- chal,
- lm_resp,
- nt_resp,
+ NULL,
+ data_blob_null, data_blob_null,
true, /* interactive */
&authoritative,
&flags,
- &my_info3);
+ &validation_level,
+ &validation);
if (!NT_STATUS_IS_OK(result)) {
goto done;
}
* the samlogon reply info3. When accurate info3 is required by the
* caller, we look up the account flags ourselves - gd */
+ switch (validation_level) {
+ case 3:
+ base_info = &validation->sam3->base;
+ break;
+ case 6:
+ base_info = &validation->sam6->base;
+ break;
+ default:
+ DBG_ERR("Bad validation level %d", (int)validation_level);
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
if ((request_flags & WBFLAG_PAM_INFO3_TEXT) &&
- NT_STATUS_IS_OK(result) && (my_info3->base.acct_flags == 0)) {
-
+ (base_info->acct_flags == 0))
+ {
struct rpc_pipe_client *samr_pipe;
struct policy_handle samr_domain_handle, user_pol;
union samr_UserInfo *info = NULL;
status_tmp = dcerpc_samr_OpenUser(b, mem_ctx,
&samr_domain_handle,
MAXIMUM_ALLOWED_ACCESS,
- my_info3->base.rid,
+ base_info->rid,
&user_pol,
&result_tmp);
&info,
&result_tmp);
- if (!NT_STATUS_IS_OK(status_tmp)) {
+ if (any_nt_status_not_ok(status_tmp, result_tmp,
+ &status_tmp)) {
DEBUG(3, ("could not query user info on SAMR pipe: %s\n",
nt_errstr(status_tmp)));
dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp);
goto done;
}
- if (!NT_STATUS_IS_OK(result_tmp)) {
- DEBUG(3, ("could not query user info on SAMR pipe: %s\n",
- nt_errstr(result_tmp)));
- dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp);
- goto done;
- }
acct_flags = info->info16.acct_flags;
goto done;
}
- my_info3->base.acct_flags = acct_flags;
+ base_info->acct_flags = acct_flags;
DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags));
dcerpc_samr_Close(b, mem_ctx, &user_pol, &result_tmp);
}
- *info3 = my_info3;
done:
+ if (NT_STATUS_IS_OK(result)) {
+ *_validation_level = validation_level;
+ *_validation = validation;
+ }
return result;
}
fstring name_domain, name_user;
char *mapped_user;
fstring domain_user;
- struct netr_SamInfo3 *info3 = NULL;
+ uint16_t validation_level = UINT16_MAX;
+ union netr_Validation *validation = NULL;
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
/* Ensure null termination */
/* Check for Kerberos authentication */
if (domain->online && (state->request->flags & WBFLAG_PAM_KRB5)) {
+ struct netr_SamInfo3 *info3 = NULL;
result = winbindd_dual_pam_auth_kerberos(domain, state, &info3);
/* save for later */
if (NT_STATUS_IS_OK(result)) {
DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
+
+ result = map_info3_to_validation(state->mem_ctx,
+ info3,
+ &validation_level,
+ &validation);
+ TALLOC_FREE(info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ DBG_ERR("map_info3_to_validation failed\n");
+ goto done;
+ }
goto process_result;
- } else {
- DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result)));
}
+ DBG_DEBUG("winbindd_dual_pam_auth_kerberos failed: %s\n",
+ nt_errstr(result));
+
if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
sam_logon:
/* Check for Samlogon authentication */
if (domain->online) {
+ struct netr_SamBaseInfo *base_info = NULL;
+
result = winbindd_dual_pam_auth_samlogon(
state->mem_ctx, domain,
state->request->data.auth.user,
state->request->data.auth.pass,
state->request->flags,
- &info3);
+ &validation_level,
+ &validation);
if (NT_STATUS_IS_OK(result)) {
DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n"));
+
+ switch (validation_level) {
+ case 3:
+ base_info = &validation->sam3->base;
+ break;
+ case 6:
+ base_info = &validation->sam6->base;
+ break;
+ default:
+ DBG_ERR("Bad validation level %d\n",
+ validation_level);
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
/* add the Krb5 err if we have one */
if ( NT_STATUS_EQUAL(krb5_result, NT_STATUS_TIME_DIFFERENCE_AT_DC ) ) {
- info3->base.user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW;
+ base_info->user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW;
}
+
goto process_result;
}
goto cached_logon;
}
- if (domain->online) {
- /* We're still online - fail. */
- goto done;
- }
+ if (domain->online) {
+ /* We're still online - fail. */
+ goto done;
+ }
}
cached_logon:
/* Check for Cached logons */
if (!domain->online && (state->request->flags & WBFLAG_PAM_CACHED_LOGIN) &&
lp_winbind_offline_logon()) {
+ struct netr_SamInfo3 *info3 = NULL;
result = winbindd_dual_pam_auth_cached(domain, state, &info3);
- if (NT_STATUS_IS_OK(result)) {
- DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
- goto process_result;
- } else {
+ if (!NT_STATUS_IS_OK(result)) {
DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result)));
goto done;
}
+ DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
+
+ result = map_info3_to_validation(state->mem_ctx,
+ info3,
+ &validation_level,
+ &validation);
+ TALLOC_FREE(info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ DBG_ERR("map_info3_to_validation failed\n");
+ goto done;
+ }
}
process_result:
if (NT_STATUS_IS_OK(result)) {
-
struct dom_sid user_sid;
-
- /* In all codepaths where result == NT_STATUS_OK info3 must have
- been initialized. */
- if (!info3) {
+ TALLOC_CTX *base_ctx = NULL;
+ struct netr_SamBaseInfo *base_info = NULL;
+ struct netr_SamInfo3 *info3 = NULL;
+
+ switch (validation_level) {
+ case 3:
+ base_ctx = validation->sam3;
+ base_info = &validation->sam3->base;
+ break;
+ case 6:
+ base_ctx = validation->sam6;
+ base_info = &validation->sam6->base;
+ break;
+ default:
result = NT_STATUS_INTERNAL_ERROR;
goto done;
}
- sid_compose(&user_sid, info3->base.domain_sid,
- info3->base.rid);
+ sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
- if (info3->base.full_name.string == NULL) {
+ if (base_info->full_name.string == NULL) {
struct netr_SamInfo3 *cached_info3;
cached_info3 = netsamlogon_cache_get(state->mem_ctx,
&user_sid);
if (cached_info3 != NULL &&
cached_info3->base.full_name.string != NULL) {
- info3->base.full_name.string =
- talloc_strdup(info3,
- cached_info3->base.full_name.string);
+ base_info->full_name.string = talloc_strdup(
+ base_ctx,
+ cached_info3->base.full_name.string);
+ if (base_info->full_name.string == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
} else {
/* this might fail so we don't check the return code */
wcache_query_user_fullname(domain,
- info3,
+ base_ctx,
&user_sid,
- &info3->base.full_name.string);
+ &base_info->full_name.string);
}
}
+ result = map_validation_to_info3(talloc_tos(),
+ validation_level,
+ validation,
+ &info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
wcache_invalidate_samlogon(find_domain_from_name(name_domain),
&user_sid);
netsamlogon_cache_store(name_user, info3);
}
result = append_auth_data(state->mem_ctx, state->response,
- state->request->flags, info3,
+ state->request->flags,
+ validation_level,
+ validation,
name_domain, name_user);
if (!NT_STATUS_IS_OK(result)) {
goto done;
}
if (state->request->flags & WBFLAG_PAM_GET_PWD_POLICY) {
- struct winbindd_domain *our_domain = find_our_domain();
-
- /* This is not entirely correct I believe, but it is
- consistent. Only apply the password policy settings
- too warn users for our own domain. Cannot obtain these
- from trusted DCs all the time so don't do it at all.
- -- jerry */
-
- result = NT_STATUS_NOT_SUPPORTED;
- if (our_domain == domain ) {
- result = fillup_password_policy(
- our_domain, state->response);
- }
-
- if (!NT_STATUS_IS_OK(result)
- && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) )
- {
- DEBUG(10,("Failed to get password policies for domain %s: %s\n",
- domain->name, nt_errstr(result)));
- goto done;
- }
+ /*
+ * WBFLAG_PAM_GET_PWD_POLICY is not used within
+ * any Samba caller anymore.
+ *
+ * We just fake this based on the effective values
+ * for the user, for legacy callers.
+ */
+ fake_password_policy(state->response, &info3->base);
}
result = NT_STATUS_OK;
DATA_BLOB lm_response,
DATA_BLOB nt_response,
uint8_t *authoritative,
+ bool skip_sam,
uint32_t *flags,
- struct netr_SamInfo3 **info3)
+ uint16_t *_validation_level,
+ union netr_Validation **_validation)
{
+ uint16_t validation_level;
+ union netr_Validation *validation = NULL;
NTSTATUS result;
- if (strequal(name_domain, get_global_sam_name())) {
+ /*
+ * We check against domain->name instead of
+ * name_domain, as find_auth_domain() ->
+ * find_domain_from_name_noinit() already decided
+ * that we are in a child for the correct domain.
+ *
+ * name_domain can also be lp_realm()
+ * we need to check against domain->name.
+ */
+ if (!skip_sam && strequal(domain->name, get_global_sam_name())) {
DATA_BLOB chal_blob = data_blob_const(
chal, 8);
+ struct netr_SamInfo3 *info3 = NULL;
result = winbindd_dual_auth_passdb(
- mem_ctx,
+ talloc_tos(),
logon_parameters,
name_domain, name_user,
&chal_blob, &lm_response, &nt_response,
false, /* interactive */
authoritative,
- info3);
+ &info3);
+ if (NT_STATUS_IS_OK(result)) {
+ result = map_info3_to_validation(mem_ctx,
+ info3,
+ &validation_level,
+ &validation);
+ TALLOC_FREE(info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+ }
- /*
+ /*
* We need to try the remote NETLOGON server if this is
* not authoritative.
*/
false, /* interactive */
authoritative,
flags,
- info3);
+ &validation_level,
+ &validation);
if (!NT_STATUS_IS_OK(result)) {
goto done;
}
if (NT_STATUS_IS_OK(result)) {
struct dom_sid user_sid;
+ TALLOC_CTX *base_ctx = NULL;
+ struct netr_SamBaseInfo *base_info = NULL;
+ struct netr_SamInfo3 *info3 = NULL;
+
+ switch (validation_level) {
+ case 3:
+ base_ctx = validation->sam3;
+ base_info = &validation->sam3->base;
+ break;
+ case 6:
+ base_ctx = validation->sam6;
+ base_info = &validation->sam6->base;
+ break;
+ default:
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
- sid_compose(&user_sid, (*info3)->base.domain_sid,
- (*info3)->base.rid);
+ sid_compose(&user_sid, base_info->domain_sid, base_info->rid);
- if ((*info3)->base.full_name.string == NULL) {
+ if (base_info->full_name.string == NULL) {
struct netr_SamInfo3 *cached_info3;
cached_info3 = netsamlogon_cache_get(mem_ctx,
&user_sid);
if (cached_info3 != NULL &&
- cached_info3->base.full_name.string != NULL) {
- (*info3)->base.full_name.string =
- talloc_strdup(*info3,
- cached_info3->base.full_name.string);
+ cached_info3->base.full_name.string != NULL)
+ {
+ base_info->full_name.string = talloc_strdup(
+ base_ctx,
+ cached_info3->base.full_name.string);
} else {
/* this might fail so we don't check the return code */
wcache_query_user_fullname(domain,
- *info3,
+ base_ctx,
&user_sid,
- &(*info3)->base.full_name.string);
+ &base_info->full_name.string);
}
}
+ result = map_validation_to_info3(talloc_tos(),
+ validation_level,
+ validation,
+ &info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
wcache_invalidate_samlogon(find_domain_from_name(name_domain),
&user_sid);
- netsamlogon_cache_store(name_user, *info3);
+ netsamlogon_cache_store(name_user, info3);
+ TALLOC_FREE(info3);
}
done:
name_user,
nt_errstr(result)));
- return result;
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ *_validation_level = validation_level;
+ *_validation = validation;
+ return NT_STATUS_OK;
}
enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
NTSTATUS result;
- struct netr_SamInfo3 *info3 = NULL;
const char *name_user = NULL;
const char *name_domain = NULL;
const char *workstation;
- uint8_t authoritative;
- uint32_t flags;
-
+ uint8_t authoritative = 0;
+ uint32_t flags = 0;
+ uint16_t validation_level;
+ union netr_Validation *validation = NULL;
DATA_BLOB lm_resp, nt_resp;
/* This is child-only, so no check for privileged access is needed
lm_resp,
nt_resp,
&authoritative,
+ false,
&flags,
- &info3);
+ &validation_level,
+ &validation);
if (!NT_STATUS_IS_OK(result)) {
state->response->data.auth.authoritative = authoritative;
goto done;
}
if (NT_STATUS_IS_OK(result)) {
- /* Check if the user is in the right group */
+ struct netr_SamInfo3 *info3 = NULL;
+ result = map_validation_to_info3(state->mem_ctx,
+ validation_level,
+ validation,
+ &info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Check if the user is in the right group */
result = check_info3_in_group(
info3,
state->request->data.auth_crap.require_membership_of_sid);
}
result = append_auth_data(state->mem_ctx, state->response,
- state->request->flags, info3,
+ state->request->flags,
+ validation_level,
+ validation,
name_domain, name_user);
if (!NT_STATUS_IS_OK(result)) {
goto done;
* We're in the parent here, so find the child
* pointer from the PAC domain name.
*/
- domain = find_domain_from_name_noinit(
+ domain = find_lookup_domain_from_name(
info3_copy->base.logon_domain.string);
if (domain && domain->primary ) {
struct dom_sid user_sid;
SID_NAME_USER,
&user_sid);
- DBG_INFO("PAC for user %s\%s SID %s primed cache\n",
+ DBG_INFO("PAC for user %s\\%s SID %s primed cache\n",
info3_copy->base.logon_domain.string,
info3_copy->base.account_name.string,
sid_string_dbg(&user_sid));
* returning a copy talloc'ed off
* the state->mem_ctx.
*/
- info3_copy = copy_netr_SamInfo3(state->mem_ctx,
- &logon_info->info3);
- if (info3_copy == NULL) {
- return NT_STATUS_NO_MEMORY;
+ result = copy_netr_SamInfo3(state->mem_ctx,
+ &logon_info->info3,
+ &info3_copy);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
}
}
}