b1571536eb02ab701b0ab4c7020cf59c730fdc55
[nivanova/samba-autobuild/.git] / source3 / lib / smbldap.c
1 /* 
2    Unix SMB/CIFS implementation.
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 /* Try not to hit the up or down server forever */
29
30 #define SMBLDAP_DONT_PING_TIME 10       /* ping only all 10 seconds */
31 #define SMBLDAP_NUM_RETRIES 8           /* retry only 8 times */
32
33 #define SMBLDAP_IDLE_TIME 150           /* After 2.5 minutes disconnect */
34
35
36 /* attributes used by Samba 2.2 */
37
38 ATTRIB_MAP_ENTRY attrib_map_v22[] = {
39         { LDAP_ATTR_UID,                "uid"           },
40         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
41         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
42         { LDAP_ATTR_UNIX_HOME,          "homeDirectory" },
43         { LDAP_ATTR_PWD_LAST_SET,       "pwdLastSet"    },
44         { LDAP_ATTR_PWD_CAN_CHANGE,     "pwdCanChange"  },
45         { LDAP_ATTR_PWD_MUST_CHANGE,    "pwdMustChange" },
46         { LDAP_ATTR_LOGON_TIME,         "logonTime"     },
47         { LDAP_ATTR_LOGOFF_TIME,        "logoffTime"    },
48         { LDAP_ATTR_KICKOFF_TIME,       "kickoffTime"   },
49         { LDAP_ATTR_CN,                 "cn"            },
50         { LDAP_ATTR_SN,                 "sn"            },
51         { LDAP_ATTR_DISPLAY_NAME,       "displayName"   },
52         { LDAP_ATTR_HOME_PATH,          "smbHome"       },
53         { LDAP_ATTR_HOME_DRIVE,         "homeDrive"     },
54         { LDAP_ATTR_LOGON_SCRIPT,       "scriptPath"    },
55         { LDAP_ATTR_PROFILE_PATH,       "profilePath"   },
56         { LDAP_ATTR_DESC,               "description"   },
57         { LDAP_ATTR_USER_WKS,           "userWorkstations"},
58         { LDAP_ATTR_USER_RID,           "rid"           },
59         { LDAP_ATTR_PRIMARY_GROUP_RID,  "primaryGroupID"},
60         { LDAP_ATTR_LMPW,               "lmPassword"    },
61         { LDAP_ATTR_NTPW,               "ntPassword"    },
62         { LDAP_ATTR_DOMAIN,             "domain"        },
63         { LDAP_ATTR_OBJCLASS,           "objectClass"   },
64         { LDAP_ATTR_ACB_INFO,           "acctFlags"     },
65         { LDAP_ATTR_MOD_TIMESTAMP,      "modifyTimestamp"       },
66         { LDAP_ATTR_LIST_END,           NULL            }
67 };
68
69 ATTRIB_MAP_ENTRY attrib_map_to_delete_v22[] = {
70         { LDAP_ATTR_PWD_LAST_SET,       "pwdLastSet"    },
71         { LDAP_ATTR_PWD_CAN_CHANGE,     "pwdCanChange"  },
72         { LDAP_ATTR_PWD_MUST_CHANGE,    "pwdMustChange" },
73         { LDAP_ATTR_LOGON_TIME,         "logonTime"     },
74         { LDAP_ATTR_LOGOFF_TIME,        "logoffTime"    },
75         { LDAP_ATTR_KICKOFF_TIME,       "kickoffTime"   },
76         { LDAP_ATTR_DISPLAY_NAME,       "displayName"   },
77         { LDAP_ATTR_HOME_PATH,          "smbHome"       },
78         { LDAP_ATTR_HOME_DRIVE,         "homeDrives"    },
79         { LDAP_ATTR_LOGON_SCRIPT,       "scriptPath"    },
80         { LDAP_ATTR_PROFILE_PATH,       "profilePath"   },
81         { LDAP_ATTR_USER_WKS,           "userWorkstations"},
82         { LDAP_ATTR_USER_RID,           "rid"           },
83         { LDAP_ATTR_PRIMARY_GROUP_RID,  "primaryGroupID"},
84         { LDAP_ATTR_LMPW,               "lmPassword"    },
85         { LDAP_ATTR_NTPW,               "ntPassword"    },
86         { LDAP_ATTR_DOMAIN,             "domain"        },
87         { LDAP_ATTR_ACB_INFO,           "acctFlags"     },
88         { LDAP_ATTR_LIST_END,           NULL            }
89 };
90
91 /* attributes used by Samba 3.0's sambaSamAccount */
92
93 ATTRIB_MAP_ENTRY attrib_map_v30[] = {
94         { LDAP_ATTR_UID,                "uid"                   },
95         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
96         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
97         { LDAP_ATTR_UNIX_HOME,          "homeDirectory"         },
98         { LDAP_ATTR_PWD_LAST_SET,       "sambaPwdLastSet"       },
99         { LDAP_ATTR_PWD_CAN_CHANGE,     "sambaPwdCanChange"     },
100         { LDAP_ATTR_PWD_MUST_CHANGE,    "sambaPwdMustChange"    },
101         { LDAP_ATTR_LOGON_TIME,         "sambaLogonTime"        },
102         { LDAP_ATTR_LOGOFF_TIME,        "sambaLogoffTime"       },
103         { LDAP_ATTR_KICKOFF_TIME,       "sambaKickoffTime"      },
104         { LDAP_ATTR_CN,                 "cn"                    },
105         { LDAP_ATTR_SN,                 "sn"                    },
106         { LDAP_ATTR_DISPLAY_NAME,       "displayName"           },
107         { LDAP_ATTR_HOME_DRIVE,         "sambaHomeDrive"        },
108         { LDAP_ATTR_HOME_PATH,          "sambaHomePath"         },
109         { LDAP_ATTR_LOGON_SCRIPT,       "sambaLogonScript"      },
110         { LDAP_ATTR_PROFILE_PATH,       "sambaProfilePath"      },
111         { LDAP_ATTR_DESC,               "description"           },
112         { LDAP_ATTR_USER_WKS,           "sambaUserWorkstations" },
113         { LDAP_ATTR_USER_SID,           LDAP_ATTRIBUTE_SID      },
114         { LDAP_ATTR_PRIMARY_GROUP_SID,  "sambaPrimaryGroupSID"  },
115         { LDAP_ATTR_LMPW,               "sambaLMPassword"       },
116         { LDAP_ATTR_NTPW,               "sambaNTPassword"       },
117         { LDAP_ATTR_DOMAIN,             "sambaDomainName"       },
118         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
119         { LDAP_ATTR_ACB_INFO,           "sambaAcctFlags"        },
120         { LDAP_ATTR_MUNGED_DIAL,        "sambaMungedDial"       },
121         { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" },
122         { LDAP_ATTR_BAD_PASSWORD_TIME,  "sambaBadPasswordTime"  },
123         { LDAP_ATTR_PWD_HISTORY,        "sambaPasswordHistory"  },
124         { LDAP_ATTR_MOD_TIMESTAMP,      "modifyTimestamp"       },
125         { LDAP_ATTR_LOGON_HOURS,        "sambaLogonHours"       },
126         { LDAP_ATTR_LIST_END,           NULL                    }
127 };
128
129 ATTRIB_MAP_ENTRY attrib_map_to_delete_v30[] = {
130         { LDAP_ATTR_PWD_LAST_SET,       "sambaPwdLastSet"       },
131         { LDAP_ATTR_PWD_CAN_CHANGE,     "sambaPwdCanChange"     },
132         { LDAP_ATTR_PWD_MUST_CHANGE,    "sambaPwdMustChange"    },
133         { LDAP_ATTR_LOGON_TIME,         "sambaLogonTime"        },
134         { LDAP_ATTR_LOGOFF_TIME,        "sambaLogoffTime"       },
135         { LDAP_ATTR_KICKOFF_TIME,       "sambaKickoffTime"      },
136         { LDAP_ATTR_DISPLAY_NAME,       "displayName"           },
137         { LDAP_ATTR_HOME_DRIVE,         "sambaHomeDrive"        },
138         { LDAP_ATTR_HOME_PATH,          "sambaHomePath"         },
139         { LDAP_ATTR_LOGON_SCRIPT,       "sambaLogonScript"      },
140         { LDAP_ATTR_PROFILE_PATH,       "sambaProfilePath"      },
141         { LDAP_ATTR_USER_WKS,           "sambaUserWorkstations" },
142         { LDAP_ATTR_USER_SID,           LDAP_ATTRIBUTE_SID      },
143         { LDAP_ATTR_PRIMARY_GROUP_SID,  "sambaPrimaryGroupSID"  },
144         { LDAP_ATTR_LMPW,               "sambaLMPassword"       },
145         { LDAP_ATTR_NTPW,               "sambaNTPassword"       },
146         { LDAP_ATTR_DOMAIN,             "sambaDomainName"       },
147         { LDAP_ATTR_ACB_INFO,           "sambaAcctFlags"        },
148         { LDAP_ATTR_MUNGED_DIAL,        "sambaMungedDial"       },
149         { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" },
150         { LDAP_ATTR_BAD_PASSWORD_TIME,  "sambaBadPasswordTime"  },
151         { LDAP_ATTR_PWD_HISTORY,        "sambaPasswordHistory"  },
152         { LDAP_ATTR_LOGON_HOURS,        "sambaLogonHours"       },
153         { LDAP_ATTR_LIST_END,           NULL                    }
154 };
155
156 /* attributes used for allocating RIDs */
157
158 ATTRIB_MAP_ENTRY dominfo_attr_list[] = {
159         { LDAP_ATTR_DOMAIN,             "sambaDomainName"       },
160         { LDAP_ATTR_NEXT_RID,           "sambaNextRid"          },
161         { LDAP_ATTR_NEXT_USERRID,       "sambaNextUserRid"      },
162         { LDAP_ATTR_NEXT_GROUPRID,      "sambaNextGroupRid"     },
163         { LDAP_ATTR_DOM_SID,            LDAP_ATTRIBUTE_SID      },
164         { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"},
165         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
166         { LDAP_ATTR_LIST_END,           NULL                    },
167 };
168
169 /* Samba 3.0 group mapping attributes */
170
171 ATTRIB_MAP_ENTRY groupmap_attr_list[] = {
172         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
173         { LDAP_ATTR_GROUP_SID,          LDAP_ATTRIBUTE_SID      },
174         { LDAP_ATTR_GROUP_TYPE,         "sambaGroupType"        },
175         { LDAP_ATTR_SID_LIST,           "sambaSIDList"          },
176         { LDAP_ATTR_DESC,               "description"           },
177         { LDAP_ATTR_DISPLAY_NAME,       "displayName"           },
178         { LDAP_ATTR_CN,                 "cn"                    },
179         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
180         { LDAP_ATTR_LIST_END,           NULL                    }       
181 };
182
183 ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = {
184         { LDAP_ATTR_GROUP_SID,          LDAP_ATTRIBUTE_SID      },
185         { LDAP_ATTR_GROUP_TYPE,         "sambaGroupType"        },
186         { LDAP_ATTR_DESC,               "description"           },
187         { LDAP_ATTR_DISPLAY_NAME,       "displayName"           },
188         { LDAP_ATTR_SID_LIST,           "sambaSIDList"          },
189         { LDAP_ATTR_LIST_END,           NULL                    }       
190 };
191
192 /* idmap_ldap sambaUnixIdPool */
193
194 ATTRIB_MAP_ENTRY idpool_attr_list[] = {
195         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
196         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
197         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
198         { LDAP_ATTR_LIST_END,           NULL                    }       
199 };
200
201 ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
202         { LDAP_ATTR_SID,                LDAP_ATTRIBUTE_SID      },
203         { LDAP_ATTR_UIDNUMBER,          LDAP_ATTRIBUTE_UIDNUMBER},
204         { LDAP_ATTR_GIDNUMBER,          LDAP_ATTRIBUTE_GIDNUMBER},
205         { LDAP_ATTR_OBJCLASS,           "objectClass"           },
206         { LDAP_ATTR_LIST_END,           NULL                    }       
207 };
208
209 /**********************************************************************
210  perform a simple table lookup and return the attribute name 
211  **********************************************************************/
212  
213  const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key )
214 {
215         int i = 0;
216
217         while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
218                 if ( table[i].attrib == key )
219                         return table[i].name;
220                 i++;
221         }
222
223         return NULL;
224 }
225
226
227 /**********************************************************************
228  Return the list of attribute names from a mapping table
229  **********************************************************************/
230
231  const char** get_attr_list( TALLOC_CTX *mem_ctx, ATTRIB_MAP_ENTRY table[] )
232 {
233         const char **names;
234         int i = 0;
235
236         while ( table[i].attrib != LDAP_ATTR_LIST_END )
237                 i++;
238         i++;
239
240         names = TALLOC_ARRAY( mem_ctx, const char*, i );
241         if ( !names ) {
242                 DEBUG(0,("get_attr_list: out of memory\n"));
243                 return NULL;
244         }
245
246         i = 0;
247         while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
248                 names[i] = talloc_strdup( names, table[i].name );
249                 i++;
250         }
251         names[i] = NULL;
252
253         return names;
254 }
255
256 /*******************************************************************
257  Search an attribute and return the first value found.
258 ******************************************************************/
259
260  bool smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
261                                     const char *attribute, char *value,
262                                     int max_len)
263 {
264         char **values;
265
266         if ( !attribute )
267                 return False;
268
269         value[0] = '\0';
270
271         if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
272                 DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
273
274                 return False;
275         }
276
277         if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, False) == (size_t)-1) {
278                 DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n", 
279                           attribute, values[0]));
280                 ldap_value_free(values);
281                 return False;
282         }
283
284         ldap_value_free(values);
285 #ifdef DEBUG_PASSWORDS
286         DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
287 #endif  
288         return True;
289 }
290
291  char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
292                                         const char *attribute,
293                                         TALLOC_CTX *mem_ctx)
294 {
295         char **values;
296         char *result;
297         size_t converted_size;
298
299         if (attribute == NULL) {
300                 return NULL;
301         }
302
303         values = ldap_get_values(ldap_struct, entry, attribute);
304
305         if (values == NULL) {
306                 DEBUG(10, ("attribute %s does not exist\n", attribute));
307                 return NULL;
308         }
309
310         if (ldap_count_values(values) != 1) {
311                 DEBUG(10, ("attribute %s has %d values, expected only one\n",
312                            attribute, ldap_count_values(values)));
313                 ldap_value_free(values);
314                 return NULL;
315         }
316
317         if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
318                 DEBUG(10, ("pull_utf8_talloc failed\n"));
319                 ldap_value_free(values);
320                 return NULL;
321         }
322
323         ldap_value_free(values);
324
325 #ifdef DEBUG_PASSWORDS
326         DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
327                      attribute, result));
328 #endif  
329         return result;
330 }
331
332  char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
333                                        const char *attribute,
334                                        TALLOC_CTX *mem_ctx)
335 {
336         char **values;
337         char *result;
338         size_t converted_size;
339
340         if (attribute == NULL) {
341                 return NULL;
342         }
343
344         values = ldap_get_values(ldap_struct, entry, attribute);
345
346         if (values == NULL) {
347                 DEBUG(10, ("attribute %s does not exist\n", attribute));
348                 return NULL;
349         }
350
351         if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
352                 DEBUG(10, ("pull_utf8_talloc failed\n"));
353                 ldap_value_free(values);
354                 return NULL;
355         }
356
357         ldap_value_free(values);
358
359 #ifdef DEBUG_PASSWORDS
360         DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
361                      attribute, result));
362 #endif
363         return result;
364 }
365
366  char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
367                                           const char *attribute,
368                                           TALLOC_CTX *mem_ctx)
369 {
370         char **values;
371         char *result;
372         size_t converted_size;
373         int i, num_values;
374
375         if (attribute == NULL) {
376                 return NULL;
377         }
378
379         values = ldap_get_values(ldap_struct, entry, attribute);
380
381         if (values == NULL) {
382                 DEBUG(10, ("attribute %s does not exist\n", attribute));
383                 return NULL;
384         }
385
386         if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
387                 DEBUG(10, ("pull_utf8_talloc failed\n"));
388                 ldap_value_free(values);
389                 return NULL;
390         }
391
392         num_values = ldap_count_values(values);
393
394         for (i=1; i<num_values; i++) {
395                 char *tmp;
396
397                 if (!pull_utf8_talloc(mem_ctx, &tmp, values[i],
398                                       &converted_size)) {
399                         DEBUG(10, ("pull_utf8_talloc failed\n"));
400                         TALLOC_FREE(result);
401                         ldap_value_free(values);
402                         return NULL;
403                 }
404
405                 if (StrCaseCmp(tmp, result) < 0) {
406                         TALLOC_FREE(result);
407                         result = tmp;
408                 } else {
409                         TALLOC_FREE(tmp);
410                 }
411         }
412
413         ldap_value_free(values);
414
415 #ifdef DEBUG_PASSWORDS
416         DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
417                      attribute, result));
418 #endif
419         return result;
420 }
421
422  bool smbldap_talloc_single_blob(TALLOC_CTX *mem_ctx, LDAP *ld,
423                                  LDAPMessage *msg, const char *attrib,
424                                  DATA_BLOB *blob)
425 {
426         struct berval **values;
427
428         values = ldap_get_values_len(ld, msg, attrib);
429         if (!values) {
430                 return false;
431         }
432
433         if (ldap_count_values_len(values) != 1) {
434                 DEBUG(10, ("Expected one value for %s, got %d\n", attrib,
435                            ldap_count_values_len(values)));
436                 return false;
437         }
438
439         *blob = data_blob_talloc(mem_ctx, values[0]->bv_val,
440                                  values[0]->bv_len);
441         ldap_value_free_len(values);
442
443         return (blob->data != NULL);
444 }
445
446  bool smbldap_pull_sid(LDAP *ld, LDAPMessage *msg, const char *attrib,
447                        struct dom_sid *sid)
448 {
449         DATA_BLOB blob;
450         bool ret;
451
452         if (!smbldap_talloc_single_blob(talloc_tos(), ld, msg, attrib,
453                                         &blob)) {
454                 return false;
455         }
456         ret = sid_parse((char *)blob.data, blob.length, sid);
457         TALLOC_FREE(blob.data);
458         return ret;
459 }
460
461  static int ldapmsg_destructor(LDAPMessage **result) {
462         ldap_msgfree(*result);
463         return 0;
464 }
465
466  void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
467 {
468         LDAPMessage **handle;
469
470         if (result == NULL) {
471                 return;
472         }
473
474         handle = TALLOC_P(mem_ctx, LDAPMessage *);
475         SMB_ASSERT(handle != NULL);
476
477         *handle = result;
478         talloc_set_destructor(handle, ldapmsg_destructor);
479 }
480
481  static int ldapmod_destructor(LDAPMod ***mod) {
482         ldap_mods_free(*mod, True);
483         return 0;
484 }
485
486  void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
487 {
488         LDAPMod ***handle;
489
490         if (mod == NULL) {
491                 return;
492         }
493
494         handle = TALLOC_P(mem_ctx, LDAPMod **);
495         SMB_ASSERT(handle != NULL);
496
497         *handle = mod;
498         talloc_set_destructor(handle, ldapmod_destructor);
499 }
500
501 /************************************************************************
502  Routine to manage the LDAPMod structure array
503  manage memory used by the array, by each struct, and values
504  ***********************************************************************/
505
506  void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
507 {
508         LDAPMod **mods;
509         int i;
510         int j;
511
512         mods = *modlist;
513
514         /* sanity checks on the mod values */
515
516         if (attribute == NULL || *attribute == '\0') {
517                 return; 
518         }
519
520 #if 0   /* commented out after discussion with abartlet.  Do not reenable.
521            left here so other do not re-add similar code   --jerry */
522         if (value == NULL || *value == '\0')
523                 return;
524 #endif
525
526         if (mods == NULL) {
527                 mods = SMB_MALLOC_P(LDAPMod *);
528                 if (mods == NULL) {
529                         smb_panic("smbldap_set_mod: out of memory!");
530                         /* notreached. */
531                 }
532                 mods[0] = NULL;
533         }
534
535         for (i = 0; mods[i] != NULL; ++i) {
536                 if (mods[i]->mod_op == modop && strequal(mods[i]->mod_type, attribute))
537                         break;
538         }
539
540         if (mods[i] == NULL) {
541                 mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
542                 if (mods == NULL) {
543                         smb_panic("smbldap_set_mod: out of memory!");
544                         /* notreached. */
545                 }
546                 mods[i] = SMB_MALLOC_P(LDAPMod);
547                 if (mods[i] == NULL) {
548                         smb_panic("smbldap_set_mod: out of memory!");
549                         /* notreached. */
550                 }
551                 mods[i]->mod_op = modop;
552                 mods[i]->mod_values = NULL;
553                 mods[i]->mod_type = SMB_STRDUP(attribute);
554                 mods[i + 1] = NULL;
555         }
556
557         if (value != NULL) {
558                 char *utf8_value = NULL;
559                 size_t converted_size;
560
561                 j = 0;
562                 if (mods[i]->mod_values != NULL) {
563                         for (; mods[i]->mod_values[j] != NULL; j++);
564                 }
565                 mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
566
567                 if (mods[i]->mod_values == NULL) {
568                         smb_panic("smbldap_set_mod: out of memory!");
569                         /* notreached. */
570                 }
571
572                 if (!push_utf8_talloc(talloc_tos(), &utf8_value, value, &converted_size)) {
573                         smb_panic("smbldap_set_mod: String conversion failure!");
574                         /* notreached. */
575                 }
576
577                 mods[i]->mod_values[j] = SMB_STRDUP(utf8_value);
578                 TALLOC_FREE(utf8_value);
579                 SMB_ASSERT(mods[i]->mod_values[j] != NULL);
580
581                 mods[i]->mod_values[j + 1] = NULL;
582         }
583         *modlist = mods;
584 }
585
586 /**********************************************************************
587   Set attribute to newval in LDAP, regardless of what value the
588   attribute had in LDAP before.
589 *********************************************************************/
590
591  void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
592                       LDAPMod ***mods,
593                       const char *attribute, const char *newval)
594 {
595         char oldval[2048]; /* current largest allowed value is mungeddial */
596         bool existed;
597
598         if (attribute == NULL) {
599                 /* This can actually happen for ldapsam_compat where we for
600                  * example don't have a password history */
601                 return;
602         }
603
604         if (existing != NULL) {
605                 existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
606         } else {
607                 existed = False;
608                 *oldval = '\0';
609         }
610
611         /* all of our string attributes are case insensitive */
612
613         if (existed && newval && (StrCaseCmp(oldval, newval) == 0)) {
614
615                 /* Believe it or not, but LDAP will deny a delete and
616                    an add at the same time if the values are the
617                    same... */
618                 DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
619                 return;
620         }
621
622         if (existed) {
623                 /* There has been no value before, so don't delete it.
624                  * Here's a possible race: We might end up with
625                  * duplicate attributes */
626                 /* By deleting exactly the value we found in the entry this
627                  * should be race-free in the sense that the LDAP-Server will
628                  * deny the complete operation if somebody changed the
629                  * attribute behind our back. */
630                 /* This will also allow modifying single valued attributes 
631                  * in Novell NDS. In NDS you have to first remove attribute and then
632                  * you could add new value */
633
634                 DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
635                 smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
636         }
637
638         /* Regardless of the real operation (add or modify)
639            we add the new value here. We rely on deleting
640            the old value, should it exist. */
641
642         if ((newval != NULL) && (strlen(newval) > 0)) {
643                 DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
644                 smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
645         }
646 }
647
648 /**********************************************************************
649  Some varients of the LDAP rebind code do not pass in the third 'arg' 
650  pointer to a void*, so we try and work around it by assuming that the 
651  value of the 'LDAP *' pointer is the same as the one we had passed in
652  **********************************************************************/
653
654 struct smbldap_state_lookup {
655         LDAP *ld;
656         struct smbldap_state *smbldap_state;
657         struct smbldap_state_lookup *prev, *next;
658 };
659
660 static struct smbldap_state_lookup *smbldap_state_lookup_list;
661
662 static struct smbldap_state *smbldap_find_state(LDAP *ld) 
663 {
664         struct smbldap_state_lookup *t;
665
666         for (t = smbldap_state_lookup_list; t; t = t->next) {
667                 if (t->ld == ld) {
668                         return t->smbldap_state;
669                 }
670         }
671         return NULL;
672 }
673
674 static void smbldap_delete_state(struct smbldap_state *smbldap_state) 
675 {
676         struct smbldap_state_lookup *t;
677
678         for (t = smbldap_state_lookup_list; t; t = t->next) {
679                 if (t->smbldap_state == smbldap_state) {
680                         DLIST_REMOVE(smbldap_state_lookup_list, t);
681                         SAFE_FREE(t);
682                         return;
683                 }
684         }
685 }
686
687 static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) 
688 {
689         struct smbldap_state *tmp_ldap_state;
690         struct smbldap_state_lookup *t;
691
692         if ((tmp_ldap_state = smbldap_find_state(ld))) {
693                 SMB_ASSERT(tmp_ldap_state == smbldap_state);
694                 return;
695         }
696
697         t = SMB_XMALLOC_P(struct smbldap_state_lookup);
698         ZERO_STRUCTP(t);
699
700         DLIST_ADD_END(smbldap_state_lookup_list, t, struct smbldap_state_lookup *);
701         t->ld = ld;
702         t->smbldap_state = smbldap_state;
703 }
704
705 /********************************************************************
706  start TLS on an existing LDAP connection
707 *******************************************************************/
708
709 int smb_ldap_start_tls(LDAP *ldap_struct, int version)
710
711 #ifdef LDAP_OPT_X_TLS
712         int rc;
713 #endif
714
715         if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
716                 return LDAP_SUCCESS;
717         }
718
719 #ifdef LDAP_OPT_X_TLS
720         if (version != LDAP_VERSION3) {
721                 DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
722                 return LDAP_OPERATIONS_ERROR;
723         }
724
725         if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS)  {
726                 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
727                          ldap_err2string(rc)));
728                 return rc;
729         }
730
731         DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
732         return LDAP_SUCCESS;
733 #else
734         DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
735         return LDAP_OPERATIONS_ERROR;
736 #endif
737 }
738
739 /********************************************************************
740  setup a connection to the LDAP server based on a uri
741 *******************************************************************/
742
743 static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
744 {
745         int rc;
746
747         DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
748
749 #ifdef HAVE_LDAP_INITIALIZE
750
751         rc = ldap_initialize(ldap_struct, uri);
752         if (rc) {
753                 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
754                 return rc;
755         }
756
757         if (lp_ldap_follow_referral() != Auto) {
758                 rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
759                      lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
760                 if (rc != LDAP_SUCCESS)
761                         DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
762                                 ldap_err2string(rc)));
763         }
764
765         return LDAP_SUCCESS;
766 #else 
767
768         /* Parse the string manually */
769
770         {
771                 int port = 0;
772                 fstring protocol;
773                 fstring host;
774                 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
775
776
777                 /* skip leading "URL:" (if any) */
778                 if ( strnequal( uri, "URL:", 4 ) ) {
779                         uri += 4;
780                 }
781
782                 sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
783
784                 if (port == 0) {
785                         if (strequal(protocol, "ldap")) {
786                                 port = LDAP_PORT;
787                         } else if (strequal(protocol, "ldaps")) {
788                                 port = LDAPS_PORT;
789                         } else {
790                                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
791                         }
792                 }
793
794                 if ((*ldap_struct = ldap_init(host, port)) == NULL)     {
795                         DEBUG(0, ("ldap_init failed !\n"));
796                         return LDAP_OPERATIONS_ERROR;
797                 }
798
799                 if (strequal(protocol, "ldaps")) {
800 #ifdef LDAP_OPT_X_TLS
801                         int tls = LDAP_OPT_X_TLS_HARD;
802                         if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
803                         {
804                                 DEBUG(0, ("Failed to setup a TLS session\n"));
805                         }
806
807                         DEBUG(3,("LDAPS option set...!\n"));
808 #else
809                         DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
810                         return LDAP_OPERATIONS_ERROR;
811 #endif /* LDAP_OPT_X_TLS */
812                 }
813         }
814 #endif /* HAVE_LDAP_INITIALIZE */
815
816         /* now set connection timeout */
817 #ifdef LDAP_X_OPT_CONNECT_TIMEOUT /* Netscape */
818         {
819                 int ct = lp_ldap_connection_timeout()*1000;
820                 rc = ldap_set_option(*ldap_struct, LDAP_X_OPT_CONNECT_TIMEOUT, &ct);
821                 if (rc != LDAP_SUCCESS) {
822                         DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
823                                 ct, ldap_err2string(rc)));
824                 }
825         }
826 #elif defined (LDAP_OPT_NETWORK_TIMEOUT) /* OpenLDAP */
827         {
828                 struct timeval ct;
829                 ct.tv_usec = 0;
830                 ct.tv_sec = lp_ldap_connection_timeout();
831                 rc = ldap_set_option(*ldap_struct, LDAP_OPT_NETWORK_TIMEOUT, &ct);
832                 if (rc != LDAP_SUCCESS) {
833                         DEBUG(0,("Failed to setup an ldap connection timeout %d: %s\n",
834                                 (int)ct.tv_sec, ldap_err2string(rc)));
835                 }
836         }
837 #endif
838
839         return LDAP_SUCCESS;
840 }
841
842 /********************************************************************
843  try to upgrade to Version 3 LDAP if not already, in either case return current
844  version 
845  *******************************************************************/
846
847 static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
848 {
849         int version;
850         int rc;
851
852         /* assume the worst */
853         *new_version = LDAP_VERSION2;
854
855         rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
856         if (rc) {
857                 return rc;
858         }
859
860         if (version == LDAP_VERSION3) {
861                 *new_version = LDAP_VERSION3;
862                 return LDAP_SUCCESS;
863         }
864
865         /* try upgrade */
866         version = LDAP_VERSION3;
867         rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
868         if (rc) {
869                 return rc;
870         }
871
872         *new_version = LDAP_VERSION3;
873         return LDAP_SUCCESS;
874 }
875
876 /*******************************************************************
877  open a connection to the ldap server (just until the bind)
878  ******************************************************************/
879
880 int smb_ldap_setup_full_conn(LDAP **ldap_struct, const char *uri)
881 {
882         int rc, version;
883
884         rc = smb_ldap_setup_conn(ldap_struct, uri);
885         if (rc) {
886                 return rc;
887         }
888
889         rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
890         if (rc) {
891                 return rc;
892         }
893
894         rc = smb_ldap_start_tls(*ldap_struct, version);
895         if (rc) {
896                 return rc;
897         }
898
899         return LDAP_SUCCESS;
900 }
901
902 /*******************************************************************
903  open a connection to the ldap server.
904 ******************************************************************/
905 static int smbldap_open_connection (struct smbldap_state *ldap_state)
906
907 {
908         int rc = LDAP_SUCCESS;
909         int version;
910         int deref;
911         LDAP **ldap_struct = &ldap_state->ldap_struct;
912
913         rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
914         if (rc) {
915                 return rc;
916         }
917
918         /* Store the LDAP pointer in a lookup list */
919
920         smbldap_store_state(*ldap_struct, ldap_state);
921
922         /* Upgrade to LDAPv3 if possible */
923
924         rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
925         if (rc) {
926                 return rc;
927         }
928
929         /* Start TLS if required */
930
931         rc = smb_ldap_start_tls(*ldap_struct, version);
932         if (rc) {
933                 return rc;
934         }
935
936         /* Set alias dereferencing method */
937         deref = lp_ldap_deref();
938         if (deref != -1) {
939                 if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
940                         DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
941                 } else {
942                         DEBUG(5,("Set dereferencing method: %d\n", deref));
943                 }
944         }
945
946         DEBUG(2, ("smbldap_open_connection: connection opened\n"));
947         return rc;
948 }
949
950 /*******************************************************************
951  a rebind function for authenticated referrals
952  This version takes a void* that we can shove useful stuff in :-)
953 ******************************************************************/
954 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
955 #else
956 static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
957                                    int *methodp, int freeit, void *arg)
958 {
959         struct smbldap_state *ldap_state = arg;
960
961         /** @TODO Should we be doing something to check what servers we rebind to?
962             Could we get a referral to a machine that we don't want to give our
963             username and password to? */
964
965         if (freeit) {
966                 SAFE_FREE(*whop);
967                 if (*credp) {
968                         memset(*credp, '\0', strlen(*credp));
969                 }
970                 SAFE_FREE(*credp);
971         } else {
972                 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", 
973                           ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
974
975                 if (ldap_state->anonymous) {
976                         *whop = NULL;
977                         *credp = NULL;
978                 } else {
979                         *whop = SMB_STRDUP(ldap_state->bind_dn);
980                         if (!*whop) {
981                                 return LDAP_NO_MEMORY;
982                         }
983                         *credp = SMB_STRDUP(ldap_state->bind_secret);
984                         if (!*credp) {
985                                 SAFE_FREE(*whop);
986                                 return LDAP_NO_MEMORY;
987                         }
988                 }
989                 *methodp = LDAP_AUTH_SIMPLE;
990         }
991
992         GetTimeOfDay(&ldap_state->last_rebind);
993
994         return 0;
995 }
996 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
997
998 /*******************************************************************
999  a rebind function for authenticated referrals
1000  This version takes a void* that we can shove useful stuff in :-)
1001  and actually does the connection.
1002 ******************************************************************/
1003 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
1004 static int rebindproc_connect_with_state (LDAP *ldap_struct, 
1005                                           LDAP_CONST char *url, 
1006                                           ber_tag_t request,
1007                                           ber_int_t msgid, void *arg)
1008 {
1009         struct smbldap_state *ldap_state =
1010                 (struct smbldap_state *)arg;
1011         int rc;
1012         int version;
1013
1014         DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n", 
1015                  url, ldap_state->bind_dn?ldap_state->bind_dn:"[Anonymous bind]"));
1016
1017         /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
1018          * itself) before rebinding to another LDAP server to avoid to expose
1019          * our credentials. At least *try* to secure the connection - Guenther */
1020
1021         smb_ldap_upgrade_conn(ldap_struct, &version);
1022         smb_ldap_start_tls(ldap_struct, version);
1023
1024         /** @TODO Should we be doing something to check what servers we rebind to?
1025             Could we get a referral to a machine that we don't want to give our
1026             username and password to? */
1027
1028         rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
1029
1030         /* only set the last rebind timestamp when we did rebind after a
1031          * non-read LDAP operation. That way we avoid the replication sleep
1032          * after a simple redirected search operation - Guenther */
1033
1034         switch (request) {
1035
1036                 case LDAP_REQ_MODIFY:
1037                 case LDAP_REQ_ADD:
1038                 case LDAP_REQ_DELETE:
1039                 case LDAP_REQ_MODDN:
1040                 case LDAP_REQ_EXTENDED:
1041                         DEBUG(10,("rebindproc_connect_with_state: "
1042                                 "setting last_rebind timestamp "
1043                                 "(req: 0x%02x)\n", (unsigned int)request));
1044                         GetTimeOfDay(&ldap_state->last_rebind);
1045                         break;
1046                 default:
1047                         ZERO_STRUCT(ldap_state->last_rebind);
1048                         break;
1049         }
1050
1051         return rc;
1052 }
1053 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1054
1055 /*******************************************************************
1056  Add a rebind function for authenticated referrals
1057 ******************************************************************/
1058 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
1059 #else
1060 # if LDAP_SET_REBIND_PROC_ARGS == 2
1061 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
1062                        int *method, int freeit )
1063 {
1064         struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct);
1065
1066         return rebindproc_with_state(ldap_struct, whop, credp,
1067                                      method, freeit, ldap_state);
1068 }
1069 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
1070 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1071
1072 /*******************************************************************
1073  a rebind function for authenticated referrals
1074  this also does the connection, but no void*.
1075 ******************************************************************/
1076 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
1077 # if LDAP_SET_REBIND_PROC_ARGS == 2
1078 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
1079                                ber_int_t msgid)
1080 {
1081         struct smbldap_state *ldap_state = smbldap_find_state(ld);
1082
1083         return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
1084                                              ldap_state);
1085 }
1086 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
1087 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1088
1089 /*******************************************************************
1090  connect to the ldap server under system privilege.
1091 ******************************************************************/
1092 static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_struct)
1093 {
1094         int rc;
1095         int version;
1096
1097         if (!ldap_state->anonymous && !ldap_state->bind_dn) {
1098                 char *bind_dn = NULL;
1099                 char *bind_secret = NULL;
1100
1101                 /* get the default dn and password only if they are not set already */
1102                 if (!fetch_ldap_pw(&bind_dn, &bind_secret)) {
1103                         DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
1104                         return LDAP_INVALID_CREDENTIALS;
1105                 }
1106                 smbldap_set_creds(ldap_state, false, bind_dn, bind_secret);
1107                 SAFE_FREE(bind_dn);
1108                 memset(bind_secret, '\0', strlen(bind_secret));
1109                 SAFE_FREE(bind_secret);
1110         }
1111
1112         /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
1113            (OpenLDAP) doesnt' seem to support it */
1114
1115         DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
1116                   ldap_state->uri, ldap_state->bind_dn));
1117
1118 #ifdef HAVE_LDAP_SET_REBIND_PROC
1119 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
1120 # if LDAP_SET_REBIND_PROC_ARGS == 2     
1121         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); 
1122 # endif
1123 # if LDAP_SET_REBIND_PROC_ARGS == 3     
1124         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
1125 # endif
1126 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1127 # if LDAP_SET_REBIND_PROC_ARGS == 2     
1128         ldap_set_rebind_proc(ldap_struct, &rebindproc); 
1129 # endif
1130 # if LDAP_SET_REBIND_PROC_ARGS == 3     
1131         ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
1132 # endif
1133 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
1134 #endif
1135
1136         rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
1137
1138         if (rc != LDAP_SUCCESS) {
1139                 char *ld_error = NULL;
1140                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1141                                 &ld_error);
1142                 DEBUG(ldap_state->num_failures ? 2 : 0,
1143                       ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
1144                                ldap_state->uri,
1145                                ldap_state->bind_dn ? ldap_state->bind_dn : "[Anonymous bind]",
1146                                ldap_err2string(rc),
1147                                ld_error ? ld_error : "(unknown)"));
1148                 SAFE_FREE(ld_error);
1149                 ldap_state->num_failures++;
1150                 return rc;
1151         }
1152
1153         ldap_state->num_failures = 0;
1154         ldap_state->paged_results = False;
1155
1156         ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
1157
1158         if (smbldap_has_control(ldap_state->ldap_struct, ADS_PAGE_CTL_OID) && version == 3) {
1159                 ldap_state->paged_results = True;
1160         }
1161
1162         DEBUG(3, ("ldap_connect_system: successful connection to the LDAP server\n"));
1163         DEBUGADD(10, ("ldap_connect_system: LDAP server %s support paged results\n", 
1164                 ldap_state->paged_results ? "does" : "does not"));
1165         return rc;
1166 }
1167
1168 static void smbldap_idle_fn(struct event_context *event_ctx,
1169                             struct timed_event *te,
1170                             struct timeval now,
1171                             void *private_data);
1172
1173 /**********************************************************************
1174  Connect to LDAP server (called before every ldap operation)
1175 *********************************************************************/
1176 static int smbldap_open(struct smbldap_state *ldap_state)
1177 {
1178         int rc, opt_rc;
1179         bool reopen = False;
1180         SMB_ASSERT(ldap_state);
1181
1182         if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time(NULL))) {
1183
1184 #ifdef HAVE_UNIXSOCKET
1185                 struct sockaddr_un addr;
1186 #else
1187                 struct sockaddr addr;
1188 #endif
1189                 socklen_t len = sizeof(addr);
1190                 int sd;
1191
1192                 opt_rc = ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd);
1193                 if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
1194                         reopen = True;
1195
1196 #ifdef HAVE_UNIXSOCKET
1197                 if (opt_rc == 0 && addr.sun_family == AF_UNIX)
1198                         reopen = True;
1199 #endif
1200                 if (reopen) {
1201                         /* the other end has died. reopen. */
1202                         ldap_unbind(ldap_state->ldap_struct);
1203                         ldap_state->ldap_struct = NULL;
1204                         ldap_state->last_ping = (time_t)0;
1205                 } else {
1206                         ldap_state->last_ping = time(NULL);
1207                 } 
1208         }
1209
1210         if (ldap_state->ldap_struct != NULL) {
1211                 DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
1212                 return LDAP_SUCCESS;
1213         }
1214
1215         if ((rc = smbldap_open_connection(ldap_state))) {
1216                 return rc;
1217         }
1218
1219         if ((rc = smbldap_connect_system(ldap_state, ldap_state->ldap_struct))) {
1220                 ldap_unbind(ldap_state->ldap_struct);
1221                 ldap_state->ldap_struct = NULL;
1222                 return rc;
1223         }
1224
1225
1226         ldap_state->last_ping = time(NULL);
1227         ldap_state->pid = sys_getpid();
1228
1229         TALLOC_FREE(ldap_state->idle_event);
1230
1231         if (ldap_state->event_context != NULL) {
1232                 ldap_state->idle_event = event_add_timed(
1233                         ldap_state->event_context, NULL,
1234                         timeval_current_ofs(SMBLDAP_IDLE_TIME, 0),
1235                         smbldap_idle_fn, ldap_state);
1236         }
1237
1238         DEBUG(4,("The LDAP server is successfully connected\n"));
1239
1240         return LDAP_SUCCESS;
1241 }
1242
1243 /**********************************************************************
1244 Disconnect from LDAP server 
1245 *********************************************************************/
1246 static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
1247 {
1248         if (!ldap_state)
1249                 return NT_STATUS_INVALID_PARAMETER;
1250
1251         if (ldap_state->ldap_struct != NULL) {
1252                 ldap_unbind(ldap_state->ldap_struct);
1253                 ldap_state->ldap_struct = NULL;
1254         }
1255
1256         smbldap_delete_state(ldap_state);
1257
1258         DEBUG(5,("The connection to the LDAP server was closed\n"));
1259         /* maybe free the results here --metze */
1260
1261         return NT_STATUS_OK;
1262 }
1263
1264 static bool got_alarm;
1265
1266 static void (*old_handler)(int);
1267
1268 static void gotalarm_sig(int dummy)
1269 {
1270         got_alarm = True;
1271 }
1272
1273 static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
1274                             int *attempts, time_t endtime)
1275 {
1276         time_t now = time(NULL);
1277         int open_rc = LDAP_SERVER_DOWN;
1278
1279         if (*rc != LDAP_SERVER_DOWN)
1280                 goto no_next;
1281
1282         if (now >= endtime) {
1283                 smbldap_close(ldap_state);
1284                 *rc = LDAP_TIMEOUT;
1285                 goto no_next;
1286         }
1287
1288         if (*attempts == 0) {
1289                 got_alarm = False;
1290                 old_handler = CatchSignal(SIGALRM, gotalarm_sig);
1291                 alarm(endtime - now);
1292
1293                 if (ldap_state->pid != sys_getpid())
1294                         smbldap_close(ldap_state);
1295         }
1296
1297         while (1) {
1298
1299                 if (*attempts != 0)
1300                         smb_msleep(1000);
1301
1302                 *attempts += 1;
1303
1304                 open_rc = smbldap_open(ldap_state);
1305
1306                 if (open_rc == LDAP_SUCCESS) {
1307                         ldap_state->last_use = now;
1308                         return True;
1309                 }
1310
1311                 if (open_rc == LDAP_INSUFFICIENT_ACCESS) {
1312                         /* The fact that we are non-root or any other
1313                          * access-denied condition will not change in the next
1314                          * round of trying */
1315                         *rc = open_rc;
1316                         break;
1317                 }
1318
1319                 if (got_alarm) {
1320                         *rc = LDAP_TIMEOUT;
1321                         break;
1322                 }
1323
1324                 if (open_rc != LDAP_SUCCESS) {
1325                         DEBUG(1, ("Connection to LDAP server failed for the "
1326                                   "%d try!\n", *attempts));
1327                 }
1328         }
1329
1330  no_next:
1331         CatchSignal(SIGALRM, old_handler);
1332         alarm(0);
1333         ldap_state->last_use = now;
1334         return False;
1335 }
1336
1337 /*********************************************************************
1338  ********************************************************************/
1339
1340 static int smbldap_search_ext(struct smbldap_state *ldap_state,
1341                               const char *base, int scope, const char *filter, 
1342                               const char *attrs[], int attrsonly,
1343                               LDAPControl **sctrls, LDAPControl **cctrls, 
1344                               int sizelimit, LDAPMessage **res)
1345 {
1346         int             rc = LDAP_SERVER_DOWN;
1347         int             attempts = 0;
1348         char           *utf8_filter;
1349         time_t          endtime = time(NULL)+lp_ldap_timeout();
1350         struct          timeval timeout;
1351         size_t          converted_size;
1352
1353         SMB_ASSERT(ldap_state);
1354
1355         DEBUG(5,("smbldap_search_ext: base => [%s], filter => [%s], "
1356                  "scope => [%d]\n", base, filter, scope));
1357
1358         if (ldap_state->last_rebind.tv_sec > 0) {
1359                 struct timeval  tval;
1360                 int64_t tdiff = 0;
1361                 int             sleep_time = 0;
1362
1363                 ZERO_STRUCT(tval);
1364                 GetTimeOfDay(&tval);
1365
1366                 tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
1367                 tdiff /= 1000; /* Convert to milliseconds. */
1368
1369                 sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
1370                 sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
1371
1372                 if (sleep_time > 0) {
1373                         /* we wait for the LDAP replication */
1374                         DEBUG(5,("smbldap_search_ext: waiting %d milliseconds "
1375                                  "for LDAP replication.\n",sleep_time));
1376                         smb_msleep(sleep_time);
1377                         DEBUG(5,("smbldap_search_ext: go on!\n"));
1378                 }
1379                 ZERO_STRUCT(ldap_state->last_rebind);
1380         }
1381
1382         if (!push_utf8_talloc(talloc_tos(), &utf8_filter, filter, &converted_size)) {
1383                 return LDAP_NO_MEMORY;
1384         }
1385
1386         /* Setup timeout for the ldap_search_ext_s call - local and remote. */
1387         timeout.tv_sec = lp_ldap_timeout();
1388         timeout.tv_usec = 0;
1389
1390         /* Setup alarm timeout.... Do we need both of these ? JRA.
1391          * Yes, I think we do need both of these. The server timeout only
1392          * covers the case where the server's operation takes too long. It
1393          * does not cover the case where the request hangs on its way to the
1394          * server. The server side timeout is not strictly necessary, it's
1395          * just a bit more kind to the server. VL. */
1396
1397         got_alarm = 0;
1398         CatchSignal(SIGALRM, gotalarm_sig);
1399         alarm(lp_ldap_timeout());
1400         /* End setup timeout. */
1401
1402         while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
1403                 rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope, 
1404                                        utf8_filter,
1405                                        CONST_DISCARD(char **, attrs),
1406                                        attrsonly, sctrls, cctrls, &timeout,
1407                                        sizelimit, res);
1408                 if (rc != LDAP_SUCCESS) {
1409                         char *ld_error = NULL;
1410                         int ld_errno;
1411
1412                         ldap_get_option(ldap_state->ldap_struct,
1413                                         LDAP_OPT_ERROR_NUMBER, &ld_errno);
1414
1415                         ldap_get_option(ldap_state->ldap_struct,
1416                                         LDAP_OPT_ERROR_STRING, &ld_error);
1417                         DEBUG(10, ("Failed search for base: %s, error: %d (%s) "
1418                                    "(%s)\n", base, ld_errno,
1419                                    ldap_err2string(rc),
1420                                    ld_error ? ld_error : "unknown"));
1421                         SAFE_FREE(ld_error);
1422
1423                         if (ld_errno == LDAP_SERVER_DOWN) {
1424                                 ldap_unbind(ldap_state->ldap_struct);
1425                                 ldap_state->ldap_struct = NULL;
1426                         }
1427                 }
1428         }
1429
1430         TALLOC_FREE(utf8_filter);
1431
1432         /* Teardown timeout. */
1433         CatchSignal(SIGALRM, SIG_IGN);
1434         alarm(0);
1435
1436         if (got_alarm != 0)
1437                 return LDAP_TIMELIMIT_EXCEEDED;
1438
1439         return rc;
1440 }
1441
1442 int smbldap_search(struct smbldap_state *ldap_state, 
1443                    const char *base, int scope, const char *filter, 
1444                    const char *attrs[], int attrsonly, 
1445                    LDAPMessage **res)
1446 {
1447         return smbldap_search_ext(ldap_state, base, scope, filter, attrs,
1448                                   attrsonly, NULL, NULL, LDAP_NO_LIMIT, res);
1449 }
1450
1451 int smbldap_search_paged(struct smbldap_state *ldap_state, 
1452                          const char *base, int scope, const char *filter, 
1453                          const char **attrs, int attrsonly, int pagesize,
1454                          LDAPMessage **res, void **cookie)
1455 {
1456         LDAPControl     pr;
1457         LDAPControl     **rcontrols;
1458         LDAPControl     *controls[2] = { NULL, NULL};
1459         BerElement      *cookie_be = NULL;
1460         struct berval   *cookie_bv = NULL;
1461         int             tmp = 0, i, rc;
1462         bool            critical = True;
1463
1464         *res = NULL;
1465
1466         DEBUG(3,("smbldap_search_paged: base => [%s], filter => [%s],"
1467                  "scope => [%d], pagesize => [%d]\n",
1468                  base, filter, scope, pagesize));
1469
1470         cookie_be = ber_alloc_t(LBER_USE_DER);
1471         if (cookie_be == NULL) {
1472                 DEBUG(0,("smbldap_create_page_control: ber_alloc_t returns "
1473                          "NULL\n"));
1474                 return LDAP_NO_MEMORY;
1475         }
1476
1477         /* construct cookie */
1478         if (*cookie != NULL) {
1479                 ber_printf(cookie_be, "{iO}", (ber_int_t) pagesize, *cookie);
1480                 ber_bvfree((struct berval *)*cookie); /* don't need it from last time */
1481                 *cookie = NULL;
1482         } else {
1483                 ber_printf(cookie_be, "{io}", (ber_int_t) pagesize, "", 0);
1484         }
1485         ber_flatten(cookie_be, &cookie_bv);
1486
1487         pr.ldctl_oid = CONST_DISCARD(char *, ADS_PAGE_CTL_OID);
1488         pr.ldctl_iscritical = (char) critical;
1489         pr.ldctl_value.bv_len = cookie_bv->bv_len;
1490         pr.ldctl_value.bv_val = cookie_bv->bv_val;
1491
1492         controls[0] = &pr;
1493         controls[1] = NULL;
1494
1495         rc = smbldap_search_ext(ldap_state, base, scope, filter, attrs, 
1496                                  0, controls, NULL, LDAP_NO_LIMIT, res);
1497
1498         ber_free(cookie_be, 1);
1499         ber_bvfree(cookie_bv);
1500
1501         if (rc != 0) {
1502                 DEBUG(3,("smbldap_search_paged: smbldap_search_ext(%s) "
1503                          "failed with [%s]\n", filter, ldap_err2string(rc)));
1504                 goto done;
1505         }
1506
1507         DEBUG(3,("smbldap_search_paged: search was successful\n"));
1508
1509         rc = ldap_parse_result(ldap_state->ldap_struct, *res, NULL, NULL, 
1510                                NULL, NULL, &rcontrols,  0);
1511         if (rc != 0) {
1512                 DEBUG(3,("smbldap_search_paged: ldap_parse_result failed " \
1513                          "with [%s]\n", ldap_err2string(rc)));
1514                 goto done;
1515         }
1516
1517         if (rcontrols == NULL)
1518                 goto done;
1519
1520         for (i=0; rcontrols[i]; i++) {
1521
1522                 if (strcmp(ADS_PAGE_CTL_OID, rcontrols[i]->ldctl_oid) != 0)
1523                         continue;
1524
1525                 cookie_be = ber_init(&rcontrols[i]->ldctl_value);
1526                 ber_scanf(cookie_be,"{iO}", &tmp, &cookie_bv);
1527                 /* the berval is the cookie, but must be freed when it is all
1528                    done */
1529                 if (cookie_bv->bv_len)
1530                         *cookie=ber_bvdup(cookie_bv);
1531                 else
1532                         *cookie=NULL;
1533                 ber_bvfree(cookie_bv);
1534                 ber_free(cookie_be, 1);
1535                 break;
1536         }
1537         ldap_controls_free(rcontrols);
1538 done:   
1539         return rc;
1540 }
1541
1542 int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1543 {
1544         int             rc = LDAP_SERVER_DOWN;
1545         int             attempts = 0;
1546         char           *utf8_dn;
1547         time_t          endtime = time(NULL)+lp_ldap_timeout();
1548         size_t          converted_size;
1549
1550         SMB_ASSERT(ldap_state);
1551
1552         DEBUG(5,("smbldap_modify: dn => [%s]\n", dn ));
1553
1554         if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1555                 return LDAP_NO_MEMORY;
1556         }
1557
1558         while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
1559                 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
1560                 if (rc != LDAP_SUCCESS) {
1561                         char *ld_error = NULL;
1562                         int ld_errno;
1563
1564                         ldap_get_option(ldap_state->ldap_struct,
1565                                         LDAP_OPT_ERROR_NUMBER, &ld_errno);
1566
1567                         ldap_get_option(ldap_state->ldap_struct,
1568                                         LDAP_OPT_ERROR_STRING, &ld_error);
1569                         DEBUG(10, ("Failed to modify dn: %s, error: %d (%s) "
1570                                    "(%s)\n", dn, ld_errno,
1571                                    ldap_err2string(rc),
1572                                    ld_error ? ld_error : "unknown"));
1573                         SAFE_FREE(ld_error);
1574
1575                         if (ld_errno == LDAP_SERVER_DOWN) {
1576                                 ldap_unbind(ldap_state->ldap_struct);
1577                                 ldap_state->ldap_struct = NULL;
1578                         }
1579                 }
1580         }
1581
1582         TALLOC_FREE(utf8_dn);
1583         return rc;
1584 }
1585
1586 int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[])
1587 {
1588         int             rc = LDAP_SERVER_DOWN;
1589         int             attempts = 0;
1590         char           *utf8_dn;
1591         time_t          endtime = time(NULL)+lp_ldap_timeout();
1592         size_t          converted_size;
1593
1594         SMB_ASSERT(ldap_state);
1595
1596         DEBUG(5,("smbldap_add: dn => [%s]\n", dn ));
1597
1598         if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1599                 return LDAP_NO_MEMORY;
1600         }
1601
1602         while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
1603                 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
1604                 if (rc != LDAP_SUCCESS) {
1605                         char *ld_error = NULL;
1606                         int ld_errno;
1607
1608                         ldap_get_option(ldap_state->ldap_struct,
1609                                         LDAP_OPT_ERROR_NUMBER, &ld_errno);
1610
1611                         ldap_get_option(ldap_state->ldap_struct,
1612                                         LDAP_OPT_ERROR_STRING, &ld_error);
1613                         DEBUG(10, ("Failed to add dn: %s, error: %d (%s) "
1614                                    "(%s)\n", dn, ld_errno,
1615                                    ldap_err2string(rc),
1616                                    ld_error ? ld_error : "unknown"));
1617                         SAFE_FREE(ld_error);
1618
1619                         if (ld_errno == LDAP_SERVER_DOWN) {
1620                                 ldap_unbind(ldap_state->ldap_struct);
1621                                 ldap_state->ldap_struct = NULL;
1622                         }
1623                 }
1624         }
1625
1626         TALLOC_FREE(utf8_dn);
1627         return rc;
1628 }
1629
1630 int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
1631 {
1632         int             rc = LDAP_SERVER_DOWN;
1633         int             attempts = 0;
1634         char           *utf8_dn;
1635         time_t          endtime = time(NULL)+lp_ldap_timeout();
1636         size_t          converted_size;
1637
1638         SMB_ASSERT(ldap_state);
1639
1640         DEBUG(5,("smbldap_delete: dn => [%s]\n", dn ));
1641
1642         if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1643                 return LDAP_NO_MEMORY;
1644         }
1645
1646         while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
1647                 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
1648                 if (rc != LDAP_SUCCESS) {
1649                         char *ld_error = NULL;
1650                         int ld_errno;
1651
1652                         ldap_get_option(ldap_state->ldap_struct,
1653                                         LDAP_OPT_ERROR_NUMBER, &ld_errno);
1654
1655                         ldap_get_option(ldap_state->ldap_struct,
1656                                         LDAP_OPT_ERROR_STRING, &ld_error);
1657                         DEBUG(10, ("Failed to delete dn: %s, error: %d (%s) "
1658                                    "(%s)\n", dn, ld_errno,
1659                                    ldap_err2string(rc),
1660                                    ld_error ? ld_error : "unknown"));
1661                         SAFE_FREE(ld_error);
1662
1663                         if (ld_errno == LDAP_SERVER_DOWN) {
1664                                 ldap_unbind(ldap_state->ldap_struct);
1665                                 ldap_state->ldap_struct = NULL;
1666                         }
1667                 }
1668         }
1669
1670         TALLOC_FREE(utf8_dn);
1671         return rc;
1672 }
1673
1674 int smbldap_extended_operation(struct smbldap_state *ldap_state, 
1675                                LDAP_CONST char *reqoid, struct berval *reqdata, 
1676                                LDAPControl **serverctrls, LDAPControl **clientctrls, 
1677                                char **retoidp, struct berval **retdatap)
1678 {
1679         int             rc = LDAP_SERVER_DOWN;
1680         int             attempts = 0;
1681         time_t          endtime = time(NULL)+lp_ldap_timeout();
1682
1683         if (!ldap_state)
1684                 return (-1);
1685
1686         while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
1687                 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
1688                                                reqdata, serverctrls,
1689                                                clientctrls, retoidp, retdatap);
1690                 if (rc != LDAP_SUCCESS) {
1691                         char *ld_error = NULL;
1692                         int ld_errno;
1693
1694                         ldap_get_option(ldap_state->ldap_struct,
1695                                         LDAP_OPT_ERROR_NUMBER, &ld_errno);
1696
1697                         ldap_get_option(ldap_state->ldap_struct,
1698                                         LDAP_OPT_ERROR_STRING, &ld_error);
1699                         DEBUG(10, ("Extended operation failed with error: "
1700                                    "%d (%s) (%s)\n", ld_errno,
1701                                    ldap_err2string(rc),
1702                                    ld_error ? ld_error : "unknown"));
1703                         SAFE_FREE(ld_error);
1704
1705                         if (ld_errno == LDAP_SERVER_DOWN) {
1706                                 ldap_unbind(ldap_state->ldap_struct);
1707                                 ldap_state->ldap_struct = NULL;
1708                         }
1709                 }
1710         }
1711
1712         return rc;
1713 }
1714
1715 /*******************************************************************
1716  run the search by name.
1717 ******************************************************************/
1718 int smbldap_search_suffix (struct smbldap_state *ldap_state,
1719                            const char *filter, const char **search_attr,
1720                            LDAPMessage ** result)
1721 {
1722         return smbldap_search(ldap_state, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE,
1723                               filter, search_attr, 0, result);
1724 }
1725
1726 static void smbldap_idle_fn(struct event_context *event_ctx,
1727                             struct timed_event *te,
1728                             struct timeval now,
1729                             void *private_data)
1730 {
1731         struct smbldap_state *state = (struct smbldap_state *)private_data;
1732
1733         TALLOC_FREE(state->idle_event);
1734
1735         if (state->ldap_struct == NULL) {
1736                 DEBUG(10,("ldap connection not connected...\n"));
1737                 return;
1738         }
1739
1740         if ((state->last_use+SMBLDAP_IDLE_TIME) > now.tv_sec) {
1741                 DEBUG(10,("ldap connection not idle...\n"));
1742
1743                 state->idle_event = event_add_timed(
1744                         event_ctx, NULL,
1745                         timeval_add(&now, SMBLDAP_IDLE_TIME, 0),
1746                         smbldap_idle_fn,
1747                         private_data);
1748                 return;
1749         }
1750
1751         DEBUG(7,("ldap connection idle...closing connection\n"));
1752         smbldap_close(state);
1753 }
1754
1755 /**********************************************************************
1756  Housekeeping
1757  *********************************************************************/
1758
1759 void smbldap_free_struct(struct smbldap_state **ldap_state) 
1760 {
1761         smbldap_close(*ldap_state);
1762
1763         if ((*ldap_state)->bind_secret) {
1764                 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1765         }
1766
1767         SAFE_FREE((*ldap_state)->bind_dn);
1768         SAFE_FREE((*ldap_state)->bind_secret);
1769
1770         TALLOC_FREE((*ldap_state)->idle_event);
1771
1772         *ldap_state = NULL;
1773
1774         /* No need to free any further, as it is talloc()ed */
1775 }
1776
1777
1778 /**********************************************************************
1779  Intitalise the 'general' ldap structures, on which ldap operations may be conducted
1780  *********************************************************************/
1781
1782 NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, struct event_context *event_ctx,
1783                       const char *location,
1784                       struct smbldap_state **smbldap_state)
1785 {
1786         *smbldap_state = TALLOC_ZERO_P(mem_ctx, struct smbldap_state);
1787         if (!*smbldap_state) {
1788                 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1789                 return NT_STATUS_NO_MEMORY;
1790         }
1791
1792         if (location) {
1793                 (*smbldap_state)->uri = talloc_strdup(mem_ctx, location);
1794         } else {
1795                 (*smbldap_state)->uri = "ldap://localhost";
1796         }
1797
1798         (*smbldap_state)->event_context = event_ctx;
1799
1800         return NT_STATUS_OK;
1801 }
1802
1803  char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
1804                          LDAPMessage *entry)
1805 {
1806         char *utf8_dn, *unix_dn;
1807         size_t converted_size;
1808
1809         utf8_dn = ldap_get_dn(ld, entry);
1810         if (!utf8_dn) {
1811                 DEBUG (5, ("smbldap_talloc_dn: ldap_get_dn failed\n"));
1812                 return NULL;
1813         }
1814         if (!pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn, &converted_size)) {
1815                 DEBUG (0, ("smbldap_talloc_dn: String conversion failure utf8 "
1816                            "[%s]\n", utf8_dn));
1817                 return NULL;
1818         }
1819         ldap_memfree(utf8_dn);
1820         return unix_dn;
1821 }
1822
1823 /*******************************************************************
1824  Check if root-dse has a certain Control or Extension
1825 ********************************************************************/
1826
1827 static bool smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value) 
1828 {
1829         LDAPMessage *msg = NULL;
1830         LDAPMessage *entry = NULL;
1831         char **values = NULL;
1832         int rc, num_result, num_values, i;
1833         bool result = False;
1834
1835         if (!attrs[0]) {
1836                 DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
1837                 return False;
1838         }
1839
1840         if (!strequal(attrs[0], "supportedExtension") && 
1841             !strequal(attrs[0], "supportedControl") && 
1842             !strequal(attrs[0], "namingContexts")) {
1843                 DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
1844                 return False;
1845         }
1846
1847         rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE, 
1848                            "(objectclass=*)", CONST_DISCARD(char **, attrs), 0 , &msg);
1849
1850         if (rc != LDAP_SUCCESS) {
1851                 DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
1852                 return False;
1853         }
1854
1855         num_result = ldap_count_entries(ld, msg);
1856
1857         if (num_result != 1) {
1858                 DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
1859                 goto done;
1860         }
1861
1862         entry = ldap_first_entry(ld, msg);
1863
1864         if (entry == NULL) {
1865                 DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
1866                 goto done;
1867         }
1868
1869         values = ldap_get_values(ld, entry, attrs[0]);
1870
1871         if (values == NULL) {
1872                 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
1873                 goto done;
1874         }
1875
1876         num_values = ldap_count_values(values);
1877
1878         if (num_values == 0) {
1879                 DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
1880                 goto done;
1881         }
1882
1883         for (i=0; i<num_values; i++) {
1884                 if (strcmp(values[i], value) == 0)
1885                         result = True;
1886         }
1887
1888
1889  done:
1890         if (values != NULL)
1891                 ldap_value_free(values);
1892         if (msg != NULL)
1893                 ldap_msgfree(msg);
1894
1895         return result;
1896
1897 }
1898
1899 /*******************************************************************
1900  Check if LDAP-Server supports a certain Control (OID in string format)
1901 ********************************************************************/
1902
1903 bool smbldap_has_control(LDAP *ld, const char *control)
1904 {
1905         const char *attrs[] = { "supportedControl", NULL };
1906         return smbldap_check_root_dse(ld, attrs, control);
1907 }
1908
1909 /*******************************************************************
1910  Check if LDAP-Server supports a certain Extension (OID in string format)
1911 ********************************************************************/
1912
1913 bool smbldap_has_extension(LDAP *ld, const char *extension)
1914 {
1915         const char *attrs[] = { "supportedExtension", NULL };
1916         return smbldap_check_root_dse(ld, attrs, extension);
1917 }
1918
1919 /*******************************************************************
1920  Check if LDAP-Server holds a given namingContext
1921 ********************************************************************/
1922
1923 bool smbldap_has_naming_context(LDAP *ld, const char *naming_context)
1924 {
1925         const char *attrs[] = { "namingContexts", NULL };
1926         return smbldap_check_root_dse(ld, attrs, naming_context);
1927 }
1928
1929 bool smbldap_set_creds(struct smbldap_state *ldap_state, bool anon, const char *dn, const char *secret)
1930 {
1931         ldap_state->anonymous = anon;
1932
1933         /* free any previously set credential */
1934
1935         SAFE_FREE(ldap_state->bind_dn);
1936         if (ldap_state->bind_secret) {
1937                 /* make sure secrets are zeroed out of memory */
1938                 memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
1939                 SAFE_FREE(ldap_state->bind_secret);
1940         }
1941
1942         if ( ! anon) {
1943                 ldap_state->bind_dn = SMB_STRDUP(dn);
1944                 ldap_state->bind_secret = SMB_STRDUP(secret);
1945         }
1946
1947         return True;
1948 }