*/
#include "includes.h"
+#include "librpc/gen_ndr/ndr_schannel.h"
+#include "auth/auth.h"
enum schannel_position {
DCERPC_SCHANNEL_STATE_START = 0,
struct dcerpc_schannel_state {
enum schannel_position state;
struct schannel_state *schannel_state;
- struct creds_CredentialState creds;
+ struct creds_CredentialState *creds;
char *account_name;
};
const char *username,
const char *password,
int chan_type,
- uint8_t new_session_key[16]);
+ struct creds_CredentialState *creds);
/*
wrappers for the schannel_*() functions
return NT_STATUS_OK;
}
+ status = schannel_start(&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 */
/* start up the schannel server code */
status = schannel_start(&dce_schan_state->schannel_state,
- dce_schan_state->creds.session_key, False);
+ dce_schan_state->creds->session_key, False);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("Could not initialise schannel state for account %s: %s\n",
account_name, nt_errstr(status)));
{
struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data;
- *creds = talloc_p(mem_ctx, struct creds_CredentialState);
+ *creds = talloc_reference(mem_ctx, dce_schan_state->creds);
if (!*creds) {
return NT_STATUS_NO_MEMORY;
}
-
- **creds = dce_schan_state->creds;
return NT_STATUS_OK;
}
+/*
+ end crypto state
+*/
+static int dcerpc_schannel_destroy(void *ptr)
+{
+ struct dcerpc_schannel_state *dce_schan_state = ptr;
+
+ schannel_end(&dce_schan_state->schannel_state);
+
+ return 0;
+}
+
static NTSTATUS dcerpc_schannel_start(struct gensec_security *gensec_security)
{
struct dcerpc_schannel_state *dce_schan_state;
dce_schan_state->state = DCERPC_SCHANNEL_STATE_START;
gensec_security->private_data = dce_schan_state;
+ gensec_security->have_features =
+ GENSEC_FEATURE_SESSION_KEY |
+ GENSEC_FEATURE_SIGN |
+ GENSEC_FEATURE_SEAL;
+
+ talloc_set_destructor(dce_schan_state, dcerpc_schannel_destroy);
return NT_STATUS_OK;
}
static NTSTATUS dcerpc_schannel_server_start(struct gensec_security *gensec_security)
{
NTSTATUS status;
- struct dcerpc_schannel_state *dce_schan_state;
status = dcerpc_schannel_start(gensec_security);
-
- dce_schan_state = gensec_security->private_data;
- dce_schan_state->schannel_state = NULL;
-
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;
- struct dcerpc_schannel_state *dce_schan_state;
status = dcerpc_schannel_start(gensec_security);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- dce_schan_state = gensec_security->private_data;
-
- status = schannel_start(&dce_schan_state->schannel_state,
- gensec_security->user.schan_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);
return NT_STATUS_OK;
}
-/*
- end crypto state
-*/
-static void dcerpc_schannel_end(struct gensec_security *gensec_security)
-{
- struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data;
-
- schannel_end(&dce_schan_state->schannel_state);
-
- talloc_free(dce_schan_state);
-
- gensec_security->private_data = NULL;
-}
-
/*
get a schannel key using a netlogon challenge on a secondary pipe
const char *username,
const char *password,
int chan_type,
- uint8_t new_session_key[16])
+ struct creds_CredentialState *creds)
{
NTSTATUS status;
struct dcerpc_pipe *p2;
struct netr_ServerAuthenticate2 a;
struct netr_Credential credentials1, credentials2, credentials3;
struct samr_Password mach_pwd;
- struct creds_CredentialState creds;
const char *workgroup, *workstation;
uint32_t negotiate_flags;
step 3 - authenticate on the netlogon pipe
*/
E_md4hash(password, mach_pwd.hash);
- creds_client_init(&creds, &credentials1, &credentials2, &mach_pwd, &credentials3,
+ creds_client_init(creds, &credentials1, &credentials2, &mach_pwd, &credentials3,
negotiate_flags);
a.in.server_name = r.in.server_name;
return status;
}
- if (!creds_client_check(&creds, a.out.credentials)) {
+ if (!creds_client_check(creds, a.out.credentials)) {
return NT_STATUS_UNSUCCESSFUL;
}
*/
dcerpc_pipe_close(p2);
- memcpy(new_session_key, creds.session_key, 16);
-
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(struct dcerpc_pipe *p,
- const char *uuid, uint_t version,
- const char *domain,
- const char *username,
- const char *password)
+NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p,
+ const char *uuid, uint_t version,
+ const char *domain,
+ const char *username,
+ const char *password,
+ struct creds_CredentialState *creds)
{
NTSTATUS status;
- int chan_type = 0;
+ struct dcerpc_schannel_state *dce_schan_state;
status = gensec_client_start(p, &p->security_state.generic_state);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- if (p->flags & DCERPC_SCHANNEL_BDC) {
- chan_type = SEC_CHAN_BDC;
- } else if (p->flags & DCERPC_SCHANNEL_WORKSTATION) {
- chan_type = SEC_CHAN_WKSTA;
- } else if (p->flags & DCERPC_SCHANNEL_DOMAIN) {
- chan_type = SEC_CHAN_DOMAIN;
- }
-
- status = dcerpc_schannel_key(p, domain,
- username,
- password,
- chan_type,
- p->security_state.generic_state->user.schan_session_key);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to fetch schannel session key: %s\n", nt_errstr(status)));
- gensec_end(&p->security_state.generic_state);
- return status;
- }
-
status = gensec_set_username(p->security_state.generic_state, username);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to set schannel username to %s: %s\n", username, nt_errstr(status)));
- gensec_end(&p->security_state.generic_state);
+ talloc_free(p->security_state.generic_state);
+ p->security_state.generic_state = NULL;
return status;
}
status = gensec_set_domain(p->security_state.generic_state, domain);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to set schannel domain to %s: %s\n", domain, nt_errstr(status)));
- gensec_end(&p->security_state.generic_state);
+ talloc_free(p->security_state.generic_state);
+ p->security_state.generic_state = NULL;
return status;
}
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start SCHANNEL GENSEC backend: %s\n", nt_errstr(status)));
- gensec_end(&p->security_state.generic_state);
+ talloc_free(p->security_state.generic_state);
+ p->security_state.generic_state = NULL;
return status;
}
+ dce_schan_state = p->security_state.generic_state->private_data;
+ dce_schan_state->creds = talloc_reference(dce_schan_state, creds);
+
status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p),
uuid, version);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to bind to pipe with SCHANNEL: %s\n", nt_errstr(status)));
- gensec_end(&p->security_state.generic_state);
+ talloc_free(p->security_state.generic_state);
+ p->security_state.generic_state = NULL;
return status;
}
return NT_STATUS_OK;
}
+NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
+ const char *uuid, uint_t version,
+ const char *domain,
+ const char *username,
+ const char *password)
+{
+ NTSTATUS status;
+ int chan_type = 0;
+ struct creds_CredentialState *creds;
+ creds = talloc_p(p, struct creds_CredentialState);
+ if (!creds) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (p->flags & DCERPC_SCHANNEL_BDC) {
+ chan_type = SEC_CHAN_BDC;
+ } else if (p->flags & DCERPC_SCHANNEL_WORKSTATION) {
+ chan_type = SEC_CHAN_WKSTA;
+ } else if (p->flags & DCERPC_SCHANNEL_DOMAIN) {
+ chan_type = SEC_CHAN_DOMAIN;
+ }
+
+ status = dcerpc_schannel_key(p, domain,
+ username,
+ password,
+ chan_type,
+ creds);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to fetch schannel session key: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+
+ return dcerpc_bind_auth_schannel_withkey(p, uuid, version, domain,
+ username, password,
+ creds);
+}
static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = {
.name = "dcerpc_schannel",
.session_key = dcerpc_schannel_session_key,
.session_info = dcerpc_schannel_session_info,
.sig_size = dcerpc_schannel_sig_size,
- .end = dcerpc_schannel_end
};
NTSTATUS gensec_dcerpc_schannel_init(void)
{
NTSTATUS ret;
- ret = register_backend("gensec", &gensec_dcerpc_schannel_security_ops);
+ 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));