7b4cf4d079f8ffa6e636091d533892dc5a16202a
[samba.git] / source3 / lib / smbldap_util.c
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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    
24 */
25
26 #include "includes.h"
27 #include "smbldap.h"
28
29 /**********************************************************************
30  Add the account-policies below the sambaDomain object to LDAP, 
31 *********************************************************************/
32 static 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         pstring dn;
40         LDAPMod **mods = NULL;
41
42         DEBUG(3,("Adding new account policies for domain\n"));
43         
44         pstr_sprintf(dn, "%s=%s,%s", 
45                 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
46                 domain_name, lp_ldap_suffix());
47
48         for (i=1; decode_account_policy_name(i) != NULL; i++) {
49
50                 pstring val;
51
52                 policy_attr = get_account_policy_attr(i);
53                 if (!policy_attr) {
54                         DEBUG(0,("add_new_domain_account_policies: ops. no policy!\n"));
55                         continue;
56                 }
57
58                 if (!account_policy_get_default(i, &policy_default)) {
59                         DEBUG(0,("add_new_domain_account_policies: failed to get default account policy\n"));
60                         return ntstatus;
61                 }
62
63                 DEBUG(10,("add_new_domain_account_policies: adding \"%s\" with value: %d\n", policy_attr, policy_default));
64
65                 pstr_sprintf(val, "%d", policy_default); 
66
67                 smbldap_set_mod( &mods, LDAP_MOD_REPLACE, policy_attr, val);
68
69                 rc = smbldap_modify(ldap_state, dn, mods);
70
71                 if (rc!=LDAP_SUCCESS) {
72                         char *ld_error = NULL;
73                         ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
74                         DEBUG(1,("failed to add account policies to dn= %s with: %s\n\t%s\n",
75                                 dn, ldap_err2string(rc),
76                                 ld_error ? ld_error : "unknown"));
77                         SAFE_FREE(ld_error);
78                         ldap_mods_free(mods, True);
79                         return ntstatus;
80                 }
81         }
82
83         ldap_mods_free(mods, True);
84
85         return NT_STATUS_OK;
86 }
87
88 /**********************************************************************
89  Add the sambaDomain to LDAP, so we don't have to search for this stuff
90  again.  This is a once-add operation for now.
91
92  TODO:  Add other attributes, and allow modification.
93 *********************************************************************/
94 static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, 
95                                     const char *domain_name) 
96 {
97         fstring sid_string;
98         fstring algorithmic_rid_base_string;
99         pstring filter, dn;
100         LDAPMod **mods = NULL;
101         int rc;
102         LDAPMessage *result = NULL;
103         int num_result;
104         const char **attr_list;
105
106         slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", 
107                   get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
108                   domain_name, LDAP_OBJ_DOMINFO);
109
110         attr_list = get_attr_list( NULL, dominfo_attr_list );
111         rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
112         talloc_free( attr_list );
113
114         if (rc != LDAP_SUCCESS) {
115                 return NT_STATUS_UNSUCCESSFUL;
116         }
117
118         num_result = ldap_count_entries(ldap_state->ldap_struct, result);
119         
120         if (num_result > 1) {
121                 DEBUG (0, ("More than domain with that name exists: bailing "
122                            "out!\n"));
123                 ldap_msgfree(result);
124                 return NT_STATUS_UNSUCCESSFUL;
125         }
126         
127         /* Check if we need to add an entry */
128         DEBUG(3,("Adding new domain\n"));
129
130         pstr_sprintf(dn, "%s=%s,%s",
131                      get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
132                      domain_name, lp_ldap_suffix());
133
134         /* Free original search */
135         ldap_msgfree(result);
136
137         /* make the changes - the entry *must* not already have samba
138          * attributes */
139
140         smbldap_set_mod(&mods, LDAP_MOD_ADD,
141                         get_attr_key2string(dominfo_attr_list,
142                                             LDAP_ATTR_DOMAIN), 
143                         domain_name);
144
145         /* If we don't have an entry, then ask secrets.tdb for what it thinks.
146            It may choose to make it up */
147
148         sid_to_string(sid_string, get_global_sam_sid());
149         smbldap_set_mod(&mods, LDAP_MOD_ADD,
150                         get_attr_key2string(dominfo_attr_list,
151                                             LDAP_ATTR_DOM_SID),
152                         sid_string);
153
154         slprintf(algorithmic_rid_base_string,
155                  sizeof(algorithmic_rid_base_string) - 1, "%i",
156                  algorithmic_rid_base());
157         smbldap_set_mod(&mods, LDAP_MOD_ADD,
158                         get_attr_key2string(dominfo_attr_list,
159                                             LDAP_ATTR_ALGORITHMIC_RID_BASE), 
160                         algorithmic_rid_base_string);
161         smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
162         
163         /* add the sambaNextUserRid attributes. */
164         
165         {
166                 uint32 rid = BASE_RID;
167                 fstring rid_str;
168                 
169                 fstr_sprintf( rid_str, "%i", rid );
170                 DEBUG(10,("setting next available user rid [%s]\n", rid_str));
171                 smbldap_set_mod(&mods, LDAP_MOD_ADD, 
172                         get_attr_key2string(dominfo_attr_list,
173                                             LDAP_ATTR_NEXT_USERRID), 
174                         rid_str);
175         }
176
177
178         rc = smbldap_add(ldap_state, dn, mods);
179
180         if (rc!=LDAP_SUCCESS) {
181                 char *ld_error = NULL;
182                 ldap_get_option(ldap_state->ldap_struct,
183                                 LDAP_OPT_ERROR_STRING, &ld_error);
184                 DEBUG(1,("failed to add domain dn= %s with: %s\n\t%s\n",
185                          dn, ldap_err2string(rc),
186                          ld_error?ld_error:"unknown"));
187                 SAFE_FREE(ld_error);
188
189                 ldap_mods_free(mods, True);
190                 return NT_STATUS_UNSUCCESSFUL;
191         }
192
193         DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name));
194         ldap_mods_free(mods, True);
195         return NT_STATUS_OK;
196 }
197
198 /**********************************************************************
199 Search for the domain info entry
200 *********************************************************************/
201 NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
202                                     LDAPMessage ** result, const char *domain_name,
203                                     BOOL try_add)
204 {
205         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
206         pstring filter;
207         int rc;
208         const char **attr_list;
209         int count;
210
211         pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
212                 LDAP_OBJ_DOMINFO,
213                 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
214                 domain_name);
215
216         DEBUG(2, ("Searching for:[%s]\n", filter));
217
218         attr_list = get_attr_list( NULL, dominfo_attr_list );
219         rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
220         talloc_free( attr_list );
221
222         if (rc != LDAP_SUCCESS) {
223                 DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
224                 DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
225                 goto failed;
226         }
227
228         count = ldap_count_entries(ldap_state->ldap_struct, *result);
229
230         if (count == 1)
231                 return NT_STATUS_OK;
232
233         ldap_msgfree(*result);
234         *result = NULL;
235         
236         if (count < 1) {
237
238                 DEBUG(3, ("Got no domain info entries for domain\n"));
239
240                 if (!try_add)
241                         goto failed;
242
243                 status = add_new_domain_info(ldap_state, domain_name);
244                 if (!NT_STATUS_IS_OK(status)) {
245                         DEBUG(0, ("Adding domain info for %s failed with %s\n", 
246                                 domain_name, nt_errstr(status)));
247                         goto failed;
248                 }
249                         
250                 status = add_new_domain_account_policies(ldap_state, domain_name);
251                 if (!NT_STATUS_IS_OK(status)) {
252                         DEBUG(0, ("Adding domain account policies for %s failed with %s\n", 
253                                 domain_name, nt_errstr(status)));
254                         goto failed;
255                 }
256
257                 return smbldap_search_domain_info(ldap_state, result, domain_name, False);
258                 
259         } 
260         
261         if (count > 1 ) {
262         
263                 DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
264                           count, domain_name));
265                 goto failed;
266         }
267
268 failed:
269         return status;
270         
271 }
272