diff options
Diffstat (limited to 'source4')
45 files changed, 597 insertions, 963 deletions
diff --git a/source4/auth/auth_domain.c b/source4/auth/auth_domain.c index 6a968592bd..a6950445cb 100644 --- a/source4/auth/auth_domain.c +++ b/source4/auth/auth_domain.c @@ -51,7 +51,15 @@ static NTSTATUS domain_check_password(struct auth_method_context *ctx, binding = bindings[0]; } + if (!user_info->account_name) { + return NT_STATUS_INVALID_PARAMETER; + } + if (!user_info->workstation_name) { + return NT_STATUS_INVALID_PARAMETER; + } + credentials = cli_credentials_init(mem_ctx); + cli_credentials_set_conf(credentials); status = cli_credentials_set_machine_account(credentials); if (!NT_STATUS_IS_OK(status)) { @@ -101,7 +109,7 @@ static NTSTATUS domain_check_password(struct auth_method_context *ctx, ninfo.lm.data = user_info->lm_resp.data; r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); - r.in.workstation = creds->computer_name; + r.in.workstation = cli_credentials_get_workstation(credentials); r.in.credential = &auth; r.in.return_authenticator = &auth2; r.in.logon_level = 2; diff --git a/source4/client/client.c b/source4/client/client.c index 4ce686cdcf..9738292f03 100644 --- a/source4/client/client.c +++ b/source4/client/client.c @@ -3043,7 +3043,7 @@ static struct smbcli_state *do_connect(const char *server, const char *share, st smbcli_parse_unc(share, NULL, &server, &share); } - status = smbcli_full_connection(NULL, &c, lp_netbios_name(), server, + status = smbcli_full_connection(NULL, &c, server, share, NULL, cred); if (!NT_STATUS_IS_OK(status)) { d_printf("Connection to \\\\%s\\%s failed - %s\n", diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h index 1052a6297d..af9f6efd7a 100644 --- a/source4/include/smb_interfaces.h +++ b/source4/include/smb_interfaces.h @@ -269,14 +269,14 @@ union smb_sesssetup { DATA_BLOB secblob; const char *os; const char *lanman; - const char *domain; + const char *workgroup; } in; struct { uint16_t action; DATA_BLOB secblob; char *os; char *lanman; - char *domain; + char *workgroup; uint16_t vuid; } out; } spnego; diff --git a/source4/libcli/auth/config.mk b/source4/libcli/auth/config.mk index b37e214360..0c013ce0ef 100644 --- a/source4/libcli/auth/config.mk +++ b/source4/libcli/auth/config.mk @@ -1,8 +1,7 @@ ################################# # Start SUBSYSTEM GENSEC [SUBSYSTEM::LIBCLI_AUTH] -ADD_OBJ_FILES = libcli/auth/schannel_sign.o \ - libcli/auth/credentials.o \ +ADD_OBJ_FILES = libcli/auth/credentials.o \ libcli/auth/session.o \ libcli/auth/smbencrypt.o REQUIRED_SUBSYSTEMS = \ diff --git a/source4/libcli/auth/credentials.c b/source4/libcli/auth/credentials.c index 90b8313c9d..bcb462ae9d 100644 --- a/source4/libcli/auth/credentials.c +++ b/source4/libcli/auth/credentials.c @@ -192,18 +192,12 @@ next comes the client specific functions void creds_client_init(struct creds_CredentialState *creds, const struct netr_Credential *client_challenge, const struct netr_Credential *server_challenge, - const char *computer_name, - const char *domain, - const char *account_name, const struct samr_Password *machine_password, struct netr_Credential *initial_credential, uint32_t negotiate_flags) { creds->sequence = time(NULL); creds->negotiate_flags = negotiate_flags; - creds->computer_name = talloc_strdup(creds, computer_name); - creds->domain = talloc_strdup(creds, domain); - creds->account_name = talloc_strdup(creds, account_name); dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data)); dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data)); diff --git a/source4/libcli/auth/gensec.c b/source4/libcli/auth/gensec.c index 69de016156..cc7327187c 100644 --- a/source4/libcli/auth/gensec.c +++ b/source4/libcli/auth/gensec.c @@ -4,7 +4,7 @@ Generic Authentication Interface Copyright (C) Andrew Tridgell 2003 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -130,13 +130,7 @@ static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx, struct gensec_security **gense (*gensec_security)->ops = NULL; - ZERO_STRUCT((*gensec_security)->user); ZERO_STRUCT((*gensec_security)->target); - ZERO_STRUCT((*gensec_security)->default_user); - - (*gensec_security)->default_user.name = ""; - (*gensec_security)->default_user.domain = talloc_strdup(*gensec_security, lp_workgroup()); - (*gensec_security)->default_user.realm = talloc_strdup(*gensec_security, lp_realm()); (*gensec_security)->subcontext = False; (*gensec_security)->want_features = 0; @@ -185,8 +179,6 @@ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx, struct gensec_security **gense (*gensec_security)->gensec_role = GENSEC_CLIENT; (*gensec_security)->password_callback = NULL; - ZERO_STRUCT((*gensec_security)->user); - return status; } @@ -507,163 +499,24 @@ BOOL gensec_have_feature(struct gensec_security *gensec_security, } /** - * Set a username on a GENSEC context - ensures it is talloc()ed - * - */ - -NTSTATUS gensec_set_username(struct gensec_security *gensec_security, const char *user) -{ - gensec_security->user.name = talloc_strdup(gensec_security, user); - if (user && !gensec_security->user.name) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -/** - * Set a username on a GENSEC context - ensures it is talloc()ed - * - */ - -const char *gensec_get_username(struct gensec_security *gensec_security) -{ - if (gensec_security->user.name) { - return gensec_security->user.name; - } - return gensec_security->default_user.name; -} - -/** - * Set a domain on a GENSEC context - ensures it is talloc()ed + * Associate a credentails structure with a GENSEC context - talloc_reference()s it to the context * */ -NTSTATUS gensec_set_domain(struct gensec_security *gensec_security, const char *domain) +NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials) { - gensec_security->user.domain = talloc_strdup(gensec_security, domain); - if (domain && !gensec_security->user.domain) { - return NT_STATUS_NO_MEMORY; - } + gensec_security->credentials = talloc_reference(gensec_security, credentials); return NT_STATUS_OK; } /** - * Return the NT domain for this GENSEC context + * Return the credentails structure associated with a GENSEC context * */ -const char *gensec_get_domain(struct gensec_security *gensec_security) +struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security) { - if (gensec_security->user.domain) { - return gensec_security->user.domain; - } else if (gensec_security->user.realm) { - return gensec_security->user.realm; - } - return gensec_security->default_user.domain; -} - -/** - * Set the client workstation on a GENSEC context - ensures it is talloc()ed - * - */ - -NTSTATUS gensec_set_workstation(struct gensec_security *gensec_security, const char *workstation) -{ - gensec_security->user.workstation = talloc_strdup(gensec_security, workstation); - if (workstation && !gensec_security->user.workstation) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -/** - * Return the client workstation on a GENSEC context - ensures it is talloc()ed - * - */ - -const char *gensec_get_workstation(struct gensec_security *gensec_security) -{ - if (gensec_security->user.workstation) { - return gensec_security->user.workstation; - } else { - return lp_netbios_name(); - } -} - -/** - * Set a kerberos realm on a GENSEC context - ensures it is talloc()ed - * - */ - -NTSTATUS gensec_set_realm(struct gensec_security *gensec_security, const char *realm) -{ - gensec_security->user.realm = talloc_strdup(gensec_security, realm); - if (realm && !gensec_security->user.realm) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -/** - * Return the Krb5 realm for this context - * - */ - -const char *gensec_get_realm(struct gensec_security *gensec_security) -{ - if (gensec_security->user.realm) { - return gensec_security->user.realm; - } else if (gensec_security->user.domain) { - return gensec_security->user.domain; - } - return gensec_security->default_user.realm; -} - -/** - * Return a kerberos principal for this context, if one has been set - * - */ - -char *gensec_get_client_principal(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx) -{ - const char *realm = gensec_get_realm(gensec_security); - if (realm) { - return talloc_asprintf(mem_ctx, "%s@%s", - gensec_get_username(gensec_security), - gensec_get_realm(gensec_security)); - } else { - return talloc_strdup(mem_ctx, gensec_get_username(gensec_security)); - } -} - -/** - * Set the password outright on GENSEC context - ensures it is talloc()ed, and that we will - * not do a callback - * - */ - -NTSTATUS gensec_set_password(struct gensec_security *gensec_security, - const char *password) -{ - gensec_security->user.password = talloc_strdup(gensec_security, password); - if (password && !gensec_security->user.password) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -/** - * Set the target principal name (if already known) on a GENSEC context - ensures it is talloc()ed - * - */ - -NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal) -{ - gensec_security->target.principal = talloc_strdup(gensec_security, principal); - if (!gensec_security->target.principal) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; + return gensec_security->credentials; } /** @@ -713,54 +566,6 @@ const char *gensec_get_target_service(struct gensec_security *gensec_security) return "host"; } -const char *gensec_get_target_principal(struct gensec_security *gensec_security) -{ - const char *mechListMIC; - - if (gensec_security->target.principal) { - return gensec_security->target.principal; - } - - mechListMIC = talloc_asprintf(gensec_security,"%s$@%s", - lp_netbios_name(), - lp_realm()); - return mechListMIC; -} - -/** - * Set a password callback, if the gensec module we use demands a password - */ - -void gensec_set_password_callback(struct gensec_security *gensec_security, - gensec_password_callback callback, void *callback_private_data) -{ - gensec_security->password_callback = callback; - gensec_security->password_callback_private = callback_private_data; -} - -/** - * Get (or call back for) a password. - */ - -NTSTATUS gensec_get_password(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - char **password) -{ - if (gensec_security->user.password) { - *password = talloc_strdup(mem_ctx, gensec_security->user.password); - if (!*password) { - return NT_STATUS_NO_MEMORY; - } else { - return NT_STATUS_OK; - } - } - if (!gensec_security->password_callback) { - *password = NULL; - return NT_STATUS_OK; - } - return gensec_security->password_callback(gensec_security, mem_ctx, password); -} - /* register a GENSEC backend. @@ -821,6 +626,5 @@ const struct gensec_critical_sizes *gensec_interface_version(void) */ NTSTATUS gensec_init(void) { - gensec_dcerpc_schannel_init(); return NT_STATUS_OK; } diff --git a/source4/libcli/auth/gensec.h b/source4/libcli/auth/gensec.h index a4383d852c..91c817d48a 100644 --- a/source4/libcli/auth/gensec.h +++ b/source4/libcli/auth/gensec.h @@ -4,7 +4,7 @@ Generic Authentication Interface Copyright (C) Andrew Tridgell 2003 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,13 +28,6 @@ #define GENSEC_OID_KERBEROS5_USER2USER "1 2 840 113554 1 2 2 3" struct gensec_security; -struct gensec_user { - const char *workstation; - const char *domain; - const char *realm; - const char *name; - const char *password; -}; struct gensec_target { const char *principal; const char *hostname; @@ -105,8 +98,7 @@ struct gensec_security { void *password_callback_private; const struct gensec_security_ops *ops; void *private_data; - struct gensec_user user; - struct gensec_user default_user; + struct cli_credentials *credentials; struct gensec_target target; enum gensec_role gensec_role; BOOL subcontext; diff --git a/source4/libcli/auth/gensec.mk b/source4/libcli/auth/gensec.mk index 7e2e34081d..b4c612da14 100644 --- a/source4/libcli/auth/gensec.mk +++ b/source4/libcli/auth/gensec.mk @@ -69,6 +69,18 @@ REQUIRED_SUBSYSTEMS = AUTH ################################################ ################################################ +# Start MODULE gensec_schannel +[MODULE::gensec_schannel] +SUBSYSTEM = GENSEC +INIT_FUNCTION = gensec_schannel_init +INIT_OBJ_FILES = libcli/auth/schannel.o +ADD_OBJ_FILES = \ + libcli/auth/schannel_sign.o +REQUIRED_SUBSYSTEMS = AUTH SCHANNELDB +# End MODULE gensec_ntlmssp +################################################ + +################################################ # Start SUBSYSTEM SCHANNELDB [SUBSYSTEM::SCHANNELDB] INIT_OBJ_FILES = \ diff --git a/source4/libcli/auth/gensec_krb5.c b/source4/libcli/auth/gensec_krb5.c index 71670632b9..453485d816 100644 --- a/source4/libcli/auth/gensec_krb5.c +++ b/source4/libcli/auth/gensec_krb5.c @@ -320,7 +320,12 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security struct gensec_krb5_state *gensec_krb5_state; krb5_error_code ret; NTSTATUS nt_status; - + const char *hostname = gensec_get_target_hostname(gensec_security); + if (!hostname) { + DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); + return NT_STATUS_ACCESS_DENIED; + } + nt_status = gensec_krb5_start(gensec_security); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; @@ -341,22 +346,8 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security } while (1) { - if (gensec_security->target.principal) { - DEBUG(5, ("Finding ticket for target [%s]\n", gensec_security->target.principal)); - ret = ads_krb5_mk_req(gensec_krb5_state->context, - &gensec_krb5_state->auth_context, - AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED, - gensec_security->target.principal, - gensec_krb5_state->ccache, - &gensec_krb5_state->ticket); - } else { + { krb5_data in_data; - const char *hostname = gensec_get_target_hostname(gensec_security); - if (!hostname) { - DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); - return NT_STATUS_ACCESS_DENIED; - } - in_data.length = 0; ret = krb5_mk_req(gensec_krb5_state->context, @@ -372,36 +363,40 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security case 0: return NT_STATUS_OK; case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: - DEBUG(3, ("Server is not registered with our KDC: %s\n", - error_message(ret))); + DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n", + hostname, error_message(ret))); return NT_STATUS_ACCESS_DENIED; case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5KRB_AP_ERR_TKT_EXPIRED: case KRB5_CC_END: + /* Too much clock skew - we will need to kinit to re-skew the clock */ + case KRB5KRB_AP_ERR_SKEW: + case KRB5_KDCREP_SKEW: { DEBUG(3, ("kerberos (mk_req) failed: %s\n", error_message(ret))); /* fall down to remaining code */ } + + /* just don't print a message for these really ordinary messages */ case KRB5_FCC_NOFILE: case KRB5_CC_NOTFOUND: case ENOENT: + { - char *password; + const char *password; char *ccache_string; time_t kdc_time = 0; - nt_status = gensec_get_password(gensec_security, - gensec_security, - &password); + password = cli_credentials_get_password(gensec_security->credentials); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } /* this string should be unique */ ccache_string = talloc_asprintf(gensec_krb5_state, "MEMORY:%s:%s:%s", - gensec_get_client_principal(gensec_security, gensec_krb5_state), - gensec_get_target_principal(gensec_security), + cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state), + gensec_get_target_hostname(gensec_security), generate_random_str(gensec_krb5_state, 16)); ret = krb5_cc_resolve(gensec_krb5_state->context, ccache_string, &gensec_krb5_state->ccache); @@ -413,8 +408,8 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security } ret = kerberos_kinit_password_cc(gensec_krb5_state->context, gensec_krb5_state->ccache, - gensec_get_client_principal(gensec_security, gensec_krb5_state), - password, NULL, &kdc_time); + cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state), + password, NULL, &kdc_time); /* cope with ticket being in the future due to clock skew */ if ((unsigned)kdc_time > time(NULL)) { @@ -422,10 +417,18 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security int time_offset =(unsigned)kdc_time-t; DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset)); krb5_set_real_time(gensec_krb5_state->context, t + time_offset + 1, 0); + break; } + if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) { + DEBUG(1,("kinit for %s failed (%s)\n", + cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state), + error_message(ret))); + return NT_STATUS_TIME_DIFFERENCE_AT_DC; + } if (ret) { - DEBUG(1,("kinit failed (%s)\n", + DEBUG(1,("kinit for %s failed (%s)\n", + cli_credentials_get_principal(gensec_security->credentials, gensec_krb5_state), error_message(ret))); return NT_STATUS_WRONG_PASSWORD; } diff --git a/source4/libcli/auth/gensec_ntlmssp.c b/source4/libcli/auth/gensec_ntlmssp.c index 51456d9107..5955904886 100644 --- a/source4/libcli/auth/gensec_ntlmssp.c +++ b/source4/libcli/auth/gensec_ntlmssp.c @@ -109,7 +109,7 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, NT_STATUS_NOT_OK_RETURN(nt_status); nt_status = auth_check_password(gensec_ntlmssp_state->auth_context, gensec_ntlmssp_state, - user_info, &gensec_ntlmssp_state->server_info); + user_info, &gensec_ntlmssp_state->server_info); talloc_free(user_info); NT_STATUS_NOT_OK_RETURN(nt_status); @@ -197,7 +197,7 @@ static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_secur static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security) { struct gensec_ntlmssp_state *gensec_ntlmssp_state; - char *password = NULL; + const char *password = NULL; NTSTATUS nt_status; nt_status = gensec_ntlmssp_start(gensec_security); @@ -228,25 +228,20 @@ static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_secur } nt_status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, - gensec_security->user.domain); + cli_credentials_get_domain(gensec_security->credentials)); NT_STATUS_NOT_OK_RETURN(nt_status); nt_status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, - gensec_security->user.name); + cli_credentials_get_username(gensec_security->credentials)); NT_STATUS_NOT_OK_RETURN(nt_status); - if (gensec_security->user.name) { - nt_status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password); - NT_STATUS_NOT_OK_RETURN(nt_status); - } + password = cli_credentials_get_password(gensec_security->credentials); - if (password) { - nt_status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, password); - NT_STATUS_NOT_OK_RETURN(nt_status); - } + nt_status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, password); + NT_STATUS_NOT_OK_RETURN(nt_status); nt_status = ntlmssp_set_workstation(gensec_ntlmssp_state->ntlmssp_state, - gensec_get_workstation(gensec_security)); + cli_credentials_get_workstation(gensec_security->credentials)); gensec_security->private_data = gensec_ntlmssp_state; diff --git a/source4/libcli/auth/kerberos.h b/source4/libcli/auth/kerberos.h index 9bb6d22eb6..c9b2eae55c 100644 --- a/source4/libcli/auth/kerberos.h +++ b/source4/libcli/auth/kerberos.h @@ -93,5 +93,6 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype); BOOL kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, krb5_enctype enctype2); void kerberos_free_data_contents(krb5_context context, krb5_data *pdata); +krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry); #endif /* HAVE_KRB5 */ diff --git a/source4/libcli/auth/ntlmssp_sign.c b/source4/libcli/auth/ntlmssp_sign.c index 1b391306bc..347a85da77 100644 --- a/source4/libcli/auth/ntlmssp_sign.c +++ b/source4/libcli/auth/ntlmssp_sign.c @@ -3,7 +3,7 @@ * Version 3.0 * NTLMSSP Signing routines * Copyright (C) Luke Kenneth Casson Leighton 1996-2001 - * Copyright (C) Andrew Bartlett 2003 + * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source4/libcli/auth/schannel.c b/source4/libcli/auth/schannel.c new file mode 100644 index 0000000000..3dbf10580b --- /dev/null +++ b/source4/libcli/auth/schannel.c @@ -0,0 +1,268 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc schannel operations + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "librpc/gen_ndr/ndr_schannel.h" +#include "auth/auth.h" +#include "libcli/auth/schannel.h" + +static size_t schannel_sig_size(struct gensec_security *gensec_security) +{ + return 32; +} + +static NTSTATUS schannel_session_key(struct gensec_security *gensec_security, + DATA_BLOB *session_key) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, + const DATA_BLOB in, DATA_BLOB *out) +{ + struct schannel_state *state = gensec_security->private_data; + NTSTATUS status; + struct schannel_bind bind_schannel; + struct schannel_bind_ack bind_schannel_ack; + struct creds_CredentialState *creds; + + const char *workstation; + const char *domain; + *out = data_blob(NULL, 0); + + switch (gensec_security->gensec_role) { + case GENSEC_CLIENT: + if (state->state != SCHANNEL_STATE_START) { + /* we could parse the bind ack, but we don't know what it is yet */ + return NT_STATUS_OK; + } + + state->creds = talloc_reference(state, cli_credentials_get_netlogon_creds(gensec_security->credentials)); + + bind_schannel.unknown1 = 0; +#if 0 + /* to support this we'd need to have access to the full domain name */ + bind_schannel.bind_type = 23; + bind_schannel.u.info23.domain = cli_credentials_get_domain(gensec_security->credentials); + bind_schannel.u.info23.account_name = cli_credentials_get_username(gensec_security->credentials); + bind_schannel.u.info23.dnsdomain = str_format_nbt_domain(out_mem_ctx, fulldomainname); + bind_schannel.u.info23.workstation = str_format_nbt_domain(out_mem_ctx, cli_credentials_get_workstation(gensec_security->credentials)); +#else + bind_schannel.bind_type = 3; + bind_schannel.u.info3.domain = cli_credentials_get_domain(gensec_security->credentials); + bind_schannel.u.info3.workstation = cli_credentials_get_workstation(gensec_security->credentials); +#endif + + status = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, + (ndr_push_flags_fn_t)ndr_push_schannel_bind); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not create schannel bind: %s\n", + nt_errstr(status))); + return status; + } + + state->state = SCHANNEL_STATE_UPDATE_1; + + return NT_STATUS_MORE_PROCESSING_REQUIRED; + case GENSEC_SERVER: + + if (state->state != SCHANNEL_STATE_START) { + /* no third leg on this protocol */ + return NT_STATUS_INVALID_PARAMETER; + } + + /* parse the schannel startup blob */ + status = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel, + (ndr_pull_flags_fn_t)ndr_pull_schannel_bind); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (bind_schannel.bind_type == 23) { + workstation = bind_schannel.u.info23.workstation; + domain = bind_schannel.u.info23.domain; + } else { + workstation = bind_schannel.u.info3.workstation; + domain = bind_schannel.u.info3.domain; + } + + /* pull the session key for this client */ + status = schannel_fetch_session_key(out_mem_ctx, workstation, + domain, &creds); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", + workstation, nt_errstr(status))); + return status; + } + + state->creds = talloc_reference(state, creds); + + bind_schannel_ack.unknown1 = 1; + bind_schannel_ack.unknown2 = 0; + bind_schannel_ack.unknown3 = 0x6c0000; + + status = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack, + (ndr_push_flags_fn_t)ndr_push_schannel_bind_ack); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", + workstation, nt_errstr(status))); + return status; + } + + state->state = SCHANNEL_STATE_UPDATE_1; + + return NT_STATUS_OK; + } + return NT_STATUS_INVALID_PARAMETER; +} + +/** + * Return the struct creds_CredentialState. + * + * Make sure not to call this unless gensec is using schannel... + */ + +NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + struct creds_CredentialState **creds) +{ + struct schannel_state *state = gensec_security->private_data; + + *creds = talloc_reference(mem_ctx, state->creds); + if (!*creds) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + + +/** + * Return the credentials of a logged on user, including session keys + * etc. + * + * Only valid after a successful authentication + * + * May only be called once per authentication. + * + */ + +static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, + struct auth_session_info **session_info) +{ + (*session_info) = talloc(gensec_security, struct auth_session_info); + NT_STATUS_HAVE_NO_MEMORY(*session_info); + + ZERO_STRUCTP(*session_info); + + return NT_STATUS_OK; +} + +static NTSTATUS schannel_start(struct gensec_security *gensec_security) +{ + struct schannel_state *state; + + state = talloc(gensec_security, struct schannel_state); + if (!state) { + return NT_STATUS_NO_MEMORY; + } + + state->state = SCHANNEL_STATE_START; + state->seq_num = 0; + gensec_security->private_data = state; + + return NT_STATUS_OK; +} + +static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) +{ + NTSTATUS status; + struct schannel_state *state; + + status = schannel_start(gensec_security); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + state = gensec_security->private_data; + state->initiator = False; + + return NT_STATUS_OK; +} + +static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) +{ + NTSTATUS status; + struct schannel_state *state; + + status = schannel_start(gensec_security); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + state = gensec_security->private_data; + state->initiator = True; + + return NT_STATUS_OK; +} + + +static BOOL schannel_have_feature(struct gensec_security *gensec_security, + uint32_t feature) +{ + if (feature & (GENSEC_FEATURE_SIGN | + GENSEC_FEATURE_SEAL)) { + return True; + } + return False; +} + + +static const struct gensec_security_ops gensec_schannel_security_ops = { + .name = "schannel", + .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, + .client_start = schannel_client_start, + .server_start = schannel_server_start, + .update = schannel_update, + .seal_packet = schannel_seal_packet, + .sign_packet = schannel_sign_packet, + .check_packet = schannel_check_packet, + .unseal_packet = schannel_unseal_packet, + .session_key = schannel_session_key, + .session_info = schannel_session_info, + .sig_size = schannel_sig_size, + .have_feature = schannel_have_feature, + .enabled = True +}; + +NTSTATUS gensec_schannel_init(void) +{ + NTSTATUS ret; + ret = gensec_register(&gensec_schannel_security_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' gensec backend!\n", + gensec_schannel_security_ops.name)); + return ret; + } + + return ret; +} diff --git a/source4/libcli/auth/schannel_sign.c b/source4/libcli/auth/schannel_sign.c index d582ff2dd0..3b493bd0d3 100644 --- a/source4/libcli/auth/schannel_sign.c +++ b/source4/libcli/auth/schannel_sign.c @@ -4,6 +4,7 @@ schannel library code Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,12 +23,9 @@ #include "includes.h" #include "lib/crypto/crypto.h" - -struct schannel_state { - uint8_t session_key[16]; - uint32_t seq_num; - BOOL initiator; -}; +#include "libcli/auth/schannel.h" +#include "libcli/auth/gensec.h" +#include "libcli/auth/credentials.h" #define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } #define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } @@ -43,7 +41,7 @@ static void netsec_deal_with_seq_num(struct schannel_state *state, uint8_t sequence_key[16]; uint8_t digest1[16]; - hmac_md5(state->session_key, zeros, sizeof(zeros), digest1); + hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); hmac_md5(digest1, packet_digest, 8, sequence_key); arcfour_crypt(seq_num, sequence_key, 8); @@ -102,11 +100,14 @@ static void schannel_digest(const uint8_t sess_key[16], /* unseal a packet */ -NTSTATUS schannel_unseal_packet(struct schannel_state *state, +NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { + struct schannel_state *state = gensec_security->private_data; + uint8_t digest_final[16]; uint8_t confounder[8]; uint8_t seq_num[8]; @@ -122,11 +123,11 @@ NTSTATUS schannel_unseal_packet(struct schannel_state *state, RSIVAL(seq_num, 0, state->seq_num); SIVAL(seq_num, 4, state->initiator?0:0x80); - netsec_get_sealing_key(state->session_key, seq_num, sealing_key); + netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key); arcfour_crypt(confounder, sealing_key, 8); arcfour_crypt(data, sealing_key, length); - schannel_digest(state->session_key, + schannel_digest(state->creds->session_key, netsec_sig, confounder, data, length, digest_final); @@ -150,10 +151,14 @@ NTSTATUS schannel_unseal_packet(struct schannel_state *state, /* check the signature on a packet */ -NTSTATUS schannel_check_packet(struct schannel_state *state, +NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, const DATA_BLOB *sig) { + struct schannel_state *state = gensec_security->private_data; + uint8_t digest_final[16]; uint8_t seq_num[8]; static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE; @@ -167,9 +172,9 @@ NTSTATUS schannel_check_packet(struct schannel_state *state, SIVAL(seq_num, 4, state->initiator?0:0x80); dump_data_pw("seq_num:\n", seq_num, 8); - dump_data_pw("sess_key:\n", state->session_key, 16); + dump_data_pw("sess_key:\n", state->creds->session_key, 16); - schannel_digest(state->session_key, + schannel_digest(state->creds->session_key, netsec_sig, NULL, data, length, digest_final); @@ -194,11 +199,14 @@ NTSTATUS schannel_check_packet(struct schannel_state *state, /* seal a packet */ -NTSTATUS schannel_seal_packet(struct schannel_state *state, +NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { + struct schannel_state *state = gensec_security->private_data; + uint8_t digest_final[16]; uint8_t confounder[8]; uint8_t seq_num[8]; @@ -210,11 +218,11 @@ NTSTATUS schannel_seal_packet(struct schannel_state *state, RSIVAL(seq_num, 0, state->seq_num); SIVAL(seq_num, 4, state->initiator?0x80:0); - schannel_digest(state->session_key, + schannel_digest(state->creds->session_key, netsec_sig, confounder, data, length, digest_final); - netsec_get_sealing_key(state->session_key, seq_num, sealing_key); + netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key); arcfour_crypt(confounder, sealing_key, 8); arcfour_crypt(data, sealing_key, length); @@ -239,11 +247,14 @@ NTSTATUS schannel_seal_packet(struct schannel_state *state, /* sign a packet */ -NTSTATUS schannel_sign_packet(struct schannel_state *state, +NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { + struct schannel_state *state = gensec_security->private_data; + uint8_t digest_final[16]; uint8_t seq_num[8]; static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE; @@ -251,7 +262,7 @@ NTSTATUS schannel_sign_packet(struct schannel_state *state, RSIVAL(seq_num, 0, state->seq_num); SIVAL(seq_num, 4, state->initiator?0x80:0); - schannel_digest(state->session_key, + schannel_digest(state->creds->session_key, netsec_sig, NULL, data, length, digest_final); @@ -271,23 +282,3 @@ NTSTATUS schannel_sign_packet(struct schannel_state *state, return NT_STATUS_OK; } - -/* - create an schannel context state -*/ -NTSTATUS schannel_start(TALLOC_CTX *mem_ctx, - struct schannel_state **state, - const uint8_t session_key[16], - BOOL initiator) -{ - (*state) = talloc(mem_ctx, struct schannel_state); - if (!(*state)) { - return NT_STATUS_NO_MEMORY; - } - - memcpy((*state)->session_key, session_key, 16); - (*state)->initiator = initiator; - (*state)->seq_num = 0; - - return NT_STATUS_OK; -} diff --git a/source4/libcli/auth/spnego.c b/source4/libcli/auth/spnego.c index 3980767165..f5a091cd78 100644 --- a/source4/libcli/auth/spnego.c +++ b/source4/libcli/auth/spnego.c @@ -610,7 +610,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA spnego_out.negTokenInit.mechTypes = mechlist; spnego_out.negTokenInit.reqFlags = 0; spnego_out.negTokenInit.mechListMIC - = data_blob_string_const(gensec_get_target_principal(gensec_security)); + = data_blob_string_const(talloc_asprintf(out_mem_ctx, "%s$@%s", lp_netbios_name(), lp_realm())); spnego_out.negTokenInit.mechToken = unwrapped_out; if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) { @@ -657,13 +657,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA } if (spnego.negTokenInit.targetPrincipal) { - DEBUG(5, ("Server claims it's principal name is %s\n", spnego.negTokenInit.targetPrincipal)); - nt_status = gensec_set_target_principal(gensec_security, - spnego.negTokenInit.targetPrincipal); - if (!NT_STATUS_IS_OK(nt_status)) { - spnego_free_data(&spnego); - return nt_status; - } + DEBUG(5, ("Server claims it's principal name is %s (ignored)\n", spnego.negTokenInit.targetPrincipal)); } nt_status = gensec_spnego_client_parse_negTokenInit(gensec_security, diff --git a/source4/libcli/cliconnect.c b/source4/libcli/cliconnect.c index 7459460137..53a97da168 100644 --- a/source4/libcli/cliconnect.c +++ b/source4/libcli/cliconnect.c @@ -63,7 +63,7 @@ NTSTATUS smbcli_negprot(struct smbcli_state *cli) /* wrapper around smb_raw_session_setup() */ NTSTATUS smbcli_session_setup(struct smbcli_state *cli, - struct cli_credentials *credentials) + struct cli_credentials *credentials) { struct smb_composite_sesssetup setup; NTSTATUS status; @@ -77,15 +77,8 @@ NTSTATUS smbcli_session_setup(struct smbcli_state *cli, setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; - if (cli_credentials_is_anonymous(credentials)) { - if (cli->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) { - setup.in.password = cli_credentials_get_password(credentials); - } else { - setup.in.password = NULL; - } - setup.in.user = cli_credentials_get_username(credentials); - setup.in.domain = cli_credentials_get_domain(credentials); - } + setup.in.credentials = credentials; + setup.in.workgroup = lp_workgroup(); status = smb_composite_sesssetup(cli->session, &setup); @@ -144,7 +137,6 @@ NTSTATUS smbcli_send_tconX(struct smbcli_state *cli, const char *sharename, */ NTSTATUS smbcli_full_connection(TALLOC_CTX *parent_ctx, struct smbcli_state **ret_cli, - const char *myname, const char *host, const char *sharename, const char *devtype, @@ -159,7 +151,7 @@ NTSTATUS smbcli_full_connection(TALLOC_CTX *parent_ctx, *ret_cli = NULL; status = smbcli_tree_full_connection(parent_ctx, - &tree, myname, host, 0, sharename, devtype, + &tree, host, 0, sharename, devtype, credentials); if (!NT_STATUS_IS_OK(status)) { goto done; diff --git a/source4/libcli/composite/composite.h b/source4/libcli/composite/composite.h index bf0fb9ed48..18922127ee 100644 --- a/source4/libcli/composite/composite.h +++ b/source4/libcli/composite/composite.h @@ -70,12 +70,10 @@ struct smb_composite_fetchfile { const char *dest_host; int port; const char *called_name; - const char *calling_name; const char *service; const char *service_type; - const char *user; - const char *domain; - const char *password; + struct cli_credentials *credentials; + const char *workgroup; const char *filename; } in; struct { @@ -111,12 +109,10 @@ struct smb_composite_connect { const char *dest_host; int port; const char *called_name; - const char *calling_name; const char *service; const char *service_type; - const char *user; - const char *domain; - const char *password; + struct cli_credentials *credentials; + const char *workgroup; } in; struct { struct smbcli_tree *tree; @@ -132,9 +128,8 @@ struct smb_composite_sesssetup { struct { uint32_t sesskey; uint32_t capabilities; - const char *password; - const char *user; - const char *domain; + struct cli_credentials *credentials; + const char *workgroup; } in; struct { uint16_t vuid; diff --git a/source4/libcli/composite/connect.c b/source4/libcli/composite/connect.c index 5f5275f7e6..0da71df992 100644 --- a/source4/libcli/composite/connect.c +++ b/source4/libcli/composite/connect.c @@ -166,9 +166,8 @@ static NTSTATUS connect_negprot(struct composite_context *c, /* prepare a session setup to establish a security context */ state->io_setup->in.sesskey = state->transport->negotiate.sesskey; state->io_setup->in.capabilities = state->transport->negotiate.capabilities; - state->io_setup->in.domain = io->in.domain; - state->io_setup->in.user = io->in.user; - state->io_setup->in.password = io->in.password; + state->io_setup->in.credentials = io->in.credentials; + state->io_setup->in.workgroup = io->in.workgroup; state->creq = smb_composite_sesssetup_send(state->session, state->io_setup); NT_STATUS_HAVE_NO_MEMORY(state->creq); @@ -214,7 +213,7 @@ static NTSTATUS connect_socket(struct composite_context *c, state->transport = smbcli_transport_init(state->sock, state, True); NT_STATUS_HAVE_NO_MEMORY(state->transport); - calling.name = io->in.calling_name; + calling.name = cli_credentials_get_workstation(io->in.credentials); calling.type = NBT_NAME_CLIENT; calling.scope = NULL; @@ -254,7 +253,7 @@ static NTSTATUS connect_resolve(struct composite_context *c, status = resolve_name_recv(state->creq, state, &address); NT_STATUS_NOT_OK_RETURN(status); - state->creq = smbcli_sock_connect_send(state->sock, address, state->io->in.port); + state->creq = smbcli_sock_connect_send(state->sock, address, state->io->in.port, io->in.dest_host); NT_STATUS_HAVE_NO_MEMORY(state->creq); state->stage = CONNECT_SOCKET; diff --git a/source4/libcli/composite/fetchfile.c b/source4/libcli/composite/fetchfile.c index 2bf6ef9023..fb9226985e 100644 --- a/source4/libcli/composite/fetchfile.c +++ b/source4/libcli/composite/fetchfile.c @@ -140,12 +140,10 @@ struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetc state->connect->in.dest_host = io->in.dest_host; state->connect->in.port = io->in.port; state->connect->in.called_name = io->in.called_name; - state->connect->in.calling_name = io->in.calling_name; state->connect->in.service = io->in.service; state->connect->in.service_type = io->in.service_type; - state->connect->in.user = io->in.user; - state->connect->in.domain = io->in.domain; - state->connect->in.password = io->in.password; + state->connect->in.credentials = io->in.credentials; + state->connect->in.workgroup = io->in.workgroup; state->req = smb_composite_connect_send(state->connect, event_ctx); if (state->req == NULL) goto failed; diff --git a/source4/libcli/composite/sesssetup.c b/source4/libcli/composite/sesssetup.c index 07c718b05b..31ca5caed7 100644 --- a/source4/libcli/composite/sesssetup.c +++ b/source4/libcli/composite/sesssetup.c @@ -142,7 +142,7 @@ static void request_handler(struct smbcli_request *req) } /* enforce the local signing required flag */ - if (NT_STATUS_IS_OK(c->status) && state->io->in.user && state->io->in.user[0]) { + if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) { if (!session->transport->negotiate.sign_info.doing_signing && session->transport->negotiate.sign_info.mandatory_signing) { DEBUG(0, ("SMB signing required, but server does not support it\n")); @@ -169,6 +169,7 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c, struct smb_composite_sesssetup *io) { struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state); + const char *password = cli_credentials_get_password(io->in.credentials); state->setup.nt1.level = RAW_SESSSETUP_NT1; state->setup.nt1.in.bufsize = session->transport->options.max_xmit; @@ -176,23 +177,23 @@ static struct smbcli_request *session_setup_nt1(struct composite_context *c, state->setup.nt1.in.vc_num = 1; state->setup.nt1.in.sesskey = io->in.sesskey; state->setup.nt1.in.capabilities = io->in.capabilities; - state->setup.nt1.in.domain = io->in.domain; - state->setup.nt1.in.user = io->in.user; state->setup.nt1.in.os = "Unix"; state->setup.nt1.in.lanman = "Samba"; - if (!io->in.password) { + state->setup.old.in.domain = cli_credentials_get_domain(io->in.credentials); + state->setup.old.in.user = cli_credentials_get_username(io->in.credentials); + if (!password) { state->setup.nt1.in.password1 = data_blob(NULL, 0); state->setup.nt1.in.password2 = data_blob(NULL, 0); } else if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { - state->setup.nt1.in.password1 = lanman_blob(state, io->in.password, + state->setup.nt1.in.password1 = lanman_blob(state, password, session->transport->negotiate.secblob); - state->setup.nt1.in.password2 = nt_blob(state, io->in.password, + state->setup.nt1.in.password2 = nt_blob(state, password, session->transport->negotiate.secblob); - use_nt1_session_keys(session, io->in.password, &state->setup.nt1.in.password2); + use_nt1_session_keys(session, password, &state->setup.nt1.in.password2); } else { - state->setup.nt1.in.password1 = data_blob_talloc(state, io->in.password, strlen(io->in.password)); + state->setup.nt1.in.password1 = data_blob_talloc(state, password, strlen(password)); state->setup.nt1.in.password2 = data_blob(NULL, 0); } @@ -208,26 +209,27 @@ static struct smbcli_request *session_setup_old(struct composite_context *c, struct smb_composite_sesssetup *io) { struct sesssetup_state *state = talloc_get_type(c->private, struct sesssetup_state); + const char *password = cli_credentials_get_password(io->in.credentials); state->setup.old.level = RAW_SESSSETUP_OLD; state->setup.old.in.bufsize = session->transport->options.max_xmit; state->setup.old.in.mpx_max = session->transport->options.max_mux; state->setup.old.in.vc_num = 1; state->setup.old.in.sesskey = io->in.sesskey; - state->setup.old.in.domain = io->in.domain; - state->setup.old.in.user = io->in.user; + state->setup.old.in.domain = cli_credentials_get_domain(io->in.credentials); + state->setup.old.in.user = cli_credentials_get_username(io->in.credentials); state->setup.old.in.os = "Unix"; state->setup.old.in.lanman = "Samba"; - if (!io->in.password) { + if (!password) { state->setup.old.in.password = data_blob(NULL, 0); } else if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { - state->setup.old.in.password = lanman_blob(state, io->in.password, + state->setup.old.in.password = lanman_blob(state, password, session->transport->negotiate.secblob); } else { state->setup.old.in.password = data_blob_talloc(state, - io->in.password, - strlen(io->in.password)); + password, + strlen(password)); } return smb_raw_session_setup_send(session, &state->setup); @@ -253,9 +255,10 @@ static struct smbcli_request *session_setup_spnego(struct composite_context *c, state->setup.spnego.in.vc_num = 1; state->setup.spnego.in.sesskey = io->in.sesskey; state->setup.spnego.in.capabilities = io->in.capabilities; - state->setup.spnego.in.domain = io->in.domain; state->setup.spnego.in.os = "Unix"; state->setup.spnego.in.lanman = "Samba"; + state->setup.spnego.in.workgroup = io->in.workgroup; + state->setup.spnego.out.vuid = session->vuid; smbcli_temp_set_signing(session->transport); @@ -268,30 +271,23 @@ static struct smbcli_request *session_setup_spnego(struct composite_context *c, gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY); - status = gensec_set_domain(session->gensec, io->in.domain); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", - io->in.domain, nt_errstr(status))); - return NULL; - } - - status = gensec_set_username(session->gensec, io->in.user); + status = gensec_set_credentials(session->gensec, io->in.credentials); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", - io->in.user, nt_errstr(status))); + DEBUG(1, ("Failed to start set GENSEC client credentails: %s\n", + nt_errstr(status))); return NULL; } - status = gensec_set_password(session->gensec, io->in.password); + status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client password: %s\n", + DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", nt_errstr(status))); return NULL; } - status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname); + status = gensec_set_target_service(session->gensec, "cifs"); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", + DEBUG(1, ("Failed to start set GENSEC target service: %s\n", nt_errstr(status))); return NULL; } diff --git a/source4/libcli/ldap/ldap.h b/source4/libcli/ldap/ldap.h index 3e51e4f60f..710c022a3c 100644 --- a/source4/libcli/ldap/ldap.h +++ b/source4/libcli/ldap/ldap.h @@ -337,11 +337,11 @@ struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid, struct ldap_message *ldap_transaction(struct ldap_connection *conn, struct ldap_message *request); int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password); -int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password); +int ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *creds); struct ldap_connection *ldap_setup_connection(TALLOC_CTX *mem_ctx, const char *url, const char *userdn, const char *password); struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, const char *url, - const char *username, const char *domain, const char *password); + struct cli_credentials *creds); BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid, const struct timeval *endtime); BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg, diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c index e3904c7a6b..71b57e116e 100644 --- a/source4/libcli/ldap/ldap_client.c +++ b/source4/libcli/ldap/ldap_client.c @@ -605,7 +605,7 @@ int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const cha return result; } -int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password) +int ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *creds) { NTSTATUS status; TALLOC_CTX *mem_ctx = NULL; @@ -626,23 +626,9 @@ int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const cha gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL); - status = gensec_set_domain(conn->gensec, domain); + status = gensec_set_credentials(conn->gensec, creds); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", - domain, nt_errstr(status))); - goto done; - } - - status = gensec_set_username(conn->gensec, username); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", - username, nt_errstr(status))); - goto done; - } - - status = gensec_set_password(conn->gensec, password); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client password: %s\n", + DEBUG(1, ("Failed to start set GENSEC creds: %s\n", nt_errstr(status))); goto done; } @@ -739,8 +725,9 @@ struct ldap_connection *ldap_setup_connection(TALLOC_CTX *mem_ctx, const char *u return conn; } -struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, const char *url, - const char *username, const char *domain, const char *password) +struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, + const char *url, + struct cli_credentials *creds) { struct ldap_connection *conn; int result; @@ -750,7 +737,7 @@ struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, con return NULL; } - result = ldap_bind_sasl(conn, username, domain, password); + result = ldap_bind_sasl(conn, creds); if (result != LDAP_SUCCESS) { talloc_free(conn); return NULL; diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c index 5f75701871..3156624589 100644 --- a/source4/libcli/raw/clisession.c +++ b/source4/libcli/raw/clisession.c @@ -134,7 +134,7 @@ struct smbcli_request *smb_raw_session_setup_send(struct smbcli_session *session smbcli_req_append_blob(req, &parms->spnego.in.secblob); smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE); smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE); - smbcli_req_append_string(req, parms->spnego.in.domain, STR_TERMINATE); + smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE); break; } @@ -210,7 +210,7 @@ NTSTATUS smb_raw_session_setup_recv(struct smbcli_request *req, p += parms->spnego.out.secblob.length; p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE); p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE); - p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.domain, p, -1, STR_TERMINATE); + p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE); break; } diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c index cbb479ca1a..7cb7040131 100644 --- a/source4/libcli/raw/clisocket.c +++ b/source4/libcli/raw/clisocket.c @@ -34,7 +34,8 @@ struct clisocket_connect { int port_num; int *iports; struct smbcli_socket *sock; - const char *dest_host; + const char *dest_host_addr; + const char *dest_hostname; }; @@ -83,7 +84,7 @@ static void smbcli_sock_connect_handler(struct event_context *ev, struct fd_even c->status = socket_connect_complete(conn->sock->sock, 0); if (NT_STATUS_IS_OK(c->status)) { socket_set_option(conn->sock->sock, lp_socket_options(), NULL); - conn->sock->hostname = talloc_strdup(conn->sock, conn->dest_host); + conn->sock->hostname = talloc_strdup(conn->sock, conn->dest_hostname); c->state = SMBCLI_REQUEST_DONE; if (c->async.fn) { c->async.fn(c); @@ -95,7 +96,7 @@ static void smbcli_sock_connect_handler(struct event_context *ev, struct fd_even for (i=conn->port_num+1;conn->iports[i];i++) { conn->port_num = i; c->status = smbcli_sock_connect_one(conn->sock, - conn->dest_host, + conn->dest_host_addr, conn->iports[i], c); if (NT_STATUS_IS_OK(c->status) || NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { @@ -151,7 +152,8 @@ static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock, this is the async send side of the interface */ struct composite_context *smbcli_sock_connect_send(struct smbcli_socket *sock, - const char *host_addr, int port) + const char *host_addr, int port, + const char *host_name) { struct composite_context *c; struct clisocket_connect *conn; @@ -184,8 +186,11 @@ struct composite_context *smbcli_sock_connect_send(struct smbcli_socket *sock, conn->iports[1] = 0; } - conn->dest_host = talloc_strdup(c, host_addr); - if (conn->dest_host == NULL) goto failed; + conn->dest_host_addr = talloc_strdup(c, host_addr); + if (conn->dest_host_addr == NULL) goto failed; + + conn->dest_hostname = talloc_strdup(c, host_name); + if (conn->dest_hostname == NULL) goto failed; c->private = conn; c->state = SMBCLI_REQUEST_SEND; @@ -196,7 +201,7 @@ struct composite_context *smbcli_sock_connect_send(struct smbcli_socket *sock, conn->port_num = i; conn->sock->port = conn->iports[i]; c->status = smbcli_sock_connect_one(sock, - conn->dest_host, + conn->dest_host_addr, conn->iports[i], c); if (NT_STATUS_IS_OK(c->status) || NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { @@ -229,11 +234,12 @@ NTSTATUS smbcli_sock_connect_recv(struct composite_context *c) sync version of the function */ -NTSTATUS smbcli_sock_connect(struct smbcli_socket *sock, const char *host_addr, int port) +NTSTATUS smbcli_sock_connect(struct smbcli_socket *sock, const char *host_addr, int port, + const char *host_name) { struct composite_context *c; - c = smbcli_sock_connect_send(sock, host_addr, port); + c = smbcli_sock_connect_send(sock, host_addr, port, host_name); if (c == NULL) { return NT_STATUS_NO_MEMORY; } @@ -337,9 +343,7 @@ BOOL smbcli_sock_connect_byname(struct smbcli_socket *sock, const char *host, in return False; } - sock->hostname = name; - - status = smbcli_sock_connect(sock, address, port); + status = smbcli_sock_connect(sock, address, port, name); return NT_STATUS_IS_OK(status); } diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c index f333cf7a98..87c2dbba7c 100644 --- a/source4/libcli/raw/clitree.c +++ b/source4/libcli/raw/clitree.c @@ -164,7 +164,6 @@ NTSTATUS smb_tree_disconnect(struct smbcli_tree *tree) */ NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx, struct smbcli_tree **ret_tree, - const char *my_name, const char *dest_host, int port, const char *service, const char *service_type, struct cli_credentials *credentials) @@ -175,12 +174,10 @@ NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx, io.in.dest_host = dest_host; io.in.port = port; io.in.called_name = strupper_talloc(parent_ctx, dest_host); - io.in.calling_name = strupper_talloc(parent_ctx, my_name); io.in.service = service; io.in.service_type = service_type; - io.in.domain = cli_credentials_get_domain(credentials); - io.in.user = cli_credentials_get_username(credentials); - io.in.password = cli_credentials_get_password(credentials); + io.in.credentials = credentials; + io.in.workgroup = lp_workgroup(); status = smb_composite_connect(&io, parent_ctx); if (NT_STATUS_IS_OK(status)) { diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk index 70fafdaf3b..f6b05a41b5 100644 --- a/source4/librpc/config.mk +++ b/source4/librpc/config.mk @@ -20,9 +20,9 @@ INIT_OBJ_FILES = \ librpc/rpc/dcerpc.o ADD_OBJ_FILES = \ librpc/rpc/dcerpc_auth.o \ + librpc/rpc/dcerpc_schannel.o \ librpc/rpc/dcerpc_util.o \ librpc/rpc/dcerpc_error.o \ - librpc/rpc/dcerpc_schannel.o \ librpc/rpc/dcerpc_smb.o \ librpc/rpc/dcerpc_sock.o REQUIRED_SUBSYSTEMS = SOCKET diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index c5bfe150bd..ae0a89910e 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -4,7 +4,7 @@ Generic Authentication Interface Copyright (C) Andrew Tridgell 2003 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 Copyright (C) Stefan Metzmacher 2004 This program is free software; you can redistribute it and/or modify @@ -159,34 +159,10 @@ NTSTATUS dcerpc_bind_auth_password(struct dcerpc_pipe *p, return status; } - status = gensec_set_workstation(p->conn->security_state.generic_state, - cli_credentials_get_workstation(credentials)); + status = gensec_set_credentials(p->conn->security_state.generic_state, + credentials); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client workstation name to %s: %s\n", - cli_credentials_get_workstation(credentials), nt_errstr(status))); - return status; - } - - status = gensec_set_domain(p->conn->security_state.generic_state, - cli_credentials_get_domain(credentials)); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", - cli_credentials_get_domain(credentials), nt_errstr(status))); - return status; - } - - status = gensec_set_username(p->conn->security_state.generic_state, - cli_credentials_get_username(credentials)); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", - cli_credentials_get_username(credentials), nt_errstr(status))); - return status; - } - - status = gensec_set_password(p->conn->security_state.generic_state, - cli_credentials_get_password(credentials)); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start set GENSEC client password: %s\n", + DEBUG(1, ("Failed to start set GENSEC client credentails: %s\n", nt_errstr(status))); return status; } diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 77453cf476..3ae2624ff9 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -4,7 +4,8 @@ dcerpc schannel operations Copyright (C) Andrew Tridgell 2004 - + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -24,281 +25,13 @@ #include "librpc/gen_ndr/ndr_schannel.h" #include "auth/auth.h" -enum schannel_position { - DCERPC_SCHANNEL_STATE_START = 0, - DCERPC_SCHANNEL_STATE_UPDATE_1 -}; - -struct dcerpc_schannel_state { - enum schannel_position state; - struct schannel_state *schannel_state; - struct creds_CredentialState *creds; -}; - -/* - wrappers for the schannel_*() functions - - These will become static again, when we get dynamic registration, and - decrpc_schannel_security_ops come back here. -*/ -static NTSTATUS dcerpc_schannel_unseal_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) -{ - struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; - - return schannel_unseal_packet(dce_schan_state->schannel_state, mem_ctx, data, length, sig); -} - -static NTSTATUS dcerpc_schannel_check_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - const DATA_BLOB *sig) -{ - struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; - - return schannel_check_packet(dce_schan_state->schannel_state, data, length, sig); -} - -static NTSTATUS dcerpc_schannel_seal_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) -{ - struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; - - return schannel_seal_packet(dce_schan_state->schannel_state, mem_ctx, data, length, sig); -} - -static NTSTATUS dcerpc_schannel_sign_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) -{ - struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; - - return schannel_sign_packet(dce_schan_state->schannel_state, mem_ctx, data, length, sig); -} - -static size_t dcerpc_schannel_sig_size(struct gensec_security *gensec_security) -{ - return 32; -} - -static NTSTATUS dcerpc_schannel_session_key(struct gensec_security *gensec_security, - DATA_BLOB *session_key) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, - const DATA_BLOB in, DATA_BLOB *out) -{ - struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; - NTSTATUS status; - struct schannel_bind bind_schannel; - struct schannel_bind_ack bind_schannel_ack; - const char *workstation; - const char *domain; - *out = data_blob(NULL, 0); - - switch (gensec_security->gensec_role) { - case GENSEC_CLIENT: - if (dce_schan_state->state != DCERPC_SCHANNEL_STATE_START) { - /* we could parse the bind ack, but we don't know what it is yet */ - return NT_STATUS_OK; - } - - status = schannel_start(dce_schan_state, - &dce_schan_state->schannel_state, - dce_schan_state->creds->session_key, - True); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start schannel client\n")); - return status; - } - talloc_steal(dce_schan_state, dce_schan_state->schannel_state); - - bind_schannel.unknown1 = 0; -#if 0 - /* to support this we'd need to have access to the full domain name */ - bind_schannel.bind_type = 23; - bind_schannel.u.info23.domain = gensec_security->user.domain; - bind_schannel.u.info23.account_name = gensec_security->user.name; - bind_schannel.u.info23.dnsdomain = str_format_nbt_domain(out_mem_ctx, fulldomainname); - bind_schannel.u.info23.workstation = str_format_nbt_domain(out_mem_ctx, gensec_get_workstation(gensec_security)); -#else - bind_schannel.bind_type = 3; - bind_schannel.u.info3.domain = gensec_security->user.domain; - bind_schannel.u.info3.workstation = gensec_get_workstation(gensec_security); -#endif - - status = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, - (ndr_push_flags_fn_t)ndr_push_schannel_bind); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not create schannel bind: %s\n", - nt_errstr(status))); - return status; - } - - dce_schan_state->state = DCERPC_SCHANNEL_STATE_UPDATE_1; - - return NT_STATUS_MORE_PROCESSING_REQUIRED; - case GENSEC_SERVER: - - if (dce_schan_state->state != DCERPC_SCHANNEL_STATE_START) { - /* no third leg on this protocol */ - return NT_STATUS_INVALID_PARAMETER; - } - - /* parse the schannel startup blob */ - status = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel, - (ndr_pull_flags_fn_t)ndr_pull_schannel_bind); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (bind_schannel.bind_type == 23) { - workstation = bind_schannel.u.info23.workstation; - domain = bind_schannel.u.info23.domain; - } else { - workstation = bind_schannel.u.info3.workstation; - domain = bind_schannel.u.info3.domain; - } - - /* pull the session key for this client */ - status = schannel_fetch_session_key(out_mem_ctx, workstation, - domain, &dce_schan_state->creds); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", - workstation, nt_errstr(status))); - return status; - } - - /* start up the schannel server code */ - status = schannel_start(dce_schan_state, - &dce_schan_state->schannel_state, - dce_schan_state->creds->session_key, False); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not initialise schannel state from client %s: %s\n", - workstation, nt_errstr(status))); - return status; - } - talloc_steal(dce_schan_state, dce_schan_state->schannel_state); - - bind_schannel_ack.unknown1 = 1; - bind_schannel_ack.unknown2 = 0; - bind_schannel_ack.unknown3 = 0x6c0000; - - status = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack, - (ndr_push_flags_fn_t)ndr_push_schannel_bind_ack); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", - workstation, nt_errstr(status))); - return status; - } - - dce_schan_state->state = DCERPC_SCHANNEL_STATE_UPDATE_1; - - return NT_STATUS_OK; - } - return NT_STATUS_INVALID_PARAMETER; -} - -/** - * Return the credentials of a logged on user, including session keys - * etc. - * - * Only valid after a successful authentication - * - * May only be called once per authentication. - * - */ - -NTSTATUS dcerpc_schannel_session_info(struct gensec_security *gensec_security, - struct auth_session_info **session_info) -{ - (*session_info) = talloc(gensec_security, struct auth_session_info); - NT_STATUS_HAVE_NO_MEMORY(*session_info); - - ZERO_STRUCTP(*session_info); - - return NT_STATUS_OK; -} - -/** - * Return the struct creds_CredentialState. - * - * Make sure not to call this unless gensec is using schannel... - */ - -NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - struct creds_CredentialState **creds) -{ - struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; - - *creds = talloc_reference(mem_ctx, dce_schan_state->creds); - if (!*creds) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - - -static NTSTATUS dcerpc_schannel_start(struct gensec_security *gensec_security) -{ - struct dcerpc_schannel_state *dce_schan_state; - - dce_schan_state = talloc(gensec_security, struct dcerpc_schannel_state); - if (!dce_schan_state) { - return NT_STATUS_NO_MEMORY; - } - - dce_schan_state->state = DCERPC_SCHANNEL_STATE_START; - gensec_security->private_data = dce_schan_state; - - return NT_STATUS_OK; -} - -static NTSTATUS dcerpc_schannel_server_start(struct gensec_security *gensec_security) -{ - NTSTATUS status; - - status = dcerpc_schannel_start(gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} - -static NTSTATUS dcerpc_schannel_client_start(struct gensec_security *gensec_security) -{ - NTSTATUS status; - - status = dcerpc_schannel_start(gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} - - /* get a schannel key using a netlogon challenge on a secondary pipe */ static NTSTATUS dcerpc_schannel_key(TALLOC_CTX *tmp_ctx, struct dcerpc_pipe *p, struct cli_credentials *credentials, - int chan_type, - struct creds_CredentialState *creds) + int chan_type) { NTSTATUS status; struct dcerpc_binding *b; @@ -307,8 +40,12 @@ static NTSTATUS dcerpc_schannel_key(TALLOC_CTX *tmp_ctx, struct netr_ServerAuthenticate2 a; struct netr_Credential credentials1, credentials2, credentials3; struct samr_Password mach_pwd; - const char *workgroup; uint32_t negotiate_flags; + struct creds_CredentialState *creds; + creds = talloc(tmp_ctx, struct creds_CredentialState); + if (!creds) { + return NT_STATUS_NO_MEMORY; + } if (p->conn->flags & DCERPC_SCHANNEL_128) { negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; @@ -316,8 +53,6 @@ static NTSTATUS dcerpc_schannel_key(TALLOC_CTX *tmp_ctx, negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; } - workgroup = cli_credentials_get_domain(credentials); - /* step 1 - establish a netlogon connection, with no authentication */ @@ -369,9 +104,6 @@ static NTSTATUS dcerpc_schannel_key(TALLOC_CTX *tmp_ctx, */ E_md4hash(cli_credentials_get_password(credentials), mach_pwd.hash); creds_client_init(creds, &credentials1, &credentials2, - cli_credentials_get_workstation(credentials), - cli_credentials_get_domain(credentials), - cli_credentials_get_username(credentials), &mach_pwd, &credentials3, negotiate_flags); @@ -393,6 +125,8 @@ static NTSTATUS dcerpc_schannel_key(TALLOC_CTX *tmp_ctx, return NT_STATUS_UNSUCCESSFUL; } + cli_credentials_set_netlogon_creds(credentials, creds); + /* the schannel session key is now in creds.session_key @@ -403,76 +137,6 @@ static NTSTATUS dcerpc_schannel_key(TALLOC_CTX *tmp_ctx, return NT_STATUS_OK; } -/* - do a schannel style bind on a dcerpc pipe. The username is usually - of the form HOSTNAME$ and the password is the domain trust password -*/ -NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p, - const char *uuid, uint_t version, - struct creds_CredentialState *creds) -{ - NTSTATUS status; - struct dcerpc_schannel_state *dce_schan_state; - - status = gensec_client_start(p, &p->conn->security_state.generic_state); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = gensec_set_workstation(p->conn->security_state.generic_state, creds->computer_name); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to set schannel workstation to %s: %s\n", - creds->computer_name, nt_errstr(status))); - talloc_free(p->conn->security_state.generic_state); - p->conn->security_state.generic_state = NULL; - return status; - } - - status = gensec_set_username(p->conn->security_state.generic_state, creds->account_name); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to set schannel username to %s: %s\n", - creds->account_name, nt_errstr(status))); - talloc_free(p->conn->security_state.generic_state); - p->conn->security_state.generic_state = NULL; - return status; - } - - status = gensec_set_domain(p->conn->security_state.generic_state, creds->domain); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to set schannel domain to %s: %s\n", - creds->domain, nt_errstr(status))); - talloc_free(p->conn->security_state.generic_state); - p->conn->security_state.generic_state = NULL; - return status; - } - - status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, - DCERPC_AUTH_TYPE_SCHANNEL, - dcerpc_auth_level(p->conn)); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to start SCHANNEL GENSEC backend: %s\n", nt_errstr(status))); - talloc_free(p->conn->security_state.generic_state); - p->conn->security_state.generic_state = NULL; - return status; - } - - dce_schan_state = p->conn->security_state.generic_state->private_data; - dce_schan_state->creds = talloc_reference(dce_schan_state, creds); - - status = dcerpc_bind_auth(p, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), - uuid, version); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to bind to pipe with SCHANNEL: %s\n", nt_errstr(status))); - talloc_free(p->conn->security_state.generic_state); - p->conn->security_state.generic_state = NULL; - return status; - } - - return NT_STATUS_OK; -} - NTSTATUS dcerpc_bind_auth_schannel(TALLOC_CTX *tmp_ctx, struct dcerpc_pipe *p, const char *uuid, uint_t version, @@ -480,11 +144,6 @@ NTSTATUS dcerpc_bind_auth_schannel(TALLOC_CTX *tmp_ctx, { NTSTATUS status; int chan_type = 0; - struct creds_CredentialState *creds; - creds = talloc(tmp_ctx, struct creds_CredentialState); - if (!creds) { - return NT_STATUS_NO_MEMORY; - } if (p->conn->flags & DCERPC_SCHANNEL_BDC) { chan_type = SEC_CHAN_BDC; @@ -494,58 +153,20 @@ NTSTATUS dcerpc_bind_auth_schannel(TALLOC_CTX *tmp_ctx, chan_type = SEC_CHAN_DOMAIN; } + /* Fills in NETLOGON credentials */ status = dcerpc_schannel_key(tmp_ctx, p, credentials, - chan_type, - creds); + chan_type); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to fetch schannel session key: %s\n", + DEBUG(1, ("Failed to setup credentials for account %s: %s\n", + cli_credentials_get_username(credentials), nt_errstr(status))); return status; } - return dcerpc_bind_auth_schannel_withkey(p, uuid, version, creds); + return dcerpc_bind_auth_password(p, uuid, version, + credentials, DCERPC_AUTH_TYPE_SCHANNEL, + NULL); } -static BOOL dcerpc_schannel_have_feature(struct gensec_security *gensec_security, - uint32_t feature) -{ - if (feature & (GENSEC_FEATURE_SESSION_KEY | - GENSEC_FEATURE_SIGN | - GENSEC_FEATURE_SEAL)) { - return True; - } - return False; -} - - -static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = { - .name = "dcerpc_schannel", - .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, - .client_start = dcerpc_schannel_client_start, - .server_start = dcerpc_schannel_server_start, - .update = dcerpc_schannel_update, - .seal_packet = dcerpc_schannel_seal_packet, - .sign_packet = dcerpc_schannel_sign_packet, - .check_packet = dcerpc_schannel_check_packet, - .unseal_packet = dcerpc_schannel_unseal_packet, - .session_key = dcerpc_schannel_session_key, - .session_info = dcerpc_schannel_session_info, - .sig_size = dcerpc_schannel_sig_size, - .have_feature = dcerpc_schannel_have_feature, - .enabled = True -}; - -NTSTATUS gensec_dcerpc_schannel_init(void) -{ - NTSTATUS ret; - ret = gensec_register(&gensec_dcerpc_schannel_security_ops); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' gensec backend!\n", - gensec_dcerpc_schannel_security_ops.name)); - return ret; - } - - return ret; -} diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 88b1c54cef..ffefd5111c 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2003 Copyright (C) Jelmer Vernooij 2004 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -926,7 +927,12 @@ NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe *p, p->conn->binding_string = dcerpc_binding_string(p, binding); if (!cli_credentials_is_anonymous(credentials) && - (binding->flags & DCERPC_SCHANNEL_ANY)) { + (binding->flags & DCERPC_SCHANNEL_ANY) && + !cli_credentials_get_netlogon_creds(credentials)) { + + /* If we don't already have netlogon credentials for + * the schannel bind, then we have to get these + * first */ status = dcerpc_bind_auth_schannel(tmp_ctx, p, pipe_uuid, pipe_version, credentials); @@ -936,6 +942,8 @@ NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe *p, auth_type = DCERPC_AUTH_TYPE_SPNEGO; } else if (binding->flags & DCERPC_AUTH_KRB5) { auth_type = DCERPC_AUTH_TYPE_KRB5; + } else if (binding->flags & DCERPC_SCHANNEL_ANY) { + auth_type = DCERPC_AUTH_TYPE_SCHANNEL; } else { auth_type = DCERPC_AUTH_TYPE_NTLMSSP; } @@ -974,13 +982,11 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(TALLOC_CTX *tmp_ctx, cli_credentials_set_anonymous(anon_creds); cli_credentials_guess(anon_creds); status = smbcli_full_connection(p->conn, &cli, - cli_credentials_get_workstation(credentials), binding->host, "IPC$", NULL, anon_creds); } else { status = smbcli_full_connection(p->conn, &cli, - cli_credentials_get_workstation(credentials), binding->host, "IPC$", NULL, credentials); diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index 0bb47bab2a..e283e12f24 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -90,6 +90,8 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, struct composite_context *creq; struct fd_event *fde; + struct cli_credentials *credentials; + /* Here we need to determine which server to connect to. * For now we use parametric options, type cifs. * Later we will use security=server and auth_server.c. @@ -116,16 +118,20 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->private_data = private; + credentials = cli_credentials_init(private); + cli_credentials_set_username(credentials, user, CRED_SPECIFIED); + cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); + cli_credentials_set_password(credentials, pass, CRED_SPECIFIED); + cli_credentials_set_workstation(credentials, "vfs_cifs", CRED_SPECIFIED); + /* connect to the server, using the smbd event context */ io.in.dest_host = host; io.in.port = 0; io.in.called_name = host; - io.in.calling_name = "vfs_cifs"; + io.in.credentials = credentials; + io.in.workgroup = lp_workgroup(); io.in.service = remote_share; io.in.service_type = "?????"; - io.in.domain = domain; - io.in.user = user; - io.in.password = pass; creq = smb_composite_connect_send(&io, tcon->smb_conn->connection->event.ctx); status = smb_composite_connect_recv(creq, private); diff --git a/source4/smb_server/reply.c b/source4/smb_server/reply.c index 17dcb8623a..9c8478d6d3 100644 --- a/source4/smb_server/reply.c +++ b/source4/smb_server/reply.c @@ -2106,9 +2106,9 @@ static void reply_sesssetup_spnego(struct smbsrv_request *req) } p += blob_len; - p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE); - p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE); - p += req_pull_string(req, &sess.spnego.in.domain, p, -1, STR_TERMINATE); + p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE); + p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE); + p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE); /* call the generic handler */ status = sesssetup_backend(req, &sess); @@ -2134,9 +2134,9 @@ static void reply_sesssetup_spnego(struct smbsrv_request *req) SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid); memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length); - req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE); - req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE); - req_push_str(req, NULL, sess.spnego.out.domain, -1, STR_TERMINATE); + req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE); + req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE); + req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE); chain_reply(req); } diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c index dc3a60874a..0f0dcb837e 100644 --- a/source4/smb_server/sesssetup.c +++ b/source4/smb_server/sesssetup.c @@ -296,7 +296,7 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup sesssetup_common_strings(req, &sess->spnego.out.os, &sess->spnego.out.lanman, - &sess->spnego.out.domain); + &sess->spnego.out.workgroup); return status; } diff --git a/source4/torture/basic/secleak.c b/source4/torture/basic/secleak.c index 31c23ff5f7..50d5c40d07 100644 --- a/source4/torture/basic/secleak.c +++ b/source4/torture/basic/secleak.c @@ -34,9 +34,13 @@ static BOOL try_failed_login(struct smbcli_state *cli) session = smbcli_session_init(cli->transport, cli, False); setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; - setup.in.password = "INVALID-PASSWORD"; - setup.in.user = "INVALID-USERNAME"; - setup.in.domain = "INVALID-DOMAIN"; + setup.in.workgroup = lp_workgroup(); + + setup.in.credentials = cli_credentials_init(NULL); + cli_credentials_set_conf(setup.in.credentials); + cli_credentials_set_domain(setup.in.credentials, "INVALID-DOMAIN", CRED_SPECIFIED); + cli_credentials_set_username(setup.in.credentials, "INVALID-USERNAME", CRED_SPECIFIED); + cli_credentials_set_password(setup.in.credentials, "INVALID-PASSWORD", CRED_SPECIFIED); status = smb_composite_sesssetup(session, &setup); talloc_free(session); diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index 5f036910b6..3e13bf12c0 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -177,8 +177,10 @@ static BOOL connect_servers(void) servers[i].server_name, servers[i].share_name, servers[i].credentials->username, j); + cli_credentials_set_workstation(servers[i].credentials, + "gentest", CRED_SPECIFIED); + status = smbcli_full_connection(NULL, &servers[i].cli[j], - "gentest", servers[i].server_name, servers[i].share_name, NULL, servers[i].credentials); diff --git a/source4/torture/ldap/basic.c b/source4/torture/ldap/basic.c index d0255abe01..b53515fdbc 100644 --- a/source4/torture/ldap/basic.c +++ b/source4/torture/ldap/basic.c @@ -38,14 +38,14 @@ BOOL test_bind_simple(struct ldap_connection *conn, const char *userdn, const ch return ret; } -BOOL test_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password) +BOOL test_bind_sasl(struct ldap_connection *conn, struct cli_credentials *creds) { NTSTATUS status; BOOL ret = True; printf("Testing sasl bind as user\n"); - status = torture_ldap_bind_sasl(conn, username, domain, password); + status = torture_ldap_bind_sasl(conn, creds); if (!NT_STATUS_IS_OK(status)) { ret = False; } @@ -189,9 +189,6 @@ BOOL torture_ldap_basic(void) TALLOC_CTX *mem_ctx; BOOL ret = True; const char *host = lp_parm_string(-1, "torture", "host"); - const char *username = cli_credentials_get_username(cmdline_credentials); - const char *domain = cli_credentials_get_domain(cmdline_credentials); - const char *password = cli_credentials_get_password(cmdline_credentials); const char *userdn = lp_parm_string(-1, "torture", "ldap_userdn"); /*const char *basedn = lp_parm_string(-1, "torture", "ldap_basedn");*/ const char *secret = lp_parm_string(-1, "torture", "ldap_secret"); @@ -217,7 +214,7 @@ BOOL torture_ldap_basic(void) ret = False; } - if (!test_bind_sasl(conn, username, domain, password)) { + if (!test_bind_sasl(conn, cmdline_credentials)) { ret = False; } diff --git a/source4/torture/ldap/common.c b/source4/torture/ldap/common.c index f421565cbd..9dbe2557eb 100644 --- a/source4/torture/ldap/common.c +++ b/source4/torture/ldap/common.c @@ -46,7 +46,8 @@ NTSTATUS torture_ldap_bind(struct ldap_connection *conn, const char *userdn, con return NT_STATUS_OK; } -NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password) +NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, + struct cli_credentials *creds) { NTSTATUS status = NT_STATUS_UNSUCCESSFUL; int result; @@ -56,7 +57,7 @@ NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, const char *userna return status; } - result = ldap_bind_sasl(conn, username, domain, password); + result = ldap_bind_sasl(conn, creds); if (result != LDAP_SUCCESS) { printf("Failed to bind with provided credentials and SASL mechanism\n"); /* FIXME: what abut actually implementing an ldap_connection_free() function ? diff --git a/source4/torture/locktest.c b/source4/torture/locktest.c index 4051f9c411..fe5dfe5178 100644 --- a/source4/torture/locktest.c +++ b/source4/torture/locktest.c @@ -116,9 +116,10 @@ static struct smbcli_state *connect_one(char *share, int snum) share++; slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), snum); + cli_credentials_set_workstation(servers[snum], myname, CRED_SPECIFIED); do { - status = smbcli_full_connection(NULL, &c, myname, + status = smbcli_full_connection(NULL, &c, server, share, NULL, servers[snum]); diff --git a/source4/torture/masktest.c b/source4/torture/masktest.c index d760934334..21e22e91d8 100644 --- a/source4/torture/masktest.c +++ b/source4/torture/masktest.c @@ -77,7 +77,9 @@ static struct smbcli_state *connect_one(char *share) *share = 0; share++; - status = smbcli_full_connection(NULL, &c, "masktest", + cli_credentials_set_workstation(credentials, "masktest", CRED_SPECIFIED); + + status = smbcli_full_connection(NULL, &c, server, share, NULL, credentials); diff --git a/source4/torture/raw/composite.c b/source4/torture/raw/composite.c index b9c7609b5f..f836e1eb4b 100644 --- a/source4/torture/raw/composite.c +++ b/source4/torture/raw/composite.c @@ -147,13 +147,11 @@ static BOOL test_fetchfile(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) io2.in.dest_host = lp_parm_string(-1, "torture", "host"); io2.in.port = 0; io2.in.called_name = lp_parm_string(-1, "torture", "host"); - io2.in.calling_name = lp_netbios_name(); io2.in.service = lp_parm_string(-1, "torture", "share"); io2.in.service_type = "A:"; - io2.in.user = cli_credentials_get_username(cmdline_credentials); - io2.in.domain = cli_credentials_get_domain(cmdline_credentials); - io2.in.password = cli_credentials_get_password(cmdline_credentials); + io2.in.credentials = cmdline_credentials; + io2.in.workgroup = lp_workgroup(); io2.in.filename = fname; printf("testing parallel fetchfile with %d ops\n", torture_numops); diff --git a/source4/torture/raw/context.c b/source4/torture/raw/context.c index 3eb848eebd..a610eaa79e 100644 --- a/source4/torture/raw/context.c +++ b/source4/torture/raw/context.c @@ -81,9 +81,9 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */ - setup.in.password = cli_credentials_get_password(cmdline_credentials); - setup.in.user = cli_credentials_get_username(cmdline_credentials); - setup.in.domain = cli_credentials_get_domain(cmdline_credentials); + setup.in.workgroup = lp_workgroup(); + + setup.in.credentials = cmdline_credentials; status = smb_composite_sesssetup(session, &setup); CHECK_STATUS(status, NT_STATUS_OK); @@ -96,10 +96,9 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) session2->vuid = session->vuid; setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */ + setup.in.workgroup = lp_workgroup(); - setup.in.password = cli_credentials_get_password(cmdline_credentials); - setup.in.user = cli_credentials_get_username(cmdline_credentials); - setup.in.domain = cli_credentials_get_domain(cmdline_credentials); + setup.in.credentials = cmdline_credentials; status = smb_composite_sesssetup(session2, &setup); CHECK_STATUS(status, NT_STATUS_OK); @@ -117,11 +116,10 @@ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) session3->vuid = session->vuid; setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = 0; /* force a non extended security login (should fail) */ - - - setup.in.password = cli_credentials_get_password(cmdline_credentials); - setup.in.user = cli_credentials_get_username(cmdline_credentials); - setup.in.domain = cli_credentials_get_domain(cmdline_credentials); + setup.in.workgroup = lp_workgroup(); + + setup.in.credentials = cmdline_credentials; + status = smb_composite_sesssetup(session3, &setup); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index d9ce350428..c12560ad53 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -116,9 +116,6 @@ BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, a.out.credentials = &credentials3; creds_client_init(creds, &credentials1, &credentials2, - machine_name, - lp_workgroup(), - a.in.account_name, &mach_password, &credentials3, 0); @@ -185,9 +182,6 @@ BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, a.out.credentials = &credentials3; creds_client_init(creds, &credentials1, &credentials2, - machine_name, - lp_workgroup(), - a.in.account_name, &mach_password, &credentials3, negotiate_flags); @@ -258,9 +252,6 @@ BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, a.out.rid = &rid; creds_client_init(creds, &credentials1, &credentials2, - machine_name, - lp_workgroup(), - a.in.account_name, &mach_password, &credentials3, negotiate_flags); diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index d60a8bb60b..7bc184f42e 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -194,10 +194,11 @@ static BOOL test_schannel(TALLOC_CTX *mem_ctx, goto failed; } - status = dcerpc_bind_auth_schannel_withkey(p_netlogon, - DCERPC_NETLOGON_UUID, - DCERPC_NETLOGON_VERSION, - creds); + status = dcerpc_bind_auth_password(p_netlogon, + DCERPC_NETLOGON_UUID, + DCERPC_NETLOGON_VERSION, + credentials, DCERPC_AUTH_TYPE_SCHANNEL, + NULL); if (!NT_STATUS_IS_OK(status)) { goto failed; diff --git a/source4/torture/rpc/xplogin.c b/source4/torture/rpc/xplogin.c index cf42f938c1..f55f6684bc 100644 --- a/source4/torture/rpc/xplogin.c +++ b/source4/torture/rpc/xplogin.c @@ -118,11 +118,11 @@ static NTSTATUS anon_ipc(struct smbcli_transport *transport, /* prepare a session setup to establish a security context */ setup.in.sesskey = transport->negotiate.sesskey; setup.in.capabilities = transport->negotiate.capabilities; - setup.in.password = NULL; - setup.in.user = ""; - setup.in.domain = ""; setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; + setup.in.credentials = cli_credentials_init(mem_ctx); + cli_credentials_set_anonymous(setup.in.credentials); + status = smb_composite_sesssetup(session, &setup); if (!NT_STATUS_IS_OK(status)) { talloc_free(session); @@ -479,9 +479,6 @@ static NTSTATUS setup_netlogon_creds(struct smbcli_transport *transport, a.out.credentials = &credentials3; creds_client_init(creds, &credentials1, &credentials2, - machine_name, - domain, - a.in.account_name, &mach_password, &credentials3, negotiate_flags); @@ -978,6 +975,7 @@ static NTSTATUS test_remoteTOD(struct smbcli_transport *transport) return status; } +#if 0 static BOOL xp_login(const char *dcname, const char *wksname, const char *domain, const char *wkspwd, const char *user1name, const char *user1pw, @@ -1033,10 +1031,10 @@ static BOOL xp_login(const char *dcname, const char *wksname, netlogon_schannel_pipe->conn->flags |= DCERPC_SEAL; - status = dcerpc_bind_auth_schannel_withkey(netlogon_schannel_pipe, - DCERPC_NETLOGON_UUID, - DCERPC_NETLOGON_VERSION, - netlogon_creds); + status = dcerpc_bind_auth_password(netlogon_schannel_pipe, + DCERPC_NETLOGON_UUID, + DCERPC_NETLOGON_VERSION, + creds, NULL); if (!NT_STATUS_IS_OK(status)) return False; @@ -1096,6 +1094,8 @@ static BOOL xp_login(const char *dcname, const char *wksname, return True; } +#endif + struct user_pw { const char *username; const char *password; @@ -1124,10 +1124,13 @@ BOOL torture_rpc_login(void) users[useridx1].username, users[useridx2].username); +#if 0 return xp_login(pdcname, machines[machidx].username, domainname, machines[machidx].password, users[useridx1].username, users[useridx1].password, users[useridx2].username, users[useridx2].password); +#endif + return False; } diff --git a/source4/torture/torture.c b/source4/torture/torture.c index 4fca36a9ae..eb4dd0b84a 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -82,8 +82,7 @@ BOOL torture_open_connection_share(struct smbcli_state **c, NTSTATUS status; status = smbcli_full_connection(NULL, - c, lp_netbios_name(), - hostname, + c, hostname, sharename, NULL, cmdline_credentials); if (!NT_STATUS_IS_OK(status)) { @@ -725,8 +724,7 @@ static BOOL run_tcon_devtype_test(void) const char *share = lp_parm_string(-1, "torture", "share"); status = smbcli_full_connection(NULL, - &cli1, lp_netbios_name(), - host, + &cli1, host, share, NULL, cmdline_credentials); diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index 81c7f90c9b..3bc479e061 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -52,22 +52,22 @@ enum stdio_helper_mode { typedef void (*stdio_helper_function)(enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id); + unsigned int mux_id, void **private2); static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id); + unsigned int mux_id, void **private2); static void manage_gensec_request (enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id); + unsigned int mux_id, void **private2); static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id); + unsigned int mux_id, void **private2); static void manage_squid_request(enum stdio_helper_mode helper_mode, - stdio_helper_function fn); + stdio_helper_function fn, void **private2); static const struct { enum stdio_helper_mode mode; @@ -203,7 +203,7 @@ static NTSTATUS local_pw_check_specified(const char *username, static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id) + unsigned int mux_id, void **private2) { char *user, *pass; user=buf; @@ -234,10 +234,9 @@ static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id) + unsigned int mux_id, void **password) { DATA_BLOB in; - struct gensec_security **gensec_state = (struct gensec_security **)private; if (strlen(buf) < 2) { DEBUG(1, ("query [%s] invalid", buf)); mux_printf(mux_id, "BH\n"); @@ -252,10 +251,10 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod if (strncmp(buf, "PW ", 3) == 0) { - (*gensec_state)->password_callback_private = talloc_strndup((*gensec_state), - (const char *)in.data, in.length); + *password = talloc_strndup(*private /* hopefully the right gensec context, useful to use for talloc */, + (const char *)in.data, in.length); - if ((*gensec_state)->password_callback_private == NULL) { + if (*password == NULL) { DEBUG(1, ("Out of memory\n")); mux_printf(mux_id, "BH\n"); data_blob_free(&in); @@ -271,33 +270,27 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod data_blob_free(&in); } -/* - * Callback for gensec, to ask the calling application for a password. Uses the above function - * for the stdio part of this. +/** + * Callback for password credentails. This is not async, and when + * GENSEC and the credentails code is made async, it will look rather + * different. */ -static NTSTATUS get_password(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - char **password) +static const char *get_password(struct cli_credentials *credentials) { - *password = NULL; + char *password = NULL; /* Ask for a password */ - mux_printf((unsigned int)gensec_security->password_callback_private, "PW\n"); - gensec_security->password_callback_private = NULL; + mux_printf((unsigned int)credentials->priv_data, "PW\n"); + credentials->priv_data = NULL; - manage_squid_request(NUM_HELPER_MODES /* bogus */, manage_gensec_get_pw_request); - *password = (char *)gensec_security->password_callback_private; - if (*password) { - return NT_STATUS_OK; - } else { - return NT_STATUS_INVALID_PARAMETER; - } + manage_squid_request(NUM_HELPER_MODES /* bogus */, manage_gensec_get_pw_request, (void **)&password); + return password; } static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id) + unsigned int mux_id, void **private2) { DATA_BLOB in; DATA_BLOB out = data_blob(NULL, 0); @@ -307,6 +300,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, NTSTATUS nt_status; BOOL first = False; const char *reply_code; + struct cli_credentials *creds; if (strlen(buf) < 2) { DEBUG(1, ("query [%s] invalid", buf)); @@ -351,19 +345,25 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, if (!NT_STATUS_IS_OK(gensec_client_start(NULL, gensec_state))) { exit(1); } - gensec_set_username(*gensec_state, opt_username); - gensec_set_domain(*gensec_state, opt_domain); + + creds = cli_credentials_init(*gensec_state); + cli_credentials_set_conf(creds); + if (opt_username) { + cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED); + } + if (opt_domain) { + cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED); + } if (opt_password) { - if (!NT_STATUS_IS_OK(gensec_set_password(*gensec_state, opt_password))) { - DEBUG(1, ("Out of memory\n")); - mux_printf(mux_id, "BH\n"); - data_blob_free(&in); - return; - } + cli_credentials_set_password(creds, opt_password, CRED_SPECIFIED); } else { - gensec_set_password_callback(*gensec_state, get_password, (void*)mux_id); + creds->password_obtained = CRED_CALLBACK; + creds->password_cb = get_password; + creds->priv_data = (void*)mux_id; } - + + gensec_set_credentials(*gensec_state, creds); + break; case GSS_SPNEGO_SERVER: case SQUID_2_5_NTLMSSP: @@ -395,7 +395,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, } if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(1, ("SPNEGO login failed to initialise: %s\n", nt_errstr(nt_status))); + DEBUG(1, ("GENSEC mech failed to start: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH\n"); return; } @@ -403,16 +403,11 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, if (strncmp(buf, "PW ", 3) == 0) { - if (!NT_STATUS_IS_OK(gensec_set_password(*gensec_state, - talloc_strndup((*gensec_state), - (const char *)in.data, - in.length)))) { - DEBUG(1, ("gensec_set_password failed: %s\n", nt_errstr(nt_status))); - mux_printf(mux_id, "BH %s\n", nt_errstr(nt_status)); - data_blob_free(&in); - return; - } - + cli_credentials_set_password((*gensec_state)->credentials, + talloc_strndup((*gensec_state), + (const char *)in.data, + in.length), + CRED_SPECIFIED); mux_printf(mux_id, "OK\n"); data_blob_free(&in); return; @@ -528,7 +523,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode, char *buf, int length, void **private, - unsigned int mux_id) + unsigned int mux_id, void **private2) { char *request, *parameter; static DATA_BLOB challenge; @@ -723,7 +718,7 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod } static void manage_squid_request(enum stdio_helper_mode helper_mode, - stdio_helper_function fn) + stdio_helper_function fn, void **private2) { char buf[SQUID_BUFFER_SIZE+1]; unsigned int mux_id; @@ -785,7 +780,12 @@ static void manage_squid_request(enum stdio_helper_mode helper_mode, mux_private->private_pointers = NULL; } - c=memchr(buf,' ',sizeof(buf)-1); + c=strchr(buf,' '); + if (!c) { + DEBUG(0, ("Invalid Request - no data after multiplex id\n")); + x_fprintf(x_stdout, "ERR\n"); + return; + } c++; if (mux_id >= mux_private->max_mux) { unsigned int prev_max = mux_private->max_mux; @@ -804,7 +804,7 @@ static void manage_squid_request(enum stdio_helper_mode helper_mode, private = &normal_private; } - fn(helper_mode, c, length, private, mux_id); + fn(helper_mode, c, length, private, mux_id, private2); } static void squid_stream(enum stdio_helper_mode stdio_mode, @@ -813,7 +813,7 @@ static void squid_stream(enum stdio_helper_mode stdio_mode, x_setbuf(x_stdout, NULL); x_setbuf(x_stderr, NULL); while(1) { - manage_squid_request(stdio_mode, fn); + manage_squid_request(stdio_mode, fn, NULL); } } |