The branch, master has been updated via f65c1f0 s4:librpc: use authenticated epmapping for ncacn_http via 3b18dea librpc/idl: specify ncacn_http endpoint mapper endpoint via 9e1313d s4:rpc_server: ignore ncacn_http endpoints for now via 594d036 ncacn_http: DCERPC pipe open using http transport via d617230 ncacn_http: Client implementation via cc55bc2 ncacn_http: Authentication modules for http library via 8260ae6 ncacn_http: Add http library from 6148c94 s3:smbtorture: align explanations for parameters
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f65c1f0e2f6a8c23a94003f61b0b98d963b2424b Author: Stefan Metzmacher <me...@samba.org> Date: Sun Sep 21 09:20:26 2014 +0200 s4:librpc: use authenticated epmapping for ncacn_http We need to authenticate against the RpcProxy. In future we could have a way to specify alternative credentials for the RpcProxy and HttpProxy. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Tue Sep 23 01:34:05 CEST 2014 on sn-devel-104 commit 3b18dea1310cfe9e9b4ec0f2b3b5b14ac4771c83 Author: Stefan Metzmacher <me...@samba.org> Date: Sun Sep 21 08:38:42 2014 +0200 librpc/idl: specify ncacn_http endpoint mapper endpoint Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 9e1313d2b6eced3f3d13fcf989f031c32e06aef0 Author: Stefan Metzmacher <me...@samba.org> Date: Sun Sep 21 08:38:10 2014 +0200 s4:rpc_server: ignore ncacn_http endpoints for now Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 594d036afd78ae04b848607579707bcdced91ec3 Author: Samuel Cabrero <samuelcabr...@kernevil.me> Date: Tue Sep 16 17:01:02 2014 +0200 ncacn_http: DCERPC pipe open using http transport Signed-off-by: Samuel Cabrero <samuelcabr...@kernevil.me> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d617230888840f0d89b1d30c851f5484c1f8182d Author: Samuel Cabrero <samuelcabr...@kernevil.me> Date: Tue Sep 16 16:41:27 2014 +0200 ncacn_http: Client implementation Signed-off-by: Samuel Cabrero <samuelcabr...@kernevil.me> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit cc55bc2d45df3406130a5fe127f5eb35e466a7cd Author: Samuel Cabrero <samuelcabr...@kernevil.me> Date: Tue Sep 16 18:05:53 2014 +0200 ncacn_http: Authentication modules for http library Signed-off-by: Samuel Cabrero <samuelcabr...@kernevil.me> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8260ae6dbe5e65033d406ba26bbe97a6e4712c4c Author: Samuel Cabrero <samuelcabr...@kernevil.me> Date: Tue Sep 16 16:12:26 2014 +0200 ncacn_http: Add http library Signed-off-by: Samuel Cabrero <samuelcabr...@kernevil.me> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: librpc/idl/epmapper.idl | 4 +- source4/lib/http/gensec/basic.c | 137 +++++ source4/lib/http/gensec/ntlm.c | 120 ++++ source4/lib/http/http.c | 825 +++++++++++++++++++++++++++ source4/lib/http/http.h | 120 ++++ source4/lib/http/http_auth.c | 361 ++++++++++++ source4/lib/http/http_internal.h | 62 ++ source4/lib/http/wscript_build | 21 + source4/libnet/libnet_rpc.c | 10 +- source4/librpc/rpc/dcerpc.h | 2 + source4/librpc/rpc/dcerpc_connect.c | 206 +++++++ source4/librpc/rpc/dcerpc_roh.c | 789 +++++++++++++++++++++++++ source4/librpc/rpc/dcerpc_roh.h | 116 ++++ source4/librpc/rpc/dcerpc_roh_channel_in.c | 471 +++++++++++++++ source4/librpc/rpc/dcerpc_roh_channel_out.c | 743 ++++++++++++++++++++++++ source4/librpc/rpc/dcerpc_schannel.c | 7 +- source4/librpc/rpc/dcerpc_util.c | 20 +- source4/librpc/wscript_build | 3 +- source4/rpc_server/service_rpc.c | 10 + wscript_build | 1 + 20 files changed, 4015 insertions(+), 13 deletions(-) create mode 100644 source4/lib/http/gensec/basic.c create mode 100644 source4/lib/http/gensec/ntlm.c create mode 100644 source4/lib/http/http.c create mode 100644 source4/lib/http/http.h create mode 100644 source4/lib/http/http_auth.c create mode 100644 source4/lib/http/http_internal.h create mode 100644 source4/lib/http/wscript_build create mode 100644 source4/librpc/rpc/dcerpc_roh.c create mode 100644 source4/librpc/rpc/dcerpc_roh.h create mode 100644 source4/librpc/rpc/dcerpc_roh_channel_in.c create mode 100644 source4/librpc/rpc/dcerpc_roh_channel_out.c Changeset truncated at 500 lines: diff --git a/librpc/idl/epmapper.idl b/librpc/idl/epmapper.idl index 0ce07d8..5f3d653 100644 --- a/librpc/idl/epmapper.idl +++ b/librpc/idl/epmapper.idl @@ -14,8 +14,8 @@ import "misc.idl"; [ uuid("e1af8308-5d1f-11c9-91a4-08002b14a0fa"), version(3.0), - endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", - "ncalrpc:[EPMAPPER]"), + endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", + "ncacn_http:[593]", "ncalrpc:[EPMAPPER]"), helpstring("EndPoint Mapper"), pointer_default(ptr) ] diff --git a/source4/lib/http/gensec/basic.c b/source4/lib/http/gensec/basic.c new file mode 100644 index 0000000..86a2d51 --- /dev/null +++ b/source4/lib/http/gensec/basic.c @@ -0,0 +1,137 @@ +/* + Unix SMB/CIFS implementation. + + HTTP library - Basic authentication mechanism gensec module + + Copyright (C) 2014 Samuel Cabrero <samuelcabr...@kernevil.me> + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "auth/auth.h" +#include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" +#include "auth/credentials/credentials.h" + +_PUBLIC_ NTSTATUS gensec_http_basic_init(void); + +struct gensec_http_basic_state { + enum { + GENSEC_HTTP_BASIC_START, + GENSEC_HTTP_BASIC_DONE, + GENSEC_HTTP_BASIC_ERROR, + } step; +}; + +static NTSTATUS gensec_http_basic_client_start(struct gensec_security *gensec) +{ + struct gensec_http_basic_state *state; + + state = talloc_zero(gensec, struct gensec_http_basic_state); + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } + gensec->private_data = state; + + state->step = GENSEC_HTTP_BASIC_START; + + return NT_STATUS_OK; +} + +static NTSTATUS gensec_http_basic_update(struct gensec_security *gensec_ctx, + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const DATA_BLOB in, + DATA_BLOB *out) +{ + struct gensec_http_basic_state *state; + struct cli_credentials *creds; + char *tmp, *b64; + + state = talloc_get_type_abort(gensec_ctx->private_data, + struct gensec_http_basic_state); + creds = gensec_get_credentials(gensec_ctx); + + switch (gensec_ctx->gensec_role) { + case GENSEC_CLIENT: + switch (state->step) { + case GENSEC_HTTP_BASIC_START: + tmp = talloc_asprintf(mem_ctx, "%s\\%s:%s", + cli_credentials_get_domain(creds), + cli_credentials_get_username(creds), + cli_credentials_get_password(creds)); + if (tmp == NULL) { + state->step = GENSEC_HTTP_BASIC_ERROR; + return NT_STATUS_NO_MEMORY; + } + *out = data_blob_string_const(tmp); + + b64 = base64_encode_data_blob(mem_ctx, *out); + if (b64 == NULL) { + state->step = GENSEC_HTTP_BASIC_ERROR; + return NT_STATUS_NO_MEMORY; + } + TALLOC_FREE(tmp); + + tmp = talloc_asprintf(mem_ctx, "Basic %s", b64); + if (tmp == NULL) { + state->step = GENSEC_HTTP_BASIC_ERROR; + return NT_STATUS_NO_MEMORY; + } + TALLOC_FREE(b64); + + *out = data_blob_string_const(tmp); + state->step = GENSEC_HTTP_BASIC_DONE; + return NT_STATUS_OK; + + case GENSEC_HTTP_BASIC_DONE: + case GENSEC_HTTP_BASIC_ERROR: + default: + break; + } + state->step = GENSEC_HTTP_BASIC_ERROR; + return NT_STATUS_INTERNAL_ERROR; + + case GENSEC_SERVER: + state->step = GENSEC_HTTP_BASIC_ERROR; + return NT_STATUS_NOT_IMPLEMENTED; + } + + state->step = GENSEC_HTTP_BASIC_ERROR; + return NT_STATUS_INTERNAL_ERROR; +} + +static const struct gensec_security_ops gensec_http_basic_security_ops = { + .name = "http_basic", + .auth_type = 0, + .client_start = gensec_http_basic_client_start, + .update = gensec_http_basic_update, + .enabled = true, + .priority = GENSEC_EXTERNAL, +}; + +_PUBLIC_ NTSTATUS gensec_http_basic_init(void) +{ + NTSTATUS status; + + status = gensec_register(&gensec_http_basic_security_ops); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to register '%s' gensec backend!\n", + gensec_http_basic_security_ops.name)); + return status; + } + + return status; +} diff --git a/source4/lib/http/gensec/ntlm.c b/source4/lib/http/gensec/ntlm.c new file mode 100644 index 0000000..07470fa --- /dev/null +++ b/source4/lib/http/gensec/ntlm.c @@ -0,0 +1,120 @@ +/* + Unix SMB/CIFS implementation. + + HTTP library - NTLM authentication mechanism gensec module + + Copyright (C) 2014 Samuel Cabrero <samuelcabr...@kernevil.me> + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "auth/auth.h" +#include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" + +_PUBLIC_ NTSTATUS gensec_http_ntlm_init(void); + +struct gensec_http_ntlm_state { + struct gensec_security *sub; +}; + +static NTSTATUS gensec_http_ntlm_client_start(struct gensec_security *gensec) +{ + NTSTATUS status; + struct gensec_http_ntlm_state *state; + + state = talloc_zero(gensec, struct gensec_http_ntlm_state); + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } + gensec->private_data = state; + + status = gensec_subcontext_start(state, gensec, &state->sub); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return gensec_start_mech_by_oid(state->sub, GENSEC_OID_NTLMSSP); +} + +static NTSTATUS gensec_http_ntlm_update(struct gensec_security *gensec_ctx, + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const DATA_BLOB in, + DATA_BLOB *out) +{ + NTSTATUS status; + struct gensec_http_ntlm_state *state; + DATA_BLOB ntlm_in; + + state = talloc_get_type_abort(gensec_ctx->private_data, + struct gensec_http_ntlm_state); + + if (in.length) { + if (strncasecmp((char *)in.data, "NTLM ", 5) != 0) { + return NT_STATUS_INVALID_PARAMETER; + } + ntlm_in = base64_decode_data_blob_talloc(mem_ctx, + (char *)&in.data[5]); + } else { + ntlm_in = data_blob_null; + } + + status = gensec_update_ev(state->sub, mem_ctx, ev, ntlm_in, out); + if (NT_STATUS_IS_OK(status) || + NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + char *tmp, *b64; + b64 = base64_encode_data_blob(mem_ctx, *out); + if (b64 == NULL) { + return NT_STATUS_NO_MEMORY; + } + + tmp = talloc_asprintf(mem_ctx, "NTLM %s", b64); + TALLOC_FREE(b64); + if (tmp == NULL) { + return NT_STATUS_NO_MEMORY; + } + *out = data_blob_string_const(tmp); + } + + if (ntlm_in.data) { + data_blob_free(&ntlm_in); + } + + return status; +} + +static const struct gensec_security_ops gensec_http_ntlm_security_ops = { + .name = "http_ntlm", + .auth_type = 0, + .client_start = gensec_http_ntlm_client_start, + .update = gensec_http_ntlm_update, + .enabled = true, + .priority = GENSEC_EXTERNAL, +}; + +_PUBLIC_ NTSTATUS gensec_http_ntlm_init(void) +{ + NTSTATUS status; + + status = gensec_register(&gensec_http_ntlm_security_ops); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to register '%s' gensec backend!\n", + gensec_http_ntlm_security_ops.name)); + return status; + } + + return status; +} diff --git a/source4/lib/http/http.c b/source4/lib/http/http.c new file mode 100644 index 0000000..314ceed --- /dev/null +++ b/source4/lib/http/http.c @@ -0,0 +1,825 @@ +/* + Unix SMB/CIFS implementation. + + HTTP library + + Copyright (C) 2013 Samuel Cabrero <samuelcabr...@kernevil.me> + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include <talloc_dict.h> +#include "lib/util/tevent_ntstatus.h" +#include "http.h" +#include "http_internal.h" +#include "util/tevent_werror.h" +#include "lib/util/dlinklist.h" + + +/** + * Determines if a response should have a body. + * Follows the rules in RFC 2616 section 4.3. + * @return 1 if the response MUST have a body; 0 if the response MUST NOT have + * a body. Returns -1 on error. + */ +static int http_response_needs_body(struct http_request *req) +{ + if (!req) return -1; + + /* If response code is 503, the body contains the error description + * (2.1.2.1.3) + */ + if (req->response_code == 503) + return 1; + + return 0; +} + + +/** + * Parses the HTTP headers + */ +static enum http_read_status http_parse_headers(struct http_read_response_state *state) +{ + enum http_read_status status = HTTP_ALL_DATA_READ; + char *ptr = NULL; + char *line = NULL; + char *key = NULL; + char *value = NULL; + int n = 0; + int ret; + + /* Sanity checks */ + if (!state || !state->response) { + DEBUG(0, ("%s: Invalid Parameter\n", __func__)); + return HTTP_DATA_CORRUPTED; + } + + if (state->buffer.length > state->max_headers_size) { + DEBUG(0, ("%s: Headers too long: %zi, maximum length is %zi\n", __func__, + state->buffer.length, state->max_headers_size)); + return HTTP_DATA_TOO_LONG; + } + + line = talloc_strndup(state, (char *)state->buffer.data, state->buffer.length); + if (!line) { + DEBUG(0, ("%s: Memory error\n", __func__)); + return HTTP_DATA_CORRUPTED; + } + + ptr = strstr(line, "\r\n"); + if (ptr == NULL) { + TALLOC_FREE(line); + return HTTP_MORE_DATA_EXPECTED; + } + + state->response->headers_size += state->buffer.length; + + if (strncmp(line, "\r\n", 2) == 0) { + DEBUG(11,("%s: All headers read\n", __func__)); + + ret = http_response_needs_body(state->response); + switch (ret) { + case 0: + DEBUG(11, ("%s: Skipping body for code %d\n", __func__, + state->response->response_code)); + state->parser_state = HTTP_READING_DONE; + break; + case 1: + DEBUG(11, ("%s: Start of read body\n", __func__)); + state->parser_state = HTTP_READING_BODY; + break; + case -1: + DEBUG(0, ("%s_: Error in http_response_needs_body\n", __func__)); + TALLOC_FREE(line); + return HTTP_DATA_CORRUPTED; + break; + } + + TALLOC_FREE(line); + return HTTP_ALL_DATA_READ; + } + + n = sscanf(line, "%a[^:]: %a[^\r\n]\r\n", &key, &value); + if (n != 2) { + DEBUG(0, ("%s: Error parsing header '%s'\n", __func__, line)); + status = HTTP_DATA_CORRUPTED; + goto error; + } + + if (http_add_header(state->response, &state->response->headers, key, value) == -1) { + DEBUG(0, ("%s: Error adding header\n", __func__)); + status = HTTP_DATA_CORRUPTED; + goto error; + } + +error: + free(key); + free(value); + TALLOC_FREE(line); + return status; +} + +/** + * Parses the first line of a HTTP response + */ +static bool http_parse_response_line(struct http_read_response_state *state) +{ + bool status = true; + char *protocol; + char *msg = NULL; + char major; + char minor; + int code; + char *line = NULL; + int n; + + /* Sanity checks */ + if (!state) { + DEBUG(0, ("%s: Input parameter is NULL\n", __func__)); + return false; + } + + line = talloc_strndup(state, (char*)state->buffer.data, state->buffer.length); + if (!line) { + DEBUG(0, ("%s: Memory error\n", __func__)); + return false; + } + + n = sscanf(line, "%a[^/]/%c.%c %d %a[^\r\n]\r\n", + &protocol, &major, &minor, &code, &msg); + + DEBUG(11, ("%s: Header parsed(%i): protocol->%s, major->%c, minor->%c, " + "code->%d, message->%s\n", __func__, n, protocol, major, minor, + code, msg)); + + if (n != 5) { + DEBUG(0, ("%s: Error parsing header\n", __func__)); + status = false; + goto error; + } + + if (major != '1') { + DEBUG(0, ("%s: Bad HTTP major number '%c'\n", __func__, major)); + status = false; + goto error; + } + + if (code == 0) { + DEBUG(0, ("%s: Bad response code '%d'", __func__, code)); + status = false; + goto error; + } + + if (msg == NULL) { + DEBUG(0, ("%s: Error parsing HTTP data\n", __func__)); + status = false; + goto error; + } + + state->response->major = major; + state->response->minor = minor; + state->response->response_code = code; + state->response->response_code_line = talloc_strndup(state->response, + msg, strlen(msg)); + +error: + free(protocol); + free(msg); + TALLOC_FREE(line); + return status; +} + +/* + * Parses header lines from a request or a response into the specified + * request object given a buffer. + * + * Returns + * HTTP_DATA_CORRUPTED on error -- Samba Shared Repository