summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/rpc_server/srv_pipe.c377
1 files changed, 173 insertions, 204 deletions
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index f1bc54250a..01cf65184d 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -33,8 +33,7 @@
#include "../librpc/gen_ndr/ndr_krb5pac.h"
#include "../libcli/auth/schannel.h"
#include "../libcli/auth/spnego.h"
-#include "../libcli/auth/ntlmssp.h"
-#include "ntlmssp_wrap.h"
+#include "dcesrv_ntlmssp.h"
#include "rpc_server.h"
#include "rpc_dce.h"
#include "librpc/crypto/gse.h"
@@ -251,72 +250,49 @@ bool create_next_pdu(struct pipes_struct *p)
the pipe struct.
*******************************************************************/
-static bool pipe_ntlmssp_verify_final(struct pipes_struct *p,
- DATA_BLOB *p_resp_blob)
+static bool pipe_ntlmssp_verify_final(TALLOC_CTX *mem_ctx,
+ struct auth_ntlmssp_state *ntlmssp_ctx,
+ enum dcerpc_AuthLevel auth_level,
+ struct client_address *client_id,
+ struct ndr_syntax_id *syntax,
+ struct auth_serversupplied_info **server_info)
{
- DATA_BLOB session_key, reply;
+ DATA_BLOB session_key;
NTSTATUS status;
- struct auth_ntlmssp_state *a = p->auth.a_u.auth_ntlmssp_state;
bool ret;
- DEBUG(5,("pipe_ntlmssp_verify_final: pipe %s checking user details\n",
- get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
-
- ZERO_STRUCT(reply);
-
- /* this has to be done as root in order to verify the password */
- become_root();
- status = auth_ntlmssp_update(a, *p_resp_blob, &reply);
- unbecome_root();
-
- /* Don't generate a reply. */
- data_blob_free(&reply);
-
- if (!NT_STATUS_IS_OK(status)) {
- return False;
- }
+ DEBUG(5, (__location__ ": pipe %s checking user details\n",
+ get_pipe_name_from_syntax(talloc_tos(), syntax)));
/* Finally - if the pipe negotiated integrity (sign) or privacy (seal)
ensure the underlying NTLMSSP flags are also set. If not we should
refuse the bind. */
- if (p->auth.auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
- if (!auth_ntlmssp_negotiated_sign(a)) {
- DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet integrity requested "
- "but client declined signing.\n",
- get_pipe_name_from_syntax(talloc_tos(),
- &p->syntax)));
- return False;
- }
- }
- if (p->auth.auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
- if (!auth_ntlmssp_negotiated_seal(a)) {
- DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet privacy requested "
- "but client declined sealing.\n",
- get_pipe_name_from_syntax(talloc_tos(),
- &p->syntax)));
- return False;
- }
+ status = ntlmssp_server_check_flags(ntlmssp_ctx,
+ (auth_level ==
+ DCERPC_AUTH_LEVEL_INTEGRITY),
+ (auth_level ==
+ DCERPC_AUTH_LEVEL_PRIVACY));
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, (__location__ ": Client failed to negotatie proper "
+ "security for pipe %s\n",
+ get_pipe_name_from_syntax(talloc_tos(), syntax)));
+ return false;
}
- DEBUG(5, ("pipe_ntlmssp_verify_final: OK: user: %s domain: %s "
- "workstation: %s\n",
- auth_ntlmssp_get_username(a),
- auth_ntlmssp_get_domain(a),
- auth_ntlmssp_get_client(a)));
-
- TALLOC_FREE(p->server_info);
+ TALLOC_FREE(*server_info);
- status = auth_ntlmssp_steal_server_info(p, a, &p->server_info);
+ status = ntlmssp_server_get_user_info(ntlmssp_ctx,
+ mem_ctx, server_info);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("auth_ntlmssp_server_info failed to obtain the server info for authenticated user: %s\n",
- nt_errstr(status)));
+ DEBUG(0, (__location__ ": failed to obtain the server info "
+ "for authenticated user: %s\n", nt_errstr(status)));
return false;
}
- if (p->server_info->ptok == NULL) {
- DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
- return False;
+ if ((*server_info)->ptok == NULL) {
+ DEBUG(1, ("Auth module failed to provide nt_user_token\n"));
+ return false;
}
/*
@@ -327,20 +303,27 @@ static bool pipe_ntlmssp_verify_final(struct pipes_struct *p,
session_key = generic_session_key();
if (session_key.data == NULL) {
- return False;
+ return false;
}
- ret = server_info_set_session_key(p->server_info, session_key);
-
+ ret = server_info_set_session_key((*server_info), session_key);
data_blob_free(&session_key);
+ if (!ret) {
+ DEBUG(0, ("Failed to set session key!\n"));
+ return false;
+ }
- return True;
+ return true;
}
static NTSTATUS pipe_gssapi_auth_bind_next(struct pipes_struct *p,
TALLOC_CTX *mem_ctx,
struct dcerpc_auth *pauth_info,
DATA_BLOB *response);
+static NTSTATUS finalize_gssapi_bind(TALLOC_CTX *mem_ctx,
+ struct gse_context *gse_ctx,
+ struct client_address *client_id,
+ struct auth_serversupplied_info **sinfo);
/*******************************************************************
This is the "stage3" response after a bind request and reply.
@@ -388,22 +371,52 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt)
switch (auth_info.auth_type) {
case DCERPC_AUTH_TYPE_NTLMSSP:
- if (!pipe_ntlmssp_verify_final(p, &auth_info.credentials)) {
- goto err;
- }
+ status = ntlmssp_server_step(p->auth.a_u.auth_ntlmssp_state,
+ pkt, &auth_info.credentials,
+ &response);
break;
case DCERPC_AUTH_TYPE_KRB5:
status = pipe_gssapi_auth_bind_next(p, pkt,
&auth_info, &response);
- if (!NT_STATUS_IS_OK(status)) {
+ break;
+ default:
+ DEBUG(0, (__location__ ": incorrect auth type (%u).\n",
+ (unsigned int)auth_info.auth_type));
+ return false;
+ }
+
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_MORE_PROCESSING_REQUIRED) ||
+ response.length) {
+ DEBUG(0, (__location__ ": This was supposed to be the final "
+ "leg, but crypto machinery claims a response is "
+ "needed, aborting auth!\n"));
+ data_blob_free(&response);
+ goto err;
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Auth failed (%s)\n", nt_errstr(status)));
+ goto err;
+ }
+
+ /* Now verify auth was indeed successful and extract server info */
+
+ switch (auth_info.auth_type) {
+ case DCERPC_AUTH_TYPE_NTLMSSP:
+ if (!pipe_ntlmssp_verify_final(p,
+ p->auth.a_u.auth_ntlmssp_state,
+ p->auth.auth_level,
+ p->client_id, &p->syntax,
+ &p->server_info)) {
goto err;
}
- if (response.length) {
- DEBUG(0, (__location__ ": This was supposed to be "
- "the final leg, but gssapi machinery "
- "claims a response is needed, "
- "aborting auth!\n"));
- data_blob_free(&response);
+ break;
+ case DCERPC_AUTH_TYPE_KRB5:
+ status = finalize_gssapi_bind(p, p->auth.a_u.gssapi_state,
+ p->client_id, &p->server_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("gssapi bind failed with: %s",
+ nt_errstr(status)));
goto err;
}
@@ -638,90 +651,72 @@ static bool pipe_spnego_auth_bind_negotiate(struct pipes_struct *p,
struct dcerpc_auth *pauth_info,
DATA_BLOB *response)
{
- DATA_BLOB secblob;
- DATA_BLOB chal;
+ DATA_BLOB secblob = data_blob_null;
+ DATA_BLOB chal = data_blob_null;
char *OIDs[ASN1_MAX_OIDS];
int i;
NTSTATUS status;
bool got_kerberos_mechanism = false;
- struct auth_ntlmssp_state *a = NULL;
-
- ZERO_STRUCT(secblob);
- ZERO_STRUCT(chal);
+ bool ret;
if (pauth_info->credentials.data[0] != ASN1_APPLICATION(0)) {
- goto err;
+ ret = false;
+ goto done;
}
/* parse out the OIDs and the first sec blob */
- if (!spnego_parse_negTokenInit(talloc_tos(),
- pauth_info->credentials, OIDs, NULL, &secblob)) {
- DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to parse the security blob.\n"));
- goto err;
+ ret = spnego_parse_negTokenInit(talloc_tos(),
+ pauth_info->credentials, OIDs, NULL, &secblob);
+ if (!ret) {
+ DEBUG(0, (__location__ ": Failed to parse the secblob.\n"));
+ goto done;
}
- if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
+ if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
+ strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
got_kerberos_mechanism = true;
}
- for (i=0;OIDs[i];i++) {
- DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got OID %s\n", OIDs[i]));
+ for (i = 0; OIDs[i]; i++) {
+ DEBUG(3, (__location__ ": Got OID %s\n", OIDs[i]));
TALLOC_FREE(OIDs[i]);
}
- DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
+ DEBUG(3, (__location__ ": Got secblob of size %lu\n",
+ (unsigned long)secblob.length));
- if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || USE_KERBEROS_KEYTAB) ) {
- bool ret;
+ if (got_kerberos_mechanism &&
+ ((lp_security()==SEC_ADS) || USE_KERBEROS_KEYTAB)) {
ret = pipe_spnego_auth_bind_kerberos(p, mem_ctx, pauth_info,
&secblob, response);
- data_blob_free(&secblob);
- return ret;
+ goto done;
}
/* Free any previous auth type. */
free_pipe_auth_data(&p->auth);
+ p->auth.a_u.auth_ntlmssp_state = NULL;
if (!got_kerberos_mechanism) {
/* Initialize the NTLM engine. */
- status = auth_ntlmssp_start(&a);
- if (!NT_STATUS_IS_OK(status)) {
- goto err;
- }
-
- /* Clear flags,
- * then set them according to requested Auth Level */
- auth_ntlmssp_and_flags(a, ~(NTLMSSP_NEGOTIATE_SIGN |
- NTLMSSP_NEGOTIATE_SEAL));
- switch (pauth_info->auth_level) {
- case DCERPC_AUTH_LEVEL_INTEGRITY:
- auth_ntlmssp_or_flags(a,
- NTLMSSP_NEGOTIATE_SIGN);
- break;
- case DCERPC_AUTH_LEVEL_PRIVACY:
- /* Privacy always implies both sign and seal
- * for ntlmssp */
- auth_ntlmssp_or_flags(a,
- NTLMSSP_NEGOTIATE_SIGN |
- NTLMSSP_NEGOTIATE_SEAL);
- break;
- default:
- break;
- }
- /*
- * Pass the first security blob of data to it.
- * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
- * which means we need another packet to complete the bind.
- */
-
- status = auth_ntlmssp_update(a, secblob, &chal);
+ status = ntlmssp_server_auth_start(p,
+ (pauth_info->auth_level ==
+ DCERPC_AUTH_LEVEL_INTEGRITY),
+ (pauth_info->auth_level ==
+ DCERPC_AUTH_LEVEL_PRIVACY),
+ true, &secblob, &chal,
+ &p->auth.a_u.auth_ntlmssp_state);
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
- goto err;
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, (__location__ ": Failed to start NTLMSSP "
+ "auth (%s).\n", nt_errstr(status)));
+ ret = false;
+ goto done;
}
/* Generate the response blob we need for step 2 of the bind. */
- *response = spnego_gen_auth_response(mem_ctx, &chal, status, OID_NTLMSSP);
+ *response = spnego_gen_auth_response(
+ mem_ctx, &chal,
+ NT_STATUS_MORE_PROCESSING_REQUIRED,
+ OID_NTLMSSP);
} else {
/*
* SPNEGO negotiate down to NTLMSSP. The subsequent
@@ -733,27 +728,18 @@ static bool pipe_spnego_auth_bind_negotiate(struct pipes_struct *p,
OID_NTLMSSP);
}
- /* auth_pad_len will be handled by the caller */
-
- p->auth.a_u.auth_ntlmssp_state = a;
p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data;
p->auth.auth_type = DCERPC_AUTH_TYPE_SPNEGO;
p->auth.spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
- data_blob_free(&secblob);
- data_blob_free(&chal);
-
- /* We can't set pipe_bound True yet - we need an RPC_ALTER_CONTEXT response packet... */
- return True;
+ ret = true;
- err:
+done:
data_blob_free(&secblob);
data_blob_free(&chal);
- p->auth.a_u.auth_ntlmssp_state = NULL;
-
- return False;
+ return ret;
}
/*******************************************************************
@@ -765,61 +751,75 @@ static bool pipe_spnego_auth_bind_continue(struct pipes_struct *p,
struct dcerpc_auth *pauth_info,
DATA_BLOB *response)
{
- DATA_BLOB auth_blob;
- DATA_BLOB auth_reply;
- struct auth_ntlmssp_state *a = p->auth.a_u.auth_ntlmssp_state;
-
- ZERO_STRUCT(auth_blob);
- ZERO_STRUCT(auth_reply);
+ DATA_BLOB auth_blob = data_blob_null;
+ DATA_BLOB auth_reply = data_blob_null;
+ NTSTATUS status;
+ bool ret;
/*
* NB. If we've negotiated down from krb5 to NTLMSSP we'll currently
* fail here as 'a' == NULL.
*/
if (p->auth.auth_type != DCERPC_AUTH_TYPE_SPNEGO ||
- p->auth.spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP || !a) {
- DEBUG(0,("pipe_spnego_auth_bind_continue: not in NTLMSSP auth state.\n"));
+ p->auth.spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP ||
+ p->auth.a_u.auth_ntlmssp_state == NULL) {
+ DEBUG(0, (__location__ ": not in NTLMSSP auth state.\n"));
goto err;
}
if (pauth_info->credentials.data[0] != ASN1_CONTEXT(1)) {
- DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob type.\n"));
+ DEBUG(0, (__location__ ": invalid SPNEGO blob type.\n"));
goto err;
}
- if (!spnego_parse_auth(talloc_tos(), pauth_info->credentials, &auth_blob)) {
- DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob.\n"));
+ ret = spnego_parse_auth(talloc_tos(),
+ pauth_info->credentials, &auth_blob);
+ if (!ret) {
+ DEBUG(0, (__location__ ": invalid SPNEGO blob.\n"));
goto err;
}
- /*
- * The following call actually checks the challenge/response data.
- * for correctness against the given DOMAIN\user name.
- */
+ status = ntlmssp_server_step(p->auth.a_u.auth_ntlmssp_state,
+ p, &auth_blob, &auth_reply);
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_MORE_PROCESSING_REQUIRED) ||
+ auth_reply.length) {
+ DEBUG(0, (__location__ ": This was supposed to be the final "
+ "leg, but crypto machinery claims a response is "
+ "needed, aborting auth!\n"));
+ goto err;
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Auth failed (%s)\n", nt_errstr(status)));
+ goto err;
+ }
- if (!pipe_ntlmssp_verify_final(p, &auth_blob)) {
+ ret = pipe_ntlmssp_verify_final(p,
+ p->auth.a_u.auth_ntlmssp_state,
+ p->auth.auth_level,
+ p->client_id, &p->syntax,
+ &p->server_info);
+ if (!ret) {
goto err;
}
data_blob_free(&auth_blob);
/* Generate the spnego "accept completed" blob - no incoming data. */
- *response = spnego_gen_auth_response(mem_ctx, &auth_reply, NT_STATUS_OK, OID_NTLMSSP);
+ *response = spnego_gen_auth_response(mem_ctx, &auth_reply,
+ NT_STATUS_OK, OID_NTLMSSP);
data_blob_free(&auth_reply);
- p->pipe_bound = True;
-
- return True;
-
- err:
+ p->pipe_bound = true;
+ return true;
+err:
data_blob_free(&auth_blob);
data_blob_free(&auth_reply);
-
free_pipe_auth_data(&p->auth);
- return False;
+ return false;
}
/*******************************************************************
@@ -951,61 +951,37 @@ static bool pipe_ntlmssp_auth_bind(struct pipes_struct *p,
DATA_BLOB *response)
{
NTSTATUS status;
- struct auth_ntlmssp_state *a = NULL;
if (strncmp((char *)auth_info->credentials.data, "NTLMSSP", 7) != 0) {
DEBUG(0, ("Failed to read NTLMSSP in blob\n"));
- goto err;
+ return false;
}
/* We have an NTLMSSP blob. */
- status = auth_ntlmssp_start(&a);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("pipe_ntlmssp_auth_bind: auth_ntlmssp_start failed: %s\n",
- nt_errstr(status) ));
- goto err;
- }
-
- /* Clear flags, then set them according to requested Auth Level */
- auth_ntlmssp_and_flags(a, ~(NTLMSSP_NEGOTIATE_SIGN |
- NTLMSSP_NEGOTIATE_SEAL));
-
- switch (auth_info->auth_level) {
- case DCERPC_AUTH_LEVEL_INTEGRITY:
- auth_ntlmssp_or_flags(a, NTLMSSP_NEGOTIATE_SIGN);
- break;
- case DCERPC_AUTH_LEVEL_PRIVACY:
- /* Privacy always implies both sign and seal for ntlmssp */
- auth_ntlmssp_or_flags(a, NTLMSSP_NEGOTIATE_SIGN |
- NTLMSSP_NEGOTIATE_SEAL);
- break;
- default:
- break;
- }
-
- status = auth_ntlmssp_update(a, auth_info->credentials, response);
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(0,("pipe_ntlmssp_auth_bind: auth_ntlmssp_update failed: %s\n",
- nt_errstr(status) ));
- goto err;
+ status = ntlmssp_server_auth_start(p,
+ (auth_info->auth_level ==
+ DCERPC_AUTH_LEVEL_INTEGRITY),
+ (auth_info->auth_level ==
+ DCERPC_AUTH_LEVEL_PRIVACY),
+ true,
+ &auth_info->credentials,
+ response,
+ &p->auth.a_u.auth_ntlmssp_state);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
+ DEBUG(0, (__location__ ": auth_ntlmssp_start failed: %s\n",
+ nt_errstr(status)));
+ return false;
}
/* Make sure data is bound to the memctx, to be freed the caller */
talloc_steal(mem_ctx, response->data);
- p->auth.a_u.auth_ntlmssp_state = a;
p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data;
p->auth.auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
- DEBUG(10,("pipe_ntlmssp_auth_bind: NTLMSSP auth started\n"));
-
- /* We can't set pipe_bound True yet - we need an DCERPC_PKT_AUTH3 response packet... */
- return True;
+ DEBUG(10, (__location__ ": NTLMSSP auth started\n"));
- err:
-
- TALLOC_FREE(a);
- return False;
+ return true;
}
/*******************************************************************
@@ -1280,14 +1256,7 @@ static NTSTATUS pipe_gssapi_auth_bind_next(struct pipes_struct *p,
if (gse_require_more_processing(gse_ctx)) {
/* ask for next leg */
- return NT_STATUS_OK;
- }
-
- status = finalize_gssapi_bind(p, gse_ctx,
- p->client_id, &p->server_info);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("gssapi bind failed with: %s", nt_errstr(status)));
- return NT_STATUS_ACCESS_DENIED;
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
return NT_STATUS_OK;