r25400: Windows 2008 (Longhorn) Interop fixes for AD specific auth2 flags,
authorGerald Carter <jerry@samba.org>
Fri, 28 Sep 2007 03:54:42 +0000 (03:54 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:31:02 +0000 (12:31 -0500)
and client fixes.  Patch from Todd Stetcher <todd.stetcher@isilon.com>.

13 files changed:
source/auth/auth_domain.c
source/include/rpc_dce.h
source/libads/sasl.c
source/libads/util.c
source/libsmb/cliconnect.c
source/libsmb/clispnego.c
source/libsmb/namequery.c
source/libsmb/trusts_util.c
source/rpc_client/cli_pipe.c
source/rpcclient/rpcclient.c
source/utils/net_rpc_join.c
source/utils/net_rpc_samsync.c
source/winbindd/winbindd_cm.c

index 1e6857230f1e04d680f0c8fe35b9c5b161a00ae9..0010d8bc26932f8ee0194c0aa02b85f3e9e3d922 100644 (file)
@@ -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];
 
index 7ea3fcbc233d89659babf130d7bf05384988a3b7..3b315b7ef8bb2b33bcdc2d2d06834160934f4d6f 100644 (file)
@@ -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
index dec8756a860de13378f17e3ab7622d2cda83b6d6..590052ec85bf86c1b9066fc18e19ee3cc8b3a570 100644 (file)
@@ -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) &&
index af96c3e10a458622b39a34d4342bbc29eada9204..472fe4a21454c1040fea5050fa6b62c7f7028e1e 100644 (file)
@@ -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
index 820a904ea4f9c34ab3095dd270f0ce3c6325a8a1..a4bbf9a6ec3de63197035a48189a9a2392089db2 100644 (file)
@@ -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 : "<null>"));
 
        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 : "<null>"));
+
        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)));
 }
 
 /****************************************************************************
index 9432ce81d3c75c397bf347273350f57c42568d80..c45883d8903b5209bc275a18e840ec25efc2cf0e 100644 (file)
@@ -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);
index 49e3375f508d2cc4423efc47489e491071ec9705..4a7ae0c2e500a3ef617ef857c429d9b07672d5ec 100644 (file)
@@ -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;
+
+}
index 0922f9f41eacccc806082a2a7e57914674a5b96c..4a231dcd15ed073ff313af6e8a4eea7339c2112d 100644 (file)
@@ -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 */
index db696edae5c93aef7622294ff44e334aa9bba02f..314a694369c410fb59347453d8c220bff65b84e8 100644 (file)
@@ -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;
 
index b43ce09f469fcfc37b2f2f14b4eaa837ae3e386d..d2fa409fffe204e768e255484102f6de0e6a964c 100644 (file)
@@ -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];
        
index b32fa27284fbdbef21477c98ff49e79f2056e3e5..0561548c8f56fe20631a677b6420140c2b07d9bc 100644 (file)
@@ -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;
 
index 72b7f63cc44d84a7610adcaf28d544b782921f38..3959015dbb860fb520777f171f25ecd90865b70f 100644 (file)
@@ -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,
index 9ffb3dfb239bb6dc028c6a1ae8737d62a6141495..f08789052d18c74180b8764b425d8fe4dc8c9c37 100644 (file)
@@ -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;