auth/gensec: add gensec_child_* helper functions
authorStefan Metzmacher <metze@samba.org>
Fri, 30 Dec 2016 16:54:12 +0000 (17:54 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Sun, 21 May 2017 19:05:09 +0000 (21:05 +0200)
They will be used to simplify the spnego backend
and maybe of some use for a future negoex backend.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
auth/gensec/gensec.c
auth/gensec/gensec_internal.h
auth/gensec/gensec_start.c
auth/gensec/gensec_util.c

index 23d762b2a73e63f088fa1af3a751b0f36f36dd7e..9b1661eebcd0ea2c3db08bf8c60ff576283ec3eb 100644 (file)
@@ -330,6 +330,10 @@ _PUBLIC_ NTSTATUS gensec_update_ev(struct gensec_security *gensec_security,
        struct tevent_req *subreq = NULL;
        bool ok;
 
+       if (gensec_security->child_security != NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        if (ops->update_send == NULL) {
 
                if (ev == NULL) {
@@ -480,6 +484,11 @@ _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx,
        state->ops = gensec_security->ops;
        state->gensec_security = gensec_security;
 
+       if (gensec_security->child_security != NULL) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return tevent_req_post(req, ev);
+       }
+
        if (state->ops->update_send == NULL) {
                state->in = in;
                state->im = tevent_create_immediate(state);
index 26c9817d5dfd796c1fda83e9c902c0e867270c5d..9c160d3d0842ec04101a2a312b844510ee6f8ec9 100644 (file)
@@ -114,6 +114,7 @@ struct gensec_security {
         * PAC is found) */
        struct auth4_context *auth_context;
 
+       struct gensec_security *parent_security;
        struct gensec_security *child_security;
 };
 
@@ -129,4 +130,49 @@ NTSTATUS gensec_may_reset_crypto(struct gensec_security *gensec_security,
 
 const char *gensec_final_auth_type(struct gensec_security *gensec_security);
 
+NTSTATUS gensec_child_ready(struct gensec_security *parent,
+                           struct gensec_security *child);
+void gensec_child_want_feature(struct gensec_security *gensec_security,
+                              uint32_t feature);
+bool gensec_child_have_feature(struct gensec_security *gensec_security,
+                              uint32_t feature);
+NTSTATUS gensec_child_unseal_packet(struct gensec_security *gensec_security,
+                                   uint8_t *data, size_t length,
+                                   const uint8_t *whole_pdu, size_t pdu_length,
+                                   const DATA_BLOB *sig);
+NTSTATUS gensec_child_check_packet(struct gensec_security *gensec_security,
+                                  const uint8_t *data, size_t length,
+                                  const uint8_t *whole_pdu, size_t pdu_length,
+                                  const DATA_BLOB *sig);
+NTSTATUS gensec_child_seal_packet(struct gensec_security *gensec_security,
+                                 TALLOC_CTX *mem_ctx,
+                                 uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig);
+NTSTATUS gensec_child_sign_packet(struct gensec_security *gensec_security,
+                                 TALLOC_CTX *mem_ctx,
+                                 const uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig);
+NTSTATUS gensec_child_wrap(struct gensec_security *gensec_security,
+                          TALLOC_CTX *mem_ctx,
+                          const DATA_BLOB *in,
+                          DATA_BLOB *out);
+NTSTATUS gensec_child_unwrap(struct gensec_security *gensec_security,
+                            TALLOC_CTX *mem_ctx,
+                            const DATA_BLOB *in,
+                            DATA_BLOB *out);
+size_t gensec_child_sig_size(struct gensec_security *gensec_security,
+                            size_t data_size);
+size_t gensec_child_max_input_size(struct gensec_security *gensec_security);
+size_t gensec_child_max_wrapped_size(struct gensec_security *gensec_security);
+NTSTATUS gensec_child_session_key(struct gensec_security *gensec_security,
+                                 TALLOC_CTX *mem_ctx,
+                                 DATA_BLOB *session_key);
+NTSTATUS gensec_child_session_info(struct gensec_security *gensec_security,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct auth_session_info **session_info);
+NTTIME gensec_child_expire_time(struct gensec_security *gensec_security);
+const char *gensec_child_final_auth_type(struct gensec_security *gensec_security);
+
 #endif /* __GENSEC_H__ */
index f10f86d503722656115436d831f061e7c30980f6..c1affd6218afed170cc038242fab87ced2d55be1 100644 (file)
@@ -545,6 +545,25 @@ _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_securi
        return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
 }
 
+static int gensec_security_destructor(struct gensec_security *gctx)
+{
+       if (gctx->parent_security != NULL) {
+               if (gctx->parent_security->child_security == gctx) {
+                       gctx->parent_security->child_security = NULL;
+               }
+               gctx->parent_security = NULL;
+       }
+
+       if (gctx->child_security != NULL) {
+               if (gctx->child_security->parent_security == gctx) {
+                       gctx->child_security->parent_security = NULL;
+               }
+               gctx->child_security = NULL;
+       }
+
+       return 0;
+}
+
 /**
   Start the GENSEC system, returning a context pointer.
   @param mem_ctx The parent TALLOC memory context.
@@ -571,6 +590,7 @@ static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
         * from it */
        (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
 
+       talloc_set_destructor((*gensec_security), gensec_security_destructor);
        return NT_STATUS_OK;
 }
 
@@ -586,6 +606,10 @@ _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
                                 struct gensec_security *parent,
                                 struct gensec_security **gensec_security)
 {
+       if (parent->child_security != NULL) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
        (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
        NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
 
@@ -601,6 +625,23 @@ _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
        (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
        (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
 
+       talloc_set_destructor((*gensec_security), gensec_security_destructor);
+       return NT_STATUS_OK;
+}
+
+_PUBLIC_ NTSTATUS gensec_child_ready(struct gensec_security *parent,
+                                    struct gensec_security *child)
+{
+       if (parent->child_security != NULL) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       if (child->parent_security != NULL) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       parent->child_security = child;
+       child->parent_security = parent;
        return NT_STATUS_OK;
 }
 
@@ -670,6 +711,14 @@ static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
        talloc_unlink(gensec_security, gensec_security->private_data);
        gensec_security->private_data = NULL;
 
+       if (gensec_security->child_security != NULL) {
+               /*
+                * The talloc_unlink(.., gensec_security->private_data)
+                * should have cleared this via
+                * gensec_security_destructor().
+                */
+               return NT_STATUS_INTERNAL_ERROR;
+       }
 
        if (gensec_security->credentials) {
                const char *forced_mech = cli_credentials_get_forced_sasl_mech(gensec_security->credentials);
index da2e2e5f4b8214734f65af861b431abd83260a54..ca5e581f63f930922ff41874f03260ba99175f27 100644 (file)
@@ -110,3 +110,199 @@ NTSTATUS gensec_magic_check_krb5_oid(struct gensec_security *unused,
                return NT_STATUS_INVALID_PARAMETER;
        }
 }
+
+void gensec_child_want_feature(struct gensec_security *gensec_security,
+                              uint32_t feature)
+{
+       struct gensec_security *child_security = gensec_security->child_security;
+
+       gensec_security->want_features |= feature;
+       if (child_security == NULL) {
+               return;
+       }
+       gensec_want_feature(child_security, feature);
+}
+
+bool gensec_child_have_feature(struct gensec_security *gensec_security,
+                              uint32_t feature)
+{
+       struct gensec_security *child_security = gensec_security->child_security;
+
+       if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
+               /*
+                * All mechs with sub (child) mechs need to provide DCERPC
+                * header signing! This is required because the negotiation
+                * of header signing is done before the authentication
+                * is completed.
+                */
+               return true;
+       }
+
+       if (child_security == NULL) {
+               return false;
+       }
+
+       return gensec_have_feature(child_security, feature);
+}
+
+NTSTATUS gensec_child_unseal_packet(struct gensec_security *gensec_security,
+                                   uint8_t *data, size_t length,
+                                   const uint8_t *whole_pdu, size_t pdu_length,
+                                   const DATA_BLOB *sig)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_unseal_packet(gensec_security->child_security,
+                                   data, length,
+                                   whole_pdu, pdu_length,
+                                   sig);
+}
+
+NTSTATUS gensec_child_check_packet(struct gensec_security *gensec_security,
+                                  const uint8_t *data, size_t length,
+                                  const uint8_t *whole_pdu, size_t pdu_length,
+                                  const DATA_BLOB *sig)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_check_packet(gensec_security->child_security,
+                                  data, length,
+                                  whole_pdu, pdu_length,
+                                  sig);
+}
+
+NTSTATUS gensec_child_seal_packet(struct gensec_security *gensec_security,
+                                 TALLOC_CTX *mem_ctx,
+                                 uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_seal_packet(gensec_security->child_security,
+                                 mem_ctx,
+                                 data, length,
+                                 whole_pdu, pdu_length,
+                                 sig);
+}
+
+NTSTATUS gensec_child_sign_packet(struct gensec_security *gensec_security,
+                                 TALLOC_CTX *mem_ctx,
+                                 const uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_sign_packet(gensec_security->child_security,
+                                 mem_ctx,
+                                 data, length,
+                                 whole_pdu, pdu_length,
+                                 sig);
+}
+
+NTSTATUS gensec_child_wrap(struct gensec_security *gensec_security,
+                          TALLOC_CTX *mem_ctx,
+                          const DATA_BLOB *in,
+                          DATA_BLOB *out)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_wrap(gensec_security->child_security,
+                          mem_ctx, in, out);
+}
+
+NTSTATUS gensec_child_unwrap(struct gensec_security *gensec_security,
+                            TALLOC_CTX *mem_ctx,
+                            const DATA_BLOB *in,
+                            DATA_BLOB *out)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_unwrap(gensec_security->child_security,
+                            mem_ctx, in, out);
+}
+
+size_t gensec_child_sig_size(struct gensec_security *gensec_security,
+                            size_t data_size)
+{
+       if (gensec_security->child_security == NULL) {
+               return 0;
+       }
+
+       return gensec_sig_size(gensec_security->child_security, data_size);
+}
+
+size_t gensec_child_max_input_size(struct gensec_security *gensec_security)
+{
+       if (gensec_security->child_security == NULL) {
+               return 0;
+       }
+
+       return gensec_max_input_size(gensec_security->child_security);
+}
+
+size_t gensec_child_max_wrapped_size(struct gensec_security *gensec_security)
+{
+       if (gensec_security->child_security == NULL) {
+               return 0;
+       }
+
+       return gensec_max_wrapped_size(gensec_security->child_security);
+}
+
+NTSTATUS gensec_child_session_key(struct gensec_security *gensec_security,
+                                 TALLOC_CTX *mem_ctx,
+                                 DATA_BLOB *session_key)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_session_key(gensec_security->child_security,
+                                 mem_ctx,
+                                 session_key);
+}
+
+NTSTATUS gensec_child_session_info(struct gensec_security *gensec_security,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct auth_session_info **session_info)
+{
+       if (gensec_security->child_security == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return gensec_session_info(gensec_security->child_security,
+                                  mem_ctx,
+                                  session_info);
+}
+
+NTTIME gensec_child_expire_time(struct gensec_security *gensec_security)
+{
+       if (gensec_security->child_security == NULL) {
+               return GENSEC_EXPIRE_TIME_INFINITY;
+       }
+
+       return gensec_expire_time(gensec_security->child_security);
+}
+
+const char *gensec_child_final_auth_type(struct gensec_security *gensec_security)
+{
+       if (gensec_security->child_security == NULL) {
+               return "NONE";
+       }
+
+       return gensec_final_auth_type(gensec_security->child_security);
+}