s3-dcerpc: add spnego server helpers
authorSimo Sorce <idra@samba.org>
Tue, 31 Aug 2010 19:08:31 +0000 (15:08 -0400)
committerSimo Sorce <idra@samba.org>
Fri, 17 Sep 2010 14:53:53 +0000 (10:53 -0400)
squashed: add michlistMIC signature checks

source3/Makefile.in
source3/include/proto.h
source3/librpc/crypto/cli_spnego.c
source3/librpc/crypto/spnego.h
source3/libsmb/clispnego.c
source3/rpc_server/dcesrv_spnego.c [new file with mode: 0644]
source3/rpc_server/dcesrv_spnego.h [new file with mode: 0644]

index 831c7379a4ec87e31a93cc662894709978eb1e61..f85f16e7dc176a31ceedbb5fb605dbf6936845e0 100644 (file)
@@ -712,7 +712,8 @@ RPC_NCACN_NP = rpc_server/srv_pipe_register.o rpc_server/rpc_ncacn_np.o \
 RPC_SERVICE = rpc_server/rpc_server.o
 
 RPC_CRYPTO = rpc_server/dcesrv_ntlmssp.o \
-               rpc_server/dcesrv_gssapi.o
+               rpc_server/dcesrv_gssapi.o \
+               rpc_server/dcesrv_spnego.o
 
 RPC_PIPE_OBJ = rpc_server/srv_pipe.o rpc_server/srv_pipe_hnd.o \
               $(RPC_NCACN_NP) $(RPC_SERVICE) $(RPC_CRYPTO)
index 7796e055b9d011ff48ba406a261e9088408b5c29..16fef58c045e0e304f36ea1b47ad7d79f2fd960a 100644 (file)
@@ -2605,6 +2605,16 @@ bool spnego_parse_auth_response(TALLOC_CTX *ctx,
                                const char *mechOID,
                                DATA_BLOB *auth);
 
+bool spnego_parse_auth_and_mic(TALLOC_CTX *ctx, DATA_BLOB blob,
+                               DATA_BLOB *auth, DATA_BLOB *signature);
+DATA_BLOB spnego_gen_auth_response_and_mic(TALLOC_CTX *ctx,
+                                          NTSTATUS nt_status,
+                                          const char *mechOID,
+                                          DATA_BLOB *reply,
+                                          DATA_BLOB *mechlistMIC);
+bool spnego_mech_list_blob(TALLOC_CTX *mem_ctx,
+                          char **oid_list, DATA_BLOB *data);
+
 /* The following definitions come from libsmb/clistr.c  */
 
 size_t clistr_push_fn(const char *function,
index 07301c9dc9902176e68dec55065672696a29c55c..bf58e25d9a87d2f0379663cea06d3ccb55d8adbb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  SPNEGO Encapsulation
- *  RPC Pipe client routines
+ *  Client functions
  *  Copyright (C) Simo Sorce 2010.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -349,3 +349,88 @@ DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx,
        }
 }
 
+NTSTATUS spnego_sign(TALLOC_CTX *mem_ctx,
+                       struct spnego_context *sp_ctx,
+                       DATA_BLOB *data, DATA_BLOB *full_data,
+                       DATA_BLOB *signature)
+{
+       switch(sp_ctx->mech) {
+       case SPNEGO_KRB5:
+               return gse_sign(mem_ctx,
+                               sp_ctx->mech_ctx.gssapi_state,
+                               data, signature);
+       case SPNEGO_NTLMSSP:
+               return auth_ntlmssp_sign_packet(
+                                       sp_ctx->mech_ctx.ntlmssp_state,
+                                       mem_ctx,
+                                       data->data, data->length,
+                                       full_data->data, full_data->length,
+                                       signature);
+       default:
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+}
+
+NTSTATUS spnego_sigcheck(TALLOC_CTX *mem_ctx,
+                        struct spnego_context *sp_ctx,
+                        DATA_BLOB *data, DATA_BLOB *full_data,
+                        DATA_BLOB *signature)
+{
+       switch(sp_ctx->mech) {
+       case SPNEGO_KRB5:
+               return gse_sigcheck(mem_ctx,
+                                   sp_ctx->mech_ctx.gssapi_state,
+                                   data, signature);
+       case SPNEGO_NTLMSSP:
+               return auth_ntlmssp_check_packet(
+                                       sp_ctx->mech_ctx.ntlmssp_state,
+                                       data->data, data->length,
+                                       full_data->data, full_data->length,
+                                       signature);
+       default:
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+}
+
+NTSTATUS spnego_seal(TALLOC_CTX *mem_ctx,
+                       struct spnego_context *sp_ctx,
+                       DATA_BLOB *data, DATA_BLOB *full_data,
+                       DATA_BLOB *signature)
+{
+       switch(sp_ctx->mech) {
+       case SPNEGO_KRB5:
+               return gse_seal(mem_ctx,
+                               sp_ctx->mech_ctx.gssapi_state,
+                               data, signature);
+       case SPNEGO_NTLMSSP:
+               return auth_ntlmssp_seal_packet(
+                                       sp_ctx->mech_ctx.ntlmssp_state,
+                                       mem_ctx,
+                                       data->data, data->length,
+                                       full_data->data, full_data->length,
+                                       signature);
+       default:
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+}
+
+NTSTATUS spnego_unseal(TALLOC_CTX *mem_ctx,
+                       struct spnego_context *sp_ctx,
+                       DATA_BLOB *data, DATA_BLOB *full_data,
+                       DATA_BLOB *signature)
+{
+       switch(sp_ctx->mech) {
+       case SPNEGO_KRB5:
+               return gse_unseal(mem_ctx,
+                                   sp_ctx->mech_ctx.gssapi_state,
+                                   data, signature);
+       case SPNEGO_NTLMSSP:
+               return auth_ntlmssp_unseal_packet(
+                                       sp_ctx->mech_ctx.ntlmssp_state,
+                                       data->data, data->length,
+                                       full_data->data, full_data->length,
+                                       signature);
+       default:
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+}
index 9512ed632416b77d8bac83ca0609cc2e92dfc96f..68d9243bb05b70917b77dc8a74ba8b3a44c849ae 100644 (file)
@@ -34,8 +34,12 @@ struct spnego_context {
                struct gse_context *gssapi_state;
        } mech_ctx;
 
+       char *oid_list[ASN1_MAX_OIDS];
+       char *mech_oid;
+
        enum {
                SPNEGO_CONV_INIT = 0,
+               SPNEGO_CONV_NEGO,
                SPNEGO_CONV_AUTH_MORE,
                SPNEGO_CONV_AUTH_CONFIRM,
                SPNEGO_CONV_AUTH_DONE
@@ -43,6 +47,7 @@ struct spnego_context {
 
        bool do_sign;
        bool do_seal;
+       bool is_dcerpc;
 };
 
 NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx,
@@ -75,4 +80,22 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx,
 
 DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx,
                                 struct spnego_context *sp_ctx);
+
+NTSTATUS spnego_sign(TALLOC_CTX *mem_ctx,
+                       struct spnego_context *sp_ctx,
+                       DATA_BLOB *data, DATA_BLOB *full_data,
+                       DATA_BLOB *signature);
+NTSTATUS spnego_sigcheck(TALLOC_CTX *mem_ctx,
+                        struct spnego_context *sp_ctx,
+                        DATA_BLOB *data, DATA_BLOB *full_data,
+                        DATA_BLOB *signature);
+NTSTATUS spnego_seal(TALLOC_CTX *mem_ctx,
+                       struct spnego_context *sp_ctx,
+                       DATA_BLOB *data, DATA_BLOB *full_data,
+                       DATA_BLOB *signature);
+NTSTATUS spnego_unseal(TALLOC_CTX *mem_ctx,
+                       struct spnego_context *sp_ctx,
+                       DATA_BLOB *data, DATA_BLOB *full_data,
+                       DATA_BLOB *signature);
+
 #endif /* _CLI_SPENGO_H_ */
index 539b41105698751c88e647cee3f39692872855a9..9ef848b59ce5e4b6f13b8e5be93bb8391e7014ad 100644 (file)
@@ -408,7 +408,8 @@ DATA_BLOB spnego_gen_auth(TALLOC_CTX *ctx, DATA_BLOB blob)
 /*
  parse a SPNEGO auth packet. This contains the encrypted passwords
 */
-bool spnego_parse_auth(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *auth)
+bool spnego_parse_auth_and_mic(TALLOC_CTX *ctx, DATA_BLOB blob,
+                               DATA_BLOB *auth, DATA_BLOB *signature)
 {
        ssize_t len;
        struct spnego_data token;
@@ -429,17 +430,34 @@ bool spnego_parse_auth(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *auth)
        *auth = data_blob_talloc(ctx,
                                 token.negTokenTarg.responseToken.data,
                                 token.negTokenTarg.responseToken.length);
+
+       if (!signature) {
+               goto done;
+       }
+
+       *signature = data_blob_talloc(ctx,
+                                token.negTokenTarg.mechListMIC.data,
+                                token.negTokenTarg.mechListMIC.length);
+
+done:
        spnego_free_data(&token);
 
        return true;
 }
 
+bool spnego_parse_auth(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *auth)
+{
+       return spnego_parse_auth_and_mic(ctx, blob, auth, NULL);
+}
+
 /*
   generate a minimal SPNEGO response packet.  Doesn't contain much.
 */
-DATA_BLOB spnego_gen_auth_response(TALLOC_CTX *ctx,
-                                  DATA_BLOB *reply, NTSTATUS nt_status,
-                                  const char *mechOID)
+DATA_BLOB spnego_gen_auth_response_and_mic(TALLOC_CTX *ctx,
+                                          NTSTATUS nt_status,
+                                          const char *mechOID,
+                                          DATA_BLOB *reply,
+                                          DATA_BLOB *mechlistMIC)
 {
        ASN1_DATA *data;
        DATA_BLOB ret;
@@ -476,6 +494,14 @@ DATA_BLOB spnego_gen_auth_response(TALLOC_CTX *ctx,
                asn1_pop_tag(data);
        }
 
+       if (mechlistMIC && mechlistMIC->data != NULL) {
+               asn1_push_tag(data, ASN1_CONTEXT(3));
+               asn1_write_OctetString(data,
+                                       mechlistMIC->data,
+                                       mechlistMIC->length);
+               asn1_pop_tag(data);
+       }
+
        asn1_pop_tag(data);
        asn1_pop_tag(data);
 
@@ -484,6 +510,13 @@ DATA_BLOB spnego_gen_auth_response(TALLOC_CTX *ctx,
        return ret;
 }
 
+DATA_BLOB spnego_gen_auth_response(TALLOC_CTX *ctx, DATA_BLOB *reply,
+                                  NTSTATUS nt_status, const char *mechOID)
+{
+       return spnego_gen_auth_response_and_mic(ctx, nt_status,
+                                               mechOID, reply, NULL);
+}
+
 /*
  parse a SPNEGO auth packet. This contains the encrypted passwords
 */
@@ -558,3 +591,41 @@ bool spnego_parse_auth_response(TALLOC_CTX *ctx,
        asn1_free(data);
        return True;
 }
+
+bool spnego_mech_list_blob(TALLOC_CTX *mem_ctx,
+                          char **oid_list, DATA_BLOB *raw_data)
+{
+       ASN1_DATA *data;
+       unsigned int idx;
+
+       if (!oid_list || !oid_list[0] || !raw_data) {
+               return false;
+       }
+
+       data = asn1_init(talloc_tos());
+       if (data == NULL) {
+               return false;
+       }
+
+       asn1_push_tag(data, ASN1_SEQUENCE(0));
+       for (idx = 0; oid_list[idx]; idx++) {
+               asn1_write_OID(data, oid_list[idx]);
+       }
+       asn1_pop_tag(data);
+
+       if (data->has_error) {
+               DEBUG(3, (__location__ " failed at %d\n", (int)data->ofs));
+               asn1_free(data);
+               return false;
+       }
+
+       *raw_data = data_blob_talloc(mem_ctx, data->data, data->length);
+       if (!raw_data->data) {
+               DEBUG(3, (__location__": data_blob_talloc() failed!\n"));
+               asn1_free(data);
+               return false;
+       }
+
+       asn1_free(data);
+       return true;
+}
diff --git a/source3/rpc_server/dcesrv_spnego.c b/source3/rpc_server/dcesrv_spnego.c
new file mode 100644 (file)
index 0000000..f5a2fbb
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ *  SPNEGO Encapsulation
+ *  DCERPC Server functions
+ *  Copyright (C) Simo Sorce 2010.
+ *
+ *  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 "../libcli/auth/spnego.h"
+#include "dcesrv_ntlmssp.h"
+#include "dcesrv_gssapi.h"
+#include "dcesrv_spnego.h"
+
+static NTSTATUS spnego_init_server(TALLOC_CTX *mem_ctx,
+                                  bool do_sign, bool do_seal,
+                                  bool is_dcerpc,
+                                  struct spnego_context **spnego_ctx)
+{
+       struct spnego_context *sp_ctx = NULL;
+
+       sp_ctx = talloc_zero(mem_ctx, struct spnego_context);
+       if (!sp_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       sp_ctx->do_sign = do_sign;
+       sp_ctx->do_seal = do_seal;
+       sp_ctx->is_dcerpc = is_dcerpc;
+
+       *spnego_ctx = sp_ctx;
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS spnego_server_mech_init(struct spnego_context *sp_ctx,
+                                       DATA_BLOB *token_in,
+                                       DATA_BLOB *token_out)
+{
+       struct auth_ntlmssp_state *ntlmssp_ctx;
+       struct gse_context *gse_ctx;
+       NTSTATUS status;
+
+       switch (sp_ctx->mech) {
+       case SPNEGO_KRB5:
+               status = gssapi_server_auth_start(sp_ctx,
+                                                 sp_ctx->do_sign,
+                                                 sp_ctx->do_seal,
+                                                 sp_ctx->is_dcerpc,
+                                                 token_in,
+                                                 token_out,
+                                                 &gse_ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("Failed to init gssapi server "
+                                 "(%s)\n", nt_errstr(status)));
+                       return status;
+               }
+
+               sp_ctx->mech_ctx.gssapi_state = gse_ctx;
+               break;
+
+       case SPNEGO_NTLMSSP:
+               status = ntlmssp_server_auth_start(sp_ctx,
+                                                  sp_ctx->do_sign,
+                                                  sp_ctx->do_seal,
+                                                  sp_ctx->is_dcerpc,
+                                                  token_in,
+                                                  token_out,
+                                                  &ntlmssp_ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("Failed to init ntlmssp server "
+                                 "(%s)\n", nt_errstr(status)));
+                       return status;
+               }
+
+               sp_ctx->mech_ctx.ntlmssp_state = ntlmssp_ctx;
+               break;
+
+       default:
+               DEBUG(3, ("No known mechanisms available\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS spnego_server_step(struct spnego_context *sp_ctx,
+                           TALLOC_CTX *mem_ctx,
+                           DATA_BLOB *spnego_in,
+                           DATA_BLOB *spnego_out)
+{
+       DATA_BLOB token_in = data_blob_null;
+       DATA_BLOB token_out = data_blob_null;
+       DATA_BLOB signature = data_blob_null;
+       DATA_BLOB MICblob = data_blob_null;
+       struct spnego_data sp_in;
+       ssize_t len_in = 0;
+       NTSTATUS status;
+       bool ret;
+
+       len_in = spnego_read_data(mem_ctx, *spnego_in, &sp_in);
+       if (len_in == -1) {
+               DEBUG(1, (__location__ ": invalid SPNEGO blob.\n"));
+               dump_data(10, spnego_in->data, spnego_in->length);
+               status = NT_STATUS_INVALID_PARAMETER;
+               sp_ctx->state = SPNEGO_CONV_AUTH_DONE;
+               goto done;
+       }
+       if (sp_in.type != SPNEGO_NEG_TOKEN_TARG) {
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+       token_in = sp_in.negTokenTarg.responseToken;
+       signature = sp_in.negTokenTarg.mechListMIC;
+
+       switch (sp_ctx->state) {
+       case SPNEGO_CONV_NEGO:
+               /* still to initialize */
+               status = spnego_server_mech_init(sp_ctx,
+                                                &token_in,
+                                                &token_out);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto done;
+               }
+               /* server always need at least one reply from client */
+               status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+               sp_ctx->state = SPNEGO_CONV_AUTH_MORE;
+               break;
+
+       case SPNEGO_CONV_AUTH_MORE:
+
+               switch(sp_ctx->mech) {
+               case SPNEGO_KRB5:
+                       status = gssapi_server_step(
+                                       sp_ctx->mech_ctx.gssapi_state,
+                                       mem_ctx, &token_in, &token_out);
+                       break;
+               case SPNEGO_NTLMSSP:
+                       status = ntlmssp_server_step(
+                                       sp_ctx->mech_ctx.ntlmssp_state,
+                                       mem_ctx, &token_in, &token_out);
+                       break;
+               default:
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto done;
+               }
+
+               break;
+
+       case SPNEGO_CONV_AUTH_DONE:
+               /* we are already done, can't step further */
+               /* fall thorugh and return error */
+       default:
+               /* wrong case */
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (NT_STATUS_IS_OK(status) && signature.length != 0) {
+               /* last packet and requires signature check */
+               ret = spnego_mech_list_blob(talloc_tos(),
+                                           sp_ctx->oid_list, &MICblob);
+               if (ret) {
+                       status = spnego_sigcheck(talloc_tos(), sp_ctx,
+                                                &MICblob, &MICblob,
+                                                &signature);
+               } else {
+                       status = NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+       if (NT_STATUS_IS_OK(status) && signature.length != 0) {
+               /* if signature was good, sign our own packet too */
+               status = spnego_sign(talloc_tos(), sp_ctx,
+                                    &MICblob, &MICblob, &signature);
+       }
+
+done:
+       *spnego_out = spnego_gen_auth_response_and_mic(mem_ctx, status,
+                                                       sp_ctx->mech_oid,
+                                                       &token_out,
+                                                       &signature);
+       if (!spnego_out->data) {
+               DEBUG(1, ("SPNEGO wrapping failed!\n"));
+               status = NT_STATUS_UNSUCCESSFUL;
+       }
+
+       if (NT_STATUS_IS_OK(status) ||
+           !NT_STATUS_EQUAL(status,
+                       NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               sp_ctx->state = SPNEGO_CONV_AUTH_DONE;
+       }
+
+       data_blob_free(&token_in);
+       data_blob_free(&token_out);
+       return status;
+}
+
+NTSTATUS spnego_server_auth_start(TALLOC_CTX *mem_ctx,
+                                 bool do_sign,
+                                 bool do_seal,
+                                 bool is_dcerpc,
+                                 DATA_BLOB *spnego_in,
+                                 DATA_BLOB *spnego_out,
+                                 struct spnego_context **spnego_ctx)
+{
+       struct spnego_context *sp_ctx;
+       DATA_BLOB token_in = data_blob_null;
+       DATA_BLOB token_out = data_blob_null;
+       unsigned int i;
+       NTSTATUS status;
+       bool ret;
+
+       if (!spnego_in->length) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       status = spnego_init_server(mem_ctx, do_sign, do_seal, is_dcerpc, &sp_ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       ret = spnego_parse_negTokenInit(sp_ctx, *spnego_in,
+                                       sp_ctx->oid_list, NULL, &token_in);
+       if (!ret) {
+               DEBUG(3, ("Invalid SPNEGO message\n"));
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
+       /* try for krb auth first */
+       for (i = 0; sp_ctx->oid_list[i] && sp_ctx->mech == SPNEGO_NONE; i++) {
+               if (strcmp(OID_KERBEROS5, sp_ctx->oid_list[i]) == 0 ||
+                   strcmp(OID_KERBEROS5_OLD, sp_ctx->oid_list[i]) == 0) {
+
+                       if (lp_security() == SEC_ADS || USE_KERBEROS_KEYTAB) {
+                               sp_ctx->mech = SPNEGO_KRB5;
+                               sp_ctx->mech_oid = sp_ctx->oid_list[i];
+                       }
+               }
+       }
+
+       /* if auth type still undetermined, try for NTLMSSP */
+       for (i = 0; sp_ctx->oid_list[i] && sp_ctx->mech == SPNEGO_NONE; i++) {
+               if (strcmp(OID_NTLMSSP, sp_ctx->oid_list[i]) == 0) {
+                       sp_ctx->mech = SPNEGO_NTLMSSP;
+                       sp_ctx->mech_oid = sp_ctx->oid_list[i];
+               }
+       }
+
+       if (!sp_ctx->mech_oid) {
+               DEBUG(3, ("No known mechanisms available\n"));
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               DEBUG(10, ("Client Provided OIDs:\n"));
+               for (i = 0; sp_ctx->oid_list[i]; i++) {
+                       DEBUG(10, ("  %d: %s\n", i, sp_ctx->oid_list[i]));
+               }
+               DEBUG(10, ("Chosen OID: %s\n", sp_ctx->mech_oid));
+       }
+
+       /* If it is not the first OID, then token_in is not valid for the
+        * choosen mech */
+       if (sp_ctx->mech_oid != sp_ctx->oid_list[0]) {
+               /* request more and send back empty token */
+               status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+               sp_ctx->state = SPNEGO_CONV_NEGO;
+               goto done;
+       }
+
+       status = spnego_server_mech_init(sp_ctx, &token_in, &token_out);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       DEBUG(10, ("SPNEGO(%d) auth started\n", sp_ctx->mech));
+
+       /* server always need at least one reply from client */
+       status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+       sp_ctx->state = SPNEGO_CONV_AUTH_MORE;
+
+done:
+       *spnego_out = spnego_gen_auth_response(mem_ctx, &token_out,
+                                               status, sp_ctx->mech_oid);
+       if (!spnego_out->data) {
+               status = NT_STATUS_INVALID_PARAMETER;
+               TALLOC_FREE(sp_ctx);
+       } else {
+               status = NT_STATUS_OK;
+               *spnego_ctx = sp_ctx;
+       }
+
+       data_blob_free(&token_in);
+       data_blob_free(&token_out);
+
+       return status;
+}
+
diff --git a/source3/rpc_server/dcesrv_spnego.h b/source3/rpc_server/dcesrv_spnego.h
new file mode 100644 (file)
index 0000000..eeb865d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  SPNEGO Encapsulation
+ *  Server routines
+ *  Copyright (C) Simo Sorce 2010.
+ *
+ *  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/>.
+ */
+
+#ifndef _DCESRV_SPNEGO_H_
+#define _DCESRV_SPENGO_H_
+
+#include "librpc/crypto/spnego.h"
+
+NTSTATUS spnego_server_auth_start(TALLOC_CTX *mem_ctx,
+                                 bool do_sign,
+                                 bool do_seal,
+                                 bool is_dcerpc,
+                                 DATA_BLOB *spnego_in,
+                                 DATA_BLOB *spnego_out,
+                                 struct spnego_context **spnego_ctx);
+NTSTATUS spnego_server_step(struct spnego_context *sp_ctx,
+                           TALLOC_CTX *mem_ctx,
+                           DATA_BLOB *spnego_in,
+                           DATA_BLOB *spnego_out);
+
+#endif /* _DCESRV_SPENGO_H_ */