add privileges support to ldapsam too
[tprouty/samba.git] / source / lib / smbldap.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 #ifndef LDAP_OPT_SUCCESS
30 #define LDAP_OPT_SUCCESS 0
31 #endif
32
33 /* Try not to hit the up or down server forever */
34
35 #define SMBLDAP_DONT_PING_TIME 10       /* ping only all 10 seconds */
36 #define SMBLDAP_NUM_RETRIES 8           /* retry only 8 times */
37
38 #define SMBLDAP_IDLE_TIME 150           /* After 2.5 minutes disconnect */
39
40
41 /* attributes used by Samba 2.2 */
42
43 ATTRIB_MAP_ENTRY attrib_map_v22[] = {
44         { LDAP_ATTR_UID,                "uid"           },
45         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
46         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
47         { LDAP_ATTR_UNIX_HOME,          "homeDirectory" },
48         { LDAP_ATTR_PWD_LAST_SET,       "pwdLastSet"    },
49         { LDAP_ATTR_PWD_CAN_CHANGE,     "pwdCanChange"  },
50         { LDAP_ATTR_PWD_MUST_CHANGE,    "pwdMustChange" },
51         { LDAP_ATTR_LOGON_TIME,         "logonTime"     },
52         { LDAP_ATTR_LOGOFF_TIME,        "logoffTime"    },
53         { LDAP_ATTR_KICKOFF_TIME,       "kickoffTime"   },
54         { LDAP_ATTR_CN,                 "cn"            },
55         { LDAP_ATTR_DISPLAY_NAME,       "displayName"   },
56         { LDAP_ATTR_HOME_PATH,          "smbHome"       },
57         { LDAP_ATTR_HOME_DRIVE,         "homeDrives"    },
58         { LDAP_ATTR_LOGON_SCRIPT,       "scriptPath"    },
59         { LDAP_ATTR_PROFILE_PATH,       "profilePath"   },
60         { LDAP_ATTR_DESC,               "description"   },
61         { LDAP_ATTR_USER_WKS,           "userWorkstations"},
62         { LDAP_ATTR_USER_RID,           "rid"           },
63         { LDAP_ATTR_PRIMARY_GROUP_RID,  "primaryGroupID"},
64         { LDAP_ATTR_LMPW,               "lmPassword"    },
65         { LDAP_ATTR_NTPW,               "ntPassword"    },
66         { LDAP_ATTR_DOMAIN,             "domain"        },
67         { LDAP_ATTR_OBJCLASS,           "objectClass"   },
68         { LDAP_ATTR_ACB_INFO,           "acctFlags"     },
69         { LDAP_ATTR_LIST_END,           NULL            }
70 };
71
72 /* attributes used by Samba 3.0's sambaSamAccount */
73
74 ATTRIB_MAP_ENTRY attrib_map_v30[] = {
75         { LDAP_ATTR_UID,                "uid"                   },
76         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
77         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
78         { LDAP_ATTR_UNIX_HOME,          "homeDirectory"         },
79         { LDAP_ATTR_PWD_LAST_SET,       "sambaPwdLastSet"       },
80         { LDAP_ATTR_PWD_CAN_CHANGE,     "sambaPwdCanChange"     },
81         { LDAP_ATTR_PWD_MUST_CHANGE,    "sambaPwdMustChange"    },
82         { LDAP_ATTR_LOGON_TIME,         "sambaLogonTime"        },
83         { LDAP_ATTR_LOGOFF_TIME,        "sambaLogoffTime"       },
84         { LDAP_ATTR_KICKOFF_TIME,       "sambaKickoffTime"      },
85         { LDAP_ATTR_CN,                 "cn"                    },
86         { LDAP_ATTR_DISPLAY_NAME,       "displayName"           },
87         { LDAP_ATTR_HOME_DRIVE,         "sambaHomeDrive"        },
88         { LDAP_ATTR_HOME_PATH,          "sambaHomePath"         },
89         { LDAP_ATTR_LOGON_SCRIPT,       "sambaLogonScript"      },
90         { LDAP_ATTR_PROFILE_PATH,       "sambaProfilePath"      },
91         { LDAP_ATTR_DESC,               "description"           },
92         { LDAP_ATTR_USER_WKS,           "sambaUserWorkstations" },
93         { LDAP_ATTR_USER_SID,           LDAP_ATTRIBUTE_SID      },
94         { LDAP_ATTR_PRIMARY_GROUP_SID,  "sambaPrimaryGroupSID"  },
95         { LDAP_ATTR_LMPW,               "sambaLMPassword"       },
96         { LDAP_ATTR_NTPW,               "sambaNTPassword"       },
97         { LDAP_ATTR_DOMAIN,             "sambaDomainName"       },
98         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
99         { LDAP_ATTR_ACB_INFO,           "sambaAcctFlags"        },
100         { LDAP_ATTR_MUNGED_DIAL,        "sambaMungedDial"       },
101         { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" },
102         { LDAP_ATTR_BAD_PASSWORD_TIME,  "sambaBadPasswordTime"  },
103         { LDAP_ATTR_MOD_TIMESTAMP,      "modifyTimestamp"       },
104         { LDAP_ATTR_LIST_END,           NULL                    }
105 };
106
107 /* attributes used for allocating RIDs */
108
109 ATTRIB_MAP_ENTRY dominfo_attr_list[] = {
110         { LDAP_ATTR_DOMAIN,             "sambaDomainName"       },
111         { LDAP_ATTR_NEXT_RID,           "sambaNextRid"          },
112         { LDAP_ATTR_NEXT_USERRID,       "sambaNextUserRid"      },
113         { LDAP_ATTR_NEXT_GROUPRID,      "sambaNextGroupRid"     },
114         { LDAP_ATTR_DOM_SID,            LDAP_ATTRIBUTE_SID      },
115         { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"},
116         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
117         { LDAP_ATTR_LIST_END,           NULL                    },
118 };
119
120 /* Samba 3.0 group mapping attributes */
121
122 ATTRIB_MAP_ENTRY groupmap_attr_list[] = {
123         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
124         { LDAP_ATTR_GROUP_SID,          LDAP_ATTRIBUTE_SID      },
125         { LDAP_ATTR_GROUP_TYPE,         "sambaGroupType"        },
126         { LDAP_ATTR_DESC,               "description"           },
127         { LDAP_ATTR_DISPLAY_NAME,       "displayName"           },
128         { LDAP_ATTR_CN,                 "cn"                    },
129         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
130         { LDAP_ATTR_LIST_END,           NULL                    }       
131 };
132
133 ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = {
134         { LDAP_ATTR_GROUP_SID,          LDAP_ATTRIBUTE_SID      },
135         { LDAP_ATTR_GROUP_TYPE,         "sambaGroupType"        },
136         { LDAP_ATTR_DESC,               "description"           },
137         { LDAP_ATTR_DISPLAY_NAME,       "displayName"           },
138         { LDAP_ATTR_LIST_END,           NULL                    }       
139 };
140
141 /* idmap_ldap sambaUnixIdPool */
142
143 ATTRIB_MAP_ENTRY idpool_attr_list[] = {
144         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
145         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
146         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
147         { LDAP_ATTR_LIST_END,           NULL                    }       
148 };
149
150 ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
151         { LDAP_ATTR_SID,                LDAP_ATTRIBUTE_SID      },
152         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
153         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
154         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
155         { LDAP_ATTR_LIST_END,           NULL                    }       
156 };
157
158 /* privileges */
159
160 ATTRIB_MAP_ENTRY privilege_attr_list[] = {
161         { LDAP_ATTR_CN,                 "sambaPrivName"         },
162         { LDAP_ATTR_SID_LIST,           LDAP_ATTRIBUTE_SID_LIST },
163         { LDAP_ATTR_DESC,               "description"           },
164         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
165         { LDAP_ATTR_LIST_END,           NULL                    }
166 };
167
168 /**********************************************************************
169  perform a simple table lookup and return the attribute name 
170  **********************************************************************/
171  
172  const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key )
173 {
174         int i = 0;
175         
176         while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
177                 if ( table[i].attrib == key )
178                         return table[i].name;
179                 i++;
180         }
181         
182         return NULL;
183 }
184
185
186 /**********************************************************************
187  Return the list of attribute names from a mapping table
188  **********************************************************************/
189
190  char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
191 {
192         char **names;
193         int i = 0;
194         
195         while ( table[i].attrib != LDAP_ATTR_LIST_END )
196                 i++;
197         i++;
198
199         names = (char**)malloc( sizeof(char*)*i );
200         if ( !names ) {
201                 DEBUG(0,("get_attr_list: out of memory\n"));
202                 return NULL;
203         }
204
205         i = 0;
206         while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
207                 names[i] = strdup( table[i].name );
208                 i++;
209         }
210         names[i] = NULL;
211         
212         return names;
213 }
214
215 /*********************************************************************
216  Cleanup 
217  ********************************************************************/
218
219  void free_attr_list( char **list )
220 {
221         int i = 0;
222
223         if ( !list )
224                 return; 
225
226         while ( list[i] ) {
227                 SAFE_FREE( list[i] );
228                 i+=1;
229         }
230
231         SAFE_FREE( list );
232 }
233
234 /*******************************************************************
235  find the ldap password
236 ******************************************************************/
237 static BOOL fetch_ldap_pw(char **dn, char** pw)
238 {
239         char *key = NULL;
240         size_t size;
241         
242         *dn = smb_xstrdup(lp_ldap_admin_dn());
243         
244         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
245                 SAFE_FREE(*dn);
246                 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
247         }
248         
249         *pw=secrets_fetch(key, &size);
250         SAFE_FREE(key);
251
252         if (!size) {
253                 /* Upgrade 2.2 style entry */
254                 char *p;
255                 char* old_style_key = strdup(*dn);
256                 char *data;
257                 fstring old_style_pw;
258                 
259                 if (!old_style_key) {
260                         DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
261                         return False;
262                 }
263
264                 for (p=old_style_key; *p; p++)
265                         if (*p == ',') *p = '/';
266         
267                 data=secrets_fetch(old_style_key, &size);
268                 if (!size && size < sizeof(old_style_pw)) {
269                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
270                         SAFE_FREE(old_style_key);
271                         SAFE_FREE(*dn);
272                         return False;
273                 }
274
275                 size = MIN(size, sizeof(fstring)-1);
276                 strncpy(old_style_pw, data, size);
277                 old_style_pw[size] = 0;
278
279                 SAFE_FREE(data);
280
281                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
282                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
283                         SAFE_FREE(old_style_key);
284                         SAFE_FREE(*dn);
285                         return False;                   
286                 }
287                 if (!secrets_delete(old_style_key)) {
288                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
289                 }
290
291                 SAFE_FREE(old_style_key);
292
293                 *pw = smb_xstrdup(old_style_pw);                
294         }
295         
296         return True;
297 }
298
299 /*******************************************************************
300  Search an attribute and return the first value found.
301 ******************************************************************/
302
303  BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
304                                     const char *attribute, char *value,
305                                     int max_len)
306 {
307         char **values;
308         
309         if ( !attribute )
310                 return False;
311                 
312         value[0] = '\0';
313
314         if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
315                 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
316                 
317                 return False;
318         }
319         
320         if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, False) == (size_t)-1) {
321                 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n", 
322                           attribute, values[0]));
323                 ldap_value_free(values);
324                 return False;
325         }
326         
327         ldap_value_free(values);
328 #ifdef DEBUG_PASSWORDS
329         DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
330 #endif  
331         return True;
332 }
333
334  BOOL smbldap_get_single_pstring (LDAP * ldap_struct, LDAPMessage * entry,
335                                   const char *attribute, pstring value)
336 {
337         return smbldap_get_single_attribute(ldap_struct, entry,
338                                             attribute, value, 
339                                             sizeof(pstring));
340 }
341
342 /************************************************************************
343  Routine to manage the LDAPMod structure array
344  manage memory used by the array, by each struct, and values
345  ***********************************************************************/
346
347  void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
348 {
349         LDAPMod **mods;
350         int i;
351         int j;
352
353         mods = *modlist;
354
355         /* sanity checks on the mod values */
356
357         if (attribute == NULL || *attribute == '\0')
358                 return; 
359 #if 0   /* commented out after discussion with abartlet.  Do not reenable.
360            left here so other so re-add similar code   --jerry */
361         if (value == NULL || *value == '\0')
362                 return;
363 #endif
364
365         if (mods == NULL) 
366         {
367                 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
368                 if (mods == NULL)
369                 {
370                         DEBUG(0, ("make_a_mod: out of memory!\n"));
371                         return;
372                 }
373                 mods[0] = NULL;
374         }
375
376         for (i = 0; mods[i] != NULL; ++i) {
377                 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
378                         break;
379         }
380
381         if (mods[i] == NULL)
382         {
383                 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
384                 if (mods == NULL)
385                 {
386                         DEBUG(0, ("make_a_mod: out of memory!\n"));
387                         return;
388                 }
389                 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
390                 if (mods[i] == NULL)
391                 {
392                         DEBUG(0, ("make_a_mod: out of memory!\n"));
393                         return;
394                 }
395                 mods[i]->mod_op = modop;
396                 mods[i]->mod_values = NULL;
397                 mods[i]->mod_type = strdup(attribute);
398                 mods[i + 1] = NULL;
399         }
400
401         if (value != NULL)
402         {
403                 char *utf8_value = NULL;
404
405                 j = 0;
406                 if (mods[i]->mod_values != NULL) {
407                         for (; mods[i]->mod_values[j] != NULL; j++);
408                 }
409                 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
410                                                (j + 2) * sizeof (char *));
411                                                
412                 if (mods[i]->mod_values == NULL) {
413                         DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
414                         return;
415                 }
416
417                 if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) {
418                         DEBUG (0, ("make_a_mod: String conversion failure!\n"));
419                         return;
420                 }
421
422                 mods[i]->mod_values[j] = utf8_value;
423
424                 mods[i]->mod_values[j + 1] = NULL;
425         }
426         *modlist = mods;
427 }
428
429 /**********************************************************************
430   Set attribute to newval in LDAP, regardless of what value the
431   attribute had in LDAP before.
432 *********************************************************************/
433
434  void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
435                       LDAPMod ***mods,
436                       const char *attribute, const char *newval)
437 {
438         char oldval[2048]; /* current largest allowed value is mungeddial */
439         BOOL existed;
440
441         if (existing != NULL) {
442                 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
443         } else {
444                 existed = False;
445                 *oldval = '\0';
446         }
447
448         /* all of our string attributes are case insensitive */
449         
450         if (existed && newval && (StrCaseCmp(oldval, newval) == 0)) {
451                 
452                 /* Believe it or not, but LDAP will deny a delete and
453                    an add at the same time if the values are the
454                    same... */
455                 return;
456         }
457
458         if (existed) {
459                 /* There has been no value before, so don't delete it.
460                  * Here's a possible race: We might end up with
461                  * duplicate attributes */
462                 /* By deleting exactly the value we found in the entry this
463                  * should be race-free in the sense that the LDAP-Server will
464                  * deny the complete operation if somebody changed the
465                  * attribute behind our back. */
466                 /* This will also allow modifying single valued attributes 
467                  * in Novell NDS. In NDS you have to first remove attribute and then
468                  * you could add new value */
469                 
470                 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
471         }
472
473         /* Regardless of the real operation (add or modify)
474            we add the new value here. We rely on deleting
475            the old value, should it exist. */
476
477         if ((newval != NULL) && (strlen(newval) > 0)) {
478                 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
479         }
480 }
481
482 /**********************************************************************
483  Some varients of the LDAP rebind code do not pass in the third 'arg' 
484  pointer to a void*, so we try and work around it by assuming that the 
485  value of the 'LDAP *' pointer is the same as the one we had passed in
486  **********************************************************************/
487
488 struct smbldap_state_lookup {
489         LDAP *ld;
490         struct smbldap_state *smbldap_state;
491         struct smbldap_state_lookup *prev, *next;
492 };
493
494 static struct smbldap_state_lookup *smbldap_state_lookup_list;
495
496 static struct smbldap_state *smbldap_find_state(LDAP *ld) 
497 {
498         struct smbldap_state_lookup *t;
499
500         for (t = smbldap_state_lookup_list; t; t = t->next) {
501                 if (t->ld == ld) {
502                         return t->smbldap_state;
503                 }
504         }
505         return NULL;
506 }
507
508 static void smbldap_delete_state(struct smbldap_state *smbldap_state) 
509 {
510         struct smbldap_state_lookup *t;
511
512         for (t = smbldap_state_lookup_list; t; t = t->next) {
513                 if (t->smbldap_state == smbldap_state) {
514                         DLIST_REMOVE(smbldap_state_lookup_list, t);
515                         SAFE_FREE(t);
516                         return;
517                 }
518         }
519 }
520
521 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) 
522 {
523         struct smbldap_state *tmp_ldap_state;
524         struct smbldap_state_lookup *t;
525         struct smbldap_state_lookup *tmp;
526         
527         if ((tmp_ldap_state = smbldap_find_state(ld))) {
528                 SMB_ASSERT(tmp_ldap_state == smbldap_state);
529                 return;
530         }
531
532         t = smb_xmalloc(sizeof(*t));
533         ZERO_STRUCTP(t);
534         
535         DLIST_ADD_END(smbldap_state_lookup_list, t, tmp);
536         t->ld = ld;
537         t->smbldap_state = smbldap_state;
538 }
539
540 /*******************************************************************
541  open a connection to the ldap server.
542 ******************************************************************/
543 static int smbldap_open_connection (struct smbldap_state *ldap_state)
544
545 {
546         int rc = LDAP_SUCCESS;
547         int version;
548         BOOL ldap_v3 = False;
549         LDAP **ldap_struct = &ldap_state->ldap_struct;
550
551 #ifdef HAVE_LDAP_INITIALIZE
552         DEBUG(10, ("smbldap_open_connection: %s\n", ldap_state->uri));
553         
554         if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
555                 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
556                 return rc;
557         }
558 #else 
559
560         /* Parse the string manually */
561
562         {
563                 int port = 0;
564                 fstring protocol;
565                 fstring host;
566                 const char *p = ldap_state->uri; 
567                 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
568                 
569                 /* skip leading "URL:" (if any) */
570                 if ( strnequal( p, "URL:", 4 ) ) {
571                         p += 4;
572                 }
573                 
574                 sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
575                 
576                 if (port == 0) {
577                         if (strequal(protocol, "ldap")) {
578                                 port = LDAP_PORT;
579                         } else if (strequal(protocol, "ldaps")) {
580                                 port = LDAPS_PORT;
581                         } else {
582                                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
583                         }
584                 }
585                 
586                 if ((*ldap_struct = ldap_init(host, port)) == NULL)     {
587                         DEBUG(0, ("ldap_init failed !\n"));
588                         return LDAP_OPERATIONS_ERROR;
589                 }
590                 
591                 if (strequal(protocol, "ldaps")) {
592 #ifdef LDAP_OPT_X_TLS
593                         int tls = LDAP_OPT_X_TLS_HARD;
594                         if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
595                         {
596                                 DEBUG(0, ("Failed to setup a TLS session\n"));
597                         }
598                         
599                         DEBUG(3,("LDAPS option set...!\n"));
600 #else
601                         DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
602                         return LDAP_OPERATIONS_ERROR;
603 #endif
604                 }
605         }
606 #endif
607
608         /* Store the LDAP pointer in a lookup list */
609
610         smbldap_store_state(*ldap_struct, ldap_state);
611
612         /* Upgrade to LDAPv3 if possible */
613
614         if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
615         {
616                 if (version != LDAP_VERSION3)
617                 {
618                         version = LDAP_VERSION3;
619                         if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
620                                 ldap_v3 = True;
621                         }
622                 } else {
623                         ldap_v3 = True;
624                 }
625         }
626
627         if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
628 #ifdef LDAP_OPT_X_TLS
629                 if (ldap_v3) {
630                         if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
631                         {
632                                 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
633                                          ldap_err2string(rc)));
634                                 return rc;
635                         }
636                         DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
637                 } else {
638                         
639                         DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
640                         return LDAP_OPERATIONS_ERROR;
641                 }
642 #else
643                 DEBUG(0,("smbldap_open_connection: StartTLS not supported by LDAP client libraries!\n"));
644                 return LDAP_OPERATIONS_ERROR;
645 #endif
646         }
647
648         DEBUG(2, ("smbldap_open_connection: connection opened\n"));
649         return rc;
650 }
651
652
653 /*******************************************************************
654  a rebind function for authenticated referrals
655  This version takes a void* that we can shove useful stuff in :-)
656 ******************************************************************/
657 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
658 #else
659 static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
660                                    int *methodp, int freeit, void *arg)
661 {
662         struct smbldap_state *ldap_state = arg;
663         
664         /** @TODO Should we be doing something to check what servers we rebind to?
665             Could we get a referral to a machine that we don't want to give our
666             username and password to? */
667         
668         if (freeit) {
669                 SAFE_FREE(*whop);
670                 memset(*credp, '\0', strlen(*credp));
671                 SAFE_FREE(*credp);
672         } else {
673                 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", 
674                           ldap_state->bind_dn));
675
676                 *whop = strdup(ldap_state->bind_dn);
677                 if (!*whop) {
678                         return LDAP_NO_MEMORY;
679                 }
680                 *credp = strdup(ldap_state->bind_secret);
681                 if (!*credp) {
682                         SAFE_FREE(*whop);
683                         return LDAP_NO_MEMORY;
684                 }
685                 *methodp = LDAP_AUTH_SIMPLE;
686         }
687
688         gettimeofday(&(ldap_state->last_rebind),NULL);
689                 
690         return 0;
691 }
692 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
693
694 /*******************************************************************
695  a rebind function for authenticated referrals
696  This version takes a void* that we can shove useful stuff in :-)
697  and actually does the connection.
698 ******************************************************************/
699 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
700 static int rebindproc_connect_with_state (LDAP *ldap_struct, 
701                                           LDAP_CONST char *url, 
702                                           ber_tag_t request,
703                                           ber_int_t msgid, void *arg)
704 {
705         struct smbldap_state *ldap_state = arg;
706         int rc;
707         DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", 
708                  ldap_state->bind_dn));
709         
710         /** @TODO Should we be doing something to check what servers we rebind to?
711             Could we get a referral to a machine that we don't want to give our
712             username and password to? */
713
714         rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
715         
716         gettimeofday(&(ldap_state->last_rebind),NULL);
717
718         return rc;
719 }
720 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
721
722 /*******************************************************************
723  Add a rebind function for authenticated referrals
724 ******************************************************************/
725 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
726 #else
727 # if LDAP_SET_REBIND_PROC_ARGS == 2
728 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
729                        int *method, int freeit )
730 {
731         struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
732
733         return rebindproc_with_state(ldap_struct, whop, credp,
734                                      method, freeit, ldap_state);
735         
736 }
737 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
738 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
739
740 /*******************************************************************
741  a rebind function for authenticated referrals
742  this also does the connection, but no void*.
743 ******************************************************************/
744 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
745 # if LDAP_SET_REBIND_PROC_ARGS == 2
746 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
747                                ber_int_t msgid)
748 {
749         struct smbldap_state *ldap_state = smbldap_find_state(ld);
750
751         return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
752                                              ldap_state);
753 }
754 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
755 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
756
757 /*******************************************************************
758  connect to the ldap server under system privilege.
759 ******************************************************************/
760 static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_struct)
761 {
762         int rc;
763         char *ldap_dn;
764         char *ldap_secret;
765
766         /* get the password */
767         if (!fetch_ldap_pw(&ldap_dn, &ldap_secret))
768         {
769                 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
770                 return LDAP_INVALID_CREDENTIALS;
771         }
772
773         ldap_state->bind_dn = ldap_dn;
774         ldap_state->bind_secret = ldap_secret;
775
776         /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
777            (OpenLDAP) doesnt' seem to support it */
778            
779         DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
780                   ldap_state->uri, ldap_dn));
781
782 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
783 # if LDAP_SET_REBIND_PROC_ARGS == 2     
784         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); 
785 # endif
786 # if LDAP_SET_REBIND_PROC_ARGS == 3     
787         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
788 # endif
789 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
790 # if LDAP_SET_REBIND_PROC_ARGS == 2     
791         ldap_set_rebind_proc(ldap_struct, &rebindproc); 
792 # endif
793 # if LDAP_SET_REBIND_PROC_ARGS == 3     
794         ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
795 # endif
796 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
797
798         rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
799
800         if (rc != LDAP_SUCCESS) {
801                 char *ld_error = NULL;
802                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
803                                 &ld_error);
804                 DEBUG(ldap_state->num_failures ? 2 : 0,
805                       ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
806                                ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc),
807                                ld_error ? ld_error : "(unknown)"));
808                 SAFE_FREE(ld_error);
809                 ldap_state->num_failures++;
810                 return rc;
811         }
812
813         ldap_state->num_failures = 0;
814
815         DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
816         return rc;
817 }
818
819 /**********************************************************************
820 Connect to LDAP server (called before every ldap operation)
821 *********************************************************************/
822 static int smbldap_open(struct smbldap_state *ldap_state)
823 {
824         int rc;
825         SMB_ASSERT(ldap_state);
826                 
827 #ifndef NO_LDAP_SECURITY
828         if (geteuid() != 0) {
829                 DEBUG(0, ("smbldap_open: cannot access LDAP when not root..\n"));
830                 return  LDAP_INSUFFICIENT_ACCESS;
831         }
832 #endif
833
834         if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time(NULL))) {
835                 struct sockaddr_un addr;
836                 socklen_t len = sizeof(addr);
837                 int sd;
838                 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
839                     getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
840                         /* the other end has died. reopen. */
841                         ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
842                         ldap_state->ldap_struct = NULL;
843                         ldap_state->last_ping = (time_t)0;
844                 } else {
845                         ldap_state->last_ping = time(NULL);
846                 } 
847         }
848
849         if (ldap_state->ldap_struct != NULL) {
850                 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
851                 return LDAP_SUCCESS;
852         }
853
854         if ((rc = smbldap_open_connection(ldap_state))) {
855                 return rc;
856         }
857
858         if ((rc = smbldap_connect_system(ldap_state, ldap_state->ldap_struct))) {
859                 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
860                 ldap_state->ldap_struct = NULL;
861                 return rc;
862         }
863
864
865         ldap_state->last_ping = time(NULL);
866         DEBUG(4,("The LDAP server is succesful connected\n"));
867
868         return LDAP_SUCCESS;
869 }
870
871 /**********************************************************************
872 Disconnect from LDAP server 
873 *********************************************************************/
874 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
875 {
876         if (!ldap_state)
877                 return NT_STATUS_INVALID_PARAMETER;
878                 
879         if (ldap_state->ldap_struct != NULL) {
880                 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
881                 ldap_state->ldap_struct = NULL;
882         }
883
884         smbldap_delete_state(ldap_state);
885         
886         DEBUG(5,("The connection to the LDAP server was closed\n"));
887         /* maybe free the results here --metze */
888         
889         
890
891         return NT_STATUS_OK;
892 }
893
894 int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts)
895 {
896         int rc;
897
898         SMB_ASSERT(ldap_state && attempts);
899                 
900         if (*attempts != 0) {
901                 unsigned int sleep_time;
902                 uint8 rand_byte;
903
904                 /* Sleep for a random timeout */
905                 rand_byte = (char)(sys_random());
906
907                 sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; 
908                 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
909                    on average.  
910                  */
911                 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", 
912                           sleep_time));
913                 smb_msleep(sleep_time);
914         }
915         (*attempts)++;
916
917         if ((rc = smbldap_open(ldap_state))) {
918                 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
919                 return rc;
920         } 
921         
922         return LDAP_SUCCESS;            
923 }
924
925
926 /*********************************************************************
927  ********************************************************************/
928
929 int smbldap_search(struct smbldap_state *ldap_state, 
930                    const char *base, int scope, const char *filter, 
931                    char *attrs[], int attrsonly, 
932                    LDAPMessage **res)
933 {
934         int             rc = LDAP_SERVER_DOWN;
935         int             attempts = 0;
936         char           *utf8_filter;
937
938         SMB_ASSERT(ldap_state);
939         
940         DEBUG(5,("smbldap_search: base => [%s], filter => [%s], scope => [%d]\n",
941                 base, filter, scope));
942
943         if (ldap_state->last_rebind.tv_sec > 0) {
944                 struct timeval  tval;
945                 int             tdiff = 0;
946                 int             sleep_time = 0;
947
948                 ZERO_STRUCT(tval);
949
950                 gettimeofday(&tval,NULL);
951
952                 tdiff = 1000000 *(tval.tv_sec - ldap_state->last_rebind.tv_sec) + 
953                         (tval.tv_usec - ldap_state->last_rebind.tv_usec);
954
955                 sleep_time = ((1000*lp_ldap_replication_sleep())-tdiff)/1000;
956
957                 if (sleep_time > 0) {
958                         /* we wait for the LDAP replication */
959                         DEBUG(5,("smbldap_search: waiting %d milliseconds for LDAP replication.\n",sleep_time));
960                         smb_msleep(sleep_time);
961                         DEBUG(5,("smbldap_search: go on!\n"));
962                         ZERO_STRUCT(ldap_state->last_rebind);
963                 }
964         }
965
966         if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
967                 return LDAP_NO_MEMORY;
968         }
969
970         while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
971                 
972                 if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
973                         continue;
974                 
975                 rc = ldap_search_s(ldap_state->ldap_struct, base, scope, 
976                                    utf8_filter, attrs, attrsonly, res);
977         }
978         
979         if (rc == LDAP_SERVER_DOWN) {
980                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
981                 smbldap_close(ldap_state);      
982         }
983
984         ldap_state->last_use = time(NULL);
985
986         SAFE_FREE(utf8_filter);
987         return rc;
988 }
989
990 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
991 {
992         int             rc = LDAP_SERVER_DOWN;
993         int             attempts = 0;
994         char           *utf8_dn;
995
996         SMB_ASSERT(ldap_state);
997
998         DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
999
1000         if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
1001                 return LDAP_NO_MEMORY;
1002         }
1003
1004         while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
1005                 
1006                 if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
1007                         continue;
1008                 
1009                 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
1010         }
1011         
1012         if (rc == LDAP_SERVER_DOWN) {
1013                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
1014                 smbldap_close(ldap_state);      
1015         }
1016         
1017         ldap_state->last_use = time(NULL);
1018
1019         SAFE_FREE(utf8_dn);
1020         return rc;
1021 }
1022
1023 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1024 {
1025         int             rc = LDAP_SERVER_DOWN;
1026         int             attempts = 0;
1027         char           *utf8_dn;
1028         
1029         SMB_ASSERT(ldap_state);
1030
1031         DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1032
1033         if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
1034                 return LDAP_NO_MEMORY;
1035         }
1036
1037         while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
1038                 
1039                 if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
1040                         continue;
1041                 
1042                 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
1043         }
1044         
1045         if (rc == LDAP_SERVER_DOWN) {
1046                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
1047                 smbldap_close(ldap_state);      
1048         }
1049                 
1050         ldap_state->last_use = time(NULL);
1051
1052         SAFE_FREE(utf8_dn);
1053         return rc;
1054 }
1055
1056 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1057 {
1058         int             rc = LDAP_SERVER_DOWN;
1059         int             attempts = 0;
1060         char           *utf8_dn;
1061         
1062         SMB_ASSERT(ldap_state);
1063
1064         DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1065
1066         if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
1067                 return LDAP_NO_MEMORY;
1068         }
1069
1070         while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
1071                 
1072                 if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
1073                         continue;
1074                 
1075                 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
1076         }
1077         
1078         if (rc == LDAP_SERVER_DOWN) {
1079                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
1080                 smbldap_close(ldap_state);      
1081         }
1082                 
1083         ldap_state->last_use = time(NULL);
1084
1085         SAFE_FREE(utf8_dn);
1086         return rc;
1087 }
1088
1089 int smbldap_extended_operation(struct smbldap_state *ldap_state, 
1090                                LDAP_CONST char *reqoid, struct berval *reqdata, 
1091                                LDAPControl **serverctrls, LDAPControl **clientctrls, 
1092                                char **retoidp, struct berval **retdatap)
1093 {
1094         int             rc = LDAP_SERVER_DOWN;
1095         int             attempts = 0;
1096         
1097         if (!ldap_state)
1098                 return (-1);
1099
1100         while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
1101                 
1102                 if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
1103                         continue;
1104                 
1105                 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, 
1106                                                serverctrls, clientctrls, retoidp, retdatap);
1107         }
1108         
1109         if (rc == LDAP_SERVER_DOWN) {
1110                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
1111                 smbldap_close(ldap_state);      
1112         }
1113                 
1114         ldap_state->last_use = time(NULL);
1115
1116         return rc;
1117 }
1118
1119 /*******************************************************************
1120  run the search by name.
1121 ******************************************************************/
1122 int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, 
1123                            char **search_attr, LDAPMessage ** result)
1124 {
1125         int scope = LDAP_SCOPE_SUBTREE;
1126         int rc;
1127
1128         rc = smbldap_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result);
1129
1130         if (rc != LDAP_SUCCESS) {
1131                 char *ld_error = NULL;
1132                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1133                                 &ld_error);
1134                 DEBUG(0,("smbldap_search_suffix: Problem during the LDAP search: %s (%s)\n", 
1135                         ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
1136                 SAFE_FREE(ld_error);
1137         }
1138         
1139         return rc;
1140 }
1141
1142 static void smbldap_idle_fn(void **data, time_t *interval, time_t now)
1143 {
1144         struct smbldap_state *state = (struct smbldap_state *)(*data);
1145
1146         if (state->ldap_struct == NULL) {
1147                 DEBUG(10,("ldap connection not connected...\n"));
1148                 return;
1149         }
1150                 
1151         if ((state->last_use+SMBLDAP_IDLE_TIME) > now) {
1152                 DEBUG(10,("ldap connection not idle...\n"));
1153                 return;
1154         }
1155                 
1156         DEBUG(7,("ldap connection idle...closing connection\n"));
1157         smbldap_close(state);
1158 }
1159
1160 /**********************************************************************
1161  Housekeeping
1162  *********************************************************************/
1163
1164 void smbldap_free_struct(struct smbldap_state **ldap_state) 
1165 {
1166         smbldap_close(*ldap_state);
1167         
1168         if ((*ldap_state)->bind_secret) {
1169                 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1170         }
1171
1172         SAFE_FREE((*ldap_state)->bind_dn);
1173         SAFE_FREE((*ldap_state)->bind_secret);
1174
1175         smb_unregister_idle_event((*ldap_state)->event_id);
1176
1177         *ldap_state = NULL;
1178
1179         /* No need to free any further, as it is talloc()ed */
1180 }
1181
1182
1183 /**********************************************************************
1184  Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1185  *********************************************************************/
1186
1187 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_state **smbldap_state) 
1188 {
1189         *smbldap_state = talloc_zero(mem_ctx, sizeof(**smbldap_state));
1190         if (!*smbldap_state) {
1191                 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1192                 return NT_STATUS_NO_MEMORY;
1193         }
1194
1195         if (location) {
1196                 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1197         } else {
1198                 (*smbldap_state)->uri = "ldap://localhost";
1199         }
1200
1201         (*smbldap_state)->event_id =
1202                 smb_register_idle_event(smbldap_idle_fn, (void *)(*smbldap_state),
1203                                         SMBLDAP_IDLE_TIME);
1204
1205         if ((*smbldap_state)->event_id == SMB_EVENT_ID_INVALID) {
1206                 DEBUG(0,("Failed to register LDAP idle event!\n"));
1207                 return NT_STATUS_INVALID_HANDLE;
1208         }
1209
1210         return NT_STATUS_OK;
1211 }
1212
1213 /*******************************************************************
1214  Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX.
1215 ********************************************************************/
1216
1217 char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry)
1218 {
1219         char *utf8_dn, *unix_dn;
1220
1221         utf8_dn = ldap_get_dn(ld, entry);
1222         if (!utf8_dn) {
1223                 DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n"));
1224                 return NULL;
1225         }
1226         if (pull_utf8_allocate(&unix_dn, utf8_dn) == (size_t)-1) {
1227                 DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 [%s]\n", utf8_dn));
1228                 return NULL;
1229         }
1230         ldap_memfree(utf8_dn);
1231         return unix_dn;
1232 }