summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in4
-rw-r--r--source3/configure.in1
-rw-r--r--source3/libads/ads_status.c11
-rw-r--r--source3/libads/sasl.c17
-rw-r--r--source3/libsmb/cliconnect.c31
-rw-r--r--source3/libsmb/clikrb5.c24
-rw-r--r--source3/libsmb/clispnego.c17
-rw-r--r--source3/nsswitch/wbinfo.c14
-rw-r--r--source3/nsswitch/winbindd.c2
-rw-r--r--source3/nsswitch/winbindd.h3
-rw-r--r--source3/nsswitch/winbindd_cache.c4
-rw-r--r--source3/nsswitch/winbindd_cm.c103
-rw-r--r--source3/nsswitch/winbindd_misc.c1
-rw-r--r--source3/nsswitch/winbindd_nss.h3
-rw-r--r--source3/nsswitch/winbindd_rpc.c13
-rw-r--r--source3/nsswitch/winbindd_util.c39
-rw-r--r--source3/rpc_client/cli_lsarpc.c88
-rw-r--r--source3/rpcclient/cmd_lsarpc.c26
-rw-r--r--source3/utils/net_rpc.c40
-rw-r--r--source3/utils/ntlm_auth.c15
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);