diff options
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/auth/config.mk | 3 | ||||
-rw-r--r-- | source4/libcli/auth/credentials.c | 6 | ||||
-rw-r--r-- | source4/libcli/auth/gensec.c | 210 | ||||
-rw-r--r-- | source4/libcli/auth/gensec.h | 12 | ||||
-rw-r--r-- | source4/libcli/auth/gensec.mk | 12 | ||||
-rw-r--r-- | source4/libcli/auth/gensec_krb5.c | 57 | ||||
-rw-r--r-- | source4/libcli/auth/gensec_ntlmssp.c | 21 | ||||
-rw-r--r-- | source4/libcli/auth/kerberos.h | 1 | ||||
-rw-r--r-- | source4/libcli/auth/ntlmssp_sign.c | 2 | ||||
-rw-r--r-- | source4/libcli/auth/schannel.c | 268 | ||||
-rw-r--r-- | source4/libcli/auth/schannel_sign.c | 67 | ||||
-rw-r--r-- | source4/libcli/auth/spnego.c | 10 | ||||
-rw-r--r-- | source4/libcli/cliconnect.c | 16 | ||||
-rw-r--r-- | source4/libcli/composite/composite.h | 17 | ||||
-rw-r--r-- | source4/libcli/composite/connect.c | 9 | ||||
-rw-r--r-- | source4/libcli/composite/fetchfile.c | 6 | ||||
-rw-r--r-- | source4/libcli/composite/sesssetup.c | 54 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap.h | 4 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_client.c | 27 | ||||
-rw-r--r-- | source4/libcli/raw/clisession.c | 4 | ||||
-rw-r--r-- | source4/libcli/raw/clisocket.c | 28 | ||||
-rw-r--r-- | source4/libcli/raw/clitree.c | 7 |
22 files changed, 431 insertions, 410 deletions
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)) { |