1
0
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:
Andrew Bartlett 2005-03-24 04:14:06 +00:00 committed by Gerald (Jerry) Carter
parent 46b22b073c
commit 2eb3d68062
45 changed files with 601 additions and 967 deletions

View File

@ -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;

View File

@ -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",

View File

@ -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;

View File

@ -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 = \

View File

@ -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));

View File

@ -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;
}

View File

@ -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;

View File

@ -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]

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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

View 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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)) {

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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 ?

View File

@ -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]);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}
}