sasl_map.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  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) 2005 Red Hat, Inc.
  35. * All rights reserved.
  36. * END COPYRIGHT BLOCK **/
  37. #ifdef HAVE_CONFIG_H
  38. # include <config.h>
  39. #endif
  40. #include "slap.h"
  41. #include "slapi-plugin.h"
  42. #include "fe.h"
  43. /*
  44. * Map SASL identities to LDAP searches
  45. */
  46. static char * configDN = "cn=mapping,cn=sasl,cn=config";
  47. #define LOW_PRIORITY 100
  48. #define LOW_PRIORITY_STR "100"
  49. /*
  50. * DBDB: this is ugly, but right now there is _no_ server-wide
  51. * dynamic structure (like a Slapi_Server * type thing). All the code
  52. * that needs such a thing instead maintains a static or global variable.
  53. * Until we implement the 'right thing', we'll just follow suit here :(
  54. */
  55. static sasl_map_private *sasl_map_static_priv = NULL;
  56. static
  57. sasl_map_private *sasl_map_get_global_priv()
  58. {
  59. /* ASSERT(sasl_map_static_priv) */
  60. return sasl_map_static_priv;
  61. }
  62. static
  63. sasl_map_private *sasl_map_new_private()
  64. {
  65. Slapi_RWLock *new_lock = slapi_new_rwlock();
  66. sasl_map_private *new_priv = NULL;
  67. if (NULL == new_lock) {
  68. return NULL;
  69. }
  70. new_priv = (sasl_map_private *)slapi_ch_calloc(1,sizeof(sasl_map_private));
  71. new_priv->lock = new_lock;
  72. return new_priv;
  73. }
  74. static void
  75. sasl_map_free_private(sasl_map_private **priv)
  76. {
  77. slapi_destroy_rwlock((*priv)->lock);
  78. slapi_ch_free((void**)priv);
  79. *priv = NULL;
  80. }
  81. /* This function does a shallow copy on the payload data supplied, so the caller should not free it, and it needs to be allocated using slapi_ch_malloc() */
  82. static
  83. sasl_map_data *sasl_map_new_data(char *name, char *regex, char *dntemplate, char *filtertemplate, int priority)
  84. {
  85. sasl_map_data *new_dp = (sasl_map_data *) slapi_ch_calloc(1,sizeof(sasl_map_data));
  86. new_dp->name = name;
  87. new_dp->regular_expression = regex;
  88. new_dp->template_base_dn = dntemplate;
  89. new_dp->template_search_filter = filtertemplate;
  90. new_dp->priority = priority;
  91. new_dp->next = NULL;
  92. new_dp->prev = NULL;
  93. return new_dp;
  94. }
  95. static
  96. sasl_map_data *sasl_map_next(sasl_map_data *dp)
  97. {
  98. return dp->next;
  99. }
  100. static void
  101. sasl_map_free_data(sasl_map_data **dp)
  102. {
  103. slapi_ch_free_string(&(*dp)->name);
  104. slapi_ch_free_string(&(*dp)->regular_expression);
  105. slapi_ch_free_string(&(*dp)->template_base_dn);
  106. slapi_ch_free_string(&(*dp)->template_search_filter);
  107. slapi_ch_free((void**)dp);
  108. }
  109. static int
  110. sasl_map_remove_list_entry(sasl_map_private *priv, char *removeme)
  111. {
  112. int ret = 0;
  113. int foundit = 0;
  114. sasl_map_data *current = NULL;
  115. sasl_map_data *prev = NULL;
  116. sasl_map_data *next = NULL;
  117. slapi_rwlock_wrlock(priv->lock);
  118. current = priv->map_data_list;
  119. while (current) {
  120. next = current->next;
  121. if (0 == strcmp(current->name,removeme)) {
  122. foundit = 1;
  123. prev = current->prev;
  124. if (prev) {
  125. /* Unlink it */
  126. if (next) {
  127. next->prev = prev;
  128. }
  129. prev->next = next;
  130. } else {
  131. /* That was the first list entry */
  132. if (next) {
  133. next->prev = NULL;
  134. }
  135. priv->map_data_list = next;
  136. }
  137. /* Payload free */
  138. sasl_map_free_data(&current);
  139. /* And no need to look further */
  140. break;
  141. }
  142. current = next;
  143. }
  144. slapi_rwlock_unlock(priv->lock);
  145. if (!foundit) {
  146. ret = -1;
  147. }
  148. return ret;
  149. }
  150. static int
  151. sasl_map_cmp_data(sasl_map_data *dp0, sasl_map_data *dp1)
  152. {
  153. int rc = 0;
  154. if (NULL == dp0) {
  155. if (NULL == dp1) {
  156. return 0;
  157. } else {
  158. return -1;
  159. }
  160. } else {
  161. if (NULL == dp1) {
  162. return 1;
  163. }
  164. }
  165. rc = PL_strcmp(dp0->name, dp1->name);
  166. if (0 != rc) {
  167. /* did not match */
  168. return rc;
  169. }
  170. rc = PL_strcmp(dp0->regular_expression, dp1->regular_expression);
  171. if (0 != rc) {
  172. /* did not match */
  173. return rc;
  174. }
  175. rc = PL_strcmp(dp0->template_base_dn, dp1->template_base_dn);
  176. if (0 != rc) {
  177. /* did not match */
  178. return rc;
  179. }
  180. rc = PL_strcmp(dp0->template_search_filter, dp1->template_search_filter);
  181. return rc;
  182. }
  183. static int
  184. sasl_map_insert_list_entry(sasl_map_private *priv, sasl_map_data *dp)
  185. {
  186. int ret = 0;
  187. int ishere = 0;
  188. sasl_map_data *current = NULL;
  189. sasl_map_data *last = NULL;
  190. sasl_map_data *prev = NULL;
  191. if (NULL == dp) {
  192. return ret;
  193. }
  194. slapi_rwlock_wrlock(priv->lock);
  195. /* Check to see if it's here already */
  196. current = priv->map_data_list;
  197. while (current) {
  198. if (0 == sasl_map_cmp_data(current, dp)) {
  199. ishere = 1;
  200. break;
  201. }
  202. if (current->next) {
  203. current = current->next;
  204. } else {
  205. break;
  206. }
  207. }
  208. if (ishere) {
  209. slapi_rwlock_unlock(priv->lock);
  210. return -1;
  211. }
  212. /* insert the map in its proper place */
  213. if (NULL == priv->map_data_list) {
  214. priv->map_data_list = dp;
  215. } else {
  216. current = priv->map_data_list;
  217. while (current) {
  218. last = current;
  219. if(current->priority > dp->priority){
  220. prev = current->prev;
  221. if(prev){
  222. prev->next = dp;
  223. dp->prev = prev;
  224. } else {
  225. /* this is now the head of the list */
  226. priv->map_data_list = dp;
  227. }
  228. current->prev = dp;
  229. dp->next = current;
  230. slapi_rwlock_unlock(priv->lock);
  231. return ret;
  232. }
  233. current = current->next;
  234. }
  235. /* add the map at the end of the list */
  236. last->next = dp;
  237. dp->prev = last;
  238. }
  239. slapi_rwlock_unlock(priv->lock);
  240. return ret;
  241. }
  242. /*
  243. * Functions to handle config operations
  244. */
  245. /**
  246. * Get a list of child DNs
  247. * DBDB these functions should be folded into libslapd because it's a copy of a function in ssl.c
  248. */
  249. static char **
  250. getChildren( char *dn ) {
  251. Slapi_PBlock *new_pb = NULL;
  252. Slapi_Entry **e;
  253. int search_result = 1;
  254. int nEntries = 0;
  255. char **list = NULL;
  256. new_pb = slapi_search_internal ( dn, LDAP_SCOPE_ONELEVEL,
  257. "(objectclass=nsSaslMapping)",
  258. NULL, NULL, 0);
  259. slapi_pblock_get( new_pb, SLAPI_NENTRIES, &nEntries);
  260. if ( nEntries > 0 ) {
  261. slapi_pblock_get( new_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
  262. slapi_pblock_get( new_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &e);
  263. if ( e != NULL ) {
  264. int i;
  265. list = (char **)slapi_ch_malloc( sizeof(*list) * (nEntries + 1));
  266. for ( i = 0; e[i] != NULL; i++ ) {
  267. list[i] = slapi_ch_strdup(slapi_entry_get_dn(e[i]));
  268. }
  269. list[nEntries] = NULL;
  270. }
  271. }
  272. slapi_free_search_results_internal(new_pb);
  273. slapi_pblock_destroy(new_pb );
  274. return list;
  275. }
  276. /**
  277. * Free a list of child DNs
  278. */
  279. static void
  280. freeChildren( char **list ) {
  281. if ( list != NULL ) {
  282. int i;
  283. for ( i = 0; list[i] != NULL; i++ ) {
  284. slapi_ch_free( (void **)(&list[i]) );
  285. }
  286. slapi_ch_free( (void **)(&list) );
  287. }
  288. }
  289. /**
  290. * Get a particular entry
  291. */
  292. static Slapi_Entry *
  293. getConfigEntry( const char *dn, Slapi_Entry **e2 ) {
  294. Slapi_DN sdn;
  295. slapi_sdn_init_dn_byref( &sdn, dn );
  296. slapi_search_internal_get_entry( &sdn, NULL, e2,
  297. plugin_get_default_component_id());
  298. slapi_sdn_done( &sdn );
  299. return *e2;
  300. }
  301. /**
  302. * Free an entry
  303. */
  304. static void
  305. freeConfigEntry( Slapi_Entry ** e ) {
  306. if ( (e != NULL) && (*e != NULL) ) {
  307. slapi_entry_free( *e );
  308. *e = NULL;
  309. }
  310. }
  311. /*
  312. * unescape parenthesis in the regular expression.
  313. * E.g., ^u:\(.*\) ==> ^u:(.*)
  314. * This unescape is necessary for the new regex code using PCRE
  315. * to keep the backward compatibility.
  316. */
  317. char *
  318. _sasl_unescape_parenthesis(char *input)
  319. {
  320. char *s = NULL;
  321. char *d = NULL;
  322. for (s = input, d = input; s && *s; s++) {
  323. if (*s == '\\' && *(s+1) && (*(s+1) == '(' || *(s+1) == ')')) {
  324. *d++ = *(++s);
  325. } else {
  326. *d++ = *s;
  327. }
  328. }
  329. *d = '\0';
  330. return input;
  331. }
  332. static int
  333. sasl_map_config_parse_entry(Slapi_Entry *entry, sasl_map_data **new_dp)
  334. {
  335. int ret = 0;
  336. int priority;
  337. char *regex = NULL;
  338. char *basedntemplate = NULL;
  339. char *filtertemplate = NULL;
  340. char *priority_str = NULL;
  341. char *map_name = NULL;
  342. *new_dp = NULL;
  343. regex = _sasl_unescape_parenthesis(slapi_entry_attr_get_charptr( entry, "nsSaslMapRegexString" ));
  344. basedntemplate = slapi_entry_attr_get_charptr( entry, "nsSaslMapBaseDNTemplate" );
  345. filtertemplate = slapi_entry_attr_get_charptr( entry, "nsSaslMapFilterTemplate" );
  346. map_name = slapi_entry_attr_get_charptr( entry, "cn" );
  347. priority_str = slapi_entry_attr_get_charptr( entry, "nsSaslMapPriority" );
  348. if(priority_str){
  349. priority = atoi(priority_str);
  350. } else {
  351. priority = LOW_PRIORITY;
  352. }
  353. if(priority == 0 || priority > LOW_PRIORITY){
  354. struct berval desc;
  355. struct berval *newval[2] = {0, 0};
  356. desc.bv_val = LOW_PRIORITY_STR;
  357. desc.bv_len = strlen(desc.bv_val);
  358. newval[0] = &desc;
  359. if (entry_replace_values(entry, "nsSaslMapPriority", newval) != 0){
  360. LDAPDebug( LDAP_DEBUG_TRACE, "sasl_map_config_parse_entry: failed to reset priority to (%d)\n",
  361. LOW_PRIORITY,0,0);
  362. } else {
  363. LDAPDebug( LDAP_DEBUG_ANY, "sasl_map_config_parse_entry: resetting nsSaslMapPriority to lowest priority(%d)\n",
  364. LOW_PRIORITY,0,0);
  365. }
  366. priority = LOW_PRIORITY;
  367. }
  368. if ( (NULL == map_name) || (NULL == regex) ||
  369. (NULL == basedntemplate) || (NULL == filtertemplate) ) {
  370. /* Invalid entry */
  371. ret = -1;
  372. } else {
  373. /* Make the new dp */
  374. *new_dp = sasl_map_new_data(map_name, regex, basedntemplate, filtertemplate, priority);
  375. }
  376. if (ret) {
  377. slapi_ch_free_string(&map_name);
  378. slapi_ch_free_string(&regex);
  379. slapi_ch_free_string(&basedntemplate);
  380. slapi_ch_free_string(&filtertemplate);
  381. }
  382. slapi_ch_free_string(&priority_str);
  383. return ret;
  384. }
  385. static int
  386. sasl_map_read_config_startup(sasl_map_private *priv)
  387. {
  388. char **map_entry_list = NULL;
  389. int ret = 0;
  390. LDAPDebug( LDAP_DEBUG_TRACE, "-> sasl_map_read_config_startup\n", 0, 0, 0 );
  391. if((map_entry_list = getChildren(configDN))) {
  392. char **map_entry = NULL;
  393. Slapi_Entry *entry = NULL;
  394. sasl_map_data *dp = NULL;
  395. for (map_entry = map_entry_list; *map_entry && !ret; map_entry++) {
  396. LDAPDebug( LDAP_DEBUG_CONFIG, "sasl_map_read_config_startup - proceesing [%s]\n", *map_entry, 0, 0 );
  397. getConfigEntry( *map_entry, &entry );
  398. if ( entry == NULL ) {
  399. continue;
  400. }
  401. ret = sasl_map_config_parse_entry(entry,&dp);
  402. if (ret) {
  403. LDAPDebug( LDAP_DEBUG_ANY, "sasl_map_read_config_startup failed to parse entry\n", 0, 0, 0 );
  404. } else {
  405. ret = sasl_map_insert_list_entry(priv,dp);
  406. if (ret) {
  407. LDAPDebug( LDAP_DEBUG_ANY, "sasl_map_read_config_startup failed to insert entry\n", 0, 0, 0 );
  408. } else {
  409. LDAPDebug( LDAP_DEBUG_CONFIG, "sasl_map_read_config_startup - processed [%s]\n", *map_entry, 0, 0 );
  410. }
  411. }
  412. freeConfigEntry( &entry );
  413. }
  414. freeChildren( map_entry_list );
  415. }
  416. LDAPDebug( LDAP_DEBUG_TRACE, "<- sasl_map_read_config_startup\n", 0, 0, 0 );
  417. return ret;
  418. }
  419. int
  420. sasl_map_config_add(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg)
  421. {
  422. int ret = 0;
  423. sasl_map_data *dp = NULL;
  424. sasl_map_private *priv = sasl_map_get_global_priv();
  425. LDAPDebug( LDAP_DEBUG_TRACE, "-> sasl_map_config_add\n", 0, 0, 0 );
  426. ret = sasl_map_config_parse_entry(entryBefore,&dp);
  427. if (!ret && dp) {
  428. ret = sasl_map_insert_list_entry(priv,dp);
  429. }
  430. if (0 == ret) {
  431. ret = SLAPI_DSE_CALLBACK_OK;
  432. } else {
  433. returntext = "sasl map entry rejected";
  434. *returncode = LDAP_UNWILLING_TO_PERFORM;
  435. ret = SLAPI_DSE_CALLBACK_ERROR;
  436. }
  437. LDAPDebug( LDAP_DEBUG_TRACE, "<- sasl_map_config_add\n", 0, 0, 0 );
  438. return ret;
  439. }
  440. int
  441. sasl_map_config_modify(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg)
  442. {
  443. sasl_map_private *priv = sasl_map_get_global_priv();
  444. sasl_map_data *dp;
  445. char *map_name = NULL;
  446. int ret = SLAPI_DSE_CALLBACK_ERROR;
  447. if((map_name = slapi_entry_attr_get_charptr( entryBefore, "cn" )) == NULL){
  448. LDAPDebug( LDAP_DEBUG_TRACE, "sasl_map_config_modify: could not find name of map\n",0,0,0);
  449. return ret;
  450. }
  451. if(sasl_map_remove_list_entry(priv, map_name) == 0){
  452. ret = sasl_map_config_parse_entry(e, &dp);
  453. if (!ret && dp) {
  454. ret = sasl_map_insert_list_entry(priv, dp);
  455. if(ret == 0){
  456. ret = SLAPI_DSE_CALLBACK_OK;
  457. }
  458. }
  459. }
  460. if(ret == SLAPI_DSE_CALLBACK_ERROR){
  461. LDAPDebug( LDAP_DEBUG_TRACE, "sasl_map_config_modify: failed to update map(%s)\n",map_name,0,0);
  462. }
  463. slapi_ch_free_string(&map_name);
  464. return ret;
  465. }
  466. int
  467. sasl_map_config_delete(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg)
  468. {
  469. int ret = 0;
  470. sasl_map_private *priv = sasl_map_get_global_priv();
  471. char *entry_name = NULL;
  472. LDAPDebug( LDAP_DEBUG_TRACE, "-> sasl_map_config_delete\n", 0, 0, 0 );
  473. entry_name = slapi_entry_attr_get_charptr( entryBefore, "cn" );
  474. if (entry_name) {
  475. /* remove this entry from the list */
  476. ret = sasl_map_remove_list_entry(priv,entry_name);
  477. slapi_ch_free((void **) &entry_name);
  478. }
  479. if (ret) {
  480. ret = SLAPI_DSE_CALLBACK_ERROR;
  481. returntext = "can't delete sasl map entry";
  482. *returncode = LDAP_OPERATIONS_ERROR;
  483. } else {
  484. ret = SLAPI_DSE_CALLBACK_OK;
  485. }
  486. LDAPDebug( LDAP_DEBUG_TRACE, "<- sasl_map_config_delete\n", 0, 0, 0 );
  487. return ret;
  488. }
  489. /* Start and stop the sasl mapping code */
  490. int sasl_map_init()
  491. {
  492. int ret = 0;
  493. sasl_map_private *priv = NULL;
  494. /* Make the private structure */
  495. priv = sasl_map_new_private();
  496. if (priv) {
  497. /* Store in the static var */
  498. sasl_map_static_priv = priv;
  499. /* Read the config on startup */
  500. ret = sasl_map_read_config_startup(priv);
  501. } else {
  502. ret = -1;
  503. }
  504. return ret;
  505. }
  506. int sasl_map_done()
  507. {
  508. int ret = 0;
  509. sasl_map_private *priv = sasl_map_get_global_priv();
  510. sasl_map_data *dp = NULL;
  511. /* there is no sasl map in referral mode */
  512. if (!priv || !priv->lock || !priv->map_data_list) {
  513. return 0;
  514. }
  515. /* Free the map list */
  516. slapi_rwlock_wrlock(priv->lock);
  517. dp = priv->map_data_list;
  518. while (dp) {
  519. sasl_map_data *dp_next = dp->next;
  520. sasl_map_free_data(&dp);
  521. dp = dp_next;
  522. }
  523. slapi_rwlock_unlock(priv->lock);
  524. /* Free the private structure */
  525. sasl_map_free_private(&priv);
  526. return ret;
  527. }
  528. static int
  529. sasl_map_check(sasl_map_data *dp, char *sasl_user_and_realm, char **ldap_search_base, char **ldap_search_filter)
  530. {
  531. Slapi_Regex *re = NULL;
  532. int ret = 0;
  533. int matched = 0;
  534. const char *recomp_result = NULL;
  535. LDAPDebug( LDAP_DEBUG_TRACE, "-> sasl_map_check\n", 0, 0, 0 );
  536. /* Compiles the regex */
  537. re = slapi_re_comp(dp->regular_expression, &recomp_result);
  538. if (NULL == re) {
  539. LDAPDebug( LDAP_DEBUG_ANY,
  540. "sasl_map_check: slapi_re_comp failed for expression (%s): %s\n",
  541. dp->regular_expression, recomp_result?recomp_result:"unknown", 0 );
  542. } else {
  543. /* Matches the compiled regex against sasl_user_and_realm */
  544. matched = slapi_re_exec(re, sasl_user_and_realm, -1 /* no timelimit */);
  545. LDAPDebug( LDAP_DEBUG_TRACE, "regex: %s, id: %s, %s\n",
  546. dp->regular_expression, sasl_user_and_realm,
  547. matched ? "matched" : "didn't match" );
  548. }
  549. if (matched) {
  550. if (matched == 1) {
  551. char escape_base[BUFSIZ];
  552. char escape_filt[BUFSIZ];
  553. int ldap_search_base_len, ldap_search_filter_len;
  554. int rc = 0;
  555. /* Allocate buffers for the returned strings */
  556. /* We already computed this, so we could pass it in to speed up
  557. * a little */
  558. size_t userrealmlen = strlen(sasl_user_and_realm);
  559. /* These lengths could be precomputed and stored in the dp */
  560. ldap_search_base_len =
  561. userrealmlen + strlen(dp->template_base_dn) + 1;
  562. ldap_search_filter_len =
  563. userrealmlen + strlen(dp->template_search_filter) + 1;
  564. *ldap_search_base = (char *)slapi_ch_malloc(ldap_search_base_len);
  565. *ldap_search_filter =
  566. (char *)slapi_ch_malloc(ldap_search_filter_len);
  567. /* Substitutes '&' and/or "\#" in template_base_dn */
  568. rc = slapi_re_subs(re, sasl_user_and_realm, dp->template_base_dn,
  569. ldap_search_base, ldap_search_base_len);
  570. if (0 != rc) {
  571. LDAPDebug( LDAP_DEBUG_ANY,
  572. "sasl_map_check: slapi_re_subs failed: "
  573. "subject: %s, subst str: %s (%d)\n",
  574. sasl_user_and_realm, dp->template_base_dn, rc);
  575. slapi_ch_free_string(ldap_search_base);
  576. slapi_ch_free_string(ldap_search_filter);
  577. } else {
  578. /* Substitutes '&' and/or "\#" in template_search_filter */
  579. rc = slapi_re_subs_ext(re, sasl_user_and_realm,
  580. dp->template_search_filter, ldap_search_filter,
  581. ldap_search_filter_len, 1);
  582. if (0 != rc) {
  583. LDAPDebug( LDAP_DEBUG_ANY,
  584. "sasl_map_check: slapi_re_subs failed: "
  585. "subject: %s, subst str: %s (%d)\n",
  586. sasl_user_and_realm, dp->template_search_filter, rc);
  587. slapi_ch_free_string(ldap_search_base);
  588. slapi_ch_free_string(ldap_search_filter);
  589. } else {
  590. /* these values are internal regex representations with
  591. * lots of unprintable control chars - escape for logging */
  592. LDAPDebug( LDAP_DEBUG_TRACE,
  593. "mapped base dn: %s, filter: %s\n",
  594. escape_string( *ldap_search_base, escape_base ),
  595. escape_string( *ldap_search_filter, escape_filt ), 0 );
  596. ret = 1;
  597. }
  598. }
  599. } else {
  600. LDAPDebug( LDAP_DEBUG_ANY,
  601. "sasl_map_check: slapi_re_exec failed: "
  602. "regex: %s, subject: %s (%d)\n",
  603. dp->regular_expression, sasl_user_and_realm, matched);
  604. }
  605. }
  606. slapi_re_free(re);
  607. LDAPDebug( LDAP_DEBUG_TRACE, "<- sasl_map_check\n", 0, 0, 0 );
  608. return ret;
  609. }
  610. static char *
  611. sasl_map_str_concat(char *s1, char *s2)
  612. {
  613. if (NULL == s2) {
  614. return (slapi_ch_strdup(s1));
  615. } else {
  616. char *newstr = slapi_ch_smprintf("%s@%s",s1,s2);
  617. return newstr;
  618. }
  619. }
  620. /* Actually perform a mapping
  621. * Takes a sasl identity string, and returns an LDAP search spec to be used to find the entry
  622. * returns 1 if matched, 0 otherwise
  623. */
  624. int
  625. sasl_map_domap(sasl_map_data **map, char *sasl_user, char *sasl_realm, char **ldap_search_base, char **ldap_search_filter)
  626. {
  627. sasl_map_private *priv = sasl_map_get_global_priv();
  628. char *sasl_user_and_realm = NULL;
  629. int ret = 0;
  630. LDAPDebug( LDAP_DEBUG_TRACE, "-> sasl_map_domap\n", 0, 0, 0 );
  631. if(map == NULL){
  632. LDAPDebug( LDAP_DEBUG_TRACE, "<- sasl_map_domap: Internal error, mapping is NULL\n",0,0,0);
  633. return ret;
  634. }
  635. *ldap_search_base = NULL;
  636. *ldap_search_filter = NULL;
  637. sasl_user_and_realm = sasl_map_str_concat(sasl_user,sasl_realm);
  638. /* Walk the list of maps */
  639. if(*map == NULL)
  640. *map = priv->map_data_list;
  641. while (*map) {
  642. /* If one matches, then make the search params */
  643. LDAPDebug( LDAP_DEBUG_TRACE, "sasl_map_domap - trying map [%s]\n", (*map)->name, 0, 0 );
  644. if((ret = sasl_map_check(*map, sasl_user_and_realm, ldap_search_base, ldap_search_filter))){
  645. *map = sasl_map_next(*map);
  646. break;
  647. }
  648. *map = sasl_map_next(*map);
  649. }
  650. if (sasl_user_and_realm) {
  651. slapi_ch_free((void**)&sasl_user_and_realm);
  652. }
  653. LDAPDebug( LDAP_DEBUG_TRACE, "<- sasl_map_domap (%s)\n", (1 == ret) ? "mapped" : "not mapped", 0, 0 );
  654. return ret;
  655. }
  656. void
  657. sasl_map_read_lock()
  658. {
  659. sasl_map_private *priv = sasl_map_get_global_priv();
  660. slapi_rwlock_rdlock(priv->lock);
  661. }
  662. void
  663. sasl_map_read_unlock()
  664. {
  665. sasl_map_private *priv = sasl_map_get_global_priv();
  666. slapi_rwlock_unlock(priv->lock);
  667. }