Line data Source code
1 : /*
2 : ldb database library
3 :
4 : Copyright (C) Nadezhda Ivanova 2010
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : /*
21 : * Name: dsdb_access
22 : *
23 : * Description: utility functions for access checking on objects
24 : *
25 : * Authors: Nadezhda Ivanova
26 : */
27 :
28 : #include "includes.h"
29 : #include "ldb.h"
30 : #include "ldb_module.h"
31 : #include "ldb_errors.h"
32 : #include "libcli/security/security.h"
33 : #include "librpc/gen_ndr/ndr_security.h"
34 : #include "libcli/ldap/ldap_ndr.h"
35 : #include "param/param.h"
36 : #include "auth/auth.h"
37 : #include "dsdb/samdb/samdb.h"
38 : #include "dsdb/common/util.h"
39 :
40 47475 : void dsdb_acl_debug(struct security_descriptor *sd,
41 : struct security_token *token,
42 : struct ldb_dn *dn,
43 : bool denied,
44 : int level)
45 : {
46 47475 : if (denied) {
47 47475 : DEBUG(level, ("Access on %s denied\n", ldb_dn_get_linearized(dn)));
48 : } else {
49 0 : DEBUG(level, ("Access on %s granted\n", ldb_dn_get_linearized(dn)));
50 : }
51 :
52 47475 : DEBUG(level,("Security context: %s\n",
53 : ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_token,"", token)));
54 47475 : DEBUG(level,("Security descriptor: %s\n",
55 : ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_descriptor,"", sd)));
56 47475 : }
57 :
58 1707698 : int dsdb_get_sd_from_ldb_message(struct ldb_context *ldb,
59 : TALLOC_CTX *mem_ctx,
60 : struct ldb_message *acl_res,
61 : struct security_descriptor **sd)
62 : {
63 87277 : struct ldb_message_element *sd_element;
64 87277 : enum ndr_err_code ndr_err;
65 :
66 1707698 : sd_element = ldb_msg_find_element(acl_res, "nTSecurityDescriptor");
67 1707698 : if (sd_element == NULL) {
68 0 : return ldb_error(ldb, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS,
69 : "nTSecurityDescriptor is missing");
70 : }
71 1707698 : *sd = talloc(mem_ctx, struct security_descriptor);
72 1707698 : if(!*sd) {
73 0 : return ldb_oom(ldb);
74 : }
75 1707698 : ndr_err = ndr_pull_struct_blob(&sd_element->values[0], *sd, *sd,
76 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
77 :
78 1707698 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
79 0 : TALLOC_FREE(*sd);
80 0 : return ldb_operr(ldb);
81 : }
82 :
83 1620421 : return LDB_SUCCESS;
84 : }
85 :
86 1501129 : int dsdb_check_access_on_dn_internal(struct ldb_context *ldb,
87 : struct ldb_result *acl_res,
88 : TALLOC_CTX *mem_ctx,
89 : struct security_token *token,
90 : struct ldb_dn *dn,
91 : uint32_t access_mask,
92 : const struct GUID *guid)
93 : {
94 1501129 : struct security_descriptor *sd = NULL;
95 1501129 : struct dom_sid *sid = NULL;
96 1501129 : struct object_tree *root = NULL;
97 83746 : NTSTATUS status;
98 83746 : uint32_t access_granted;
99 83746 : int ret;
100 :
101 1501129 : ret = dsdb_get_sd_from_ldb_message(ldb, mem_ctx, acl_res->msgs[0], &sd);
102 1501129 : if (ret != LDB_SUCCESS) {
103 0 : return ldb_operr(ldb);
104 : }
105 :
106 1501129 : sid = samdb_result_dom_sid(mem_ctx, acl_res->msgs[0], "objectSid");
107 1501129 : if (guid) {
108 558368 : if (!insert_in_object_tree(mem_ctx, guid, access_mask, NULL,
109 : &root)) {
110 0 : TALLOC_FREE(sd);
111 0 : TALLOC_FREE(sid);
112 0 : return ldb_operr(ldb);
113 : }
114 : }
115 1501129 : status = sec_access_check_ds(sd, token,
116 : access_mask,
117 : &access_granted,
118 : root,
119 : sid);
120 1501129 : if (!NT_STATUS_IS_OK(status)) {
121 45933 : dsdb_acl_debug(sd,
122 : token,
123 : dn,
124 : true,
125 : 10);
126 45933 : ldb_asprintf_errstring(ldb,
127 : "dsdb_access: Access check failed on %s",
128 : ldb_dn_get_linearized(dn));
129 45933 : TALLOC_FREE(sd);
130 45933 : TALLOC_FREE(sid);
131 45933 : return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
132 : }
133 1371450 : return LDB_SUCCESS;
134 : }
135 :
136 : /* performs an access check from outside the module stack
137 : * given the dn of the object to be checked, the required access
138 : * guid is either the guid of the extended right, or NULL
139 : */
140 :
141 19404 : int dsdb_check_access_on_dn(struct ldb_context *ldb,
142 : TALLOC_CTX *mem_ctx,
143 : struct ldb_dn *dn,
144 : struct security_token *token,
145 : uint32_t access_mask,
146 : const char *ext_right)
147 : {
148 0 : int ret;
149 0 : struct GUID guid;
150 0 : struct ldb_result *acl_res;
151 0 : static const char *acl_attrs[] = {
152 : "nTSecurityDescriptor",
153 : "objectSid",
154 : NULL
155 : };
156 :
157 19404 : if (ext_right != NULL) {
158 19400 : NTSTATUS status = GUID_from_string(ext_right, &guid);
159 19400 : if (!NT_STATUS_IS_OK(status)) {
160 0 : return LDB_ERR_OPERATIONS_ERROR;
161 : }
162 : }
163 :
164 : /*
165 : * We need AS_SYSTEM in order to get the nTSecurityDescriptor attribute.
166 : * Also the result of this search not controlled by the client
167 : * nor is the result exposed to the client.
168 : */
169 19404 : ret = dsdb_search_dn(ldb, mem_ctx, &acl_res, dn, acl_attrs,
170 : DSDB_FLAG_AS_SYSTEM | DSDB_SEARCH_SHOW_RECYCLED);
171 19404 : if (ret != LDB_SUCCESS) {
172 0 : DEBUG(10,("access_check: failed to find object %s\n", ldb_dn_get_linearized(dn)));
173 0 : return ret;
174 : }
175 :
176 19404 : return dsdb_check_access_on_dn_internal(ldb, acl_res,
177 : mem_ctx,
178 : token,
179 : dn,
180 : access_mask,
181 : ext_right ? &guid : NULL);
182 : }
183 :
|