auth.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include <stdlib.h> /* getenv */
  42. #include <string.h> /* memcpy */
  43. #include <ldaputil/ldaputil.h> /* LDAPU_SUCCESS, ldapu_VTable_set */
  44. #include <ldaputil/init.h> /* ldaputil_init */
  45. #include <ldaputil/certmap.h> /* ldapu_cert_to_ldap_entry */
  46. #ifndef _WIN32
  47. #include <sys/param.h> /* MAXPATHLEN */
  48. #endif
  49. #include "slap.h" /* slapi_ch_malloc */
  50. #include "fe.h"
  51. char* client_auth_config_file = NULL;
  52. /* forward declarations */
  53. static void generate_id();
  54. static Slapi_ComponentId * auth_get_component_id();
  55. #define internal_ld NULL
  56. static int LDAP_CALL LDAP_CALLBACK
  57. slapu_msgfree( LDAP* ld, LDAPMessage* msg )
  58. {
  59. Slapi_PBlock* pb = (Slapi_PBlock*)msg;
  60. if (ld != internal_ld) {
  61. return ldap_msgfree (msg);
  62. }
  63. if (pb) {
  64. slapi_free_search_results_internal (pb);
  65. slapi_pblock_destroy (pb);
  66. }
  67. return LDAP_SUCCESS;
  68. }
  69. static int LDAP_CALL LDAP_CALLBACK
  70. slapu_search_s( LDAP* ld, const char* rawbaseDN, int scope, const char* filter,
  71. char** attrs, int attrsonly, LDAPMessage** result )
  72. {
  73. int err = LDAP_NO_SUCH_OBJECT;
  74. Slapi_PBlock* pb = NULL;
  75. LDAPControl **ctrls;
  76. char *baseDN = slapi_ch_strdup(rawbaseDN);
  77. char *normDN = NULL;
  78. size_t dnlen = 0;
  79. err = slapi_dn_normalize_ext(baseDN, 0, &normDN, &dnlen);
  80. if (err < 0) {
  81. err = LDAP_INVALID_DN_SYNTAX;
  82. LDAPDebug (LDAP_DEBUG_TRACE, "<= slapu_search_s %i\n", err, 0, 0);
  83. return err;
  84. } else if (err == 0) { /* baseDN is passed in; not terminated */
  85. *(normDN + dnlen) = '\0';
  86. } else {
  87. slapi_ch_free_string(&baseDN);
  88. baseDN = normDN;
  89. }
  90. if (ld != internal_ld) {
  91. err = ldap_search_ext_s(ld, baseDN, scope, filter, attrs, attrsonly,
  92. NULL, NULL, NULL, -1, result);
  93. slapi_ch_free_string(&baseDN);
  94. return err;
  95. }
  96. LDAPDebug (LDAP_DEBUG_TRACE, "=> slapu_search_s (\"%s\", %i, %s)\n",
  97. baseDN, scope, filter);
  98. if (filter == NULL) filter = "objectclass=*";
  99. /* use new internal search API */
  100. pb=slapi_pblock_new();
  101. /* we need to provide managedsait control to avoid returning continuation references */
  102. ctrls = (LDAPControl **)slapi_ch_calloc (2, sizeof (LDAPControl *));
  103. ctrls[0] = (LDAPControl*)slapi_ch_malloc (sizeof (LDAPControl));
  104. ctrls[0]->ldctl_oid = slapi_ch_strdup (LDAP_CONTROL_MANAGEDSAIT);
  105. ctrls[0]->ldctl_value.bv_val = NULL;
  106. ctrls[0]->ldctl_value.bv_len = 0;
  107. ctrls[0]->ldctl_iscritical = '\0';
  108. slapi_search_internal_set_pb(pb, baseDN, scope, (char *)filter, attrs, attrsonly,
  109. ctrls, NULL, auth_get_component_id(), 0 /* actions */);
  110. slapi_search_internal_pb(pb);
  111. if (pb != NULL) {
  112. if (slapi_pblock_get (pb, SLAPI_PLUGIN_INTOP_RESULT, &err)) {
  113. err = LDAP_LOCAL_ERROR;
  114. }
  115. if (err != LDAP_SUCCESS) {
  116. slapu_msgfree (ld, (LDAPMessage*)pb);
  117. pb = NULL;
  118. if (scope == LDAP_SCOPE_SUBTREE) {
  119. char ebuf[ BUFSIZ ], fbuf[ BUFSIZ ];
  120. LDAPDebug (LDAP_DEBUG_ANY, "slapi_search_internal (\"%s\", subtree, %s) err %i\n",
  121. escape_string( (char*)baseDN, ebuf ), escape_string( (char*)filter, fbuf ), err);
  122. }
  123. }
  124. } else {
  125. char ebuf[ BUFSIZ ], fbuf[ BUFSIZ ];
  126. LDAPDebug (LDAP_DEBUG_ANY, "slapi_search_internal (\"%s\", %i, %s) NULL\n",
  127. escape_string( (char*)baseDN, ebuf ), scope, escape_string( (char*)filter, fbuf ));
  128. }
  129. slapi_ch_free_string(&baseDN);
  130. *result = (LDAPMessage*)pb;
  131. LDAPDebug (LDAP_DEBUG_TRACE, "<= slapu_search_s %i\n", err, 0, 0);
  132. return err;
  133. }
  134. static int LDAP_CALL LDAP_CALLBACK
  135. slapu_count_entries( LDAP* ld, LDAPMessage* msg )
  136. {
  137. Slapi_Entry** entry = NULL;
  138. int count = 0;
  139. if (ld != internal_ld) {
  140. return ldap_count_entries (ld, msg);
  141. }
  142. if (!slapi_pblock_get ((Slapi_PBlock*)msg, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entry)
  143. && entry) {
  144. for (; *entry; ++entry) ++count;
  145. }
  146. return count;
  147. }
  148. /* slapu_search_s() returns a Slapi_PBlock*, but slapu_first_entry() and
  149. * slapu_next_entry() return a Slapi_Entry** pointing into the same array
  150. * as the PBlock. If one of the iteration (Slapi_Entry**) pointers was
  151. * passed to slapu_msgfree(), havoc would ensue. ldaputil never does this.
  152. * But ldap_msgfree() would support it (no?); so a plugin function might.
  153. * Yet another way this doesn't support plugin functions.
  154. */
  155. static LDAPMessage* LDAP_CALL LDAP_CALLBACK
  156. slapu_first_entry( LDAP* ld, LDAPMessage* msg )
  157. {
  158. Slapi_Entry** entry = NULL;
  159. if (ld != internal_ld) {
  160. return ldap_first_entry (ld, msg);
  161. }
  162. if (!slapi_pblock_get ((Slapi_PBlock*)msg, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entry)
  163. && entry && *entry) {
  164. return (LDAPMessage*)entry;
  165. }
  166. return NULL;
  167. }
  168. static LDAPMessage* LDAP_CALL LDAP_CALLBACK
  169. slapu_next_entry( LDAP* ld, LDAPMessage* msg )
  170. {
  171. Slapi_Entry** entry = (Slapi_Entry**)msg;
  172. if (ld != internal_ld) {
  173. if (msg) {
  174. return ldap_next_entry (ld, msg);
  175. } else {
  176. return NULL;
  177. }
  178. }
  179. if (entry && *entry && *++entry) {
  180. return (LDAPMessage*)entry;
  181. }
  182. return NULL;
  183. }
  184. static char* LDAP_CALL LDAP_CALLBACK
  185. slapu_get_dn( LDAP* ld, LDAPMessage* entry )
  186. {
  187. if (ld != internal_ld) {
  188. return ldap_get_dn (ld, entry);
  189. }
  190. return slapi_ch_strdup (slapi_entry_get_dn (*(Slapi_Entry**)entry));
  191. }
  192. static void LDAP_CALL LDAP_CALLBACK
  193. slapu_memfree( LDAP* ld, void* dn )
  194. {
  195. if (ld != internal_ld) {
  196. ldap_memfree (dn);
  197. } else {
  198. free (dn);
  199. }
  200. }
  201. static char*
  202. slapu_attr_get_desc( Slapi_Attr *attr )
  203. {
  204. char* desc = NULL;
  205. if (slapi_attr_get_type (attr, &desc) == LDAP_SUCCESS && desc) {
  206. return slapi_ch_strdup (desc);
  207. }
  208. return NULL;
  209. }
  210. /* slapu_first_attribute and slapu_next_attribute use a Slapi_Attr*
  211. * as an iterator. It is malloc'd by first() and free'd by ber_free().
  212. */
  213. static char* LDAP_CALL LDAP_CALLBACK
  214. slapu_first_attribute( LDAP* ld, LDAPMessage* entry, BerElement** iter )
  215. {
  216. if (ld != internal_ld) {
  217. return ldap_first_attribute (ld, entry, iter);
  218. } else {
  219. Slapi_Attr** attr = (Slapi_Attr**) slapi_ch_malloc (sizeof(Slapi_Attr*));
  220. *iter = (BerElement*) attr;
  221. if (attr && slapi_entry_first_attr (*(Slapi_Entry**)entry, attr) == LDAP_SUCCESS) {
  222. return slapu_attr_get_desc (*attr);
  223. }
  224. }
  225. return NULL;
  226. }
  227. static char* LDAP_CALL LDAP_CALLBACK
  228. slapu_next_attribute( LDAP* ld, LDAPMessage* entry, BerElement* iter)
  229. {
  230. Slapi_Attr** attr = (Slapi_Attr**)iter;
  231. if (ld != internal_ld) {
  232. return ldap_next_attribute (ld, entry, iter);
  233. }
  234. if (attr && slapi_entry_next_attr (*(Slapi_Entry**)entry, *attr, attr) == LDAP_SUCCESS) {
  235. return slapu_attr_get_desc (*attr);
  236. }
  237. return NULL;
  238. }
  239. static void LDAP_CALL LDAP_CALLBACK
  240. slapu_ber_free( LDAP* ld, BerElement* iter, int freebuf )
  241. {
  242. if (ld != internal_ld) {
  243. ber_free (iter, freebuf);
  244. } else {
  245. free ((Slapi_Attr**)iter);
  246. }
  247. }
  248. static struct berval** LDAP_CALL LDAP_CALLBACK
  249. slapu_get_values_len( LDAP *ld, LDAPMessage *entry, const char *desc )
  250. {
  251. Slapi_Attr* attr = NULL;
  252. if (ld != internal_ld) {
  253. return ldap_get_values_len (ld, entry, desc);
  254. }
  255. if (slapi_entry_attr_find (*(Slapi_Entry**)entry, desc, &attr) == LDAP_SUCCESS
  256. && attr) {
  257. struct berval** values = NULL;
  258. if ( slapi_attr_get_bervals_copy (attr, &values) == 0 ) {
  259. return (values);
  260. }
  261. }
  262. return NULL;
  263. }
  264. static void LDAP_CALL LDAP_CALLBACK
  265. slapu_value_free_len( LDAP* ld, struct berval **values )
  266. {
  267. if (ld != internal_ld) {
  268. ldap_value_free_len (values);
  269. } else {
  270. ber_bvecfree (values);
  271. }
  272. }
  273. void
  274. client_auth_init ()
  275. {
  276. int err;
  277. if (client_auth_config_file == NULL) {
  278. char *confdir = config_get_configdir();
  279. if (NULL == confdir) {
  280. LDAPDebug (LDAP_DEBUG_ANY,
  281. "client_auth_init: failed to get configdir\n",
  282. 0, 0, 0);
  283. return;
  284. }
  285. client_auth_config_file = PR_smprintf("%s/certmap.conf", confdir);
  286. if (NULL == client_auth_config_file) {
  287. LDAPDebug (LDAP_DEBUG_ANY,
  288. "client_auth_init: failed to duplicate \"%s/certmap\"\n",
  289. confdir, 0, 0);
  290. slapi_ch_free_string(&confdir);
  291. return;
  292. }
  293. slapi_ch_free_string(&confdir);
  294. }
  295. err = ldaputil_init (client_auth_config_file, "", NULL, "slapd", NULL);
  296. if (err != LDAPU_SUCCESS) {
  297. LDAPDebug (LDAP_DEBUG_TRACE, "ldaputil_init(%s,...) %i\n",
  298. client_auth_config_file, err, 0);
  299. } else {
  300. LDAPUVTable_t vtable = {
  301. NULL /* ssl_init */,
  302. NULL /* set_option */,
  303. NULL /* simple_bind_s */,
  304. NULL /* unbind */,
  305. slapu_search_s,
  306. slapu_count_entries,
  307. slapu_first_entry,
  308. slapu_next_entry,
  309. slapu_msgfree,
  310. slapu_get_dn,
  311. slapu_memfree,
  312. slapu_first_attribute,
  313. slapu_next_attribute,
  314. slapu_ber_free,
  315. NULL /* get_values */,
  316. NULL /* value_free */,
  317. slapu_get_values_len,
  318. slapu_value_free_len};
  319. ldapu_VTable_set (&vtable);
  320. }
  321. /* Generate a component id for cert-based authentication */
  322. generate_id();
  323. }
  324. #include <ssl.h>
  325. #include "slapi-plugin.h" /* SLAPI_BERVAL_EQ */
  326. #include "slapi-private.h" /* COMPONENT_CERT_AUTH */
  327. static Slapi_ComponentId * auth_component_id=NULL;
  328. static void generate_id()
  329. {
  330. if (auth_component_id == NULL ) {
  331. auth_component_id=generate_componentid (NULL /* Not a plugin */ , COMPONENT_CERT_AUTH);
  332. }
  333. }
  334. static Slapi_ComponentId * auth_get_component_id() {
  335. return auth_component_id;
  336. }
  337. static char*
  338. subject_of (CERTCertificate* cert)
  339. {
  340. char* dn = NULL;
  341. if (cert != NULL) {
  342. int err = ldapu_get_cert_subject_dn (cert, &dn);
  343. if (err != LDAPU_SUCCESS) {
  344. LDAPDebug (LDAP_DEBUG_ANY, "ldapu_get_cert_subject_dn(%p) %i (%s)\n",
  345. (void*)cert, err, ldapu_err2string (err));
  346. }
  347. }
  348. return dn;
  349. }
  350. static char*
  351. issuer_of (CERTCertificate* cert)
  352. {
  353. char* dn = NULL;
  354. if (cert != NULL) {
  355. int err = ldapu_get_cert_issuer_dn (cert, &dn);
  356. if (err != LDAPU_SUCCESS) {
  357. LDAPDebug (LDAP_DEBUG_ANY, "ldapu_get_cert_issuer_dn(%p) %i (%s)\n",
  358. (void*)cert, err, ldapu_err2string (err));
  359. }
  360. }
  361. return dn;
  362. }
  363. /*
  364. * Log a certificate that was rejected because the client didn't
  365. * authenticate it.
  366. *
  367. * Note: handle_bad_certificate() is called via slapd_ssl_badCertHook().
  368. * A Connection * is passed in client data. That connection must have its
  369. * c_mutex locked.
  370. */
  371. int
  372. handle_bad_certificate (void* clientData, PRFileDesc *prfd)
  373. {
  374. char sbuf[ BUFSIZ ], ibuf[ BUFSIZ ];
  375. Connection* conn = (Connection*) clientData;
  376. CERTCertificate* clientCert = slapd_ssl_peerCertificate (prfd);
  377. PRErrorCode errorCode = PR_GetError();
  378. char* subject = subject_of (clientCert);
  379. char* issuer = issuer_of (clientCert);
  380. slapi_log_access( LDAP_DEBUG_STATS,
  381. "conn=%" NSPRIu64 " " SLAPI_COMPONENT_NAME_NSPR " error %i (%s); unauthenticated client %s; issuer %s\n",
  382. conn->c_connid, errorCode, slapd_pr_strerror(errorCode),
  383. subject ? escape_string( subject, sbuf ) : "NULL",
  384. issuer ? escape_string( issuer, ibuf ) : "NULL" );
  385. if (issuer) free (issuer);
  386. if (subject) free (subject);
  387. if (clientCert) CERT_DestroyCertificate (clientCert);
  388. return -1; /* non-zero means reject this certificate */
  389. }
  390. /*
  391. * Get an identity from the client's certificate (if any was sent).
  392. *
  393. * Note: handle_handshake_done() is called via slapd_ssl_handshakeCallback().
  394. * A Connection * is passed in client data. That connection must have its
  395. * c_mutex locked.
  396. */
  397. void
  398. handle_handshake_done (PRFileDesc *prfd, void* clientData)
  399. {
  400. Connection* conn = (Connection*) clientData;
  401. CERTCertificate* clientCert = slapd_ssl_peerCertificate(prfd);
  402. char* clientDN = NULL;
  403. int keySize = 0;
  404. char* cipher = NULL;
  405. char* extraErrorMsg = "";
  406. SSLChannelInfo channelInfo;
  407. SSLCipherSuiteInfo cipherInfo;
  408. char* subject = NULL;
  409. if ( (slapd_ssl_getChannelInfo (prfd, &channelInfo, sizeof(channelInfo))) != SECSuccess ) {
  410. PRErrorCode errorCode = PR_GetError();
  411. slapi_log_access (LDAP_DEBUG_STATS,
  412. "conn=%" NSPRIu64 " SSL failed to obtain channel info; "
  413. SLAPI_COMPONENT_NAME_NSPR " error %i (%s)\n",
  414. conn->c_connid, errorCode, slapd_pr_strerror(errorCode));
  415. goto done;
  416. }
  417. if ( (slapd_ssl_getCipherSuiteInfo (channelInfo.cipherSuite, &cipherInfo, sizeof(cipherInfo)) )
  418. != SECSuccess) {
  419. PRErrorCode errorCode = PR_GetError();
  420. slapi_log_access (LDAP_DEBUG_STATS,
  421. "conn=%" NSPRIu64 " SSL failed to obtain cipher info; "
  422. SLAPI_COMPONENT_NAME_NSPR " error %i (%s)\n",
  423. conn->c_connid, errorCode, slapd_pr_strerror(errorCode));
  424. goto done;
  425. }
  426. keySize = cipherInfo.effectiveKeyBits;
  427. cipher = slapi_ch_strdup(cipherInfo.symCipherName);
  428. /* If inside an Start TLS operation, perform the privacy level discovery
  429. * and if the security degree achieved after the handshake is not reckoned
  430. * to be enough, close the SSL connection. */
  431. if ( conn->c_flags & CONN_FLAG_START_TLS ) {
  432. if ( cipherInfo.symKeyBits == 0 ) {
  433. start_tls_graceful_closure( conn, NULL, 1 );
  434. goto done;
  435. }
  436. }
  437. if (config_get_SSLclientAuth() == SLAPD_SSLCLIENTAUTH_OFF ) {
  438. slapi_log_access (LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " SSL %i-bit %s\n",
  439. conn->c_connid, keySize, cipher ? cipher : "NULL" );
  440. goto done;
  441. }
  442. if (clientCert == NULL) {
  443. slapi_log_access (LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " SSL %i-bit %s\n",
  444. conn->c_connid, keySize, cipher ? cipher : "NULL" );
  445. } else {
  446. subject = subject_of (clientCert);
  447. if (!subject) {
  448. slapi_log_access( LDAP_DEBUG_STATS,
  449. "conn=%" NSPRIu64 " SSL %i-bit %s; missing subject\n",
  450. conn->c_connid, keySize, cipher ? cipher : "NULL");
  451. goto done;
  452. }
  453. {
  454. char* issuer = issuer_of (clientCert);
  455. char sbuf[ BUFSIZ ], ibuf[ BUFSIZ ];
  456. slapi_log_access( LDAP_DEBUG_STATS,
  457. "conn=%" NSPRIu64 " SSL %i-bit %s; client %s; issuer %s\n",
  458. conn->c_connid, keySize, cipher ? cipher : "NULL",
  459. subject ? escape_string( subject, sbuf ) : "NULL",
  460. issuer ? escape_string( issuer, ibuf ) : "NULL");
  461. if (issuer) free (issuer);
  462. }
  463. slapi_dn_normalize (subject);
  464. {
  465. LDAPMessage* chain = NULL;
  466. char *basedn = config_get_basedn();
  467. int err;
  468. err = ldapu_cert_to_ldap_entry
  469. (clientCert, internal_ld, basedn?basedn:""/*baseDN*/, &chain);
  470. if (err == LDAPU_SUCCESS && chain) {
  471. LDAPMessage* entry = slapu_first_entry (internal_ld, chain);
  472. if (entry) {
  473. /* clientDN is duplicated in slapu_get_dn */
  474. clientDN = slapu_get_dn (internal_ld, entry);
  475. } else {
  476. extraErrorMsg = "no entry";
  477. LDAPDebug (LDAP_DEBUG_TRACE, "<= ldapu_cert_to_ldap_entry() %s\n",
  478. extraErrorMsg, 0, 0);
  479. }
  480. } else {
  481. extraErrorMsg = ldapu_err2string(err);
  482. LDAPDebug (LDAP_DEBUG_TRACE, "<= ldapu_cert_to_ldap_entry() %i (%s)%s\n",
  483. err, extraErrorMsg, chain ? "" : " NULL");
  484. }
  485. slapi_ch_free_string(&basedn);
  486. slapu_msgfree (internal_ld, chain);
  487. }
  488. }
  489. if (clientDN != NULL) {
  490. char ebuf[ BUFSIZ ];
  491. int rc = 0;
  492. char *normedDN = NULL;
  493. size_t dnlen = 0;
  494. rc = slapi_dn_normalize_ext(clientDN, 0, &normedDN, &dnlen);
  495. if (rc < 0) {
  496. /* ignoring the normalization error, use the pre normalized DN */
  497. } else if (rc == 0) { /* clientDN is passed in; not terminated */
  498. *(normedDN + dnlen) = '\0';
  499. } else {
  500. slapi_ch_free_string(&clientDN);
  501. clientDN = normedDN;
  502. }
  503. slapi_log_access (LDAP_DEBUG_STATS,
  504. "conn=%" NSPRIu64 " SSL client bound as %s\n",
  505. conn->c_connid, escape_string( clientDN, ebuf ));
  506. } else if (clientCert != NULL) {
  507. slapi_log_access (LDAP_DEBUG_STATS,
  508. "conn=%" NSPRIu64 " SSL failed to map client "
  509. "certificate to LDAP DN (%s)\n",
  510. conn->c_connid, extraErrorMsg );
  511. }
  512. /*
  513. * Associate the new credentials with the connection. Note that
  514. * clientDN and clientCert may be NULL.
  515. */
  516. bind_credentials_set( conn, SLAPD_AUTH_SSL, clientDN,
  517. SLAPD_AUTH_SSL, clientDN, clientCert , NULL);
  518. done:
  519. slapi_ch_free_string(&subject);
  520. slapi_ch_free_string(&cipher);
  521. /* clientDN and clientCert will be freed later */
  522. }