diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-08-23 05:29:37 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:34:24 -0500 |
commit | ba90b652d918fb34f1e43083f8283f669c73c340 (patch) | |
tree | 2c656b05b9d164c9294f5c47089481355685336e /source4/librpc/rpc | |
parent | 8f9478b09d39d8c13871684a6af3d3e1629a0e84 (diff) | |
download | samba-ba90b652d918fb34f1e43083f8283f669c73c340.tar.gz samba-ba90b652d918fb34f1e43083f8283f669c73c340.tar.bz2 samba-ba90b652d918fb34f1e43083f8283f669c73c340.zip |
r9505: Work on GENSEC and the code that calls it, for tighter interface
requirements, and for better error reporting.
In particular, the composite session setup (extended security/SPNEGO)
code now returns errors, rather than NT_STATUS_NO_MEMORY. This is
seen particularly when GENSEC fails to start.
The tighter interface rules apply to NTLMSSP, which must be called
exactly the right number of times. This is to match some of our other
less-tested modules, where adding flexablity is harder. (and this is
security code, so let's just get it right). As such, the DCE/RPC and
LDAP clients have been updated.
Andrew Bartlett
(This used to be commit 134550cf752b9edad66c3368750bfb4bbd9d55d1)
Diffstat (limited to 'source4/librpc/rpc')
-rw-r--r-- | source4/librpc/rpc/dcerpc_auth.c | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index 7aa563cb9d..8ad3be4ecd 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -50,6 +50,8 @@ NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth DATA_BLOB credentials; DATA_BLOB null_data_blob = data_blob(NULL, 0); + int num_passes = 0; + if (!p->conn->security_state.generic_state) { status = gensec_client_start(p, &p->conn->security_state.generic_state, p->conn->event_ctx); @@ -73,33 +75,27 @@ NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth p->conn->security_state.auth_info->auth_context_id = random(); p->conn->security_state.auth_info->credentials = null_data_blob; - status = gensec_update(p->conn->security_state.generic_state, tmp_ctx, - null_data_blob, - &credentials); - - p->conn->security_state.auth_info->credentials = credentials; - - if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - /* We are demanding a reply, so use a request that will get us one */ - status = dcerpc_bind_byuuid(p, tmp_ctx, uuid, version); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - } else if (NT_STATUS_IS_OK(status)) { - /* We don't care for the reply, so jump to the end */ - status = dcerpc_bind_byuuid(p, tmp_ctx, uuid, version); - goto done; - } else { - /* Something broke in GENSEC - bail */ - goto done; - } - while (1) { + num_passes++; status = gensec_update(p->conn->security_state.generic_state, tmp_ctx, p->conn->security_state.auth_info->credentials, &credentials); + + /* The status value here, from GENSEC is vital to the security + * of the system. Even if the other end accepts, if GENSEC + * claims 'MORE_PROCESSING_REQUIRED' then you must keep + * feeding it blobs, or else the remote host/attacker might + * avoid mutal authentication requirements. + * + * Likewise, you must not feed GENSEC too much (after the OK), + * it doesn't like that either + */ + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(1, ("Failed DCERPC client gensec_update with mechanism %s: %s\n", + gensec_get_name_by_authtype(auth_type), nt_errstr(status))); + break; } @@ -110,18 +106,25 @@ NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth p->conn->security_state.auth_info->credentials = credentials; if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - /* We are demanding a reply, so use a request that will get us one */ - status = dcerpc_alter_context(p, tmp_ctx, &p->syntax, &p->transfer_syntax); + if (num_passes == 1) { + status = dcerpc_bind_byuuid(p, tmp_ctx, uuid, version); + } else { + /* We are demanding a reply, so use a request that will get us one */ + status = dcerpc_alter_context(p, tmp_ctx, &p->syntax, &p->transfer_syntax); + } if (!NT_STATUS_IS_OK(status)) { break; } - } else { + } else if (NT_STATUS_IS_OK(status)) { /* NO reply expected, so just send it */ - status = dcerpc_auth3(p->conn, tmp_ctx); - credentials = data_blob(NULL, 0); - if (!NT_STATUS_IS_OK(status)) { - break; + if (num_passes == 1) { + status = dcerpc_bind_byuuid(p, tmp_ctx, uuid, version); + } else { + status = dcerpc_auth3(p->conn, tmp_ctx); } + break; + } else { + break; } }; |