2 Unix SMB/CIFS implementation.
4 interface functions for the sam database
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Volker Lendecke 2004
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "librpc/gen_ndr/ndr_netlogon.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_security.h"
28 #include "lib/events/events.h"
29 #include "lib/ldb/include/ldb.h"
30 #include "lib/ldb/include/ldb_errors.h"
31 #include "libcli/security/security.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "libcli/ldap/ldap_ndr.h"
34 #include "system/time.h"
35 #include "system/filesys.h"
37 #include "util/util_ldb.h"
38 #include "dsdb/samdb/samdb.h"
39 #include "dsdb/common/flags.h"
40 #include "param/param.h"
41 #include "lib/events/events.h"
43 char *samdb_relative_path(struct ldb_context
*ldb
,
47 const char *base_url
=
48 (const char *)ldb_get_opaque(ldb
, "ldb_url");
49 char *path
, *p
, *full_name
;
53 if (name
[0] == 0 || name
[0] == '/' || strstr(name
, ":/")) {
54 return talloc_strdup(mem_ctx
, name
);
56 path
= talloc_strdup(mem_ctx
, base_url
);
60 if ( (p
= strrchr(path
, '/')) != NULL
) {
62 full_name
= talloc_asprintf(mem_ctx
, "%s/%s", path
, name
);
64 full_name
= talloc_asprintf(mem_ctx
, "./%s", name
);
72 connect to the SAM database
73 return an opaque context pointer on success, or NULL on failure
75 struct ldb_context
*samdb_connect(TALLOC_CTX
*mem_ctx
,
76 struct event_context
*ev_ctx
,
77 struct loadparm_context
*lp_ctx
,
78 struct auth_session_info
*session_info
)
80 struct ldb_context
*ldb
;
81 ldb
= ldb_wrap_connect(mem_ctx
, ev_ctx
, lp_ctx
,
82 lp_sam_url(lp_ctx
), session_info
,
87 dsdb_make_schema_global(ldb
);
92 copy from a template record to a message
94 int samdb_copy_template(struct ldb_context
*ldb
,
95 struct ldb_message
*msg
, const char *name
,
96 const char **errstring
)
98 struct ldb_result
*res
;
99 struct ldb_message
*t
;
101 struct ldb_context
*templates_ldb
;
102 char *templates_ldb_path
;
103 struct ldb_dn
*basedn
;
104 struct event_context
*event_ctx
;
105 struct loadparm_context
*lp_ctx
;
107 templates_ldb
= talloc_get_type(ldb_get_opaque(ldb
, "templates_ldb"), struct ldb_context
);
109 if (!templates_ldb
) {
110 templates_ldb_path
= samdb_relative_path(ldb
,
113 if (!templates_ldb_path
) {
114 *errstring
= talloc_asprintf(msg
, "samdb_copy_template: ERROR: Failed to contruct path for template db");
115 return LDB_ERR_OPERATIONS_ERROR
;
118 event_ctx
= ldb_get_event_context(ldb
);
119 lp_ctx
= (struct loadparm_context
*)ldb_get_opaque(ldb
, "loadparm");
121 /* FIXME: need to remove this wehn we finally pass the event
122 * context around in ldb */
123 if (event_ctx
== NULL
) {
124 event_ctx
= s4_event_context_init(templates_ldb
);
127 templates_ldb
= ldb_wrap_connect(ldb
, event_ctx
, lp_ctx
,
128 templates_ldb_path
, NULL
,
130 talloc_free(templates_ldb_path
);
131 if (!templates_ldb
) {
132 *errstring
= talloc_asprintf(msg
, "samdb_copy_template: ERROR: Failed to connect to templates db at: %s",
134 return LDB_ERR_OPERATIONS_ERROR
;
137 ret
= ldb_set_opaque(ldb
, "templates_ldb", templates_ldb
);
138 if (ret
!= LDB_SUCCESS
) {
144 basedn
= ldb_dn_new(templates_ldb
, ldb
, "cn=Templates");
145 if (!ldb_dn_add_child_fmt(basedn
, "CN=Template%s", name
)) {
147 *errstring
= talloc_asprintf(msg
, "samdb_copy_template: ERROR: Failed to contruct DN for template '%s'",
149 return LDB_ERR_OPERATIONS_ERROR
;
152 /* pull the template record */
153 ret
= ldb_search(templates_ldb
, basedn
, LDB_SCOPE_BASE
, "distinguishedName=*", NULL
, &res
);
155 if (ret
!= LDB_SUCCESS
) {
156 *errstring
= talloc_steal(msg
, ldb_errstring(templates_ldb
));
159 if (res
->count
!= 1) {
160 *errstring
= talloc_asprintf(msg
, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1",
164 return LDB_ERR_OPERATIONS_ERROR
;
168 for (i
= 0; i
< t
->num_elements
; i
++) {
169 struct ldb_message_element
*el
= &t
->elements
[i
];
170 /* some elements should not be copied from the template */
171 if (ldb_attr_cmp(el
->name
, "cn") == 0 ||
172 ldb_attr_cmp(el
->name
, "name") == 0 ||
173 ldb_attr_cmp(el
->name
, "objectClass") == 0 ||
174 ldb_attr_cmp(el
->name
, "sAMAccountName") == 0 ||
175 ldb_attr_cmp(el
->name
, "sAMAccountName") == 0 ||
176 ldb_attr_cmp(el
->name
, "distinguishedName") == 0 ||
177 ldb_attr_cmp(el
->name
, "objectGUID") == 0) {
180 for (j
= 0; j
< el
->num_values
; j
++) {
181 ret
= samdb_find_or_add_attribute(ldb
, msg
, el
->name
,
182 (char *)el
->values
[j
].data
);
184 *errstring
= talloc_asprintf(msg
, "Adding attribute %s failed.", el
->name
);
197 /****************************************************************************
198 Create the SID list for this user.
199 ****************************************************************************/
200 NTSTATUS
security_token_create(TALLOC_CTX
*mem_ctx
,
201 struct event_context
*ev_ctx
,
202 struct loadparm_context
*lp_ctx
,
203 struct dom_sid
*user_sid
,
204 struct dom_sid
*group_sid
,
206 struct dom_sid
**groupSIDs
,
207 bool is_authenticated
,
208 struct security_token
**token
)
210 struct security_token
*ptoken
;
214 ptoken
= security_token_initialise(mem_ctx
);
215 NT_STATUS_HAVE_NO_MEMORY(ptoken
);
217 ptoken
->sids
= talloc_array(ptoken
, struct dom_sid
*, n_groupSIDs
+ 5);
218 NT_STATUS_HAVE_NO_MEMORY(ptoken
->sids
);
220 ptoken
->user_sid
= talloc_reference(ptoken
, user_sid
);
221 ptoken
->group_sid
= talloc_reference(ptoken
, group_sid
);
222 ptoken
->privilege_mask
= 0;
224 ptoken
->sids
[0] = ptoken
->user_sid
;
225 ptoken
->sids
[1] = ptoken
->group_sid
;
228 * Finally add the "standard" SIDs.
229 * The only difference between guest and "anonymous"
230 * is the addition of Authenticated_Users.
232 ptoken
->sids
[2] = dom_sid_parse_talloc(ptoken
->sids
, SID_WORLD
);
233 NT_STATUS_HAVE_NO_MEMORY(ptoken
->sids
[2]);
234 ptoken
->sids
[3] = dom_sid_parse_talloc(ptoken
->sids
, SID_NT_NETWORK
);
235 NT_STATUS_HAVE_NO_MEMORY(ptoken
->sids
[3]);
236 ptoken
->num_sids
= 4;
238 if (is_authenticated
) {
239 ptoken
->sids
[4] = dom_sid_parse_talloc(ptoken
->sids
, SID_NT_AUTHENTICATED_USERS
);
240 NT_STATUS_HAVE_NO_MEMORY(ptoken
->sids
[4]);
244 for (i
= 0; i
< n_groupSIDs
; i
++) {
245 size_t check_sid_idx
;
246 for (check_sid_idx
= 1;
247 check_sid_idx
< ptoken
->num_sids
;
249 if (dom_sid_equal(ptoken
->sids
[check_sid_idx
], groupSIDs
[i
])) {
254 if (check_sid_idx
== ptoken
->num_sids
) {
255 ptoken
->sids
[ptoken
->num_sids
++] = talloc_reference(ptoken
->sids
, groupSIDs
[i
]);
259 /* setup the privilege mask for this token */
260 status
= samdb_privilege_setup(ev_ctx
, lp_ctx
, ptoken
);
261 if (!NT_STATUS_IS_OK(status
)) {
266 security_token_debug(10, ptoken
);