summaryrefslogtreecommitdiff
path: root/auth
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2016-12-30 17:54:12 +0100
committerAndrew Bartlett <abartlet@samba.org>2017-05-21 21:05:09 +0200
commit8332941953c9cc42308e32f6a409c2db39c2936f (patch)
tree4af167f0cd5f8ba67059fbcb6ca90a99dc1161a8 /auth
parent2aab27fef576776520daec90fa546f3e8aff8524 (diff)
downloadsamba-8332941953c9cc42308e32f6a409c2db39c2936f.tar.gz
auth/gensec: add gensec_child_* helper functions
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>
Diffstat (limited to 'auth')
-rw-r--r--auth/gensec/gensec.c9
-rw-r--r--auth/gensec/gensec_internal.h46
-rw-r--r--auth/gensec/gensec_start.c49
-rw-r--r--auth/gensec/gensec_util.c196
4 files changed, 300 insertions, 0 deletions
diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index 23d762b2a73..9b1661eebcd 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -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);
diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h
index 26c9817d5df..9c160d3d084 100644
--- a/auth/gensec/gensec_internal.h
+++ b/auth/gensec/gensec_internal.h
@@ -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__ */
diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c
index f10f86d5037..c1affd6218a 100644
--- a/auth/gensec/gensec_start.c
+++ b/auth/gensec/gensec_start.c
@@ -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);
diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c
index da2e2e5f4b8..ca5e581f63f 100644
--- a/auth/gensec/gensec_util.c
+++ b/auth/gensec/gensec_util.c
@@ -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);
+}