Line data Source code
1 : /*
2 : Unix SMB/CIFS Implementation.
3 : LDAP protocol helper functions for SAMBA
4 : Copyright (C) Jean François Micouleau 1998
5 : Copyright (C) Gerald Carter 2001-2003
6 : Copyright (C) Shahms King 2001
7 : Copyright (C) Andrew Bartlett 2002-2003
8 : Copyright (C) Stefan (metze) Metzmacher 2002-2003
9 :
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.
14 :
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.
19 :
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/>.
22 :
23 : */
24 :
25 : #include "includes.h"
26 : #include "smbldap.h"
27 : #include "passdb.h"
28 : #include "passdb/pdb_ldap_util.h"
29 : #include "passdb/pdb_ldap_schema.h"
30 : #include "libcli/security/dom_sid.h"
31 :
32 : /**********************************************************************
33 : Add the account-policies below the sambaDomain object to LDAP,
34 : *********************************************************************/
35 :
36 0 : static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state,
37 : const char *domain_name)
38 : {
39 0 : NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
40 0 : int i, rc;
41 0 : uint32_t policy_default;
42 0 : const char *policy_attr = NULL;
43 0 : char *dn = NULL;
44 0 : LDAPMod **mods = NULL;
45 0 : char *escape_domain_name;
46 :
47 0 : DEBUG(3,("add_new_domain_account_policies: Adding new account policies for domain\n"));
48 :
49 0 : escape_domain_name = escape_rdn_val_string_alloc(domain_name);
50 0 : if (!escape_domain_name) {
51 0 : DEBUG(0, ("Out of memory!\n"));
52 0 : return NT_STATUS_NO_MEMORY;
53 : }
54 :
55 0 : if (asprintf(&dn, "%s=%s,%s",
56 : get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
57 : escape_domain_name, lp_ldap_suffix()) < 0) {
58 0 : SAFE_FREE(escape_domain_name);
59 0 : return NT_STATUS_NO_MEMORY;
60 : }
61 :
62 0 : SAFE_FREE(escape_domain_name);
63 :
64 0 : for (i=1; decode_account_policy_name(i) != NULL; i++) {
65 0 : char *val = NULL;
66 :
67 0 : policy_attr = get_account_policy_attr(i);
68 0 : if (!policy_attr) {
69 0 : DEBUG(0,("add_new_domain_account_policies: ops. no policy!\n"));
70 0 : continue;
71 : }
72 :
73 0 : if (!account_policy_get_default(i, &policy_default)) {
74 0 : DEBUG(0,("add_new_domain_account_policies: failed to get default account policy\n"));
75 0 : SAFE_FREE(dn);
76 0 : return ntstatus;
77 : }
78 :
79 0 : DEBUG(10,("add_new_domain_account_policies: adding \"%s\" with value: %d\n", policy_attr, policy_default));
80 :
81 0 : if (asprintf(&val, "%d", policy_default) < 0) {
82 0 : SAFE_FREE(dn);
83 0 : return NT_STATUS_NO_MEMORY;
84 : }
85 :
86 0 : smbldap_set_mod( &mods, LDAP_MOD_REPLACE, policy_attr, val);
87 :
88 0 : rc = smbldap_modify(ldap_state, dn, mods);
89 :
90 0 : SAFE_FREE(val);
91 :
92 0 : if (rc!=LDAP_SUCCESS) {
93 0 : char *ld_error = NULL;
94 0 : ldap_get_option(smbldap_get_ldap(ldap_state),
95 : LDAP_OPT_ERROR_STRING, &ld_error);
96 0 : DEBUG(1,("add_new_domain_account_policies: failed to add account policies to dn= %s with: %s\n\t%s\n",
97 : dn, ldap_err2string(rc),
98 : ld_error ? ld_error : "unknown"));
99 0 : SAFE_FREE(ld_error);
100 0 : SAFE_FREE(dn);
101 0 : ldap_mods_free(mods, True);
102 0 : return ntstatus;
103 : }
104 : }
105 :
106 0 : SAFE_FREE(dn);
107 0 : ldap_mods_free(mods, True);
108 :
109 0 : return NT_STATUS_OK;
110 : }
111 :
112 : /**********************************************************************
113 : Add the sambaDomain to LDAP, so we don't have to search for this stuff
114 : again. This is a once-add operation for now.
115 :
116 : TODO: Add other attributes, and allow modification.
117 : *********************************************************************/
118 :
119 0 : static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
120 : const char *domain_name)
121 : {
122 0 : struct dom_sid_buf sid_string;
123 0 : fstring algorithmic_rid_base_string;
124 0 : char *filter = NULL;
125 0 : char *dn = NULL;
126 0 : LDAPMod **mods = NULL;
127 0 : int rc;
128 0 : LDAPMessage *result = NULL;
129 0 : int num_result;
130 0 : const char **attr_list;
131 0 : char *escape_domain_name;
132 :
133 : /* escape for filter */
134 0 : escape_domain_name = escape_ldap_string(talloc_tos(), domain_name);
135 0 : if (!escape_domain_name) {
136 0 : DEBUG(0, ("Out of memory!\n"));
137 0 : return NT_STATUS_NO_MEMORY;
138 : }
139 :
140 0 : if (asprintf(&filter, "(&(%s=%s)(objectclass=%s))",
141 : get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
142 : escape_domain_name, LDAP_OBJ_DOMINFO) < 0) {
143 0 : TALLOC_FREE(escape_domain_name);
144 0 : return NT_STATUS_NO_MEMORY;
145 : }
146 :
147 0 : TALLOC_FREE(escape_domain_name);
148 :
149 0 : attr_list = get_attr_list(NULL, dominfo_attr_list );
150 0 : rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
151 0 : TALLOC_FREE( attr_list );
152 0 : SAFE_FREE(filter);
153 :
154 0 : if (rc != LDAP_SUCCESS) {
155 0 : return NT_STATUS_UNSUCCESSFUL;
156 : }
157 :
158 0 : num_result = ldap_count_entries(smbldap_get_ldap(ldap_state), result);
159 :
160 0 : if (num_result > 1) {
161 0 : DEBUG (0, ("add_new_domain_info: More than domain with that name exists: bailing "
162 : "out!\n"));
163 0 : ldap_msgfree(result);
164 0 : return NT_STATUS_UNSUCCESSFUL;
165 : }
166 :
167 : /* Check if we need to add an entry */
168 0 : DEBUG(3,("add_new_domain_info: Adding new domain\n"));
169 :
170 : /* this time escape for DN */
171 0 : escape_domain_name = escape_rdn_val_string_alloc(domain_name);
172 0 : if (!escape_domain_name) {
173 0 : DEBUG(0, ("Out of memory!\n"));
174 0 : return NT_STATUS_NO_MEMORY;
175 : }
176 :
177 0 : if (asprintf(&dn, "%s=%s,%s",
178 : get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
179 : escape_domain_name, lp_ldap_suffix()) < 0) {
180 0 : SAFE_FREE(escape_domain_name);
181 0 : return NT_STATUS_NO_MEMORY;
182 : }
183 :
184 0 : SAFE_FREE(escape_domain_name);
185 :
186 : /* Free original search */
187 0 : ldap_msgfree(result);
188 :
189 : /* make the changes - the entry *must* not already have samba
190 : * attributes */
191 :
192 0 : smbldap_set_mod(&mods, LDAP_MOD_ADD,
193 : get_attr_key2string(dominfo_attr_list,
194 : LDAP_ATTR_DOMAIN),
195 : domain_name);
196 :
197 : /* If we don't have an entry, then ask secrets.tdb for what it thinks.
198 : It may choose to make it up */
199 :
200 0 : smbldap_set_mod(&mods, LDAP_MOD_ADD,
201 : get_attr_key2string(dominfo_attr_list,
202 : LDAP_ATTR_DOM_SID),
203 0 : dom_sid_str_buf(get_global_sam_sid(), &sid_string));
204 :
205 0 : slprintf(algorithmic_rid_base_string,
206 : sizeof(algorithmic_rid_base_string) - 1, "%i",
207 : algorithmic_rid_base());
208 0 : smbldap_set_mod(&mods, LDAP_MOD_ADD,
209 : get_attr_key2string(dominfo_attr_list,
210 : LDAP_ATTR_ALGORITHMIC_RID_BASE),
211 : algorithmic_rid_base_string);
212 0 : smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
213 :
214 : /* add the sambaNextUserRid attributes. */
215 :
216 : {
217 0 : uint32_t rid = BASE_RID;
218 0 : fstring rid_str;
219 :
220 0 : fstr_sprintf( rid_str, "%i", rid );
221 0 : DEBUG(10,("add_new_domain_info: setting next available user rid [%s]\n", rid_str));
222 0 : smbldap_set_mod(&mods, LDAP_MOD_ADD,
223 : get_attr_key2string(dominfo_attr_list,
224 : LDAP_ATTR_NEXT_USERRID),
225 : rid_str);
226 : }
227 :
228 :
229 0 : rc = smbldap_add(ldap_state, dn, mods);
230 :
231 0 : if (rc!=LDAP_SUCCESS) {
232 0 : char *ld_error = NULL;
233 0 : ldap_get_option(smbldap_get_ldap(ldap_state),
234 : LDAP_OPT_ERROR_STRING, &ld_error);
235 0 : DEBUG(1,("add_new_domain_info: failed to add domain dn= %s with: %s\n\t%s\n",
236 : dn, ldap_err2string(rc),
237 : ld_error?ld_error:"unknown"));
238 0 : SAFE_FREE(ld_error);
239 0 : SAFE_FREE(dn);
240 0 : ldap_mods_free(mods, True);
241 0 : return NT_STATUS_UNSUCCESSFUL;
242 : }
243 :
244 0 : DEBUG(2,("add_new_domain_info: added: domain = %s in the LDAP database\n", domain_name));
245 0 : ldap_mods_free(mods, True);
246 0 : SAFE_FREE(dn);
247 0 : return NT_STATUS_OK;
248 : }
249 :
250 : /**********************************************************************
251 : Search for the domain info entry
252 : *********************************************************************/
253 :
254 0 : NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
255 : LDAPMessage ** result, const char *domain_name,
256 : bool try_add)
257 : {
258 0 : NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
259 0 : char *filter = NULL;
260 0 : int rc;
261 0 : const char **attr_list;
262 0 : int count;
263 0 : char *escape_domain_name;
264 :
265 0 : escape_domain_name = escape_ldap_string(talloc_tos(), domain_name);
266 0 : if (!escape_domain_name) {
267 0 : DEBUG(0, ("Out of memory!\n"));
268 0 : return NT_STATUS_NO_MEMORY;
269 : }
270 :
271 0 : if (asprintf(&filter, "(&(objectClass=%s)(%s=%s))",
272 : LDAP_OBJ_DOMINFO,
273 : get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
274 : escape_domain_name) < 0) {
275 0 : TALLOC_FREE(escape_domain_name);
276 0 : return NT_STATUS_NO_MEMORY;
277 : }
278 :
279 0 : TALLOC_FREE(escape_domain_name);
280 :
281 0 : DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter));
282 :
283 0 : attr_list = get_attr_list( NULL, dominfo_attr_list );
284 0 : rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
285 0 : TALLOC_FREE( attr_list );
286 :
287 0 : if (rc != LDAP_SUCCESS) {
288 0 : DEBUG(2,("smbldap_search_domain_info: Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
289 0 : DEBUG(2,("smbldap_search_domain_info: Query was: %s, %s\n", lp_ldap_suffix(), filter));
290 0 : goto failed;
291 : }
292 :
293 0 : SAFE_FREE(filter);
294 :
295 0 : count = ldap_count_entries(smbldap_get_ldap(ldap_state), *result);
296 :
297 0 : if (count == 1) {
298 0 : return NT_STATUS_OK;
299 : }
300 :
301 0 : ldap_msgfree(*result);
302 0 : *result = NULL;
303 :
304 0 : if (count < 1) {
305 :
306 0 : DEBUG(3, ("smbldap_search_domain_info: Got no domain info entries for domain\n"));
307 :
308 0 : if (!try_add)
309 0 : goto failed;
310 :
311 0 : status = add_new_domain_info(ldap_state, domain_name);
312 0 : if (!NT_STATUS_IS_OK(status)) {
313 0 : DEBUG(0, ("smbldap_search_domain_info: Adding domain info for %s failed with %s\n",
314 : domain_name, nt_errstr(status)));
315 0 : goto failed;
316 : }
317 :
318 0 : status = add_new_domain_account_policies(ldap_state, domain_name);
319 0 : if (!NT_STATUS_IS_OK(status)) {
320 0 : DEBUG(0, ("smbldap_search_domain_info: Adding domain account policies for %s failed with %s\n",
321 : domain_name, nt_errstr(status)));
322 0 : goto failed;
323 : }
324 :
325 0 : return smbldap_search_domain_info(ldap_state, result, domain_name, False);
326 :
327 : }
328 :
329 0 : if (count > 1 ) {
330 :
331 0 : DEBUG(0, ("smbldap_search_domain_info: Got too many (%d) domain info entries for domain %s\n",
332 : count, domain_name));
333 0 : goto failed;
334 : }
335 :
336 0 : failed:
337 0 : return status;
338 : }
|