2 Unix SMB/Netbios implementation.
4 LDAP protocol helper functions for SAMBA
5 Copyright (C) Jean François Micouleau 1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
29 /*******************************************************************
30 open a connection to the ldap serve.
31 ******************************************************************/
32 BOOL ldap_open_connection(LDAP **ldap_struct)
34 if ( (*ldap_struct = ldap_open(lp_ldap_server(),lp_ldap_port()) )== NULL)
36 DEBUG(0,("%s: The LDAP server is not responding !\n",timestring()));
39 DEBUG(2,("ldap_open_connection: connection opened\n"));
44 /*******************************************************************
45 connect anonymously to the ldap server.
47 ******************************************************************/
48 static BOOL ldap_connect_anonymous(LDAP *ldap_struct)
50 if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) != LDAP_SUCCESS)
52 DEBUG(0,("%s: Couldn't bind to the LDAP server !\n", timestring() ));
59 /*******************************************************************
60 connect to the ldap server under system privileg.
61 ******************************************************************/
62 BOOL ldap_connect_system(LDAP *ldap_struct)
64 if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) != LDAP_SUCCESS)
66 DEBUG(0,("%s: Couldn't bind to the LDAP server !\n", timestring() ));
69 DEBUG(2,("ldap_connect_system: succesfull connection to the LDAP server\n"));
73 /*******************************************************************
74 connect to the ldap server under a particular user.
75 ******************************************************************/
76 static BOOL ldap_connect_user(LDAP *ldap_struct, char *user, char *password)
78 if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) != LDAP_SUCCESS)
80 DEBUG(0,("%s: Couldn't bind to the LDAP server !\n", timestring() ));
83 DEBUG(2,("ldap_connect_user: succesfull connection to the LDAP server\n"));
87 /*******************************************************************
88 run the search by name.
89 ******************************************************************/
90 static BOOL ldap_search_one_user(LDAP *ldap_struct, char *filter, LDAPMessage **result)
92 int scope = LDAP_SCOPE_ONELEVEL;
95 DEBUG(2,("ldap_search_one_user: searching for:[%s]\n", filter));
97 rc=ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, result);
99 if (rc != LDAP_SUCCESS )
101 DEBUG(0,("%s: Problem during the LDAP search\n",timestring()));
107 /*******************************************************************
108 run the search by name.
109 ******************************************************************/
110 BOOL ldap_search_one_user_by_name(LDAP *ldap_struct, char *user, LDAPMessage **result)
114 in the filter expression, replace %u with the real name
115 so in ldap filter, %u MUST exist :-)
117 strcpy(filter,lp_ldap_filter());
118 string_sub(filter,"%u",user);
120 if ( !ldap_search_one_user(ldap_struct, filter, result) )
127 /*******************************************************************
128 run the search by uid.
129 ******************************************************************/
130 BOOL ldap_search_one_user_by_uid(LDAP *ldap_struct, int uid, LDAPMessage **result)
134 in the filter expression, replace %u with the real name
135 so in ldap filter, %u MUST exist :-)
137 snprintf(filter, sizeof(pstring), "uidAccount=%d", uid);
139 if ( !ldap_search_one_user(ldap_struct, filter, result) )
146 /*******************************************************************
147 search an attribute and return the first value found.
148 ******************************************************************/
149 void get_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, char *attribute, char *value)
153 if ( (valeurs=ldap_get_values(ldap_struct, entry, attribute)) != NULL)
155 strcpy(value, valeurs[0]);
156 ldap_value_free(valeurs);
157 DEBUG(3,("get_single_attribute: [%s]=[%s]\n", attribute, value));
165 /*******************************************************************
166 check if the returned entry is a sambaAccount objectclass.
167 ******************************************************************/
168 BOOL ldap_check_user(LDAP *ldap_struct, LDAPMessage *entry)
170 BOOL sambaAccount=False;
174 DEBUG(2,("ldap_check_user: "));
175 valeur=ldap_get_values(ldap_struct, entry, "objectclass");
178 for (i=0;valeur[i]!=NULL;i++)
180 if (!strcmp(valeur[i],"sambaAccount")) sambaAccount=True;
183 DEBUG(2,("%s\n",sambaAccount?"yes":"no"));
184 ldap_value_free(valeur);
185 return (sambaAccount);
188 /*******************************************************************
189 check if the returned entry is a sambaMachine objectclass.
190 ******************************************************************/
191 BOOL ldap_check_trust(LDAP *ldap_struct, LDAPMessage *entry)
193 BOOL sambaMachine=False;
197 DEBUG(2,("ldap_check_trust: "));
198 valeur=ldap_get_values(ldap_struct, entry, "objectclass");
201 for (i=0;valeur[i]!=NULL;i++)
203 if (!strcmp(valeur[i],"sambaMachine")) sambaMachine=True;
206 DEBUG(2,("%s\n",sambaMachine?"yes":"no"));
207 ldap_value_free(valeur);
208 return (sambaMachine);
211 /*******************************************************************
212 retrieve the user's info and contruct a smb_passwd structure.
213 ******************************************************************/
214 static void ldap_get_sam_passwd(LDAP *ldap_struct, LDAPMessage *entry,
215 struct sam_passwd *user)
217 static pstring user_name;
218 static pstring fullname;
219 static pstring home_dir;
220 static pstring dir_drive;
221 static pstring logon_script;
222 static pstring profile_path;
223 static pstring acct_desc;
224 static pstring workstations;
227 bzero(user, sizeof(*user));
229 user->logon_time = (time_t)-1;
230 user->logoff_time = (time_t)-1;
231 user->kickoff_time = (time_t)-1;
232 user->pass_last_set_time = (time_t)-1;
233 user->pass_can_change_time = (time_t)-1;
234 user->pass_must_change_time = (time_t)-1;
236 get_single_attribute(ldap_struct, entry, "logonTime", temp);
237 user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
239 get_single_attribute(ldap_struct, entry, "logoffTime", temp);
240 user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
242 get_single_attribute(ldap_struct, entry, "kickoffTime", temp);
243 user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
245 get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
246 user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
248 get_single_attribute(ldap_struct, entry, "pwdCanChange", temp);
249 user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
251 get_single_attribute(ldap_struct, entry, "pwdMustChange", temp);
252 user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
254 get_single_attribute(ldap_struct, entry, "cn", user_name);
255 user->smb_name = user_name;
257 DEBUG(2,("ldap_get_sam_passwd: user: %s\n", user_name));
259 get_single_attribute(ldap_struct, entry, "userFullName", fullname);
260 user->full_name = fullname;
262 get_single_attribute(ldap_struct, entry, "homeDirectory", home_dir);
263 user->home_dir = home_dir;
265 get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive);
266 user->dir_drive = dir_drive;
268 get_single_attribute(ldap_struct, entry, "scriptPath", logon_script);
269 user->logon_script = logon_script;
271 get_single_attribute(ldap_struct, entry, "profilePath", profile_path);
272 user->profile_path = profile_path;
274 get_single_attribute(ldap_struct, entry, "comment", acct_desc);
275 user->acct_desc = acct_desc;
277 get_single_attribute(ldap_struct, entry, "userWorkstations", workstations);
278 user->workstations = workstations;
281 user->unknown_str = NULL; /* don't know, yet! */
282 user->munged_dial = NULL; /* "munged" dial-back telephone number */
284 get_single_attribute(ldap_struct, entry, "userPassword", temp);
285 nt_lm_owf_gen(temp, user->smb_nt_passwd, user->smb_passwd);
286 bzero(temp, sizeof(temp)); /* destroy local copy of the password */
288 get_single_attribute(ldap_struct, entry, "rid", temp);
289 user->user_rid=atoi(temp);
291 get_single_attribute(ldap_struct, entry, "primaryGroupID", temp);
292 user->group_rid=atoi(temp);
294 /* the smb (unix) ids are not stored: they are created */
295 user->smb_userid = user_rid_to_uid (user->user_rid);
296 user->smb_grpid = group_rid_to_uid(user->group_rid);
298 get_single_attribute(ldap_struct, entry, "userAccountControl", temp);
299 user->acct_ctrl=atoi(temp);
301 user->unknown_3 = 0xffffff; /* don't know */
302 user->logon_divs = 168; /* hours per week */
303 user->hours_len = 21; /* 21 times 8 bits = 168 */
304 memset(user->hours, 0xff, user->hours_len); /* available at all hours */
305 user->unknown_5 = 0x00020000; /* don't know */
306 user->unknown_5 = 0x000004ec; /* don't know */
308 if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) )
310 DEBUG(0,("Inconsistency in the LDAP database\n"));
313 if (!(user->acct_ctrl & ACB_NORMAL))
315 DEBUG(0,("User's acct_ctrl bits not set to ACT_NORMAL in LDAP database\n"));
321 /*******************************************************************
322 retrieve the user's info and contruct a smb_passwd structure.
323 ******************************************************************/
324 static void ldap_get_smb_passwd(LDAP *ldap_struct,LDAPMessage *entry,
325 struct smb_passwd *user)
327 static pstring user_name;
328 static pstring user_pass;
330 static unsigned char smblmpwd[16];
331 static unsigned char smbntpwd[16];
333 user->smb_name = NULL;
334 user->smb_passwd = NULL;
335 user->smb_nt_passwd = NULL;
336 user->smb_userid = 0;
337 user->pass_last_set_time = (time_t)-1;
339 get_single_attribute(ldap_struct, entry, "cn", user_name);
340 DEBUG(2,("ldap_get_smb_passwd: user: %s\n",user_name));
342 get_single_attribute(ldap_struct, entry, "userPassword", user_pass);
343 nt_lm_owf_gen(user_pass, smbntpwd, smblmpwd);
344 bzero(user_pass, sizeof(user_pass)); /* destroy local copy of the password */
346 get_single_attribute(ldap_struct, entry, "userAccountControl", temp);
347 user->acct_ctrl=decode_acct_ctrl(temp);
349 get_single_attribute(ldap_struct, entry, "pwdLastSet", temp);
350 user->pass_last_set_time = (time_t)strtol(temp, NULL, 16);
352 get_single_attribute(ldap_struct, entry, "rid", temp);
354 /* the smb (unix) ids are not stored: they are created */
355 user->smb_userid = user_rid_to_uid (atoi(temp));
357 if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) )
359 DEBUG(0,("Inconsistency in the LDAP database\n"));
362 if (user->acct_ctrl & ACB_NORMAL)
364 user->smb_name = user_name;
365 user->smb_passwd = smblmpwd;
366 user->smb_nt_passwd = smbntpwd;
370 /*******************************************************************
371 retrieve the trust's info and contruct a smb_passwd structure.
372 ******************************************************************/
373 static void ldap_get_trust(LDAP *ldap_struct,LDAPMessage *entry,
374 struct smb_passwd *trust)
376 static pstring user_name;
377 static unsigned char smbntpwd[16];
380 get_single_attribute(ldap_struct, entry, "cn", user_name);
381 DEBUG(2,("ldap_get_trust: trust: %s\n", user_name));
383 get_single_attribute(ldap_struct, entry, "trustPassword", temp);
384 gethexpwd(temp,smbntpwd);
386 get_single_attribute(ldap_struct, entry, "rid", temp);
388 /* the smb (unix) ids are not stored: they are created */
389 trust->smb_userid = user_rid_to_uid(atoi(temp));
391 get_single_attribute(ldap_struct, entry, "trustAccountControl", temp);
392 trust->acct_ctrl=decode_acct_ctrl(temp);
394 if (trust->acct_ctrl == 0)
396 /* by default it's a workstation (or stand-alone server) */
397 trust->acct_ctrl = ACB_WSTRUST;
400 trust->smb_name = user_name;
401 trust->smb_passwd = NULL;
402 trust->smb_nt_passwd = smbntpwd;
405 /************************************************************************
406 Routine to add an entry to the ldap passwd file.
408 do not call this function directly. use passdb.c instead.
410 *************************************************************************/
411 BOOL add_ldappwd_entry(struct smb_passwd *newpwd)
416 /************************************************************************
417 Routine to search the ldap passwd file for an entry matching the username.
418 and then modify its password entry. We can't use the startldappwent()/
419 getldappwent()/endldappwent() interfaces here as we depend on looking
420 in the actual file to decide how much room we have to write data.
421 override = False, normal
422 override = True, override XXXXXXXX'd out password or NO PASS
424 do not call this function directly. use passdb.c instead.
426 ************************************************************************/
427 BOOL mod_ldappwd_entry(struct smb_passwd* pwd, BOOL override)
432 /***************************************************************
433 Start to enumerate the ldap passwd list. Returns a void pointer
434 to ensure no modification outside this module.
436 do not call this function directly. use passdb.c instead.
438 ****************************************************************/
440 struct ldap_enum_info
447 static struct ldap_enum_info ldap_ent;
449 void *startldappwent(BOOL update)
451 int scope = LDAP_SCOPE_ONELEVEL;
456 if (!ldap_open_connection(&ldap_ent.ldap_struct)) /* open a connection to the server */
459 if (!ldap_connect_system(ldap_ent.ldap_struct)) /* connect as system account */
462 /* when the class is known the search is much faster */
467 strcpy(filter, "objectclass=sambaAccount");
472 strcpy(filter, "objectclass=sambaMachine");
477 strcpy(filter, "(|(objectclass=sambaMachine)(objectclass=sambaAccount))");
482 rc=ldap_search_s(ldap_ent.ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &ldap_ent.result);
484 DEBUG(2,("%d entries in the base!\n", ldap_count_entries(ldap_ent.ldap_struct, ldap_ent.result) ));
486 ldap_ent.entry = ldap_first_entry(ldap_ent.ldap_struct, ldap_ent.result);
491 /*************************************************************************
492 Routine to return the next entry in the ldap passwd list.
494 do not call this function directly. use passdb.c instead.
496 *************************************************************************/
497 struct smb_passwd *getldappwent(void *vp)
499 static struct smb_passwd user;
500 struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
502 ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
504 if (ldap_vp->entry != NULL)
506 ldap_get_smb_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
512 /*************************************************************************
513 Routine to return the next entry in the ldap passwd list.
515 do not call this function directly. use passdb.c instead.
517 *************************************************************************/
518 struct sam_passwd *getldap21pwent(void *vp)
520 static struct sam_passwd user;
521 struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
523 ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry);
525 if (ldap_vp->entry != NULL)
527 ldap_get_sam_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user);
533 /***************************************************************
534 End enumeration of the ldap passwd list.
536 do not call this function directly. use passdb.c instead.
538 ****************************************************************/
539 void endldappwent(void *vp)
541 struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp;
542 ldap_msgfree(ldap_vp->result);
543 ldap_unbind(ldap_vp->ldap_struct);
546 /*************************************************************************
547 Return the current position in the ldap passwd list as an unsigned long.
548 This must be treated as an opaque token.
550 do not call this function directly. use passdb.c instead.
552 *************************************************************************/
553 unsigned long getldappwpos(void *vp)
558 /*************************************************************************
559 Set the current position in the ldap passwd list from unsigned long.
560 This must be treated as an opaque token.
562 do not call this function directly. use passdb.c instead.
564 *************************************************************************/
565 BOOL setldappwpos(void *vp, unsigned long tok)