From 3529156971e17c7ec13f6a6243f7b613e4666cdd Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 28 Sep 2007 03:54:42 +0000 Subject: r25400: Windows 2008 (Longhorn) Interop fixes for AD specific auth2 flags, and client fixes. Patch from Todd Stetcher . (This used to be commit 8304ccba7346597425307e260e88647e49081f68) --- source3/auth/auth_domain.c | 2 +- source3/include/rpc_dce.h | 2 ++ source3/libads/sasl.c | 4 ++- source3/libads/util.c | 54 ++++++++++++++++------------------------- source3/libsmb/cliconnect.c | 38 +++++++++++++++++++++-------- source3/libsmb/clispnego.c | 19 +++++++++++++++ source3/libsmb/namequery.c | 29 ++++++++++++++++++++++ source3/libsmb/trusts_util.c | 2 +- source3/rpc_client/cli_pipe.c | 4 +-- source3/rpcclient/rpcclient.c | 2 +- source3/utils/net_rpc_join.c | 4 +-- source3/utils/net_rpc_samsync.c | 2 +- source3/winbindd/winbindd_cm.c | 2 +- 13 files changed, 111 insertions(+), 53 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 1e6857230f..0010d8bc26 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -124,7 +124,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); if (!lp_client_schannel()) { /* We need to set up a creds chain on an unauthenticated netlogon pipe. */ - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint32 sec_chan_type = 0; unsigned char machine_pwd[16]; diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 7ea3fcbc23..3b315b7ef8 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -111,6 +111,8 @@ enum RPC_PKT_TYPE { /* these are the flags that ADS clients use */ #define NETLOGON_NEG_AUTH2_ADS_FLAGS (0x200fbffb | NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT | NETLOGON_NEG_SCHANNEL) +#define NETLOGON_NEG_SELECT_AUTH2_FLAGS ((lp_security() == SEC_ADS) ? NETLOGON_NEG_AUTH2_ADS_FLAGS : NETLOGON_NEG_AUTH2_FLAGS) + enum schannel_direction { SENDER_IS_INITIATOR, SENDER_IS_ACCEPTOR diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index dec8756a86..590052ec85 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -747,6 +747,7 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) char *OIDs[ASN1_MAX_OIDS]; #ifdef HAVE_KRB5 BOOL got_kerberos_mechanism = False; + BOOL try_kerberos = True; #endif rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred); @@ -784,7 +785,8 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) #endif free(OIDs[i]); } - DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal)); + DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", + (given_principal ? given_principal : NULL))); #ifdef HAVE_KRB5 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) && diff --git a/source3/libads/util.c b/source3/libads/util.c index af96c3e10a..472fe4a214 100644 --- a/source3/libads/util.c +++ b/source3/libads/util.c @@ -55,57 +55,45 @@ failed: ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads, char **returned_principal) { + ADS_STATUS status; char *princ = NULL; + char *server = NULL; + char *server_realm = NULL; if (ads->server.realm && ads->server.ldap_server) { - char *server, *server_realm; - server = SMB_STRDUP(ads->server.ldap_server); server_realm = SMB_STRDUP(ads->server.realm); - if (!server || !server_realm) { - return ADS_ERROR(LDAP_NO_MEMORY); - } - - strlower_m(server); - strupper_m(server_realm); - asprintf(&princ, "ldap/%s@%s", server, server_realm); - - SAFE_FREE(server); - SAFE_FREE(server_realm); - - if (!princ) { - return ADS_ERROR(LDAP_NO_MEMORY); + if (!server || !server_realm) { + status = ADS_ERROR(LDAP_NO_MEMORY); + goto fail; } } else if (ads->config.realm && ads->config.ldap_server_name) { - char *server, *server_realm; - server = SMB_STRDUP(ads->config.ldap_server_name); server_realm = SMB_STRDUP(ads->config.realm); - if (!server || !server_realm) { - return ADS_ERROR(LDAP_NO_MEMORY); - } - - strlower_m(server); - strupper_m(server_realm); - asprintf(&princ, "ldap/%s@%s", server, server_realm); - - SAFE_FREE(server); - SAFE_FREE(server_realm); - - if (!princ) { - return ADS_ERROR(LDAP_NO_MEMORY); - } + if (!server || !server_realm) { + status = ADS_ERROR(LDAP_NO_MEMORY); + goto fail; + } } + strlower_m(server); + strupper_m(server_realm); + asprintf(&princ, "ldap/%s@%s", server, server_realm); + if (!princ) { - return ADS_ERROR(LDAP_PARAM_ERROR); + status = ADS_ERROR(LDAP_PARAM_ERROR); } *returned_principal = princ; + status = ADS_SUCCESS; + +fail: + SAFE_FREE(server); + SAFE_FREE(server_realm); - return ADS_SUCCESS; + return status; } #endif diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 820a904ea4..a4bbf9a6ec 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -822,20 +822,36 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, free(OIDs[i]); } - DEBUG(3,("got principal=%s\n", principal ? principal : "")); if (got_kerberos_mechanism && (principal == NULL)) { + fstring dns_name; + fstring nb_name; + /* - * It is WRONG to depend on the principal sent in the negprot - * reply, but right now we do it. So for safety (don't - * segfault later) disable Kerberos when no principal was - * sent. -- VL - */ - DEBUG(1, ("Kerberos mech was offered, but no principal was " - "sent, disabling Kerberos\n")); - cli->use_kerberos = False; + * We didn't get a valid principal in the negTokenInit. Fake + * it, or fall back on NTLM. We prefer to fake it, and hit the + * translate_name cache to get a REAL realm name. + */ + if (!(cli->desthost && translate_name(domain, dns_name, + nb_name) && + asprintf(&principal, "host/%s@%s", cli->desthost, + dns_name))) { + + /* + * It is WRONG to depend on the principal sent in the + * negprot reply, but right now we do it. So for safety + * (don't segfault later) disable Kerberos when no + * principal was sent. -- VL + */ + DEBUG(1, ("Kerberos mech was offered, but no principal was " + "sent, disabling Kerberos\n")); + cli->use_kerberos = False; + } + } + DEBUG(3,("got principal=%s\n", principal ? principal : "")); + fstrcpy(cli->user_name, user); #ifdef HAVE_KRB5 @@ -872,7 +888,9 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, ntlmssp: - return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain)); + /* NTLM is sensitive to adding a domain with a UPN */ + return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, + (strchr(user, '@') ? NULL : domain))); } /**************************************************************************** diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index 9432ce81d3..c45883d890 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -52,7 +52,18 @@ DATA_BLOB spnego_gen_negTokenInit(char guid[16], asn1_push_tag(&data, ASN1_CONTEXT(3)); asn1_push_tag(&data, ASN1_SEQUENCE(0)); asn1_push_tag(&data, ASN1_CONTEXT(0)); + + /* + * @todo + * Windows 2008 sends a bogus principal, since this + * is not truly supported in the SPNEGO protocol. + * + * We should do the same, but I'm worried this will break things, + * such as DFS. + * todd.stecher@isilon.com + */ asn1_write_GeneralString(&data,principal); + asn1_pop_tag(&data); asn1_pop_tag(&data); asn1_pop_tag(&data); @@ -154,6 +165,14 @@ BOOL spnego_parse_negTokenInit(DATA_BLOB blob, asn1_start_tag(&data, ASN1_SEQUENCE(0)); asn1_start_tag(&data, ASN1_CONTEXT(0)); asn1_read_GeneralString(&data,principal); + /* + * Windows 2008 sends a bogus principal, since this + * is not truly supported in the SPNEGO protocol. + * todd.stecher@isilon.com + */ + if (strcmp(ADS_IGNORE_PRINCIPAL, *principal) == 0) + SAFE_FREE(*principal); + asn1_end_tag(&data); asn1_end_tag(&data); asn1_end_tag(&data); diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 49e3375f50..4a7ae0c2e5 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -1714,3 +1714,32 @@ NTSTATUS get_kdc_list( const char *realm, const char *sitename, struct ip_servic return NT_STATUS_OK; } + + +BOOL translate_name(const char *realm, fstring dns_domain_name, + fstring nb_domain_name) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS wb_result; + + /* Call winbindd */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.domain_name, realm); + wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO, + &request, &response); + + if (wb_result != NSS_STATUS_SUCCESS) { + DEBUG(0, ("Failed to translate %s\n", realm)); + return False; + } + + fstrcpy(dns_domain_name, response.data.domain_info.alt_name); + fstrcpy(nb_domain_name, response.data.domain_info.name); + + return True; + +} diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 0922f9f41e..4a231dcd15 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -40,7 +40,7 @@ static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX already have valid creds. If not we must set them up. */ if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; result = rpccli_netlogon_setup_creds(cli, cli->cli->desthost, /* server name */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index db696edae5..314a694369 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2633,7 +2633,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state const char *password, NTSTATUS *perr) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; struct rpc_pipe_client *netlogon_pipe = NULL; struct rpc_pipe_client *result = NULL; @@ -2667,7 +2667,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli, const char *domain, NTSTATUS *perr) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; struct rpc_pipe_client *netlogon_pipe = NULL; struct rpc_pipe_client *result = NULL; diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index b43ce09f46..d2fa409fff 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -605,7 +605,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, } if (cmd_entry->pipe_idx == PI_NETLOGON) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint32 sec_channel_type; uchar trust_password[16]; diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index b32fa27284..0561548c8f 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -45,7 +45,7 @@ NTSTATUS net_rpc_join_ok(const char *domain, const char *server, { enum security_types sec; unsigned int conn_flags = NET_FLAGS_PDC; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; struct cli_state *cli = NULL; struct rpc_pipe_client *pipe_hnd = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; @@ -132,7 +132,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) struct cli_state *cli; TALLOC_CTX *mem_ctx; uint32 acb_info = ACB_WSTRUST; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0); + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0); uint32 sec_channel_type; struct rpc_pipe_client *pipe_hnd = NULL; diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 72b7f63cc4..3959015dbb 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -237,7 +237,7 @@ NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid, NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uchar trust_password[16]; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint32 sec_channel_type = 0; if (!secrets_fetch_trust_account_password(domain_name, diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 9ffb3dfb23..f08789052d 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2141,7 +2141,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct winbindd_cm_conn *conn; NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; const char *account_name; -- cgit