diff options
Diffstat (limited to 'source4/rpc_server')
-rw-r--r-- | source4/rpc_server/config.mk | 1 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_server.c | 9 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_server.h | 23 | ||||
-rw-r--r-- | source4/rpc_server/dcesrv_auth.c | 17 | ||||
-rw-r--r-- | source4/rpc_server/dcesrv_crypto.c | 83 | ||||
-rw-r--r-- | source4/rpc_server/dcesrv_crypto_ntlmssp.c | 139 |
6 files changed, 231 insertions, 41 deletions
diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index 4f8b4796fd..d532256c10 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -123,6 +123,7 @@ ADD_OBJ_FILES = \ rpc_server/dcerpc_tcp.o \ rpc_server/dcesrv_auth.o \ rpc_server/dcesrv_crypto.o \ + rpc_server/dcesrv_crypto_ntlmssp.o \ rpc_server/handles.o # # End SUBSYSTEM DCERPC diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index fd806c5289..2c0db15081 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -268,8 +268,9 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx, (*p)->cli_max_recv_frag = 0; (*p)->handles = NULL; (*p)->partial_input = data_blob(NULL, 0); - (*p)->auth_state.crypto_state = NULL; (*p)->auth_state.auth_info = NULL; + (*p)->auth_state.crypto_ctx.private_data = NULL; + (*p)->auth_state.crypto_ctx.ops = NULL; (*p)->session_key = data_blob(NULL, 0); return NT_STATUS_OK; @@ -326,7 +327,11 @@ void dcesrv_endpoint_disconnect(struct dcesrv_connection *p) while (p->handles) { dcesrv_handle_destroy(p, p->handles); } - + + if (p->auth_state.crypto_ctx.ops) { + p->auth_state.crypto_ctx.ops->end(&p->auth_state); + } + talloc_destroy(p->mem_ctx); } diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h index bdda8f252f..44726b5828 100644 --- a/source4/rpc_server/dcerpc_server.h +++ b/source4/rpc_server/dcerpc_server.h @@ -45,6 +45,7 @@ struct dcesrv_ep_description { struct dcesrv_connection; struct dcesrv_call_state; +struct dcesrv_auth; /* the dispatch functions for an interface take this form */ typedef NTSTATUS (*dcesrv_dispatch_fn_t)(struct dcesrv_call_state *, TALLOC_CTX *, void *); @@ -93,10 +94,30 @@ struct dcesrv_handle { void (*destroy)(struct dcesrv_connection *, struct dcesrv_handle *); }; +struct dcesrv_cyrpto_ops { + const char *name; + uint8 auth_type; + NTSTATUS (*start)(struct dcesrv_auth *auth); + NTSTATUS (*update)(struct dcesrv_auth *auth, TALLOC_CTX *out_mem_ctx, + const DATA_BLOB in, DATA_BLOB *out); + NTSTATUS (*seal)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, DATA_BLOB *sig); + NTSTATUS (*sign)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, DATA_BLOB *sig); + NTSTATUS (*check_sig)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, const DATA_BLOB *sig); + NTSTATUS (*unseal)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, DATA_BLOB *sig); + void (*end)(struct dcesrv_auth *auth); +}; + /* hold the authentication state information */ struct dcesrv_auth { - void *crypto_state; struct dcerpc_auth *auth_info; + struct { + void *private_data; + const struct dcesrv_cyrpto_ops *ops; + } crypto_ctx; }; diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c index 7aa296c245..df1a820039 100644 --- a/source4/rpc_server/dcesrv_auth.c +++ b/source4/rpc_server/dcesrv_auth.c @@ -51,11 +51,16 @@ BOOL dcesrv_auth_bind(struct dcesrv_call_state *call) return False; } - status = dcesrv_crypto_startup(dce_conn, &dce_conn->auth_state); + status = dcesrv_crypto_select_type(dce_conn, &dce_conn->auth_state); if (!NT_STATUS_IS_OK(status)) { return False; } - + + status = dcesrv_crypto_start(&dce_conn->auth_state); + if (!NT_STATUS_IS_OK(status)) { + return False; + } + return True; } @@ -67,7 +72,7 @@ BOOL dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct dcerpc_packet * struct dcesrv_connection *dce_conn = call->conn; NTSTATUS status; - if (!call->conn->auth_state.crypto_state) { + if (!call->conn->auth_state.crypto_ctx.ops) { return True; } @@ -98,7 +103,7 @@ BOOL dcesrv_auth_auth3(struct dcesrv_call_state *call) NTSTATUS status; if (!dce_conn->auth_state.auth_info || - !dce_conn->auth_state.crypto_state || + !dce_conn->auth_state.crypto_ctx.ops || pkt->u.auth.auth_info.length == 0) { return False; } @@ -138,7 +143,7 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call) NTSTATUS status; if (!dce_conn->auth_state.auth_info || - !dce_conn->auth_state.crypto_state) { + !dce_conn->auth_state.crypto_ctx.ops) { return True; } @@ -213,7 +218,7 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call, struct ndr_push *ndr; /* non-signed packets are simple */ - if (!dce_conn->auth_state.auth_info || !dce_conn->auth_state.crypto_state) { + if (!dce_conn->auth_state.auth_info || !dce_conn->auth_state.crypto_ctx.ops) { status = dcerpc_push_auth(blob, call->mem_ctx, pkt, NULL); return NT_STATUS_IS_OK(status); } diff --git a/source4/rpc_server/dcesrv_crypto.c b/source4/rpc_server/dcesrv_crypto.c index f9e109abd2..11956fe3be 100644 --- a/source4/rpc_server/dcesrv_crypto.c +++ b/source4/rpc_server/dcesrv_crypto.c @@ -4,6 +4,7 @@ server side dcerpc authentication code - crypto support Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan (metze) Metzmacher 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 @@ -30,10 +31,9 @@ /* startup the cryptographic side of an authenticated dcerpc server */ -NTSTATUS dcesrv_crypto_startup(struct dcesrv_connection *dce_conn, +NTSTATUS dcesrv_crypto_select_type(struct dcesrv_connection *dce_conn, struct dcesrv_auth *auth) { - struct auth_ntlmssp_state *ntlmssp = NULL; NTSTATUS status; if (auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY && @@ -43,20 +43,34 @@ NTSTATUS dcesrv_crypto_startup(struct dcesrv_connection *dce_conn, return NT_STATUS_INVALID_PARAMETER; } + if (auth->crypto_ctx.ops != NULL) { + /* TODO: + * this this function should not be called + * twice per dcesrv_connection! + * + * so we need to find out the right + * dcerpc error to return + */ + } + + /* + * TODO: + * maybe a dcesrv_crypto_find_backend_by_type() whould be better here + * to make thinks more generic + */ switch (auth->auth_info->auth_type) { -/* - case DCERPC_AUTH_TYPE_SCHANNEL: - return auth_schannel_start(); -*/ +/* case DCERPC_AUTH_TYPE_SCHANNEL: + status = dcesrv_crypto_schannel_get_ops(dce_conn, auth); + break; +*/ case DCERPC_AUTH_TYPE_NTLMSSP: - status = auth_ntlmssp_start(&ntlmssp); - auth->crypto_state = ntlmssp; + status = dcesrv_crypto_ntlmssp_get_ops(dce_conn, auth); break; default: DEBUG(2,("dcesrv auth_type %d not supported\n", auth->auth_info->auth_type)); - status = NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_INVALID_PARAMETER; } DEBUG(4,("dcesrv_crypto_startup: %s\n", nt_errstr(status))); @@ -65,58 +79,63 @@ NTSTATUS dcesrv_crypto_startup(struct dcesrv_connection *dce_conn, } /* + start crypto state +*/ +NTSTATUS dcesrv_crypto_start(struct dcesrv_auth *auth) +{ + return auth->crypto_ctx.ops->start(auth); +} + +/* update crypto state */ NTSTATUS dcesrv_crypto_update(struct dcesrv_auth *auth, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { - struct auth_ntlmssp_state *ntlmssp = auth->crypto_state; - - return ntlmssp_update(ntlmssp->ntlmssp_state, out_mem_ctx, in, out); + return auth->crypto_ctx.ops->update(auth, out_mem_ctx, in, out); } - /* seal a packet */ -NTSTATUS dcesrv_crypto_seal(struct dcesrv_auth *auth, - TALLOC_CTX *sig_mem_ctx, uint8_t *data, size_t length, DATA_BLOB *sig) +NTSTATUS dcesrv_crypto_seal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, DATA_BLOB *sig) { - struct auth_ntlmssp_state *ntlmssp = auth->crypto_state; - - return ntlmssp_seal_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig); + return auth->crypto_ctx.ops->seal(auth, sig_mem_ctx, data, length, sig); } /* sign a packet */ -NTSTATUS dcesrv_crypto_sign(struct dcesrv_auth *auth, - TALLOC_CTX *sig_mem_ctx, const uint8_t *data, size_t length, DATA_BLOB *sig) +NTSTATUS dcesrv_crypto_sign(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, DATA_BLOB *sig) { - struct auth_ntlmssp_state *ntlmssp = auth->crypto_state; - - return ntlmssp_sign_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig); + return auth->crypto_ctx.ops->sign(auth, sig_mem_ctx, data, length, sig); } /* check a packet signature */ -NTSTATUS dcesrv_crypto_check_sig(struct dcesrv_auth *auth, - TALLOC_CTX *sig_mem_ctx, const uint8_t *data, size_t length, const DATA_BLOB *sig) +NTSTATUS dcesrv_crypto_check_sig(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, const DATA_BLOB *sig) { - struct auth_ntlmssp_state *ntlmssp = auth->crypto_state; - - return ntlmssp_check_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig); + return auth->crypto_ctx.ops->check_sig(auth, sig_mem_ctx, data, length, sig); } /* unseal a packet */ -NTSTATUS dcesrv_crypto_unseal(struct dcesrv_auth *auth, - TALLOC_CTX *sig_mem_ctx, uint8_t *data, size_t length, DATA_BLOB *sig) +NTSTATUS dcesrv_crypto_unseal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, DATA_BLOB *sig) { - struct auth_ntlmssp_state *ntlmssp = auth->crypto_state; + return auth->crypto_ctx.ops->unseal(auth, sig_mem_ctx, data, length, sig); +} - return ntlmssp_unseal_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig); +/* + end crypto state +*/ +void dcesrv_crypto_end(struct dcesrv_auth *auth) +{ + auth->crypto_ctx.ops->end(auth); } diff --git a/source4/rpc_server/dcesrv_crypto_ntlmssp.c b/source4/rpc_server/dcesrv_crypto_ntlmssp.c new file mode 100644 index 0000000000..b894f0f25d --- /dev/null +++ b/source4/rpc_server/dcesrv_crypto_ntlmssp.c @@ -0,0 +1,139 @@ +/* + Unix SMB/CIFS implementation. + + server side dcerpc authentication code - NTLMSSP auth/crypto code + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan (metze) Metzmacher 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 + 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. +*/ + +/* + this provides a crypto interface to the various backends (such as + NTLMSSP and SCHANNEL) for the rpc server code +*/ + +#include "includes.h" + + +/* + start crypto state +*/ +static NTSTATUS dcesrv_crypto_ntlmssp_start(struct dcesrv_auth *auth) +{ + struct auth_ntlmssp_state *ntlmssp = NULL; + NTSTATUS status; + + status = auth_ntlmssp_start(&ntlmssp); + + auth->crypto_ctx.private_data = ntlmssp; + + return status; +} + +/* + update crypto state +*/ +static NTSTATUS dcesrv_crypto_ntlmssp_update(struct dcesrv_auth *auth, TALLOC_CTX *out_mem_ctx, + const DATA_BLOB in, DATA_BLOB *out) +{ + struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data; + + return ntlmssp_update(auth_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out); +} + +/* + seal a packet +*/ +static NTSTATUS dcesrv_crypto_ntlmssp_seal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, DATA_BLOB *sig) +{ + struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data; + + return ntlmssp_seal_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig); +} + +/* + sign a packet +*/ +static NTSTATUS dcesrv_crypto_ntlmssp_sign(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, DATA_BLOB *sig) +{ + struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data; + + return ntlmssp_sign_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig); +} + +/* + check a packet signature +*/ +static NTSTATUS dcesrv_crypto_ntlmssp_check_sig(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, const DATA_BLOB *sig) +{ + struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data; + + return ntlmssp_check_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig); +} + +/* + unseal a packet +*/ +static NTSTATUS dcesrv_crypto_ntlmssp_unseal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, DATA_BLOB *sig) +{ + struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data; + + return ntlmssp_unseal_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig); +} + +/* + end crypto state +*/ +static void dcesrv_crypto_ntlmssp_end(struct dcesrv_auth *auth) +{ + struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data; + + auth->crypto_ctx.private_data = NULL; + + auth_ntlmssp_end(&auth_ntlmssp_state); + + return; +} + +static const struct dcesrv_cyrpto_ops dcesrv_crypto_ntlmssp_ops = { + .name = "ntlmssp", + .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, + .start = dcesrv_crypto_ntlmssp_start, + .update = dcesrv_crypto_ntlmssp_update, + .seal = dcesrv_crypto_ntlmssp_seal, + .sign = dcesrv_crypto_ntlmssp_sign, + .check_sig = dcesrv_crypto_ntlmssp_check_sig, + .unseal = dcesrv_crypto_ntlmssp_unseal, + .end = dcesrv_crypto_ntlmssp_end +}; + +/* + startup the cryptographic side of an authenticated dcerpc server +*/ +NTSTATUS dcesrv_crypto_ntlmssp_get_ops(struct dcesrv_connection *dce_conn, + struct dcesrv_auth *auth) +{ + NTSTATUS status = NT_STATUS_OK; + + auth->crypto_ctx.ops = &dcesrv_crypto_ntlmssp_ops; + + return status; +} |