diff options
-rw-r--r-- | source4/librpc/rpc/dcerpc_schannel.c | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 64dc6d3ad9..e868a8081c 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2004 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 + Copyright (C) Rafal Szczesniak 2006 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 @@ -49,6 +50,10 @@ static void continue_srv_challenge(struct rpc_request *req); static void continue_srv_auth2(struct rpc_request *req); +/* + Stage 2 of schannel_key: Receive endpoint mapping and request secondary + rpc connection +*/ static void continue_epm_map_binding(struct composite_context *ctx) { struct composite_context *c; @@ -58,6 +63,7 @@ static void continue_epm_map_binding(struct composite_context *ctx) c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct schannel_key_state); + /* receive endpoint mapping */ c->status = dcerpc_epm_map_binding_recv(ctx); if (!composite_is_ok(c)) { DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n", @@ -65,6 +71,7 @@ static void continue_epm_map_binding(struct composite_context *ctx) return; } + /* send a request for secondary rpc connection */ sec_conn_req = dcerpc_secondary_connection_send(s->pipe, s->binding); if (composite_nomem(sec_conn_req, c)) return; @@ -73,6 +80,10 @@ static void continue_epm_map_binding(struct composite_context *ctx) } +/* + Stage 3 of schannel_key: Receive secondary rpc connection and perform + non-authenticated bind request +*/ static void continue_secondary_connection(struct composite_context *ctx) { struct composite_context *c; @@ -82,9 +93,11 @@ static void continue_secondary_connection(struct composite_context *ctx) c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct schannel_key_state); + /* receive secondary rpc connection */ c->status = dcerpc_secondary_connection_recv(ctx, &s->pipe2); if (!composite_is_ok(c)) return; + /* initiate a non-authenticated bind */ auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe2, &dcerpc_table_netlogon); if (composite_nomem(auth_none_req, c)) return; @@ -92,6 +105,10 @@ static void continue_secondary_connection(struct composite_context *ctx) } +/* + Stage 4 of schannel_key: Receive non-authenticated bind and get + a netlogon challenge +*/ static void continue_bind_auth_none(struct composite_context *ctx) { struct composite_context *c; @@ -100,25 +117,26 @@ static void continue_bind_auth_none(struct composite_context *ctx) c = talloc_get_type(ctx->async.private_data, struct composite_context); s = talloc_get_type(c->private_data, struct schannel_key_state); - + + /* receive result of non-authenticated bind request */ c->status = dcerpc_bind_auth_none_recv(ctx); if (!composite_is_ok(c)) { talloc_free(s->pipe2); return; } - + + /* prepare a challenge request */ s->r.in.server_name = talloc_asprintf(c, "\\\\%s", dcerpc_server_name(s->pipe)); if (composite_nomem(s->r.in.server_name, c)) return; s->r.in.computer_name = cli_credentials_get_workstation(s->credentials); s->r.in.credentials = &s->credentials1; s->r.out.credentials = &s->credentials2; - + generate_random_buffer(s->credentials1.data, sizeof(s->credentials1.data)); /* - request a netlogon challenge + request a netlogon challenge - a rpc request over opened secondary pipe */ - srv_challenge_req = dcerpc_netr_ServerReqChallenge_send(s->pipe2, c, &s->r); if (composite_nomem(srv_challenge_req, c)) return; @@ -126,6 +144,10 @@ static void continue_bind_auth_none(struct composite_context *ctx) } +/* + Stage 5 of schannel_key: Receive a challenge and perform authentication + on the netlogon pipe +*/ static void continue_srv_challenge(struct rpc_request *req) { struct composite_context *c; @@ -135,18 +157,17 @@ static void continue_srv_challenge(struct rpc_request *req) c = talloc_get_type(req->async.private, struct composite_context); s = talloc_get_type(c->private_data, struct schannel_key_state); + /* receive rpc request result - netlogon challenge */ c->status = dcerpc_ndr_request_recv(req); if (!composite_is_ok(c)) return; - /* - authenticate on the netlogon pipe - */ - + /* prepare credentials for auth2 request */ s->mach_pwd = cli_credentials_get_nt_hash(s->credentials, c); creds_client_init(s->creds, &s->credentials1, &s->credentials2, s->mach_pwd, &s->credentials3, s->negotiate_flags); + /* auth2 request arguments */ s->a.in.server_name = s->r.in.server_name; s->a.in.account_name = cli_credentials_get_username(s->credentials); s->a.in.secure_channel_type = @@ -157,6 +178,9 @@ static void continue_srv_challenge(struct rpc_request *req) s->a.out.negotiate_flags = &s->negotiate_flags; s->a.out.credentials = &s->credentials3; + /* + authenticate on the netlogon pipe - a rpc request over secondary pipe + */ srv_auth2_req = dcerpc_netr_ServerAuthenticate2_send(s->pipe2, c, &s->a); if (composite_nomem(srv_auth2_req, c)) return; @@ -164,6 +188,10 @@ static void continue_srv_challenge(struct rpc_request *req) } +/* + Stage 6 of schannel_key: Receive authentication request result and verify + received credentials +*/ static void continue_srv_auth2(struct rpc_request *req) { struct composite_context *c; @@ -172,14 +200,17 @@ static void continue_srv_auth2(struct rpc_request *req) c = talloc_get_type(req->async.private, struct composite_context); s = talloc_get_type(c->private_data, struct schannel_key_state); + /* receive rpc request result - auth2 credentials */ c->status = dcerpc_ndr_request_recv(req); if (!composite_is_ok(c)) return; + /* verify credentials */ if (!creds_client_check(s->creds, s->a.out.credentials)) { composite_error(c, NT_STATUS_UNSUCCESSFUL); return; } + /* setup current netlogon credentials */ cli_credentials_set_netlogon_creds(s->credentials, s->creds); talloc_free(s->pipe2); @@ -188,7 +219,8 @@ static void continue_srv_auth2(struct rpc_request *req) /* - initiate getting a schannel key using a netlogon challenge on a secondary pipe + Initiate establishing a schannel key using netlogon challenge + on a secondary pipe */ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p, @@ -198,6 +230,7 @@ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, struct schannel_key_state *s; struct composite_context *epm_map_req; + /* composite context allocation and setup */ c = talloc_zero(mem_ctx, struct composite_context); if (c == NULL) return NULL; @@ -208,23 +241,28 @@ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, c->private_data = s; c->event_ctx = p->conn->event_ctx; + /* store parameters in the state structure */ s->pipe = p; s->credentials = credentials; + /* allocate credentials */ s->creds = talloc(c, struct creds_CredentialState); if (composite_nomem(s->creds, c)) return c; + /* type of authentication depends on schannel type */ if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) { s->negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; } else { s->negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; } + /* allocate binding structure */ s->binding = talloc(c, struct dcerpc_binding); if (composite_nomem(s->binding, c)) return c; *s->binding = *s->pipe->binding; + /* request the netlogon endpoint mapping */ epm_map_req = dcerpc_epm_map_binding_send(c, s->binding, &dcerpc_table_netlogon, s->pipe->conn->event_ctx); @@ -235,6 +273,9 @@ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, } +/* + Receive result of schannel key request + */ NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c) { NTSTATUS status = composite_wait(c); @@ -255,6 +296,10 @@ struct auth_schannel_state { static void continue_bind_auth(struct composite_context *ctx); +/* + Stage 2 of auth_schannel: Receive schannel key and intitiate an + authenticated bind using received credentials + */ static void continue_schannel_key(struct composite_context *ctx) { struct composite_context *auth_req; @@ -263,6 +308,7 @@ static void continue_schannel_key(struct composite_context *ctx) struct auth_schannel_state *s = talloc_get_type(c->private_data, struct auth_schannel_state); + /* receive schannel key */ c->status = dcerpc_schannel_key_recv(ctx); if (!composite_is_ok(c)) { DEBUG(1, ("Failed to setup credentials for account %s: %s\n", @@ -270,6 +316,7 @@ static void continue_schannel_key(struct composite_context *ctx) return; } + /* send bind auth request with received creds */ auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, DCERPC_AUTH_TYPE_SCHANNEL, s->auth_level, NULL); @@ -279,6 +326,10 @@ static void continue_schannel_key(struct composite_context *ctx) } +/* + Stage 3 of auth_schannel: Receivce result of authenticated bind + and say if we're done ok. +*/ static void continue_bind_auth(struct composite_context *ctx) { struct composite_context *c = talloc_get_type(ctx->async.private_data, @@ -291,6 +342,9 @@ static void continue_bind_auth(struct composite_context *ctx) } +/* + Initiate schannel authentication request +*/ struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx, struct dcerpc_pipe *p, const struct dcerpc_interface_table *table, @@ -301,6 +355,7 @@ struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx, struct auth_schannel_state *s; struct composite_context *schan_key_req; + /* composite context allocation and setup */ c = talloc_zero(tmp_ctx, struct composite_context); if (c == NULL) return NULL; @@ -310,12 +365,14 @@ struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx, c->state = COMPOSITE_STATE_IN_PROGRESS; c->private_data = s; c->event_ctx = p->conn->event_ctx; - + + /* store parameters in the state structure */ s->pipe = p; s->credentials = credentials; s->table = table; s->auth_level = auth_level; + /* start getting schannel key first */ schan_key_req = dcerpc_schannel_key_send(c, p, credentials); if (composite_nomem(schan_key_req, c)) return c; @@ -324,6 +381,9 @@ struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx, } +/* + Receive result of schannel authentication request +*/ NTSTATUS dcerpc_bind_auth_schannel_recv(struct composite_context *c) { NTSTATUS status = composite_wait(c); @@ -333,6 +393,9 @@ NTSTATUS dcerpc_bind_auth_schannel_recv(struct composite_context *c) } +/* + Perform schannel authenticated bind - sync version + */ NTSTATUS dcerpc_bind_auth_schannel(TALLOC_CTX *tmp_ctx, struct dcerpc_pipe *p, const struct dcerpc_interface_table *table, |