diff options
-rw-r--r-- | source3/Makefile.in | 4 | ||||
-rw-r--r-- | source3/configure.in | 1 | ||||
-rw-r--r-- | source3/libads/ads_status.c | 11 | ||||
-rw-r--r-- | source3/libads/sasl.c | 17 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 31 | ||||
-rw-r--r-- | source3/libsmb/clikrb5.c | 24 | ||||
-rw-r--r-- | source3/libsmb/clispnego.c | 17 | ||||
-rw-r--r-- | source3/nsswitch/wbinfo.c | 14 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.h | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 4 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 103 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_misc.c | 1 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_nss.h | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 13 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 39 | ||||
-rw-r--r-- | source3/rpc_client/cli_lsarpc.c | 88 | ||||
-rw-r--r-- | source3/rpcclient/cmd_lsarpc.c | 26 | ||||
-rw-r--r-- | source3/utils/net_rpc.c | 40 | ||||
-rw-r--r-- | source3/utils/ntlm_auth.c | 15 |
20 files changed, 298 insertions, 158 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 6146d3d16b..75213c2f5e 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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 diff --git a/source3/configure.in b/source3/configure.in index 1ca8512b21..7a844c337d 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -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" diff --git a/source3/libads/ads_status.c b/source3/libads/ads_status.c index 11f9d66b92..63757af860 100644 --- a/source3/libads/ads_status.c +++ b/source3/libads/ads_status.c @@ -78,6 +78,15 @@ NTSTATUS ads_ntstatus(ADS_STATUS status) 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?)"; } diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index 5122803597..1ab71c6ee5 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -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)) { diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 1dc46ab0e6..707a33881d 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -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; diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index 5568b5e033..15b244a83d 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -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 diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index 92543736ff..e6cadc466c 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -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; } diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 74f341a490..c7dc89d43f 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -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; } diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 8ce528d2b0..4d5b08b4ec 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -935,6 +935,8 @@ int main(int argc, char **argv) netsamlogon_cache_init(); /* Non-critical */ + init_domain_list(); + /* Loop waiting for requests */ process_loop(); diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 5dbe422bc1..7c8e6256e1 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -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; diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 2df2ea6374..8dec89a6aa 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -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; } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 2b561be31d..53c91c01c7 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -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; } diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 95ca57a5e3..18478992f3 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -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 = diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index 0dd00e9b39..0d110b8afa 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -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; diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index f619aa3564..21e0c3092e 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -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; diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 18946652e2..29a4ca93eb 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -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; } diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index 3b1f5478c6..eaf3109381 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -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: diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c index db74370bc0..1b1ea31c96 100644 --- a/source3/rpcclient/cmd_lsarpc.c +++ b/source3/rpcclient/cmd_lsarpc.c @@ -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) { diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index b28365274c..9f0f64edec 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -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))); diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 96e52964b4..74918045ee 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -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); |