1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00
samba-mirror/source4/dsdb/samdb/samdb.c
Andrew Bartlett e178f6b0e9 ldb_wrap: Provide a way to avoid Samba using ldb_wrap()
ldb_wrap is a caching mechansim, and it should probably be removed
but for now provide a way to avoid it in specific cases where we
know it is harmful.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Jo Sutton <josutton@catalyst.net.nz>
2024-06-10 04:27:30 +00:00

350 lines
9.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Unix SMB/CIFS implementation.
interface functions for the sam database
Copyright (C) Andrew Tridgell 2004
Copyright (C) Volker Lendecke 2004
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "librpc/gen_ndr/ndr_netlogon.h"
#include "librpc/gen_ndr/ndr_security.h"
#include "lib/events/events.h"
#include "lib/ldb-samba/ldb_wrap.h"
#include <ldb.h>
#include <ldb_errors.h>
#include "libcli/security/security.h"
#include "libcli/security/claims-conversions.h"
#include "libcli/auth/libcli_auth.h"
#include "libcli/ldap/ldap_ndr.h"
#include "system/time.h"
#include "system/filesys.h"
#include "ldb_wrap.h"
#include "../lib/util/util_ldb.h"
#include "dsdb/samdb/samdb.h"
#include "../libds/common/flags.h"
#include "param/param.h"
#include "lib/events/events.h"
#include "auth/credentials/credentials.h"
#include "param/secrets.h"
#include "auth/auth.h"
#include "lib/tsocket/tsocket.h"
#include "lib/param/loadparm.h"
/*
connect to the SAM database specified by URL
return an opaque context pointer on success, or NULL on failure
*/
int samdb_connect_url(TALLOC_CTX *mem_ctx,
struct tevent_context *ev_ctx,
struct loadparm_context *lp_ctx,
struct auth_session_info *session_info,
unsigned int flags,
const char *url,
const struct tsocket_address *remote_address,
struct ldb_context **ldb_ret,
char **errstring)
{
struct ldb_context *ldb = NULL;
int ret;
*ldb_ret = NULL;
*errstring = NULL;
/* We create sam.ldb in provision, and never anywhere else */
flags |= LDB_FLG_DONT_CREATE_DB;
if (remote_address == NULL) {
ldb = ldb_wrap_find(url, ev_ctx, lp_ctx,
session_info, NULL, flags);
if (ldb != NULL) {
*ldb_ret = talloc_reference(mem_ctx, ldb);
if (*ldb_ret == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
return LDB_SUCCESS;
}
}
ldb = samba_ldb_init(mem_ctx, ev_ctx, lp_ctx, session_info, NULL);
if (ldb == NULL) {
*errstring = talloc_asprintf(mem_ctx,
"Failed to set up Samba ldb "
"wrappers with samba_ldb_init() "
"to connect to %s",
url);
return LDB_ERR_OPERATIONS_ERROR;
}
dsdb_set_global_schema(ldb);
ret = samba_ldb_connect(ldb, lp_ctx, url, flags);
if (ret != LDB_SUCCESS) {
*errstring = talloc_asprintf(mem_ctx,
"Failed to connect to %s: %s",
url,
ldb_errstring(ldb));
talloc_free(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
/*
* If a remote_address was specified, then set it on the DB
* and do not add to the wrap list (as we need to keep the LDB
* pointer unique for the address).
*
* We use this for audit logging and for the "netlogon" attribute
*/
if (remote_address != NULL) {
ldb_set_opaque(ldb, "remoteAddress",
discard_const(remote_address));
*ldb_ret = ldb;
return LDB_SUCCESS;
}
if (flags & SAMBA_LDB_WRAP_CONNECT_FLAG_NO_SHARE_CONTEXT) {
*ldb_ret = ldb;
return LDB_SUCCESS;
}
if (!ldb_wrap_add(url, ev_ctx, lp_ctx, session_info, NULL, flags, ldb)) {
*errstring = talloc_asprintf(mem_ctx,
"Failed to add cached DB reference"
" to %s",
url);
talloc_free(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
*ldb_ret = ldb;
return LDB_SUCCESS;
}
/*
connect to the SAM database
return an opaque context pointer on success, or NULL on failure
*/
struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx,
struct tevent_context *ev_ctx,
struct loadparm_context *lp_ctx,
struct auth_session_info *session_info,
const struct tsocket_address *remote_address,
unsigned int flags)
{
char *errstring;
struct ldb_context *ldb;
int ret = samdb_connect_url(mem_ctx,
ev_ctx,
lp_ctx,
session_info,
flags,
"sam.ldb",
remote_address,
&ldb,
&errstring);
if (ret == LDB_SUCCESS) {
return ldb;
}
return NULL;
}
/****************************************************************************
Create the SID list for this user.
****************************************************************************/
NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
struct loadparm_context *lp_ctx,
uint32_t num_sids,
const struct auth_SidAttr *sids,
uint32_t num_device_sids,
const struct auth_SidAttr *device_sids,
struct auth_claims auth_claims,
uint32_t session_info_flags,
struct security_token **token)
{
struct security_token *ptoken;
uint32_t i;
NTSTATUS status;
enum claims_evaluation_control evaluate_claims;
bool sids_are_valid = false;
bool device_sids_are_valid = false;
bool authentication_was_compounded = session_info_flags & AUTH_SESSION_INFO_FORCE_COMPOUNDED_AUTHENTICATION;
/*
* Some special-case callers can't supply the lp_ctx, but do
* not interact with claims or conditional ACEs
*/
if (lp_ctx == NULL) {
evaluate_claims = CLAIMS_EVALUATION_INVALID_STATE;
} else {
enum acl_claims_evaluation claims_evaultion_setting
= lpcfg_acl_claims_evaluation(lp_ctx);
/*
* We are well inside the AD DC, so we do not need to check
* the server role etc
*/
switch (claims_evaultion_setting) {
case ACL_CLAIMS_EVALUATION_AD_DC_ONLY:
evaluate_claims = CLAIMS_EVALUATION_ALWAYS;
break;
default:
evaluate_claims = CLAIMS_EVALUATION_NEVER;
}
}
ptoken = security_token_initialise(mem_ctx, evaluate_claims);
NT_STATUS_HAVE_NO_MEMORY(ptoken);
if (num_sids > UINT32_MAX - 6) {
talloc_free(ptoken);
return NT_STATUS_INVALID_PARAMETER;
}
ptoken->sids = talloc_array(ptoken, struct dom_sid, num_sids + 6 /* over-allocate */);
if (ptoken->sids == NULL) {
talloc_free(ptoken);
return NT_STATUS_NO_MEMORY;
}
ptoken->num_sids = 0;
for (i = 0; i < num_sids; i++) {
uint32_t check_sid_idx;
for (check_sid_idx = 0;
check_sid_idx < ptoken->num_sids;
check_sid_idx++) {
if (dom_sid_equal(&ptoken->sids[check_sid_idx], &sids[i].sid)) {
break;
}
}
if (check_sid_idx == ptoken->num_sids) {
const struct dom_sid *sid = &sids[i].sid;
sids_are_valid = sids_are_valid || dom_sid_equal(
sid, &global_sid_Claims_Valid);
authentication_was_compounded = authentication_was_compounded || dom_sid_equal(
sid, &global_sid_Compounded_Authentication);
ptoken->sids = talloc_realloc(ptoken, ptoken->sids, struct dom_sid, ptoken->num_sids + 1);
if (ptoken->sids == NULL) {
talloc_free(ptoken);
return NT_STATUS_NO_MEMORY;
}
ptoken->sids[ptoken->num_sids] = *sid;
ptoken->num_sids++;
}
}
if (authentication_was_compounded && num_device_sids) {
ptoken->device_sids = talloc_array(ptoken, struct dom_sid, num_device_sids);
if (ptoken->device_sids == NULL) {
talloc_free(ptoken);
return NT_STATUS_NO_MEMORY;
}
for (i = 0; i < num_device_sids; i++) {
uint32_t check_sid_idx;
for (check_sid_idx = 0;
check_sid_idx < ptoken->num_device_sids;
check_sid_idx++) {
if (dom_sid_equal(&ptoken->device_sids[check_sid_idx], &device_sids[i].sid)) {
break;
}
}
if (check_sid_idx == ptoken->num_device_sids) {
const struct dom_sid *device_sid = &device_sids[i].sid;
device_sids_are_valid = device_sids_are_valid || dom_sid_equal(
device_sid, &global_sid_Claims_Valid);
ptoken->device_sids = talloc_realloc(ptoken,
ptoken->device_sids,
struct dom_sid,
ptoken->num_device_sids + 1);
if (ptoken->device_sids == NULL) {
talloc_free(ptoken);
return NT_STATUS_NO_MEMORY;
}
ptoken->device_sids[ptoken->num_device_sids] = *device_sid;
ptoken->num_device_sids++;
}
}
}
/* The caller may have requested simple privileges, for example if there isn't a local DB */
if (session_info_flags & AUTH_SESSION_INFO_SIMPLE_PRIVILEGES) {
/* Shortcuts to prevent recursion and avoid lookups */
if (ptoken->sids == NULL) {
ptoken->privilege_mask = 0;
} else if (security_token_is_system(ptoken)) {
ptoken->privilege_mask = ~0;
} else if (security_token_is_anonymous(ptoken)) {
ptoken->privilege_mask = 0;
} else if (security_token_has_builtin_administrators(ptoken)) {
ptoken->privilege_mask = ~0;
} else {
/* All other 'users' get a empty priv set so far */
ptoken->privilege_mask = 0;
}
} else {
/* setup the privilege mask for this token */
status = samdb_privilege_setup(lp_ctx, ptoken);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(ptoken);
DEBUG(1,("Unable to access privileges database\n"));
return status;
}
}
/*
* TODO: we might want to regard session_info_flags for the device
* SIDs as well as for the client SIDs.
*/
if (sids_are_valid) {
status = claims_data_security_claims(ptoken,
auth_claims.user_claims,
&ptoken->user_claims,
&ptoken->num_user_claims);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(ptoken);
return status;
}
}
if (device_sids_are_valid && authentication_was_compounded) {
status = claims_data_security_claims(ptoken,
auth_claims.device_claims,
&ptoken->device_claims,
&ptoken->num_device_claims);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(ptoken);
return status;
}
}
security_token_debug(0, 10, ptoken);
*token = ptoken;
return NT_STATUS_OK;
}