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