Exemple #1
0
int mit_samba_context_init(struct mit_samba_context **_ctx)
{
	NTSTATUS status;
	struct mit_samba_context *ctx;
	const char *s4_conf_file;
	int ret;
	struct samba_kdc_base_context base_ctx;

	ctx = talloc_zero(NULL, struct mit_samba_context);
	if (!ctx) {
		ret = ENOMEM;
		goto done;
	}

	base_ctx.ev_ctx = tevent_context_init(ctx);
	if (!base_ctx.ev_ctx) {
		ret = ENOMEM;
		goto done;
	}
	tevent_loop_allow_nesting(base_ctx.ev_ctx);
	base_ctx.lp_ctx = loadparm_init_global(false);
	if (!base_ctx.lp_ctx) {
		ret = ENOMEM;
		goto done;
	}

	setup_logging("mitkdc", DEBUG_STDOUT);

	/* init s4 configuration */
	s4_conf_file = lpcfg_configfile(base_ctx.lp_ctx);
	if (s4_conf_file) {
		lpcfg_load(base_ctx.lp_ctx, s4_conf_file);
	} else {
		lpcfg_load_default(base_ctx.lp_ctx);
	}

	status = samba_kdc_setup_db_ctx(ctx, &base_ctx, &ctx->db_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		ret = EINVAL;
		goto done;
	}

	/* init heimdal's krb_context and log facilities */
	ret = smb_krb5_init_context_basic(ctx,
					  ctx->db_ctx->lp_ctx,
					  &ctx->context);
	if (ret) {
		goto done;
	}

	ret = 0;

done:
	if (ret) {
		mit_samba_context_free(ctx);
	} else {
		*_ctx = ctx;
	}
	return ret;
}
Exemple #2
0
krb5_error_code smb_krb5_init_context(void *parent_ctx,
				      struct tevent_context *ev,
				      struct loadparm_context *lp_ctx,
				       struct smb_krb5_context **smb_krb5_context)
{
	krb5_error_code ret;
	TALLOC_CTX *tmp_ctx;

	initialize_krb5_error_table();

	tmp_ctx = talloc_new(parent_ctx);
	*smb_krb5_context = talloc(tmp_ctx, struct smb_krb5_context);

	if (!*smb_krb5_context || !tmp_ctx) {
		talloc_free(tmp_ctx);
		return ENOMEM;
	}

	ret = smb_krb5_init_context_basic(tmp_ctx, ev, lp_ctx,
					  &(*smb_krb5_context)->krb5_context);
	if (ret) {
		DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n",
			 error_message(ret)));
		talloc_free(tmp_ctx);
		return ret;
	}

	/* TODO: Should we have a different name here? */
	ret = krb5_initlog((*smb_krb5_context)->krb5_context, "Samba", &(*smb_krb5_context)->logf);

	if (ret) {
		DEBUG(1,("krb5_initlog failed (%s)\n",
			 smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
		krb5_free_context((*smb_krb5_context)->krb5_context);
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy);

	ret = krb5_addlog_func((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf, 0 /* min */, -1 /* max */,
			       smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL);
	if (ret) {
		DEBUG(1,("krb5_addlog_func failed (%s)\n",
			 smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
		talloc_free(tmp_ctx);
		return ret;
	}
	krb5_set_warn_dest((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf);

	/* Set use of our socket lib */
	ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context,
					smb_krb5_send_and_recv_func,
					ev);
	if (ret) {
		DEBUG(1,("krb5_set_send_recv_func failed (%s)\n",
			 smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_steal(parent_ctx, *smb_krb5_context);
	talloc_free(tmp_ctx);

	/* Set options in kerberos */

	krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context,
					   lp_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false));

	return 0;
}
krb5_error_code smb_krb5_init_context(void *parent_ctx,
				      struct loadparm_context *lp_ctx,
				      struct smb_krb5_context **smb_krb5_context)
{
	krb5_error_code ret;
	TALLOC_CTX *tmp_ctx;
	krb5_context kctx;
#ifdef SAMBA4_USES_HEIMDAL
	krb5_log_facility *logf;
#endif

	initialize_krb5_error_table();

	tmp_ctx = talloc_new(parent_ctx);
	*smb_krb5_context = talloc_zero(tmp_ctx, struct smb_krb5_context);

	if (!*smb_krb5_context || !tmp_ctx) {
		talloc_free(tmp_ctx);
		return ENOMEM;
	}

	ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, &kctx);
	if (ret) {
		DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n",
			 error_message(ret)));
		talloc_free(tmp_ctx);
		return ret;
	}
	(*smb_krb5_context)->krb5_context = kctx;

	talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy);

#ifdef SAMBA4_USES_HEIMDAL
	/* TODO: Should we have a different name here? */
	ret = krb5_initlog(kctx, "Samba", &logf);

	if (ret) {
		DEBUG(1,("krb5_initlog failed (%s)\n",
			 smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
		talloc_free(tmp_ctx);
		return ret;
	}
	(*smb_krb5_context)->pvt_log_data = logf;

	ret = krb5_addlog_func(kctx, logf, 0 /* min */, -1 /* max */,
			       smb_krb5_debug_wrapper,
				smb_krb5_debug_close, NULL);
	if (ret) {
		DEBUG(1,("krb5_addlog_func failed (%s)\n",
			 smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
		talloc_free(tmp_ctx);
		return ret;
	}
	krb5_set_warn_dest(kctx, logf);

	/* Set options in kerberos */

	krb5_set_dns_canonicalize_hostname(kctx,
			lpcfg_parm_bool(lp_ctx, NULL, "krb5",
					"set_dns_canonicalize", false));
#endif
	talloc_steal(parent_ctx, *smb_krb5_context);
	talloc_free(tmp_ctx);

	return 0;
}
Exemple #4
0
/*
  check that the SPN update should be allowed as an override
  via sam_ctx_system

  This is only called if the client is not a domain controller or
  administrator
 */
static bool writespn_check_spn(struct drsuapi_bind_state *b_state,
			       struct dcesrv_call_state *dce_call,
			       struct ldb_dn *dn,
			       const char *spn)
{
	/*
	 * we only allow SPN updates if:
	 *
	 * 1) they are on the clients own account object
	 * 2) they are of the form SERVICE/dnshostname
	 */
	struct dom_sid *user_sid, *sid;
	TALLOC_CTX *tmp_ctx = talloc_new(dce_call);
	struct ldb_result *res;
	const char *attrs[] = { "objectSID", "dNSHostName", NULL };
	int ret;
	krb5_context krb_ctx;
	krb5_error_code kerr;
	krb5_principal principal;
	const krb5_data *component;
	const char *dns_name, *dnsHostName;

	/* The service principal name shouldn't be NULL */
	if (spn == NULL) {
		talloc_free(tmp_ctx);
		return false;
	}

	/*
	  get the objectSid of the DN that is being modified, and
	  check it matches the user_sid in their token
	 */

	ret = dsdb_search_dn(b_state->sam_ctx, tmp_ctx, &res, dn, attrs,
			     DSDB_SEARCH_ONE_ONLY);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return false;
	}

	user_sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
	sid = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
	if (sid == NULL) {
		talloc_free(tmp_ctx);
		return false;
	}

	dnsHostName = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName",
						  NULL);
	if (dnsHostName == NULL) {
		talloc_free(tmp_ctx);
		return false;
	}

	if (!dom_sid_equal(sid, user_sid)) {
		talloc_free(tmp_ctx);
		return false;
	}

	kerr = smb_krb5_init_context_basic(tmp_ctx,
					   dce_call->conn->dce_ctx->lp_ctx,
					   &krb_ctx);
	if (kerr != 0) {
		talloc_free(tmp_ctx);
		return false;
	}

	ret = krb5_parse_name_flags(krb_ctx, spn, KRB5_PRINCIPAL_PARSE_NO_REALM,
				    &principal);
	if (kerr != 0) {
		krb5_free_context(krb_ctx);
		talloc_free(tmp_ctx);
		return false;
	}

	if (krb5_princ_size(krb_ctx, principal) != 2) {
		krb5_free_principal(krb_ctx, principal);
		krb5_free_context(krb_ctx);
		talloc_free(tmp_ctx);
		return false;
	}

	component = krb5_princ_component(krb_ctx, principal, 1);
	dns_name = (const char *)component->data;

	if (strcasecmp(dns_name, dnsHostName) != 0) {
		krb5_free_principal(krb_ctx, principal);
		krb5_free_context(krb_ctx);
		talloc_free(tmp_ctx);
		return false;
	}

	/* its a simple update on their own account - allow it with
	 * permissions override */
	krb5_free_principal(krb_ctx, principal);
	krb5_free_context(krb_ctx);
	talloc_free(tmp_ctx);

	return true;
}