#include "lib/param/param.h"
#include "lib/util/tsort.h"
#include "lib/util/samba_modules.h"
+#include "lib/util/base64.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
/* the list of currently registered GENSEC backends */
static const struct gensec_security_ops **generic_security_ops;
j = 0;
for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
- int oid_idx;
bool keep = false;
- for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
- if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
- keep = true;
- break;
- }
- }
+ /*
+ * We want to keep SPNGEO and other backends
+ */
+ keep = old_gensec_list[i]->glue;
if (old_gensec_list[i]->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
keep = keep_schannel;
}
backends = gensec_security_mechs(gensec_security, mem_ctx);
for (i=0; backends && backends[i]; i++) {
- if (!gensec_security_ops_enabled(backends[i], gensec_security))
- continue;
+ if (gensec_security != NULL &&
+ !gensec_security_ops_enabled(backends[i], gensec_security)) {
+ continue;
+ }
if (backends[i]->sasl_name
&& (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
backend = backends[i];
int i;
const struct gensec_security_ops **backends;
const struct gensec_security_ops *backend;
- TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
+ TALLOC_CTX *mem_ctx;
+
+ if (auth_type == DCERPC_AUTH_TYPE_NONE) {
+ return NULL;
+ }
+
+ mem_ctx = talloc_new(gensec_security);
if (!mem_ctx) {
return NULL;
}
return NULL;
}
-static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
- const char *name)
+const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
+ const char *name)
{
int i;
const struct gensec_security_ops **backends;
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.
* from it */
(*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
+ talloc_set_destructor((*gensec_security), gensec_security_destructor);
return NT_STATUS_OK;
}
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);
(**gensec_security) = *parent;
(*gensec_security)->ops = NULL;
(*gensec_security)->private_data = NULL;
+ (*gensec_security)->update_busy_ptr = NULL;
(*gensec_security)->subcontext = true;
(*gensec_security)->want_features = parent->want_features;
(*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;
}
return status;
}
-NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
+static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
{
NTSTATUS status;
+ /*
+ * Callers sometimes just reuse a context, we should
+ * clear the internal state before starting it again.
+ */
+ 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);
if (forced_mech &&
return NT_STATUS_INVALID_PARAMETER;
}
gensec_security->dcerpc_auth_level = auth_level;
+ /*
+ * We need to reset sign/seal in order to reset it.
+ * We may got some default features inherited by the credentials
+ */
+ gensec_security->want_features &= ~GENSEC_FEATURE_SIGN;
+ gensec_security->want_features &= ~GENSEC_FEATURE_SEAL;
gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
- gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
+ if (gensec_security->gensec_role == GENSEC_CLIENT) {
+ gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
+ }
+ } else if (auth_level == DCERPC_AUTH_LEVEL_PACKET) {
+ /*
+ * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
+ * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
+ */
+ if (gensec_security->gensec_role == GENSEC_CLIENT) {
+ gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
+ }
} else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
The 'name' can be later used by other backends to find the operations
structure for this backend.
*/
-_PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
+_PUBLIC_ NTSTATUS gensec_register(TALLOC_CTX *ctx,
+ const struct gensec_security_ops *ops)
{
if (gensec_security_by_name(NULL, ops->name) != NULL) {
/* its already registered! */
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- generic_security_ops = talloc_realloc(talloc_autofree_context(),
+ generic_security_ops = talloc_realloc(ctx,
generic_security_ops,
const struct gensec_security_ops *,
gensec_num_backends+2);
_PUBLIC_ NTSTATUS gensec_init(void)
{
static bool initialized = false;
-#define _MODULE_PROTO(init) extern NTSTATUS init(void);
+#define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
#ifdef STATIC_gensec_MODULES
STATIC_gensec_MODULES_PROTO;
init_module_fn static_init[] = { STATIC_gensec_MODULES };
shared_init = load_samba_modules(NULL, "gensec");
- run_init_functions(static_init);
- run_init_functions(shared_init);
+ run_init_functions(NULL, static_init);
+ run_init_functions(NULL, shared_init);
talloc_free(shared_init);