mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r6028: A MAJOR update to intergrate the new credentails system fully with
GENSEC, and to pull SCHANNEL into GENSEC, by making it less 'special'.
GENSEC now no longer has it's own handling of 'set username' etc,
instead it uses cli_credentials calls.
In order to link the credentails code right though Samba, a lot of
interfaces have changed to remove 'username, domain, password'
arguments, and these have been replaced with a single 'struct
cli_credentials'.
In the session setup code, a new parameter 'workgroup' contains the
client/server current workgroup, which seems unrelated to the
authentication exchange (it was being filled in from the auth info).
This allows in particular kerberos to only call back for passwords
when it actually needs to perform the kinit.
The kerberos code has been modified not to use the SPNEGO provided
'principal name' (in the mechListMIC), but to instead use the name the
host was connected to as. This better matches Microsoft behaviour,
is more secure and allows better use of standard kerberos functions.
To achieve this, I made changes to our socket code so that the
hostname (before name resolution) is now recorded on the socket.
In schannel, most of the code from librpc/rpc/dcerpc_schannel.c is now
in libcli/auth/schannel.c, and it looks much more like a standard
GENSEC module. The actual sign/seal code moved to
libcli/auth/schannel_sign.c in a previous commit.
The schannel credentails structure is now merged with the rest of the
credentails, as many of the values (username, workstation, domain)
where already present there. This makes handling this in a generic
manner much easier, as there is no longer a custom entry-point.
The auth_domain module continues to be developed, but is now just as
functional as auth_winbind. The changes here are consequential to the
schannel changes.
The only removed function at this point is the RPC-LOGIN test
(simulating the load of a WinXP login), which needs much more work to
clean it up (it contains copies of too much code from all over the
torture suite, and I havn't been able to penetrate its 'structure').
Andrew Bartlett
(This used to be commit 2301a4b38a
)
This commit is contained in:
parent
46b22b073c
commit
2eb3d68062
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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 = \
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
* Associate a credentails structure with a GENSEC context - talloc_reference()s it to the context
|
||||
*
|
||||
*/
|
||||
|
||||
NTSTATUS gensec_set_username(struct gensec_security *gensec_security, const char *user)
|
||||
NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
|
||||
{
|
||||
gensec_security->user.name = talloc_strdup(gensec_security, user);
|
||||
if (user && !gensec_security->user.name) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
gensec_security->credentials = talloc_reference(gensec_security, credentials);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a username on a GENSEC context - ensures it is talloc()ed
|
||||
* Return the credentails structure associated with a GENSEC context
|
||||
*
|
||||
*/
|
||||
|
||||
const char *gensec_get_username(struct gensec_security *gensec_security)
|
||||
struct cli_credentials *gensec_get_credentials(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
|
||||
*
|
||||
*/
|
||||
|
||||
NTSTATUS gensec_set_domain(struct gensec_security *gensec_security, const char *domain)
|
||||
{
|
||||
gensec_security->user.domain = talloc_strdup(gensec_security, domain);
|
||||
if (domain && !gensec_security->user.domain) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the NT domain for this GENSEC context
|
||||
*
|
||||
*/
|
||||
|
||||
const char *gensec_get_domain(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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -68,6 +68,18 @@ REQUIRED_SUBSYSTEMS = AUTH
|
||||
# End MODULE gensec_ntlmssp
|
||||
################################################
|
||||
|
||||
################################################
|
||||
# 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]
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
268
source4/libcli/auth/schannel.c
Normal file
268
source4/libcli/auth/schannel.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,23 +271,9 @@ 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);
|
||||
status = gensec_set_credentials(session->gensec, io->in.credentials);
|
||||
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);
|
||||
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)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = gensec_set_password(session->gensec, io->in.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 client credentails: %s\n",
|
||||
nt_errstr(status)));
|
||||
return NULL;
|
||||
}
|
||||
@ -296,6 +285,13 @@ static struct smbcli_request *session_setup_spnego(struct composite_context *c,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = gensec_set_target_service(session->gensec, "cifs");
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC target service: %s\n",
|
||||
nt_errstr(status)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (session->transport->negotiate.secblob.length) {
|
||||
chosen_oid = GENSEC_OID_SPNEGO;
|
||||
} else {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 ?
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
gensec_set_password_callback(*gensec_state, get_password, (void*)mux_id);
|
||||
|
||||
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) {
|
||||
cli_credentials_set_password(creds, opt_password, CRED_SPECIFIED);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user