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 47015 : 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 47015 : if (denied) {
47 47015 : DEBUG(level, ("Access on %s denied", ldb_dn_get_linearized(dn)));
48 : } else {
49 0 : DEBUG(level, ("Access on %s granted", ldb_dn_get_linearized(dn)));
50 : }
51 :
52 47015 : DEBUG(level,("Security context: %s\n",
53 : ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_token,"", token)));
54 47015 : DEBUG(level,("Security descriptor: %s\n",
55 : ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_descriptor,"", sd)));
56 47015 : }
57 :
58 1269757 : 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 : struct ldb_message_element *sd_element;
64 : enum ndr_err_code ndr_err;
65 :
66 1269757 : sd_element = ldb_msg_find_element(acl_res, "nTSecurityDescriptor");
67 1269757 : if (sd_element == NULL) {
68 0 : return ldb_error(ldb, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS,
69 : "nTSecurityDescriptor is missing");
70 : }
71 1269757 : *sd = talloc(mem_ctx, struct security_descriptor);
72 1269757 : if(!*sd) {
73 0 : return ldb_oom(ldb);
74 : }
75 1269757 : ndr_err = ndr_pull_struct_blob(&sd_element->values[0], *sd, *sd,
76 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
77 :
78 1269757 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
79 0 : return ldb_operr(ldb);
80 : }
81 :
82 1269757 : return LDB_SUCCESS;
83 : }
84 :
85 1123503 : int dsdb_check_access_on_dn_internal(struct ldb_context *ldb,
86 : struct ldb_result *acl_res,
87 : TALLOC_CTX *mem_ctx,
88 : struct security_token *token,
89 : struct ldb_dn *dn,
90 : uint32_t access_mask,
91 : const struct GUID *guid)
92 : {
93 1123503 : struct security_descriptor *sd = NULL;
94 1123503 : struct dom_sid *sid = NULL;
95 1123503 : struct object_tree *root = NULL;
96 : NTSTATUS status;
97 : uint32_t access_granted;
98 : int ret;
99 :
100 1123503 : ret = dsdb_get_sd_from_ldb_message(ldb, mem_ctx, acl_res->msgs[0], &sd);
101 1123503 : if (ret != LDB_SUCCESS) {
102 0 : return ldb_operr(ldb);
103 : }
104 :
105 1123503 : sid = samdb_result_dom_sid(mem_ctx, acl_res->msgs[0], "objectSid");
106 1123503 : if (guid) {
107 329998 : if (!insert_in_object_tree(mem_ctx, guid, access_mask, NULL,
108 : &root)) {
109 0 : return ldb_operr(ldb);
110 : }
111 : }
112 1123503 : status = sec_access_check_ds(sd, token,
113 : access_mask,
114 : &access_granted,
115 : root,
116 : sid);
117 1123503 : if (!NT_STATUS_IS_OK(status)) {
118 45831 : dsdb_acl_debug(sd,
119 : token,
120 : dn,
121 : true,
122 : 10);
123 45831 : ldb_asprintf_errstring(ldb,
124 : "dsdb_access: Access check failed on %s",
125 : ldb_dn_get_linearized(dn));
126 45831 : return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
127 : }
128 1077672 : return LDB_SUCCESS;
129 : }
130 :
131 : /* performs an access check from outside the module stack
132 : * given the dn of the object to be checked, the required access
133 : * guid is either the guid of the extended right, or NULL
134 : */
135 :
136 13568 : int dsdb_check_access_on_dn(struct ldb_context *ldb,
137 : TALLOC_CTX *mem_ctx,
138 : struct ldb_dn *dn,
139 : struct security_token *token,
140 : uint32_t access_mask,
141 : const char *ext_right)
142 : {
143 : int ret;
144 : struct GUID guid;
145 : struct ldb_result *acl_res;
146 : static const char *acl_attrs[] = {
147 : "nTSecurityDescriptor",
148 : "objectSid",
149 : NULL
150 : };
151 :
152 13568 : if (ext_right != NULL) {
153 13564 : NTSTATUS status = GUID_from_string(ext_right, &guid);
154 13564 : if (!NT_STATUS_IS_OK(status)) {
155 0 : return LDB_ERR_OPERATIONS_ERROR;
156 : }
157 : }
158 :
159 : /*
160 : * We need AS_SYSTEM in order to get the nTSecurityDescriptor attribute.
161 : * Also the result of this search not controlled by the client
162 : * nor is the result exposed to the client.
163 : */
164 13568 : ret = dsdb_search_dn(ldb, mem_ctx, &acl_res, dn, acl_attrs,
165 : DSDB_FLAG_AS_SYSTEM | DSDB_SEARCH_SHOW_RECYCLED);
166 13568 : if (ret != LDB_SUCCESS) {
167 0 : DEBUG(10,("access_check: failed to find object %s\n", ldb_dn_get_linearized(dn)));
168 0 : return ret;
169 : }
170 :
171 13568 : return dsdb_check_access_on_dn_internal(ldb, acl_res,
172 : mem_ctx,
173 : token,
174 : dn,
175 : access_mask,
176 : ext_right ? &guid : NULL);
177 : }
178 :
|