#include "includes.h"
#include "winbindd.h"
+#include "libsmb/namequery.h"
#include "../libcli/auth/libcli_auth.h"
#include "../librpc/gen_ndr/ndr_samr_c.h"
#include "rpc_client/cli_pipe.h"
DEBUG(3, ("Authentication for domain [%s] refused "
"as it is not a trusted domain\n",
domain_name));
+ return NULL;
}
- return domain;
+
+ if (domain->secure_channel_type != SEC_CHAN_NULL) {
+ return domain;
+ }
+
+ return domain->routing_domain;
}
if (strequal(domain_name, get_global_sam_name())) {
const char *pass,
const char *krb5_cc_type,
uid_t uid,
- struct netr_SamInfo3 **info3,
+ struct netr_SamInfo6 **info6,
fstring krb5ccname)
{
#ifdef HAVE_KRB5
const char *principal_s = NULL;
const char *service = NULL;
char *realm = NULL;
- fstring name_domain, name_user;
+ fstring name_namespace, name_domain, name_user;
time_t ticket_lifetime = 0;
time_t renewal_until = 0;
ADS_STRUCT *ads;
time_t time_offset = 0;
const char *user_ccache_file;
struct PAC_LOGON_INFO *logon_info = NULL;
+ struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
struct PAC_DATA *pac_data = NULL;
struct PAC_DATA_CTR *pac_data_ctr = NULL;
const char *local_service;
uint32_t i;
- struct netr_SamInfo3 *info3_copy = NULL;
+ struct netr_SamInfo6 *info6_copy = NULL;
+ bool ok;
- *info3 = NULL;
+ *info6 = NULL;
if (domain->alt_name == NULL) {
return NT_STATUS_INVALID_PARAMETER;
/* 3rd step:
* do kerberos auth and setup ccache as the user */
- parse_domain_user(user, name_domain, name_user);
+ ok = parse_domain_user(user, name_namespace, name_domain, name_user);
+ if (!ok) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
realm = talloc_strdup(mem_ctx, domain->alt_name);
if (realm == NULL) {
for (i=0; i < pac_data->num_buffers; i++) {
- if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) {
+ if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
+ logon_info = pac_data->buffers[i].info->logon_info.info;
continue;
}
- logon_info = pac_data->buffers[i].info->logon_info.info;
- if (!logon_info) {
- return NT_STATUS_INVALID_PARAMETER;
+ if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
+ upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
+ continue;
}
-
- break;
}
if (logon_info == NULL) {
DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n",
principal_s));
- result = create_info3_from_pac_logon_info(mem_ctx, logon_info, &info3_copy);
+ result = create_info6_from_pac(mem_ctx, logon_info,
+ upn_dns_info, &info6_copy);
if (!NT_STATUS_IS_OK(result)) {
goto failed;
}
}
}
- *info3 = info3_copy;
+ *info6 = info6_copy;
return NT_STATUS_OK;
failed:
{
NTSTATUS result = NT_STATUS_LOGON_FAILURE;
uint16_t max_allowed_bad_attempts;
- fstring name_domain, name_user;
+ fstring name_namespace, name_domain, name_user;
struct dom_sid sid;
enum lsa_SidType type;
uchar new_nt_pass[NT_HASH_LEN];
struct netr_SamInfo3 *my_info3;
time_t kickoff_time, must_change_time;
bool password_good = false;
+ bool ok;
#ifdef HAVE_KRB5
struct winbindd_tdc_domain *tdc_domain = NULL;
#endif
/* Parse domain and username */
- parse_domain_user(state->request->data.auth.user, name_domain, name_user);
-
+ ok = parse_domain_user(state->request->data.auth.user,
+ name_namespace,
+ name_domain,
+ name_user);
+ if (!ok) {
+ DBG_DEBUG("parse_domain_user failed\n");
+ return NT_STATUS_NO_SUCH_USER;
+ }
- if (!lookup_cached_name(name_domain,
+ if (!lookup_cached_name(name_namespace,
+ name_domain,
name_user,
&sid,
&type)) {
static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
struct winbindd_cli_state *state,
- struct netr_SamInfo3 **info3)
+ struct netr_SamInfo6 **info6)
{
struct winbindd_domain *contact_domain;
- fstring name_domain, name_user;
+ fstring name_namespace, name_domain, name_user;
NTSTATUS result;
+ bool ok;
DEBUG(10,("winbindd_dual_pam_auth_kerberos\n"));
/* Parse domain and username */
- parse_domain_user(state->request->data.auth.user, name_domain, name_user);
+ ok = parse_domain_user(state->request->data.auth.user,
+ name_namespace,
+ name_domain,
+ name_user);
+ if (!ok) {
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
/* what domain should we contact? */
if ( IS_DC ) {
- if (!(contact_domain = find_domain_from_name(name_domain))) {
+ contact_domain = find_domain_from_name(name_namespace);
+ if (contact_domain == NULL) {
DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
state->request->data.auth.user, name_domain, name_user, name_domain));
result = NT_STATUS_NO_SUCH_USER;
goto done;
}
- contact_domain = find_domain_from_name(name_domain);
+ contact_domain = find_domain_from_name(name_namespace);
if (contact_domain == NULL) {
DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
state->request->data.auth.user, name_domain, name_user, name_domain));
state->request->data.auth.pass,
state->request->data.auth.krb5_cc_type,
get_uid_from_request(state->request),
- info3, state->response->data.auth.krb5ccname);
+ info6, state->response->data.auth.krb5ccname);
done:
return result;
}
const char *password,
const char *domainname,
const char *workstation,
+ bool plaintext_given,
const uint8_t chal[8],
DATA_BLOB lm_response,
DATA_BLOB nt_response,
int netr_attempts = 0;
bool retry = false;
NTSTATUS result;
- uint16_t validation_level;
+ 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;
+ struct netlogon_creds_cli_context *netlogon_creds_ctx = NULL;
retry = false;
- result = cm_connect_netlogon(domain, &netlogon_pipe);
+ result = cm_connect_netlogon_secure(domain, &netlogon_pipe,
+ &netlogon_creds_ctx);
if (NT_STATUS_EQUAL(result,
NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) {
}
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_ctx == NULL) {
- DBG_NOTICE("No security credentials available for "
- "domain [%s]\n", domainname);
- result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- } else if (interactive) {
+ if (plaintext_given) {
result = rpccli_netlogon_password_logon(
- domain->conn.netlogon_creds_ctx,
+ netlogon_creds_ctx,
netlogon_pipe->binding_handle,
mem_ctx,
logon_parameters,
username,
password,
workstation,
- NetlogonInteractiveInformation,
+ logon_type_i,
+ authoritative,
+ flags,
+ &validation_level,
+ &validation);
+ } else if (interactive) {
+ result = rpccli_netlogon_interactive_logon(
+ netlogon_creds_ctx,
+ netlogon_pipe->binding_handle,
+ mem_ctx,
+ logon_parameters,
+ username,
+ domainname,
+ workstation,
+ lm_response,
+ nt_response,
+ logon_type_i,
authoritative,
flags,
&validation_level,
&validation);
} else {
result = rpccli_netlogon_network_logon(
- domain->conn.netlogon_creds_ctx,
+ netlogon_creds_ctx,
netlogon_pipe->binding_handle,
mem_ctx,
logon_parameters,
chal,
lm_response,
nt_response,
+ logon_type_n,
authoritative,
flags,
&validation_level,
DATA_BLOB lm_resp;
DATA_BLOB nt_resp;
unsigned char local_nt_response[24];
- fstring name_domain, name_user;
+ fstring name_namespace, name_domain, name_user;
NTSTATUS result;
uint8_t authoritative = 0;
uint32_t flags = 0;
uint16_t validation_level;
union netr_Validation *validation = NULL;
struct netr_SamBaseInfo *base_info = NULL;
+ bool ok;
DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
/* Parse domain and username */
- parse_domain_user(user, name_domain, name_user);
+ ok = parse_domain_user(user, name_namespace, name_domain, name_user);
+ if (!ok) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
/*
* We check against domain->name instead of
pass,
name_domain,
lp_netbios_name(),
+ true, /* plaintext_given */
NULL,
data_blob_null, data_blob_null,
true, /* interactive */
{
NTSTATUS result = NT_STATUS_LOGON_FAILURE;
NTSTATUS krb5_result = NT_STATUS_OK;
- fstring name_domain, name_user;
+ fstring name_namespace, name_domain, name_user;
char *mapped_user;
fstring domain_user;
uint16_t validation_level = UINT16_MAX;
union netr_Validation *validation = NULL;
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
+ bool ok;
/* Ensure null termination */
state->request->data.auth.user[sizeof(state->request->data.auth.user)-1]='\0';
mapped_user = state->request->data.auth.user;
}
- parse_domain_user(mapped_user, name_domain, name_user);
+ ok = parse_domain_user(mapped_user,
+ name_namespace,
+ name_domain,
+ name_user);
+ if (!ok) {
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto process_result;
+ }
if ( mapped_user != state->request->data.auth.user ) {
fstr_sprintf( domain_user, "%s%c%s", name_domain,
/* Check for Kerberos authentication */
if (domain->online && (state->request->flags & WBFLAG_PAM_KRB5)) {
- struct netr_SamInfo3 *info3 = NULL;
+ struct netr_SamInfo6 *info6 = NULL;
- result = winbindd_dual_pam_auth_kerberos(domain, state, &info3);
+ result = winbindd_dual_pam_auth_kerberos(domain, state, &info6);
/* save for later */
krb5_result = result;
-
if (NT_STATUS_IS_OK(result)) {
DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
- result = map_info3_to_validation(state->mem_ctx,
- info3,
+ result = map_info6_to_validation(state->mem_ctx,
+ info6,
&validation_level,
&validation);
- TALLOC_FREE(info3);
+ TALLOC_FREE(info6);
if (!NT_STATUS_IS_OK(result)) {
- DBG_ERR("map_info3_to_validation failed\n");
+ DBG_ERR("map_info6_to_validation failed\n");
goto done;
}
goto process_result;
NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
+ bool interactive,
uint32_t logon_parameters,
const char *name_user,
const char *name_domain,
uint16_t *_validation_level,
union netr_Validation **_validation)
{
- uint16_t validation_level;
+ uint16_t validation_level = 0;
union netr_Validation *validation = NULL;
NTSTATUS result;
logon_parameters,
name_domain, name_user,
&chal_blob, &lm_response, &nt_response,
- false, /* interactive */
+ interactive,
authoritative,
&info3);
if (NT_STATUS_IS_OK(result)) {
name_domain,
/* Bug #3248 - found by Stefan Burkei. */
workstation, /* We carefully set this above so use it... */
+ false, /* plaintext_given */
chal,
lm_response,
nt_response,
- false, /* interactive */
+ interactive,
authoritative,
flags,
&validation_level,
result = winbind_dual_SamLogon(domain,
state->mem_ctx,
+ false, /* interactive */
state->request->data.auth_crap.logon_parameters,
name_user,
name_domain,
struct samr_DomInfo1 *info = NULL;
struct userPwdChangeFailureInformation *reject = NULL;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- fstring domain, user;
+ fstring namespace, domain, user;
struct dcerpc_binding_handle *b = NULL;
+ bool ok;
ZERO_STRUCT(dom_pol);
DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid,
state->request->data.auth.user));
- if (!parse_domain_user(state->request->data.chauthtok.user, domain, user)) {
+ ok = parse_domain_user(state->request->data.chauthtok.user,
+ namespace,
+ domain,
+ user);
+ if (!ok) {
goto done;
}
DATA_BLOB old_nt_hash_enc;
DATA_BLOB new_lm_password;
DATA_BLOB old_lm_hash_enc;
- fstring domain,user;
+ fstring namespace, domain, user;
struct policy_handle dom_pol;
struct winbindd_domain *contact_domain = domainSt;
struct rpc_pipe_client *cli = NULL;
sizeof(state->request->data.chng_pswd_auth_crap.user)-1]=0;
state->request->data.chng_pswd_auth_crap.domain[
sizeof(state->request->data.chng_pswd_auth_crap.domain)-1]=0;
- *domain = 0;
- *user = 0;
+ domain[0] = '\0';
+ namespace[0] = '\0';
+ user[0] = '\0';
DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
(unsigned long)state->pid,
if (*state->request->data.chng_pswd_auth_crap.domain) {
fstrcpy(domain,state->request->data.chng_pswd_auth_crap.domain);
} else {
- parse_domain_user(state->request->data.chng_pswd_auth_crap.user,
- domain, user);
+ bool ok;
+
+ ok = parse_domain_user(state->request->data.chng_pswd_auth_crap.user,
+ namespace,
+ domain,
+ user);
+ if (!ok) {
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
if(!*domain) {
DEBUG(3,("no domain specified with username (%s) - "
#ifdef HAVE_KRB5
static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob,
- struct PAC_LOGON_INFO **logon_info)
+ struct PAC_DATA **p_pac_data)
{
krb5_context krbctx = NULL;
krb5_error_code k5ret;
k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor);
while (k5ret == 0) {
- status = kerberos_pac_logon_info(mem_ctx, pac_blob,
- krbctx, NULL,
- KRB5_KT_KEY(&entry), NULL, 0,
- logon_info);
+ status = kerberos_decode_pac(mem_ctx,
+ pac_blob,
+ krbctx,
+ NULL, /* krbtgt_keyblock */
+ KRB5_KT_KEY(&entry), /* service_keyblock */
+ NULL, /* client_principal */
+ 0, /* tgs_authtime */
+ p_pac_data);
if (NT_STATUS_IS_OK(status)) {
break;
}
return status;
}
-NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
- struct netr_SamInfo3 **info3)
+NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
+ bool *p_is_trusted,
+ uint16_t *p_validation_level,
+ union netr_Validation **p_validation)
{
struct winbindd_request *req = state->request;
DATA_BLOB pac_blob;
+ struct PAC_DATA *pac_data = NULL;
struct PAC_LOGON_INFO *logon_info = NULL;
+ struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
+ struct netr_SamInfo6 *info6 = NULL;
+ uint16_t validation_level = 0;
+ union netr_Validation *validation = NULL;
struct netr_SamInfo3 *info3_copy = NULL;
NTSTATUS result;
+ bool is_trusted = false;
+ uint32_t i;
+
+ *p_is_trusted = false;
+ *p_validation_level = 0;
+ *p_validation = NULL;
pac_blob = data_blob_const(req->extra_data.data, req->extra_len);
- result = extract_pac_vrfy_sigs(state->mem_ctx, pac_blob, &logon_info);
- if (!NT_STATUS_IS_OK(result) &&
- !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+ result = extract_pac_vrfy_sigs(state->mem_ctx, pac_blob, &pac_data);
+ if (NT_STATUS_IS_OK(result)) {
+ is_trusted = true;
+ }
+ if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+ /* Try without signature verification */
+ result = kerberos_decode_pac(state->mem_ctx,
+ pac_blob,
+ NULL, /* krb5_context */
+ NULL, /* krbtgt_keyblock */
+ NULL, /* service_keyblock */
+ NULL, /* client_principal */
+ 0, /* tgs_authtime */
+ &pac_data);
+ }
+ if (!NT_STATUS_IS_OK(result)) {
DEBUG(1, ("Error during PAC signature verification: %s\n",
nt_errstr(result)));
return result;
}
- if (logon_info) {
+ for (i=0; i < pac_data->num_buffers; i++) {
+ if (pac_data->buffers[i].type == PAC_TYPE_LOGON_INFO) {
+ logon_info = pac_data->buffers[i].info->logon_info.info;
+ continue;
+ }
+ if (pac_data->buffers[i].type == PAC_TYPE_UPN_DNS_INFO) {
+ upn_dns_info = &pac_data->buffers[i].info->upn_dns_info;
+ continue;
+ }
+ }
+
+ result = create_info6_from_pac(state->mem_ctx,
+ logon_info,
+ upn_dns_info,
+ &info6);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ result = map_info6_to_validation(state->mem_ctx,
+ info6,
+ &validation_level,
+ &validation);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ result = map_validation_to_info3(state->mem_ctx,
+ validation_level,
+ validation,
+ &info3_copy);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ if (is_trusted) {
/*
* Signature verification succeeded, we can
* trust the PAC and prime the netsamlogon
*/
struct winbindd_domain *domain = NULL;
- result = create_info3_from_pac_logon_info(state->mem_ctx,
- logon_info,
- &info3_copy);
- if (!NT_STATUS_IS_OK(result)) {
- return result;
- }
netsamlogon_cache_store(NULL, info3_copy);
/*
info3_copy->base.account_name.string,
sid_string_dbg(&user_sid));
}
-
- } else {
- /* Try without signature verification */
- result = kerberos_pac_logon_info(state->mem_ctx, pac_blob, NULL,
- NULL, NULL, NULL, 0,
- &logon_info);
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10, ("Could not extract PAC: %s\n",
- nt_errstr(result)));
- return result;
- }
- if (logon_info) {
- /*
- * Don't strictly need to copy here,
- * but it makes it explicit we're
- * returning a copy talloc'ed off
- * the state->mem_ctx.
- */
- result = copy_netr_SamInfo3(state->mem_ctx,
- &logon_info->info3,
- &info3_copy);
- if (!NT_STATUS_IS_OK(result)) {
- return result;
- }
- }
}
- *info3 = info3_copy;
-
+ *p_is_trusted = is_trusted;
+ *p_validation_level = validation_level;
+ *p_validation = validation;
return NT_STATUS_OK;
}
#else /* HAVE_KRB5 */
-NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
- struct netr_SamInfo3 **info3)
+NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state,
+ bool *p_is_trusted,
+ uint16_t *p_validation_level,
+ union netr_Validation **p_validation);
{
+
+ *p_is_trusted = false;
+ *p_validation_level = 0;
+ *p_validation = NULL;
return NT_STATUS_NO_SUCH_USER;
}
#endif /* HAVE_KRB5 */