This merges in my 'always use ADS' patch. Tested on a mix of NT and ADS
authorAndrew Bartlett <abartlet@samba.org>
Thu, 8 Jan 2004 08:19:18 +0000 (08:19 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 8 Jan 2004 08:19:18 +0000 (08:19 +0000)
domains, this patch ensures that we always use the ADS backend when
security=ADS, and the remote server is capable.

The routines used for this behaviour have been upgraded to modern Samba
codeing standards.

This is a change in behaviour for mixed mode domains, and if the trusted
domain cannot be reached with our current krb5.conf file, we will show
that domain as disconnected.

This is in line with existing behaviour for native mode domains, and for
our primary domain.

As a consequence of testing this patch, I found that our kerberos error
handling was well below par - we would often throw away useful error
values.  These changes move more routines to ADS_STATUS to return
kerberos errors.

Also found when valgrinding the setup, fix a few memory leaks.

While sniffing the resultant connections, I noticed we would query our
list of trusted domains twice - so I have reworked some of the code to
avoid that.

Andrew Bartlett
(This used to be commit 7c34de8096b86d2869e7177420fe129bd0c7541d)

20 files changed:
source3/Makefile.in
source3/configure.in
source3/libads/ads_status.c
source3/libads/sasl.c
source3/libsmb/cliconnect.c
source3/libsmb/clikrb5.c
source3/libsmb/clispnego.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbindd.c
source3/nsswitch/winbindd.h
source3/nsswitch/winbindd_cache.c
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_misc.c
source3/nsswitch/winbindd_nss.h
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_util.c
source3/rpc_client/cli_lsarpc.c
source3/rpcclient/cmd_lsarpc.c
source3/utils/net_rpc.c
source3/utils/ntlm_auth.c

index 6146d3d16b12a536f02bda143edcde69112fb27a..75213c2f5e2fb6e47c938a802b88ceeedd433f99 100644 (file)
@@ -198,11 +198,11 @@ UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
 
 PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o
 
-KRBCLIENT_OBJ = libads/kerberos.o
+KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o 
 
 LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
             libads/krb5_setpw.o libads/ldap_user.o \
-            libads/ads_struct.o libads/ads_status.o \
+            libads/ads_struct.o \
              libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
             libads/ads_ldap.o libads/authdata.o
 
index 1ca8512b214a01b09b8cdcb912d4c03a3f5c3693..7a844c337d4d4ccaf0daf83a140b8e0853212b3e 100644 (file)
@@ -2633,6 +2633,7 @@ if test x"$with_ads_support" != x"no"; then
   AC_CHECK_FUNC_EXT(krb5_get_permitted_enctypes, $KRB5_LIBS) 
   AC_CHECK_FUNC_EXT(krb5_get_default_in_tkt_etypes, $KRB5_LIBS) 
   AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_free_data_contents, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS)
 
   LIBS="$LIBS $KRB5_LIBS"
index 11f9d66b92df386d618d4b1ccc59ed46475b4313..63757af86093dff4f0be6e72c6d8aeaf1c0ccbe3 100644 (file)
@@ -77,6 +77,15 @@ NTSTATUS ads_ntstatus(ADS_STATUS status)
            && (status.err.rc == LDAP_NO_MEMORY)) {
                return NT_STATUS_NO_MEMORY;
        }
+#endif
+#ifdef HAVE_KRB5
+       if (status.error_type = ADS_ERROR_KRB5) { 
+               if (status.err.rc == KRB5KDC_ERR_PREAUTH_FAILED) {
+                       return NT_STATUS_LOGON_FAILURE;
+               } else if (status.err.rc == KRB5_KDC_UNREACH) {
+                       return NT_STATUS_NO_LOGON_SERVERS;
+               }
+       }
 #endif
        if (ADS_ERR_OK(status)) return NT_STATUS_OK;
        return NT_STATUS_UNSUCCESSFUL;
@@ -123,7 +132,7 @@ const char *ads_errstr(ADS_STATUS status)
        }
 #endif
        case ADS_ERROR_NT: 
-               return nt_errstr(ads_ntstatus(status));
+               return get_friendly_nt_error_msg(ads_ntstatus(status));
        default:
                return "Unknown ADS error type!? (not compiled in?)";
        }
index 51228035974b1036bb1c8486c6edf4ebff5ea1a5..1ab71c6ee514fbae1ddd25699ba09fe8b026cd33 100644 (file)
@@ -124,13 +124,13 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
 {
        DATA_BLOB blob;
        struct berval cred, *scred;
-       unsigned char sk[16];
+       DATA_BLOB session_key;
        int rc;
 
-       blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, sk);
+       rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key);
 
-       if (!blob.data) {
-               return ADS_ERROR(LDAP_OPERATIONS_ERROR);
+       if (rc) {
+               return ADS_ERROR_KRB5(rc);
        }
 
        /* now send the auth packet and we should be done */
@@ -140,6 +140,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
        rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
 
        data_blob_free(&blob);
+       data_blob_free(&session_key);
 
        return ADS_ERROR(rc);
 }
@@ -166,6 +167,8 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 
        blob = data_blob(scred->bv_val, scred->bv_len);
 
+       ber_bvfree(scred);
+
 #if 0
        file_save("sasl_spnego.dat", blob.data, blob.length);
 #endif
@@ -196,9 +199,13 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
                status = ads_sasl_spnego_krb5_bind(ads, principal);
                if (ADS_ERR_OK(status))
                        return status;
-               if (ads_kinit_password(ads) == 0) {
+
+               status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 
+
+               if (ADS_ERR_OK(status)) {
                        status = ads_sasl_spnego_krb5_bind(ads, principal);
                }
+
                /* only fallback to NTLMSSP if allowed */
                if (ADS_ERR_OK(status) || 
                    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
index 1dc46ab0e69a82bc70b1779952a10a4fbc2dfab4..707a33881df810772d33fcc46226d8fb028b639c 100644 (file)
@@ -500,19 +500,22 @@ static void use_in_memory_ccache(void) {
  Do a spnego/kerberos encrypted session setup.
 ****************************************************************************/
 
-static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
+static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
 {
        DATA_BLOB blob2, negTokenTarg;
        DATA_BLOB session_key_krb5;
        DATA_BLOB null_blob = data_blob(NULL, 0);
-       
+       int rc;
+
        DEBUG(2,("Doing kerberos session setup\n"));
 
        /* generate the encapsulated kerberos5 ticket */
-       negTokenTarg = spnego_gen_negTokenTarg(principal, 0, &session_key_krb5);
+       rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5);
 
-       if (!negTokenTarg.data)
-               return NT_STATUS_UNSUCCESSFUL;
+       if (rc) {
+               DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
+               return ADS_ERROR_KRB5(rc);
+       }
 
 #if 0
        file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
@@ -531,10 +534,10 @@ static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *pr
 
        if (cli_is_error(cli)) {
                if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
-                       return NT_STATUS_UNSUCCESSFUL;
+                       return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
                }
        } 
-       return NT_STATUS_OK;
+       return ADS_ERROR_NT(cli_nt_error(cli));
 }
 #endif /* HAVE_KRB5 */
 
@@ -661,7 +664,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
  Do a spnego encrypted session setup.
 ****************************************************************************/
 
-NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
+ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
                              const char *pass, const char *domain)
 {
        char *principal;
@@ -689,7 +692,7 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
           reply */
        if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
                data_blob_free(&blob);
-               return NT_STATUS_INVALID_PARAMETER;
+               return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
        data_blob_free(&blob);
 
@@ -719,7 +722,7 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
                        
                        if (ret){
                                DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
-                               return NT_STATUS_LOGON_FAILURE;
+                               return ADS_ERROR_KRB5(ret);
                        }
                }
                
@@ -731,7 +734,7 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
 
 ntlmssp:
 
-       return cli_session_setup_ntlmssp(cli, user, pass, domain);
+       return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain));
 }
 
 /****************************************************************************
@@ -812,9 +815,9 @@ BOOL cli_session_setup(struct cli_state *cli,
        /* if the server supports extended security then use SPNEGO */
 
        if (cli->capabilities & CAP_EXTENDED_SECURITY) {
-               NTSTATUS nt_status;
-               if (!NT_STATUS_IS_OK(nt_status = cli_session_setup_spnego(cli, user, pass, workgroup))) {
-                       DEBUG(3, ("SPENGO login failed: %s\n", get_friendly_nt_error_msg(nt_status)));
+               ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
+               if (!ADS_ERR_OK(status)) {
+                       DEBUG(3, ("SPENGO login failed: %s\n", ads_errstr(status)));
                        return False;
                }
                return True;
index 5568b5e033253ec82aedce4ad353dd89f05cc5c9..15b244a83dc273ce6e72679e1801b5d6fd424546 100644 (file)
@@ -307,14 +307,14 @@ cleanup_princ:
 /*
   get a kerberos5 ticket for the given service 
 */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
+int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5)
 {
        krb5_error_code retval;
        krb5_data packet;
        krb5_ccache ccdef;
        krb5_context context;
        krb5_auth_context auth_context = NULL;
-       DATA_BLOB ret;
        krb5_enctype enc_types[] = {
 #ifdef ENCTYPE_ARCFOUR_HMAC
                ENCTYPE_ARCFOUR_HMAC,
@@ -356,17 +356,18 @@ DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BL
 
        get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
 
-       ret = data_blob(packet.data, packet.length);
+       *ticket = data_blob(packet.data, packet.length);
+
 /* Hmm, heimdal dooesn't have this - what's the correct call? */
-/*     krb5_free_data_contents(context, &packet); */
-       krb5_free_context(context);
-       return ret;
+#ifdef HAVE_KRB5_FREE_DATA_CONTENTS
+       krb5_free_data_contents(context, &packet); 
+#endif
 
 failed:
        if ( context )
                krb5_free_context(context);
                
-       return data_blob(NULL, 0);
+       return retval;
 }
 
  BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote)
@@ -410,10 +411,11 @@ failed:
 
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
- {
+int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5) 
+{
         DEBUG(0,("NO KERBEROS SUPPORT\n"));
-        return data_blob(NULL, 0);
- }
+        return 1;
+}
 
 #endif
index 92543736ff258b767ee766c6a258965c055d8426..e6cadc466c17e501e18946913b8dc909511ef5da 100644 (file)
@@ -323,27 +323,30 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
    generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
    kerberos session setup 
 */
-DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, DATA_BLOB *session_key_krb5)
+int spnego_gen_negTokenTarg(const char *principal, int time_offset, 
+                           DATA_BLOB *targ, 
+                           DATA_BLOB *session_key_krb5)
 {
-       DATA_BLOB tkt, tkt_wrapped, targ;
+       int retval;
+       DATA_BLOB tkt, tkt_wrapped;
        const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
 
        /* get a kerberos ticket for the service and extract the session key */
-       tkt = cli_krb5_get_ticket(principal, time_offset, session_key_krb5);
+       retval = cli_krb5_get_ticket(principal, time_offset, &tkt, session_key_krb5);
 
-       if (tkt.data == NULL)
-               return tkt;
+       if (retval)
+               return retval;
 
        /* wrap that up in a nice GSS-API wrapping */
        tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
 
        /* and wrap that in a shiny SPNEGO wrapper */
-       targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
+       *targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
 
        data_blob_free(&tkt_wrapped);
        data_blob_free(&tkt);
 
-       return targ;
+       return retval;
 }
 
 
index 74f341a490456db2d43e6035707ee06187694f15..c7dc89d43f1f2837278df2f6bb86c9f275dcd570 100644 (file)
@@ -298,18 +298,20 @@ static BOOL wbinfo_domain_info(const char *domain_name)
 
        /* Display response */
 
-       d_printf("Name    : %s\n", response.data.domain_info.name);
-       d_printf("Alt_Name: %s\n", response.data.domain_info.alt_name);
+       d_printf("Name              : %s\n", response.data.domain_info.name);
+       d_printf("Alt_Name          : %s\n", response.data.domain_info.alt_name);
 
-       d_printf("SID     : %s\n", response.data.domain_info.sid);
+       d_printf("SID               : %s\n", response.data.domain_info.sid);
 
-       d_printf("Native  : %s\n",
+       d_printf("Active Directory  : %s\n",
+                response.data.domain_info.active_directory ? "Yes" : "No");
+       d_printf("Native            : %s\n",
                 response.data.domain_info.native_mode ? "Yes" : "No");
 
-       d_printf("Primary : %s\n",
+       d_printf("Primary           : %s\n",
                 response.data.domain_info.primary ? "Yes" : "No");
 
-       d_printf("Sequence: %d\n", response.data.domain_info.sequence_number);
+       d_printf("Sequence          : %d\n", response.data.domain_info.sequence_number);
 
        return True;
 }
index 8ce528d2b0d7ab8101c366b7530e304e2191d41d..4d5b08b4ec26e7694173311237e2646650edfe42 100644 (file)
@@ -935,6 +935,8 @@ int main(int argc, char **argv)
 
        netsamlogon_cache_init(); /* Non-critical */
        
+       init_domain_list();
+
        /* Loop waiting for requests */
 
        process_loop();
index 5dbe422bc148ca4563b7f07a245095216480c5b0..7c8e6256e15d51ad5e4603f724e498a12627d5d2 100644 (file)
@@ -95,7 +95,8 @@ struct winbindd_domain {
        fstring alt_name;                      /* alt Domain name (if any) */
        DOM_SID sid;                           /* SID for this domain */
        BOOL native_mode;                      /* is this a win2k domain in native mode ? */
-       BOOL primary;                           /* is this our primary domain ? */
+       BOOL active_directory;                 /* is this a win2k active directory ? */
+       BOOL primary;                          /* is this our primary domain ? */
 
        /* Lookup methods for this domain (LDAP or RPC) */
        struct winbindd_methods *methods;
index 2df2ea6374a5433de4f40bf41826a983804763ff..8dec89a6aa33ab3605aaf53befc565ae888107ec 100644 (file)
@@ -112,7 +112,9 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
                                break;
                        }
 
-                       if ( domain->native_mode ) {
+                       /* if it have either of the indications of ADS, 
+                          use ads_methods */
+                       if ( domain->active_directory || domain->native_mode ) {
                                domain->backend = &ads_methods;
                                break;
                        }
index 2b561be31db48bb3caf8daba1ab426e87754e80c..53c91c01c7bdcbb01ebc3e4d67442a04a8ba04f4 100644 (file)
@@ -174,16 +174,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
                        
                        if ((lp_security() == SEC_ADS) 
                                && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) {
+                               ADS_STATUS ads_status;
                                new_conn->cli->use_kerberos = True;
                                DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n", 
                                          new_conn->controller, global_myname(), machine_krb5_principal));
 
-                               result = NT_STATUS_OK;
-
-                               if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, 
-                                                             machine_password, 
-                                                             lp_workgroup()))) {
-                                       DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
+                               ads_status = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, 
+                                                                     machine_password, 
+                                                                     lp_workgroup());
+                               if (!ADS_ERR_OK(ads_status)) {
+                                       DEBUG(4,("failed kerberos session setup with %s\n", ads_errstr(ads_status)));
+                                       result = ads_ntstatus(ads_status);
+                               } else {
+                                       result = NT_STATUS_OK;
                                }
                        }
                        new_conn->cli->use_kerberos = False;
@@ -405,46 +408,116 @@ static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const
 }
 
 /**********************************************************************************
+ We can 'sense' certain things about the DC by it's replies to certain questions.
+
+ This tells us if this particular remote server is Active Directory, and if it is
+ native mode.
 **********************************************************************************/
 
-BOOL cm_check_for_native_mode_win2k( struct winbindd_domain *domain )
+void set_dc_type_and_flags( struct winbindd_domain *domain )
 {
        NTSTATUS                result;
        struct winbindd_cm_conn conn;
        DS_DOMINFO_CTR          ctr;
-       BOOL                    ret = False;
+       TALLOC_CTX              *mem_ctx;
        
        ZERO_STRUCT( conn );
        ZERO_STRUCT( ctr );
        
+       domain->native_mode = False;
+       domain->active_directory = False;
        
        if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
-               DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", 
+               DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n", 
                          domain->name, nt_errstr(result)));
-               return False;
+               return;
        }
        
        if ( conn.cli ) {
                if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, 
                                conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) {
-                       ret = False;
                        goto done;
                }
        }
                                
        if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) 
                        && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
-               ret = True;
+               domain->native_mode = True;
 
-done:
+       /* Cheat - shut down the DS pipe, and open LSA */
+
+       cli_nt_session_close(conn.cli);
+
+       if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) {
+               char *domain_name = NULL;
+               char *dns_name = NULL;
+               DOM_SID *dom_sid = NULL;
+
+               mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name);
+               if (!mem_ctx) {
+                       DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
+                       return;
+               }
+
+               result = cli_lsa_open_policy2(conn.cli, mem_ctx, True, 
+                                             SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                             &conn.pol);
+               
+               if (NT_STATUS_IS_OK(result)) {
+                       /* This particular query is exactly what Win2k clients use 
+                          to determine that the DC is active directory */
+                       result = cli_lsa_query_info_policy2(conn.cli, mem_ctx, 
+                                                           &conn.pol,
+                                                           12, &domain_name,
+                                                           &dns_name, NULL,
+                                                           NULL, &dom_sid);
+               }
+
+               if (NT_STATUS_IS_OK(result)) {
+                       if (domain_name)
+                               fstrcpy(domain->name, domain_name);
+                       
+                       if (dns_name)
+                               fstrcpy(domain->alt_name, dns_name);
 
+                       if (dom_sid) 
+                               sid_copy(&domain->sid, dom_sid);
+
+                       domain->active_directory = True;
+               } else {
+                       
+                       result = cli_lsa_open_policy(conn.cli, mem_ctx, True, 
+                                                    SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                                    &conn.pol);
+                       
+                       if (!NT_STATUS_IS_OK(result))
+                               goto done;
+                       
+                       result = cli_lsa_query_info_policy(conn.cli, mem_ctx, 
+                                                          &conn.pol, 5, &domain_name, 
+                                                          &dom_sid);
+                       
+                       if (NT_STATUS_IS_OK(result)) {
+                               if (domain_name)
+                                       fstrcpy(domain->name, domain_name);
+                               
+                               if (dom_sid) 
+                                       sid_copy(&domain->sid, dom_sid);
+                       }
+               }
+       }
+       
+done:
+       
        /* close the connection;  no other cals use this pipe and it is called only
           on reestablishing the domain list   --jerry */
-
+       
        if ( conn.cli )
                cli_shutdown( conn.cli );
        
-       return ret;
+       talloc_destroy(mem_ctx);
+       
+       return;
 }
 
 
index 95ca57a5e348e20fd30cadf804d46ac311139a16..18478992f3e1714c43cdce3a909a237bbb29e08a 100644 (file)
@@ -223,6 +223,7 @@ enum winbindd_result winbindd_domain_info(struct winbindd_cli_state *state)
                sid_string_static(&domain->sid));
        
        state->response.data.domain_info.native_mode = domain->native_mode;
+       state->response.data.domain_info.active_directory = domain->active_directory;
        state->response.data.domain_info.primary = domain->primary;
 
        state->response.data.domain_info.sequence_number =
index 0dd00e9b39edb955b4bc96ab1e3c621bd1ab5800..0d110b8afa87fb503cde0264cd2e6d5341e60a05 100644 (file)
@@ -36,7 +36,7 @@
 
 /* Update this when you change the interface.  */
 
-#define WINBIND_INTERFACE_VERSION 8
+#define WINBIND_INTERFACE_VERSION 9
 
 /* Socket commands */
 
@@ -272,6 +272,7 @@ struct winbindd_response {
                        fstring alt_name;
                        fstring sid;
                        BOOL native_mode;
+                       BOOL active_directory;
                        BOOL primary;
                        uint32 sequence_number;
                } domain_info;
index f619aa3564aa0d7faa4a632afcbc6f05253788b1..21e0c3092e3f62bb8a70991e1095c4a32730cbf1 100644 (file)
@@ -950,7 +950,8 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        TALLOC_CTX *mem_ctx;
        CLI_POLICY_HND *hnd;
-       fstring level5_dom;
+       char *level5_dom;
+       DOM_SID *alloc_sid;
        int retry;
 
        DEBUG(3,("rpc: domain_sid\n"));
@@ -965,9 +966,17 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
                        goto done;
 
                result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
-                                          &hnd->pol, 0x05, level5_dom, sid);
+                                          &hnd->pol, 0x05, &level5_dom, &alloc_sid);
        } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
 
+       if (NT_STATUS_IS_OK(result)) {
+               if (alloc_sid) {
+                       sid_copy(sid, alloc_sid);
+               } else {
+                       result = NT_STATUS_NO_MEMORY;
+               }
+       }
+
 done:
        talloc_destroy(mem_ctx);
        return result;
index 18946652e265ec4f95fdfafe448eb81adb8f8705..29a4ca93ebd896a848c4b4d4321cbfa186e8f920 100644 (file)
@@ -49,6 +49,14 @@ static const fstring name_deadbeef = "<deadbeef>";
 
 static struct winbindd_domain *_domain_list;
 
+/**
+   When was the last scan of trusted domains done?
+   
+   0 == not ever
+*/
+
+static time_t last_trustdom_scan;
+
 struct winbindd_domain *domain_list(void)
 {
        /* Initialise list */
@@ -83,6 +91,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 {
        struct winbindd_domain *domain;
        const char *alternative_name = NULL;
+       static const DOM_SID null_sid;
        
        /* ignore alt_name if we are not in an AD domain */
        
@@ -103,6 +112,13 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
                                return domain;
                        }
                }
+               if (sid) {
+                       if (sid_equal(sid, &null_sid) ) {
+                               
+                       } else if (sid_equal(sid, &domain->sid)) {
+                               return domain;
+                       }
+               }
        }
         
        /* Create new domain entry */
@@ -134,12 +150,14 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
                sid_copy(&domain->sid, sid);
        }
        
-       /* see if this is a native mode win2k domain */
+       /* set flags about native_mode, active_directory */
           
-       domain->native_mode = cm_check_for_native_mode_win2k( domain );
+       set_dc_type_and_flags( domain );
        
-       DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain->name,
-               domain->native_mode ? "native" : "mixed (or NT4)" ));
+       DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
+                domain->active_directory ? "ADS" : "NT4", 
+                domain->native_mode ? "native mode" : 
+                ((domain->active_directory && !domain->native_mode) ? "mixed mode" : "")));
 
        /* Link to domain list */
        DLIST_ADD(_domain_list, domain);
@@ -157,13 +175,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 
 void rescan_trusted_domains( void )
 {
-       static time_t last_scan;
        time_t now = time(NULL);
        struct winbindd_domain *mydomain = NULL;
        
        /* see if the time has come... */
        
-       if ( (now > last_scan) && ((now-last_scan) < WINBINDD_RESCAN_FREQ) )
+       if ( (now > last_trustdom_scan) && ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
                return;
                
        if ( (mydomain = find_our_domain()) == NULL ) {
@@ -175,7 +192,7 @@ void rescan_trusted_domains( void )
        
        add_trusted_domains( mydomain );
 
-       last_scan = now;
+       last_trustdom_scan = now;
        
        return; 
 }
@@ -222,7 +239,7 @@ void add_trusted_domains( struct winbindd_domain *domain )
                for(i = 0; i < num_domains; i++) {
                        DEBUG(10,("Found domain %s\n", names[i]));
                        add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
-                               domain->methods, &dom_sids[i]);
+                                          domain->methods, &dom_sids[i]);
                                           
                        /* if the SID was empty, we better set it now */
                        
@@ -264,7 +281,7 @@ BOOL init_domain_list(void)
        /* Free existing list */
        free_domain_list();
 
-       /* Add ourselves as the first entry.  It *must* be the first entry */
+       /* Add ourselves as the first entry. */
        
        domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL);
        
@@ -287,7 +304,9 @@ BOOL init_domain_list(void)
 
        /* do an initial scan for trusted domains */
        add_trusted_domains(domain);
-
+       
+       /* avoid rescanning this right away */
+       last_trustdom_scan = time(NULL);
        return True;
 }
 
index 3b1f5478c6a56b8210d0ead73f565d843afe53a5..eaf3109381e5d42d002a484170de1a998928346e 100644 (file)
@@ -443,7 +443,7 @@ NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *pol, uint16 info_class, 
-                                   fstring domain_name, DOM_SID *domain_sid)
+                                   char **domain_name, DOM_SID **domain_sid)
 {
        prs_struct qbuf, rbuf;
        LSA_Q_QUERY_INFO q;
@@ -481,39 +481,40 @@ NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Return output parameters */
 
-       ZERO_STRUCTP(domain_sid);
-       domain_name[0] = '\0';
-
        switch (info_class) {
 
        case 3:
-               if (r.dom.id3.buffer_dom_name != 0) {
-                       unistr2_to_ascii(domain_name,
-                                        &r.dom.id3.
-                                        uni_domain_name,
-                                        sizeof (fstring) - 1);
+               if (domain_name && (r.dom.id3.buffer_dom_name != 0)) {
+                       *domain_name = unistr2_tdup(mem_ctx, 
+                                                  &r.dom.id3.
+                                                  uni_domain_name);
                }
 
-               if (r.dom.id3.buffer_dom_sid != 0) {
-                       *domain_sid = r.dom.id3.dom_sid.sid;
+               if (domain_sid && (r.dom.id3.buffer_dom_sid != 0)) {
+                       *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+                       if (*domain_sid) {
+                               sid_copy(*domain_sid, &r.dom.id3.dom_sid.sid);
+                       }
                }
 
                break;
 
        case 5:
                
-               if (r.dom.id5.buffer_dom_name != 0) {
-                       unistr2_to_ascii(domain_name, &r.dom.id5.
-                                        uni_domain_name,
-                                        sizeof (fstring) - 1);
+               if (domain_name && (r.dom.id5.buffer_dom_name != 0)) {
+                       *domain_name = unistr2_tdup(mem_ctx, 
+                                                  &r.dom.id5.
+                                                  uni_domain_name);
                }
                        
-               if (r.dom.id5.buffer_dom_sid != 0) {
-                       *domain_sid = r.dom.id5.dom_sid.sid;
+               if (domain_sid && (r.dom.id5.buffer_dom_sid != 0)) {
+                       *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+                       if (*domain_sid) {
+                               sid_copy(*domain_sid, &r.dom.id5.dom_sid.sid);
+                       }
                }
-
                break;
-               
+                       
        default:
                DEBUG(3, ("unknown info class %d\n", info_class));
                break;                
@@ -536,9 +537,9 @@ NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *pol, uint16 info_class, 
-                                   fstring domain_name, fstring dns_name,
-                                   fstring forest_name, GUID *domain_guid,
-                                   DOM_SID *domain_sid)
+                                   char **domain_name, char **dns_name,
+                                   char **forest_name, GUID **domain_guid,
+                                   DOM_SID **domain_sid)
 {
        prs_struct qbuf, rbuf;
        LSA_Q_QUERY_INFO2 q;
@@ -579,30 +580,37 @@ NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Return output parameters */
 
-       ZERO_STRUCTP(domain_sid);
        ZERO_STRUCTP(domain_guid);
-       domain_name[0] = '\0';
 
-       if (r.info.dns_dom_info.hdr_nb_dom_name.buffer) {
-               unistr2_to_ascii(domain_name,
-                                &r.info.dns_dom_info.uni_nb_dom_name,
-                                sizeof(fstring) - 1);
+       if (domain_name && r.info.dns_dom_info.hdr_nb_dom_name.buffer) {
+               *domain_name = unistr2_tdup(mem_ctx, 
+                                           &r.info.dns_dom_info
+                                           .uni_nb_dom_name);
        }
-       if (r.info.dns_dom_info.hdr_dns_dom_name.buffer) {
-               unistr2_to_ascii(dns_name,
-                                &r.info.dns_dom_info.uni_dns_dom_name,
-                                sizeof(fstring) - 1);
+       if (dns_name && r.info.dns_dom_info.hdr_dns_dom_name.buffer) {
+               *dns_name = unistr2_tdup(mem_ctx, 
+                                        &r.info.dns_dom_info
+                                        .uni_dns_dom_name);
        }
-       if (r.info.dns_dom_info.hdr_forest_name.buffer) {
-               unistr2_to_ascii(forest_name,
-                                &r.info.dns_dom_info.uni_forest_name,
-                                sizeof(fstring) - 1);
+       if (forest_name && r.info.dns_dom_info.hdr_forest_name.buffer) {
+               *forest_name = unistr2_tdup(mem_ctx, 
+                                           &r.info.dns_dom_info
+                                           .uni_forest_name);
        }
        
-       memcpy(domain_guid, &r.info.dns_dom_info.dom_guid, sizeof(GUID));
-
-       if (r.info.dns_dom_info.ptr_dom_sid != 0) {
-               *domain_sid = r.info.dns_dom_info.dom_sid.sid;
+       if (domain_guid) {
+               *domain_guid = talloc(mem_ctx, sizeof(**domain_guid));
+               memcpy(*domain_guid, 
+                      &r.info.dns_dom_info.dom_guid, 
+                      sizeof(GUID));
+       }
+
+       if (domain_sid && r.info.dns_dom_info.ptr_dom_sid != 0) {
+               *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+               if (*domain_sid) {
+                       sid_copy(*domain_sid, 
+                                &r.info.dns_dom_info.dom_sid.sid);
+               }
        }
        
  done:
index db74370bc0bd0299f696d876628fb94e004d3af9..1b1ea31c96f94ecf4d4615e564a6eb5af9eae47c 100644 (file)
@@ -68,9 +68,13 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
 {
        POLICY_HND pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       DOM_SID dom_sid;
-       GUID dom_guid;
-       fstring sid_str, domain_name="", dns_name="", forest_name="";
+       DOM_SID *dom_sid;
+       GUID *dom_guid;
+       fstring sid_str;
+       char *domain_name = NULL;
+       char *dns_name = NULL;
+       char *forest_name = NULL;
+
        uint32 info_class = 3;
 
        if (argc > 2) {
@@ -91,8 +95,8 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
                if (!NT_STATUS_IS_OK(result))
                        goto done;
                result = cli_lsa_query_info_policy2(cli, mem_ctx, &pol,
-                                                   info_class, domain_name,
-                                                   dns_name, forest_name,
+                                                   info_class, &domain_name,
+                                                   &dns_name, &forest_name,
                                                    &dom_guid, &dom_sid);
                break;
        default:
@@ -103,23 +107,23 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
                if (!NT_STATUS_IS_OK(result))
                        goto done;
                result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, 
-                                                  info_class, domain_name, 
+                                                  info_class, &domain_name, 
                                                   &dom_sid);
        }
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
+       
+       sid_to_string(sid_str, dom_sid);
 
-       sid_to_string(sid_str, &dom_sid);
-
-       if (domain_name[0])
+       if (domain_name)
                printf("domain %s has sid %s\n", domain_name, sid_str);
        else
                printf("could not query info for level %d\n", info_class);
 
-       if (dns_name[0])
+       if (dns_name)
                printf("domain dns name is %s\n", dns_name);
-       if (forest_name[0])
+       if (forest_name)
                printf("forest name is %s\n", forest_name);
 
        if (info_class == 12) {
index b28365274c066c21a53d98e2e504a291c7fdbb1d..9f0f64edecb960d0141da0b61d1a0dab82098695 100644 (file)
@@ -48,27 +48,14 @@ typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_C
  * @return The Domain SID of the remote machine.
  **/
 
-static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
+static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx)
 {
        DOM_SID *domain_sid;
        POLICY_HND pol;
        NTSTATUS result = NT_STATUS_OK;
        uint32 info_class = 5;
-       fstring domain_name;
-       TALLOC_CTX *mem_ctx;
+        char *domain_name;
        
-       if (!(domain_sid = malloc(sizeof(DOM_SID)))){
-               DEBUG(0,("net_get_remote_domain_sid: malloc returned NULL!\n"));
-               goto error;
-       }
-           
-       if (!(mem_ctx=talloc_init("net_get_remote_domain_sid")))
-       {
-               DEBUG(0,("net_get_remote_domain_sid: talloc_init returned NULL!\n"));
-               goto error;
-       }
-
-
        if (!cli_nt_session_open (cli, PI_LSARPC)) {
                fprintf(stderr, "could not initialise lsa pipe\n");
                goto error;
@@ -82,7 +69,7 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
        }
 
        result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
-                                          domain_name, domain_sid);
+                                          &domain_name, &domain_sid);
        if (!NT_STATUS_IS_OK(result)) {
  error:
                fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
@@ -96,7 +83,6 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
 
        cli_lsa_close(cli, mem_ctx, &pol);
        cli_nt_session_close(cli);
-       talloc_destroy(mem_ctx);
 
        return domain_sid;
 }
@@ -132,7 +118,7 @@ static int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int co
                return -1;
        }
 
-       domain_sid = net_get_remote_domain_sid(cli);
+       domain_sid = net_get_remote_domain_sid(cli, mem_ctx);
 
        /* Create mem_ctx */
        
@@ -1928,10 +1914,11 @@ static int rpc_trustdom_establish(int argc, const char **argv)
        POLICY_HND connect_hnd;
        TALLOC_CTX *mem_ctx;
        NTSTATUS nt_status;
-       DOM_SID domain_sid;
+       DOM_SID *domain_sid;
        WKS_INFO_100 wks_info;
        
        char* domain_name;
+       char* domain_name_pol;
        char* acct_name;
        fstring pdc_name;
 
@@ -2052,7 +2039,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
        /* Querying info level 5 */
        
        nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
-                                             5 /* info level */, domain_name,
+                                             5 /* info level */, &domain_name_pol,
                                              &domain_sid);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
@@ -2072,7 +2059,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
 
        if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
                                                   wks_info.uni_lan_grp.uni_str_len, opt_password,
-                                                  domain_sid)) {
+                                                  *domain_sid)) {
                DEBUG(0, ("Storing password for trusted domain failed.\n"));
                return -1;
        }
@@ -2163,7 +2150,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        struct cli_state *cli, *remote_cli;
        NTSTATUS nt_status;
        const char *domain_name = NULL;
-       DOM_SID queried_dom_sid;
+       DOM_SID *queried_dom_sid;
        fstring ascii_sid, padding;
        int ascii_dom_name_len;
        POLICY_HND connect_hnd;
@@ -2173,7 +2160,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
        int i, pad_len, col_len = 20;
        DOM_SID *domain_sids;
        char **trusted_dom_names;
-       fstring pdc_name, dummy;
+       fstring pdc_name;
+       char *dummy;
        
        /* trusting domains listing variables */
        POLICY_HND domain_hnd;
@@ -2222,7 +2210,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        /* query info level 5 to obtain sid of a domain being queried */
        nt_status = cli_lsa_query_info_policy(
                cli, mem_ctx, &connect_hnd, 5 /* info level */, 
-               dummy, &queried_dom_sid);
+               &dummy, &queried_dom_sid);
 
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
@@ -2304,8 +2292,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
        /* SamrOpenDomain - we have to open domain policy handle in order to be
           able to enumerate accounts*/
        nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
-                                                                        SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
-                                                                        &queried_dom_sid, &domain_hnd);                                                                         
+                                        SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
+                                        queried_dom_sid, &domain_hnd);                                                                  
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("Couldn't open domain object. Error was %s\n",
                        nt_errstr(nt_status)));
index 96e52964b43c65357689d38e34154c726fd25ec7..74918045ee992bdf6a5dabac0b38ba5acf1bcad9 100644 (file)
@@ -1072,6 +1072,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
        DATA_BLOB session_key_krb5;
        SPNEGO_DATA reply;
        char *reply_base64;
+       int retval;
        
        const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL};
        ssize_t len;
@@ -1093,9 +1094,9 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
               spnego.negTokenInit.mechListMIC.length);
        principal[spnego.negTokenInit.mechListMIC.length] = '\0';
 
-       tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
+       retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
 
-       if (tkt.data == NULL) {
+       if (retval) {
 
                pstring user;
 
@@ -1110,13 +1111,17 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
 
                pstr_sprintf(user, "%s@%s", opt_username, opt_domain);
 
-               if (kerberos_kinit_password(user, opt_password, 0) != 0) {
-                       DEBUG(10, ("Requesting TGT failed\n"));
+               if ((retval = kerberos_kinit_password(user, opt_password, 0))) {
+                       DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
                        x_fprintf(x_stdout, "NA\n");
                        return True;
                }
 
-               tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
+               retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
+
+               if (retval) {
+                       DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
+               }
        }
 
        data_blob_free(&session_key_krb5);