summaryrefslogtreecommitdiff
path: root/source3/librpc/rpc/dcerpc_spnego.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/librpc/rpc/dcerpc_spnego.c')
-rw-r--r--source3/librpc/rpc/dcerpc_spnego.c108
1 files changed, 104 insertions, 4 deletions
diff --git a/source3/librpc/rpc/dcerpc_spnego.c b/source3/librpc/rpc/dcerpc_spnego.c
index e733469ac3..a0832ce09f 100644
--- a/source3/librpc/rpc/dcerpc_spnego.c
+++ b/source3/librpc/rpc/dcerpc_spnego.c
@@ -19,6 +19,8 @@
#include "includes.h"
#include "../libcli/auth/spnego.h"
+#include "include/ntlmssp_wrap.h"
+#include "librpc/gen_ndr/ntlmssp.h"
#include "dcerpc_spnego.h"
#include "dcerpc_gssapi.h"
@@ -26,7 +28,7 @@ struct spnego_context {
enum dcerpc_AuthType auth_type;
union {
- struct auth_ntlmssp_state *auth_ntlmssp_state;
+ struct auth_ntlmssp_state *ntlmssp_state;
struct gse_context *gssapi_state;
} mech_ctx;
@@ -88,12 +90,80 @@ NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+NTSTATUS spnego_ntlmssp_init_client(TALLOC_CTX *mem_ctx,
+ enum dcerpc_AuthLevel auth_level,
+ const char *domain,
+ const char *username,
+ const char *password,
+ struct spnego_context **spnego_ctx)
+{
+ struct spnego_context *sp_ctx;
+ NTSTATUS status;
+
+ status = spnego_context_init(mem_ctx,
+ DCERPC_AUTH_TYPE_NTLMSSP, &sp_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = auth_ntlmssp_client_start(sp_ctx,
+ global_myname(),
+ lp_workgroup(),
+ lp_client_ntlmv2_auth(),
+ &sp_ctx->mech_ctx.ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(sp_ctx);
+ return status;
+ }
+
+ status = auth_ntlmssp_set_username(sp_ctx->mech_ctx.ntlmssp_state,
+ username);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(sp_ctx);
+ return status;
+ }
+
+ status = auth_ntlmssp_set_domain(sp_ctx->mech_ctx.ntlmssp_state,
+ domain);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(sp_ctx);
+ return status;
+ }
+
+ status = auth_ntlmssp_set_password(sp_ctx->mech_ctx.ntlmssp_state,
+ password);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(sp_ctx);
+ return status;
+ }
+
+ /*
+ * Turn off sign+seal to allow selected auth level to turn it back on.
+ */
+ auth_ntlmssp_and_flags(sp_ctx->mech_ctx.ntlmssp_state,
+ ~(NTLMSSP_NEGOTIATE_SIGN |
+ NTLMSSP_NEGOTIATE_SEAL));
+
+ if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
+ auth_ntlmssp_or_flags(sp_ctx->mech_ctx.ntlmssp_state,
+ NTLMSSP_NEGOTIATE_SIGN);
+ } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+ auth_ntlmssp_or_flags(sp_ctx->mech_ctx.ntlmssp_state,
+ NTLMSSP_NEGOTIATE_SEAL |
+ NTLMSSP_NEGOTIATE_SIGN);
+ }
+
+ *spnego_ctx = sp_ctx;
+ return NT_STATUS_OK;
+}
+
NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx,
struct spnego_context *sp_ctx,
DATA_BLOB *spnego_in,
DATA_BLOB *spnego_out)
{
struct gse_context *gse_ctx;
+ struct auth_ntlmssp_state *ntlmssp_ctx;
struct spnego_data sp_in, sp_out;
DATA_BLOB token_in = data_blob_null;
DATA_BLOB token_out = data_blob_null;
@@ -129,6 +199,7 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx,
if (sp_ctx->state == SPNEGO_CONV_AUTH_CONFIRM) {
if (sp_in.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) {
sp_ctx->state = SPNEGO_CONV_AUTH_DONE;
+ *spnego_out = data_blob_null;
status = NT_STATUS_OK;
} else {
status = NT_STATUS_ACCESS_DENIED;
@@ -152,8 +223,21 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx,
break;
case DCERPC_AUTH_TYPE_NTLMSSP:
- status = NT_STATUS_NOT_IMPLEMENTED;
- goto done;
+
+ ntlmssp_ctx = sp_ctx->mech_ctx.ntlmssp_state;
+ status = auth_ntlmssp_update(ntlmssp_ctx,
+ token_in, &token_out);
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ mech_wants_more = true;
+ } else if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ mech_oids[0] = OID_NTLMSSP;
+
+ break;
+
default:
status = NT_STATUS_INTERNAL_ERROR;
goto done;
@@ -227,6 +311,8 @@ bool spnego_require_more_processing(struct spnego_context *sp_ctx)
case DCERPC_AUTH_TYPE_KRB5:
gse_ctx = sp_ctx->mech_ctx.gssapi_state;
return gse_require_more_processing(gse_ctx);
+ case DCERPC_AUTH_TYPE_NTLMSSP:
+ return false;
default:
DEBUG(0, ("Unsupported type in request!\n"));
return false;
@@ -242,7 +328,7 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx,
*auth_context = sp_ctx->mech_ctx.gssapi_state;
break;
case DCERPC_AUTH_TYPE_NTLMSSP:
- *auth_context = sp_ctx->mech_ctx.auth_ntlmssp_state;
+ *auth_context = sp_ctx->mech_ctx.ntlmssp_state;
break;
default:
return NT_STATUS_INTERNAL_ERROR;
@@ -252,3 +338,17 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx,
return NT_STATUS_OK;
}
+DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx)
+{
+ switch (sp_ctx->auth_type) {
+ case DCERPC_AUTH_TYPE_KRB5:
+ return gse_get_session_key(sp_ctx->mech_ctx.gssapi_state);
+ case DCERPC_AUTH_TYPE_NTLMSSP:
+ return auth_ntlmssp_get_session_key(
+ sp_ctx->mech_ctx.ntlmssp_state);
+ default:
+ DEBUG(0, ("Unsupported type in request!\n"));
+ return data_blob_null;
+ }
+}
+