2 Unix SMB/Netbios implementation.
4 LDAP protocol helper functions for SAMBA
5 Copyright (C) Jean François Micouleau 1998
6 Copyright (C) Matthew Chapman 1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 extern int DEBUGLEVEL;
35 LDAPMessage *ldap_results;
36 LDAPMessage *ldap_entry;
39 static pstring ldap_secret;
42 /*******************************************************************
43 Open connections to the LDAP server.
44 ******************************************************************/
46 BOOL ldap_open_connection(BOOL modify)
50 if (!(ldap_struct = ldap_open(lp_ldap_server(), lp_ldap_port()))) {
51 DEBUG(0, ("open: %s\n", strerror(errno)));
55 err = ldap_simple_bind_s(ldap_struct, lp_ldap_bind_as(), ldap_secret);
56 if (err != LDAP_SUCCESS) {
57 DEBUG(0, ("bind: %s\n", ldap_err2string(err)));
61 DEBUG(2,("Connected to LDAP server\n"));
65 /*******************************************************************
66 close connections to the LDAP server.
67 ******************************************************************/
69 void ldap_close_connection(void)
75 ldap_msgfree(ldap_results);
76 ldap_results = NULL; }
78 ldap_unbind(ldap_struct);
81 DEBUG(2,("Connection closed\n"));
85 /*******************************************************************
86 Search the directory using a given filter.
87 ******************************************************************/
89 BOOL ldap_search_for(char *filter)
93 DEBUG(2,("Searching in [%s] for [%s]\n", lp_ldap_suffix(), filter));
95 err = ldap_search_s(ldap_struct, lp_ldap_suffix(), LDAP_SCOPE_ONELEVEL,
96 filter, NULL, 0, &ldap_results);
98 if(err != LDAP_SUCCESS) {
99 DEBUG(0, ("search: %s\n", ldap_err2string(err)));
102 DEBUG(2, ("%d matching entries found\n",
103 ldap_count_entries(ldap_struct, ldap_results)));
105 ldap_entry = ldap_first_entry(ldap_struct, ldap_results);
109 BOOL ldap_search_by_name(const char *user)
113 slprintf(filter, sizeof(filter)-1,
114 "(&(uid=%s)(objectclass=sambaAccount))", user);
115 return ldap_search_for(filter);
118 BOOL ldap_search_by_uid(int uid)
122 slprintf(filter, sizeof(filter)-1,
123 "(&(uidNumber=%d)(objectclass=sambaAccount))", uid);
124 return ldap_search_for(filter);
128 /*******************************************************************
129 Get the first value of an attribute.
130 ******************************************************************/
132 BOOL ldap_get_attribute(char *attribute, char *value)
136 if(!(values = ldap_get_values(ldap_struct, ldap_entry, attribute)))
139 pstrcpy(value, values[0]);
140 ldap_value_free(values);
141 DEBUG(3, ("get: [%s] = [%s]\n", attribute, value));
147 /*******************************************************************
148 Contruct an smb_passwd structure
149 ******************************************************************/
151 struct smb_passwd *ldap_getpw()
153 static struct smb_passwd smbpw;
154 static pstring unix_name;
155 static pstring nt_name;
156 static unsigned char smblmpwd[16];
157 static unsigned char smbntpwd[16];
163 if(!ldap_get_attribute("uid", unix_name)) {
164 DEBUG(0,("Missing uid\n"));
166 smbpw.unix_name = unix_name;
168 DEBUG(2,("Retrieving account [%s]\n",unix_name));
170 if(!ldap_get_attribute("uidNumber", temp)) {
171 DEBUG(0,("Missing uidNumber\n"));
173 smbpw.unix_uid = atoi(temp);
175 if(ldap_get_attribute("ntuid", nt_name)) {
176 DEBUG(0,("Missing ntuid\n"));
178 smbpw.nt_name = nt_name;
180 if(!ldap_get_attribute("rid", temp)) {
181 DEBUG(0,("Missing rid\n"));
183 smbpw.user_rid = atoi(temp);
185 if(ldap_get_attribute("acctFlags", temp))
186 smbpw.acct_ctrl = pwdb_decode_acct_ctrl(temp);
188 smbpw.acct_ctrl = ACB_NORMAL;
190 if(ldap_get_attribute("lmPassword", temp)) {
191 pwdb_gethexpwd(temp, smblmpwd);
192 smbpw.smb_passwd = smblmpwd;
194 smbpw.smb_passwd = NULL;
195 smbpw.acct_ctrl |= ACB_DISABLED;
198 if(ldap_get_attribute("ntPassword", temp)) {
199 pwdb_gethexpwd(temp, smbntpwd);
200 smbpw.smb_nt_passwd = smbntpwd;
202 smbpw.smb_nt_passwd = NULL;
205 if(ldap_get_attribute("pwdLastSet", temp))
206 smbpw.pass_last_set_time = (time_t)strtol(temp, NULL, 16);
208 smbpw.pass_last_set_time = (time_t)(-1);
210 ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
215 /************************************************************************
216 Adds a modification to a LDAPMod queue.
217 ************************************************************************/
219 void ldap_make_mod(LDAPMod ***modlist,int modop, char *attribute, char *value)
225 DEBUG(3, ("set: [%s] = [%s]\n", attribute, value));
230 mods = (LDAPMod **)malloc(sizeof(LDAPMod *));
234 for (i = 0; mods[i] != NULL; ++i) {
235 if (mods[i]->mod_op == modop &&
236 !strcasecmp(mods[i]->mod_type, attribute)) {
241 if (mods[i] == NULL) {
242 mods = (LDAPMod **)realloc(mods, (i+2) * sizeof(LDAPMod *));
243 mods[i] = (LDAPMod *)malloc(sizeof(LDAPMod));
244 mods[i]->mod_op = modop;
245 mods[i]->mod_values = NULL;
246 mods[i]->mod_type = strdup(attribute);
252 if (mods[i]->mod_values) {
253 for (; mods[i]->mod_values[j]; j++);
255 mods[i]->mod_values = (char **)realloc(mods[i]->mod_values,
256 (j+2) * sizeof(char *));
257 mods[i]->mod_values[j] = strdup(value);
258 mods[i]->mod_values[j+1] = NULL;
265 /************************************************************************
266 Queues the necessary modifications to save a smb_passwd structure
267 ************************************************************************/
269 void ldap_smbpwmods(struct smb_passwd *newpwd, LDAPMod ***mods, int operation)
275 if(operation == LDAP_MOD_ADD) { /* immutable attributes */
276 ldap_make_mod(mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
278 ldap_make_mod(mods, LDAP_MOD_ADD, "uid", newpwd->unix_name);
279 slprintf(temp, sizeof(temp)-1, "%d", newpwd->unix_uid);
280 ldap_make_mod(mods, LDAP_MOD_ADD, "uidNumber", temp);
282 ldap_make_mod(mods, LDAP_MOD_ADD, "ntuid", newpwd->nt_name);
283 slprintf(temp, sizeof(temp)-1, "%d", newpwd->user_rid);
284 ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp);
287 if (newpwd->smb_passwd) {
288 for( i = 0; i < 16; i++) {
289 slprintf(&temp[2*i], 3, "%02X", newpwd->smb_passwd[i]);
291 ldap_make_mod(mods, operation, "lmPassword", temp);
294 if (newpwd->smb_nt_passwd) {
295 for( i = 0; i < 16; i++) {
296 slprintf(&temp[2*i], 3, "%02X", newpwd->smb_nt_passwd[i]);
298 ldap_make_mod(mods, operation, "ntPassword", temp);
301 newpwd->pass_last_set_time = time(NULL);
302 slprintf(temp, sizeof(temp)-1, "%08X", newpwd->pass_last_set_time);
303 ldap_make_mod(mods, operation, "pwdLastSet", temp);
305 ldap_make_mod(mods, operation, "acctFlags",
306 pwdb_encode_acct_ctrl(newpwd->acct_ctrl,
307 NEW_PW_FORMAT_SPACE_PADDED_LEN));
311 /************************************************************************
312 Commit changes to a directory entry.
313 *************************************************************************/
314 BOOL ldap_makemods(char *attribute, char *value, LDAPMod **mods, BOOL add)
321 slprintf(dn, sizeof(dn)-1, "%s=%s, %s", attribute, value,
324 if(!ldap_open_connection(True))
328 err = ldap_add_s(ldap_struct, dn, mods);
330 if(!add || (err = LDAP_ALREADY_EXISTS))
331 err = ldap_modify_s(ldap_struct, dn, mods);
333 if(err == LDAP_SUCCESS) {
334 DEBUG(2,("Updated entry [%s]\n",value));
337 DEBUG(0,("update: %s\n", ldap_err2string(err)));
341 ldap_close_connection();
342 ldap_mods_free(mods, 1);
347 /***************************************************************
348 Begin/end account enumeration.
349 ****************************************************************/
351 static void *ldap_enumfirst(BOOL update)
353 if (!ldap_open_connection(False))
356 ldap_search_for("objectclass=sambaAccount");
361 static void ldap_enumclose(void *vp)
363 ldap_close_connection();
367 /*************************************************************************
368 Save/restore the current position in a query
369 *************************************************************************/
371 static SMB_BIG_UINT ldap_getdbpos(void *vp)
373 return (SMB_BIG_UINT)((ulong)ldap_entry);
376 static BOOL ldap_setdbpos(void *vp, SMB_BIG_UINT tok)
378 ldap_entry = (LDAPMessage *)((ulong)tok);
383 /*************************************************************************
384 Return smb_passwd information.
385 *************************************************************************/
387 static struct smb_passwd *ldap_getpwbynam(const char *name)
389 struct smb_passwd *ret;
391 if(!ldap_open_connection(False))
394 ldap_search_by_name(name);
397 ldap_close_connection();
401 static struct smb_passwd *ldap_getpwbyuid(uid_t userid)
403 struct smb_passwd *ret;
405 if(!ldap_open_connection(False))
408 ldap_search_by_uid(userid);
411 ldap_close_connection();
415 static struct smb_passwd *ldap_getcurrentpw(void *vp)
421 /************************************************************************
422 Modify user information given an smb_passwd struct.
423 *************************************************************************/
424 static BOOL ldap_addpw(struct smb_passwd *newpwd)
428 ldap_smbpwmods(newpwd, &mods, LDAP_MOD_ADD);
429 return ldap_makemods("uid", newpwd->unix_name, mods, True);
432 static BOOL ldap_modpw(struct smb_passwd *pwd, BOOL override)
436 ldap_smbpwmods(pwd, &mods, LDAP_MOD_REPLACE);
437 return ldap_makemods("uid", pwd->unix_name, mods, False);
441 static struct smb_passdb_ops ldap_ops =
455 struct smb_passdb_ops *ldap_initialise_password_db(void)
461 pwdfilename = lp_ldap_passwd_file();
464 if(pwdfile = sys_fopen(pwdfilename, "r")) {
465 fgets(ldap_secret, sizeof(ldap_secret), pwdfile);
466 if(p = strchr(ldap_secret, '\n'))
470 DEBUG(0,("Failed to open LDAP passwd file\n"));
478 void ldap_dummy_function(void);
479 void ldap_dummy_function(void) { } /* stop some compilers complaining */