s3-dcerpc: properly implement gse/spnego_get_session_key
authorSimo Sorce <idra@samba.org>
Mon, 2 Aug 2010 16:15:43 +0000 (12:15 -0400)
committerSimo Sorce <idra@samba.org>
Tue, 17 Aug 2010 10:33:13 +0000 (06:33 -0400)
source3/librpc/rpc/dcerpc_gssapi.c
source3/librpc/rpc/dcerpc_gssapi.h
source3/librpc/rpc/dcerpc_spnego.c
source3/librpc/rpc/dcerpc_spnego.h
source3/rpc_client/cli_pipe.c

index 2de46b57525db5ad1c0d888d3a9cf40d0d9372f2..777f5f1caddd2abd0d381a8da77b4cd1126e5584 100644 (file)
 #include <gssapi/gssapi_krb5.h>
 #include <gssapi/gssapi_ext.h>
 
+#ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
+#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11
+#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"
+#endif
+
+#ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID
+#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10
+#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID  "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"
+#endif
+
+gss_OID_desc gse_sesskey_inq_oid = { GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH,
+                               (void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID };
+gss_OID_desc gse_sesskeytype_oid = { GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
+                               (void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID };
+
 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
 
 struct gse_context {
@@ -44,8 +59,6 @@ struct gse_context {
        gss_name_t server_name;
        gss_cred_id_t cli_creds;
 
-       DATA_BLOB session_key;
-
        bool more_processing;
 };
 
@@ -348,9 +361,39 @@ bool gse_require_more_processing(struct gse_context *gse_ctx)
        return gse_ctx->more_processing;
 }
 
-DATA_BLOB gse_get_session_key(struct gse_context *gse_ctx)
+DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
+                               struct gse_context *gse_ctx)
 {
-       return gse_ctx->session_key;
+       OM_uint32 gss_min, gss_maj;
+       gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
+       DATA_BLOB ret;
+
+       gss_maj = gss_inquire_sec_context_by_oid(
+                               &gss_min, gse_ctx->gss_ctx,
+                               &gse_sesskey_inq_oid, &set);
+       if (gss_maj) {
+               DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
+                         gse_errstr(talloc_tos(), gss_maj, gss_min)));
+               return data_blob_null;
+       }
+
+       if ((set == GSS_C_NO_BUFFER_SET) ||
+           (set->count != 2) ||
+           (memcmp(set->elements[1].value,
+                   gse_sesskeytype_oid.elements,
+                   gse_sesskeytype_oid.length) != 0)) {
+               DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
+                         "OID for data in results:\n"));
+               dump_data(1, set->elements[1].value,
+                            set->elements[1].length);
+               return data_blob_null;
+       }
+
+       ret = data_blob_talloc(mem_ctx, set->elements[0].value,
+                                       set->elements[0].length);
+
+       gss_maj = gss_release_buffer_set(&gss_min, &set);
+       return ret;
 }
 
 size_t gse_get_signature_length(struct gse_context *gse_ctx,
index 3152033841894635876ad8144726e8ee458b9190..28bf9d1c27792606b2165e4cca8cb69202bd3dc5 100644 (file)
@@ -43,7 +43,8 @@ NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
                                   DATA_BLOB *token_out);
 
 bool gse_require_more_processing(struct gse_context *gse_ctx);
-DATA_BLOB gse_get_session_key(struct gse_context *gse_ctx);
+DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
+                               struct gse_context *gse_ctx);
 
 size_t gse_get_signature_length(struct gse_context *gse_ctx,
                                int seal, size_t payload_size);
index 5627a0d7e70a8205f4f7d5ac71da138eb4a2104a..ec81a2c70180611d9d01b5a9bc6c5a766d21f05a 100644 (file)
@@ -338,14 +338,19 @@ 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)
+DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx,
+                                struct spnego_context *sp_ctx)
 {
+       DATA_BLOB sk;
+
        switch (sp_ctx->auth_type) {
        case DCERPC_AUTH_TYPE_KRB5:
-               return gse_get_session_key(sp_ctx->mech_ctx.gssapi_state);
+               return gse_get_session_key(mem_ctx,
+                                          sp_ctx->mech_ctx.gssapi_state);
        case DCERPC_AUTH_TYPE_NTLMSSP:
-               return auth_ntlmssp_get_session_key(
+               sk = auth_ntlmssp_get_session_key(
                                        sp_ctx->mech_ctx.ntlmssp_state);
+               return data_blob_dup_talloc(mem_ctx, &sk);
        default:
                DEBUG(0, ("Unsupported type in request!\n"));
                return data_blob_null;
index 58363fd07234bdc920cba499397c4b9e3dcb7297..9d37fd1e38a528dbc589ea3fd20188d842e0c72a 100644 (file)
@@ -49,5 +49,6 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx,
                                    enum dcerpc_AuthType *auth_type,
                                    void **auth_context);
 
-DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx);
+DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx,
+                                struct spnego_context *sp_ctx);
 #endif /* _DCERPC_SPENGO_H_ */
index 1bee2f875b8c5e6d605fb19b773821c68c89dacc..2466418e3998cb6782c671b63192961f4afc1eb2 100644 (file)
@@ -3451,19 +3451,16 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
                make_dup = true;
                break;
        case DCERPC_AUTH_TYPE_SPNEGO:
-               sk = spnego_get_session_key(a->a_u.spnego_state);
-               if (sk.length == 0) {
-                       return NT_STATUS_NO_USER_SESSION_KEY;
-               }
-               make_dup = true;
+               sk = spnego_get_session_key(mem_ctx, a->a_u.spnego_state);
+               make_dup = false;
                break;
        case DCERPC_AUTH_TYPE_NTLMSSP:
                sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state);
                make_dup = true;
                break;
        case DCERPC_AUTH_TYPE_KRB5:
-               sk = gse_get_session_key(a->a_u.gssapi_state);
-               make_dup = true;
+               sk = gse_get_session_key(mem_ctx, a->a_u.gssapi_state);
+               make_dup = false;
                break;
        case DCERPC_AUTH_TYPE_NONE:
                sk = data_blob_const(a->user_session_key.data,