pam_ptpreop.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2005 Red Hat, Inc.
  3. * All rights reserved.
  4. *
  5. * License: GPL (version 3 or any later version).
  6. * See LICENSE for details.
  7. * END COPYRIGHT BLOCK **/
  8. #ifdef HAVE_CONFIG_H
  9. # include <config.h>
  10. #endif
  11. /*
  12. * pamptpreop.c - bind pre-operation plugin for Pass Through Authentication to PAM
  13. *
  14. */
  15. #include "pam_passthru.h"
  16. static Slapi_PluginDesc pdesc = { "pam_passthruauth", VENDOR, DS_PACKAGE_VERSION,
  17. "PAM pass through authentication plugin" };
  18. static void *pam_passthruauth_plugin_identity = NULL;
  19. static const Slapi_DN *pam_passthruauth_plugin_sdn = NULL;
  20. static Slapi_RWLock *g_pam_config_lock = NULL;
  21. /*
  22. * Plug-in globals
  23. */
  24. PRCList *pam_passthru_global_config = NULL;
  25. /*
  26. * function prototypes
  27. */
  28. static int pam_passthru_bindpreop( Slapi_PBlock *pb );
  29. static int pam_passthru_bindpreop_start( Slapi_PBlock *pb );
  30. static int pam_passthru_bindpreop_close( Slapi_PBlock *pb );
  31. static int pam_passthru_preop(Slapi_PBlock *pb, int modtype);
  32. static int pam_passthru_add_preop(Slapi_PBlock *pb);
  33. static int pam_passthru_mod_preop(Slapi_PBlock *pb);
  34. static int pam_passthru_del_preop(Slapi_PBlock *pb);
  35. static int pam_passthru_modrdn_preop(Slapi_PBlock *pb);
  36. static int pam_passthru_postop(Slapi_PBlock *pb);
  37. static int pam_passthru_internal_postop_init(Slapi_PBlock *pb);
  38. static int pam_passthru_postop_init(Slapi_PBlock *pb);
  39. static int pam_passthru_preop_init(Slapi_PBlock *pb);
  40. /*
  41. ** Plugin identity mgmt
  42. */
  43. void pam_passthruauth_set_plugin_identity(void * identity)
  44. {
  45. pam_passthruauth_plugin_identity=identity;
  46. }
  47. void * pam_passthruauth_get_plugin_identity()
  48. {
  49. return pam_passthruauth_plugin_identity;
  50. }
  51. void pam_passthruauth_set_plugin_sdn(const Slapi_DN *plugin_sdn)
  52. {
  53. pam_passthruauth_plugin_sdn = plugin_sdn;
  54. }
  55. const Slapi_DN *pam_passthruauth_get_plugin_sdn()
  56. {
  57. return pam_passthruauth_plugin_sdn;
  58. }
  59. const char *pam_passthruauth_get_plugin_dn()
  60. {
  61. return slapi_sdn_get_ndn(pam_passthruauth_plugin_sdn);
  62. }
  63. /*
  64. * Plugin initialization function (which must be listed in the appropriate
  65. * slapd config file).
  66. */
  67. int
  68. pam_passthruauth_init( Slapi_PBlock *pb )
  69. {
  70. int status = 0;
  71. Slapi_Entry *plugin_entry = NULL;
  72. char *plugin_type = NULL;
  73. int is_betxn = 0;
  74. int preadd = SLAPI_PLUGIN_PRE_ADD_FN;
  75. int premod = SLAPI_PLUGIN_PRE_MODIFY_FN;
  76. int predel = SLAPI_PLUGIN_PRE_DELETE_FN;
  77. int premdn = SLAPI_PLUGIN_PRE_MODRDN_FN;
  78. PAM_PASSTHRU_ASSERT( pb != NULL );
  79. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  80. "=> pam_passthruauth_init\n" );
  81. slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &pam_passthruauth_plugin_identity);
  82. PR_ASSERT (pam_passthruauth_plugin_identity);
  83. if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
  84. plugin_entry &&
  85. (plugin_type = slapi_entry_attr_get_charptr(plugin_entry,
  86. "nsslapd-plugintype")) &&
  87. plugin_type && strstr(plugin_type, "betxn")) {
  88. is_betxn = 1;
  89. preadd = SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN;
  90. premod = SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN;
  91. predel = SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN;
  92. premdn = SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN;
  93. }
  94. slapi_ch_free_string(&plugin_type);
  95. if (is_betxn) {
  96. if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
  97. (void *)SLAPI_PLUGIN_VERSION_01 ) ||
  98. slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc ) ||
  99. slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN,
  100. (void *)pam_passthru_bindpreop_start ) ||
  101. slapi_pblock_set( pb, preadd, (void *)pam_passthru_add_preop ) ||
  102. slapi_pblock_set( pb, premod, (void *)pam_passthru_mod_preop ) ||
  103. slapi_pblock_set( pb, predel, (void *)pam_passthru_del_preop ) ||
  104. slapi_pblock_set( pb, premdn, (void *)pam_passthru_modrdn_preop )) {
  105. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  106. "pam_passthruauth_init - Failed\n");
  107. status = -1;
  108. goto bail;
  109. }
  110. /* Register preop functions for the betxn enabled case */
  111. if (slapi_register_plugin("preoperation", /* op type */
  112. 1, /* Enabled */
  113. "pam_passthruauth_init", /* this function desc */
  114. pam_passthru_preop_init, /* init func for pre op */
  115. PAM_PASSTHRU_PREOP_DESC, /* plugin desc */
  116. NULL, /* ? */
  117. pam_passthruauth_plugin_identity /* access control */
  118. )) {
  119. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  120. "pam_passthruauth_init - "
  121. "Failed to register preop plugin\n");
  122. status = -1;
  123. goto bail;
  124. }
  125. } else {
  126. if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
  127. (void *)SLAPI_PLUGIN_VERSION_01 ) ||
  128. slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc ) ||
  129. slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN,
  130. (void *)pam_passthru_bindpreop_start ) ||
  131. slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_BIND_FN,
  132. (void *)pam_passthru_bindpreop ) ||
  133. slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN,
  134. (void *)pam_passthru_bindpreop_close ) ||
  135. slapi_pblock_set( pb, preadd, (void *)pam_passthru_add_preop ) ||
  136. slapi_pblock_set( pb, premod, (void *)pam_passthru_mod_preop ) ||
  137. slapi_pblock_set( pb, predel, (void *)pam_passthru_del_preop ) ||
  138. slapi_pblock_set( pb, premdn, (void *)pam_passthru_modrdn_preop )) {
  139. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  140. "pam_passthruauth_init - Failed\n");
  141. status = -1;
  142. goto bail;
  143. }
  144. /* Register internal postop functions. */
  145. /* If betxn is enabled, internal op is a part of betxn */
  146. if (slapi_register_plugin("internalpostoperation", /* op type */
  147. 1, /* Enabled */
  148. "pam_passthruauth_init", /* this function desc */
  149. pam_passthru_internal_postop_init, /* init func */
  150. PAM_PASSTHRU_INT_POSTOP_DESC, /* plugin desc */
  151. NULL, /* ? */
  152. pam_passthruauth_plugin_identity /* access control */
  153. )) {
  154. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  155. "pam_passthruauth_init - "
  156. "Failed to register internal postop plugin\n");
  157. status = -1;
  158. goto bail;
  159. }
  160. }
  161. /* Register postop functions */
  162. if (slapi_register_plugin(is_betxn ? "postoperation" : "betxnpostoperation", /* op type */
  163. 1, /* Enabled */
  164. "pam_passthruauth_init", /* this function desc */
  165. pam_passthru_postop_init, /* init func for post op */
  166. PAM_PASSTHRU_POSTOP_DESC, /* plugin desc */
  167. NULL, /* ? */
  168. pam_passthruauth_plugin_identity /* access control */
  169. )) {
  170. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  171. "pam_passthruauth_init - "
  172. "Failed to register (%s) plugin\n",
  173. is_betxn ? "postoperation" : "betxnpostoperation");
  174. status = -1;
  175. goto bail;
  176. }
  177. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  178. "<= pam_passthruauth_init\n" );
  179. bail:
  180. return status;
  181. }
  182. /*
  183. * Only if betxn is on, register just pre bind and close as perop operation.
  184. * The other preops (add/del/mod/mdn) are registered as betxn pre ops.
  185. */
  186. static int
  187. pam_passthru_preop_init(Slapi_PBlock *pb)
  188. {
  189. int status = 0;
  190. if ( slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_BIND_FN,
  191. (void *)pam_passthru_bindpreop ) ||
  192. slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *)pam_passthru_bindpreop_close )) {
  193. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  194. "pam_passthru_preop_init - Failed\n");
  195. status = -1;
  196. }
  197. return status;
  198. }
  199. static int
  200. pam_passthru_internal_postop_init(Slapi_PBlock *pb)
  201. {
  202. int status = 0;
  203. if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
  204. SLAPI_PLUGIN_VERSION_01) != 0 ||
  205. slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
  206. (void *) &pdesc) != 0 ||
  207. slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN,
  208. (void *) pam_passthru_postop) != 0 ||
  209. slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN,
  210. (void *) pam_passthru_postop) != 0 ||
  211. slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN,
  212. (void *) pam_passthru_postop) != 0 ||
  213. slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN,
  214. (void *) pam_passthru_postop) != 0) {
  215. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  216. "pam_passthru_internal_postop_init: failed to register plugin\n");
  217. status = -1;
  218. }
  219. return status;
  220. }
  221. static int
  222. pam_passthru_postop_init(Slapi_PBlock *pb)
  223. {
  224. int status = 0;
  225. Slapi_Entry *plugin_entry = NULL;
  226. char *plugin_type = NULL;
  227. int is_betxn = 0;
  228. int postadd = SLAPI_PLUGIN_POST_ADD_FN;
  229. int postmod = SLAPI_PLUGIN_POST_MODIFY_FN;
  230. int postmdn = SLAPI_PLUGIN_POST_MODRDN_FN;
  231. int postdel = SLAPI_PLUGIN_POST_DELETE_FN;
  232. if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
  233. plugin_entry &&
  234. (plugin_type = slapi_entry_attr_get_charptr(plugin_entry,
  235. "nsslapd-plugintype")) &&
  236. plugin_type && strstr(plugin_type, "betxn")) {
  237. postadd = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN;
  238. postmod = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN;
  239. postmdn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN;
  240. postdel = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN;
  241. is_betxn = 1;
  242. }
  243. slapi_ch_free_string(&plugin_type);
  244. if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) ||
  245. slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) ||
  246. slapi_pblock_set(pb, postadd, (void *) pam_passthru_postop) ||
  247. slapi_pblock_set(pb, postdel, (void *) pam_passthru_postop) ||
  248. slapi_pblock_set(pb, postmod, (void *) pam_passthru_postop) ||
  249. slapi_pblock_set(pb, postmdn, (void *) pam_passthru_postop) ) {
  250. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  251. "pam_passthru_postop_init - "
  252. "Failed to register (%s) plugin\n",
  253. is_betxn ? "betxn postop" : "postop");
  254. status = -1;
  255. }
  256. return status;
  257. }
  258. /*
  259. * pam_passthru_bindpreop_start() is called before the directory server
  260. * is fully up. We parse our configuration and initialize any mutexes, etc.
  261. */
  262. static int
  263. pam_passthru_bindpreop_start( Slapi_PBlock *pb )
  264. {
  265. int rc = PAM_PASSTHRU_SUCCESS;
  266. Slapi_DN *pluginsdn = NULL;
  267. char *config_area = NULL;
  268. PAM_PASSTHRU_ASSERT( pb != NULL );
  269. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  270. "=> pam_passthru_bindpreop_start\n" );
  271. /* Get the plug-in configuration DN and store it for later use. */
  272. slapi_pblock_get(pb, SLAPI_TARGET_SDN, &pluginsdn);
  273. if (NULL == pluginsdn || 0 == slapi_sdn_get_ndn_len(pluginsdn)) {
  274. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  275. "pam_passthru_bindpreop_start - Unable to determine plug-in config dn\n");
  276. rc = PAM_PASSTHRU_FAILURE;
  277. goto done;
  278. }
  279. /* Dup the plugin SDN to save it. */
  280. pam_passthruauth_set_plugin_sdn(slapi_sdn_dup(pluginsdn));
  281. /* Set the alternate config area if one is defined. */
  282. slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area);
  283. if (config_area) {
  284. pam_passthru_set_config_area(slapi_sdn_new_normdn_byval(config_area));
  285. } else {
  286. pam_passthru_set_config_area(slapi_sdn_dup(pluginsdn));
  287. }
  288. slapi_log_error(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  289. "pam_passthru_bindpreop_start - Config at %s\n",
  290. slapi_sdn_get_ndn(pam_passthru_get_config_area()));
  291. /* Create the lock that protects the config . */
  292. g_pam_config_lock = slapi_new_rwlock();
  293. if (!g_pam_config_lock) {
  294. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  295. "pam_passthru_bindpreop_start - Lock creation failed\n");
  296. rc = PAM_PASSTHRU_FAILURE;
  297. goto done;
  298. }
  299. /* Allocate the config list. */
  300. pam_passthru_global_config = (PRCList *)
  301. slapi_ch_calloc(1, sizeof(Pam_PassthruConfig));
  302. PR_INIT_CLIST(pam_passthru_global_config);
  303. /* Load config. */
  304. pam_passthru_load_config(0 /* don't skip validation */);
  305. if (( rc = pam_passthru_pam_init()) != LDAP_SUCCESS ) {
  306. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  307. "pam_passthru_bindpreop_start - Could not initialize PAM subsystem (%d)\n", rc);
  308. rc = PAM_PASSTHRU_FAILURE;
  309. goto done;
  310. }
  311. done:
  312. if ( rc != PAM_PASSTHRU_SUCCESS ) {
  313. pam_passthru_delete_config();
  314. slapi_destroy_rwlock(g_pam_config_lock);
  315. g_pam_config_lock = NULL;
  316. slapi_ch_free((void **)&pam_passthru_global_config);
  317. } else {
  318. slapi_log_error(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  319. "pam_passthru_bindpreop_start - Ready for service\n" );
  320. }
  321. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  322. "<= pam_passthru_bindpreop_start\n" );
  323. return( rc );
  324. }
  325. /*
  326. * Called right before the Directory Server shuts down.
  327. */
  328. static int
  329. pam_passthru_bindpreop_close( Slapi_PBlock *pb )
  330. {
  331. PAM_PASSTHRU_ASSERT( pb != NULL );
  332. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  333. "=> pam_passthru_bindpreop_close\n" );
  334. pam_passthru_delete_config();
  335. pam_passthru_unlock();
  336. slapi_sdn_free((Slapi_DN **)&pam_passthruauth_plugin_sdn);
  337. pam_passthru_free_config_area();
  338. slapi_ch_free((void **)&pam_passthru_global_config);
  339. pam_passthru_pam_free();
  340. slapi_destroy_rwlock(g_pam_config_lock);
  341. g_pam_config_lock = NULL;
  342. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  343. "<= pam_passthru_bindpreop_close\n" );
  344. return( 0 );
  345. }
  346. static int
  347. pam_passthru_bindpreop( Slapi_PBlock *pb )
  348. {
  349. int rc = LDAP_SUCCESS;
  350. ber_tag_t method;
  351. const char *normbinddn;
  352. char *errmsg = NULL;
  353. Slapi_DN *bindsdn = NULL;
  354. Pam_PassthruConfig *cfg;
  355. struct berval *creds;
  356. int retcode = PAM_PASSTHRU_OP_NOT_HANDLED;
  357. PAM_PASSTHRU_ASSERT( pb != NULL );
  358. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  359. "=> pam_passthru_bindpreop\n" );
  360. /*
  361. * retrieve parameters for bind operation
  362. */
  363. if ( slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method ) != 0 ||
  364. slapi_pblock_get( pb, SLAPI_BIND_TARGET_SDN, &bindsdn ) != 0 ||
  365. slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &creds ) != 0 ) {
  366. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  367. "pam_passthru_bindpreop - not handled (unable to retrieve bind parameters)\n" );
  368. return retcode;
  369. }
  370. normbinddn = slapi_sdn_get_dn(bindsdn);
  371. /*
  372. * We only handle simple bind requests that include non-NULL binddn and
  373. * credentials. Let the Directory Server itself handle everything else.
  374. */
  375. if ((method != LDAP_AUTH_SIMPLE) || (*normbinddn == '\0') ||
  376. (creds->bv_len == 0)) {
  377. slapi_log_error(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  378. "pam_passthru_bindpreop - Not handled (not simple bind or NULL dn/credentials)\n" );
  379. return retcode;
  380. }
  381. /* Get the config lock. From this point on, we must go to done
  382. * to be sure we unlock. */
  383. pam_passthru_read_lock();
  384. /* Bail out if the plug-in close function was just called. */
  385. if (!slapi_plugin_running(pb)) {
  386. goto done;
  387. }
  388. /* See if any of our config entries apply to this user */
  389. cfg = pam_passthru_get_config(bindsdn);
  390. if (!cfg) {
  391. slapi_log_error(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  392. "pam_passthru_bindpreop - \"%s\" Not handled (doesn't meet configuration criteria)\n", normbinddn );
  393. goto done;
  394. }
  395. if (cfg->pamptconfig_secure) { /* is a secure connection required? */
  396. int is_ssl = 0;
  397. slapi_pblock_get(pb, SLAPI_CONN_IS_SSL_SESSION, &is_ssl);
  398. if (!is_ssl) {
  399. slapi_log_error(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  400. "pam_passthru_bindpreop - Connection not secure (secure connection required; check config)\n");
  401. goto done;
  402. }
  403. }
  404. /*
  405. * We are now committed to handling this bind request.
  406. * Chain it off to PAM
  407. */
  408. rc = pam_passthru_do_pam_auth(pb, cfg);
  409. /*
  410. * If bind succeeded, change authentication information associated
  411. * with this connection.
  412. */
  413. if (rc == LDAP_SUCCESS) {
  414. char *ndn = slapi_ch_strdup(normbinddn);
  415. if ((slapi_pblock_set(pb, SLAPI_CONN_DN, ndn) != 0) ||
  416. (slapi_pblock_set(pb, SLAPI_CONN_AUTHMETHOD,
  417. SLAPD_AUTH_SIMPLE) != 0)) {
  418. slapi_ch_free_string(&ndn);
  419. rc = LDAP_OPERATIONS_ERROR;
  420. errmsg = "unable to set connection DN or AUTHTYPE";
  421. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  422. "pam_passthru_bindpreop - %s\n", errmsg);
  423. } else {
  424. LDAPControl **reqctrls = NULL;
  425. slapi_pblock_get(pb, SLAPI_REQCONTROLS, &reqctrls);
  426. if (slapi_control_present(reqctrls, LDAP_CONTROL_AUTH_REQUEST, NULL, NULL)) {
  427. slapi_add_auth_response_control(pb, ndn);
  428. }
  429. }
  430. }
  431. if (rc == LDAP_SUCCESS) {
  432. /* we are handling the result */
  433. slapi_send_ldap_result(pb, rc, NULL, errmsg, 0, NULL);
  434. /* tell bind code we handled the result */
  435. retcode = PAM_PASSTHRU_OP_HANDLED;
  436. } else if (!cfg->pamptconfig_fallback) {
  437. /* tell bind code we already sent back the error result in pam_ptimpl.c */
  438. retcode = PAM_PASSTHRU_OP_HANDLED;
  439. }
  440. done:
  441. pam_passthru_unlock();
  442. slapi_log_error(SLAPI_LOG_PLUGIN, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  443. "pam_passthru_bindpreop - handled (error %d - %s)\n", rc, ldap_err2string(rc));
  444. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  445. "<= pam_passthru_bindpreop\n" );
  446. return retcode;
  447. }
  448. /*
  449. * Pre-op callbacks for config change validation
  450. */
  451. static int
  452. pam_passthru_preop(Slapi_PBlock *pb, int modtype)
  453. {
  454. Slapi_DN *sdn = NULL;
  455. Slapi_Entry *e = NULL;
  456. LDAPMod **mods;
  457. char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
  458. int ret = SLAPI_PLUGIN_SUCCESS;
  459. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  460. "=> pam_passthru_preop\n");
  461. /* Get the target SDN. */
  462. slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
  463. if (!sdn) {
  464. goto bail;
  465. }
  466. /* If this is a config entry, we need to validate it. */
  467. if (pam_passthru_dn_is_config(sdn)) {
  468. switch (modtype) {
  469. case LDAP_CHANGETYPE_ADD:
  470. slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
  471. /* Validate the entry being added. */
  472. if (PAM_PASSTHRU_FAILURE == pam_passthru_validate_config(e, returntext)) {
  473. ret = LDAP_UNWILLING_TO_PERFORM;
  474. goto bail;
  475. }
  476. break;
  477. case LDAP_CHANGETYPE_MODIFY:
  478. /* Fetch the entry being modified so we can
  479. * create the resulting entry for validation. */
  480. slapi_search_internal_get_entry(sdn, 0, &e,
  481. pam_passthruauth_get_plugin_identity());
  482. /* If the entry doesn't exist, just bail and
  483. * let the server handle it. */
  484. if (e == NULL) {
  485. goto bail;
  486. }
  487. /* Grab the mods. */
  488. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  489. /* Apply the mods to create the resulting entry. If the mods
  490. * don't apply cleanly, we just let the main server code handle it. */
  491. if (mods && (slapi_entry_apply_mods(e, mods) == LDAP_SUCCESS)) {
  492. /* Validate the resulting entry. */
  493. if (PAM_PASSTHRU_FAILURE == pam_passthru_validate_config(e, returntext)) {
  494. ret = LDAP_UNWILLING_TO_PERFORM;
  495. /* Don't bail here, as we need to free the entry. */
  496. }
  497. }
  498. /* Free the entry. */
  499. slapi_entry_free(e);
  500. break;
  501. case LDAP_CHANGETYPE_DELETE:
  502. case LDAP_CHANGETYPE_MODDN:
  503. /* Don't allow the plug-in container in DSE to be deleted or renamed. */
  504. if (slapi_sdn_compare(sdn, pam_passthruauth_get_plugin_sdn()) == 0) {
  505. ret = LDAP_UNWILLING_TO_PERFORM;
  506. }
  507. break;
  508. }
  509. }
  510. bail:
  511. /* If we are refusing the operation, return the result to the client. */
  512. if (ret) {
  513. slapi_send_ldap_result(pb, ret, NULL, returntext, 0, NULL);
  514. ret = SLAPI_PLUGIN_FAILURE;
  515. }
  516. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  517. "<= pam_passthru_preop\n");
  518. return ret;
  519. }
  520. static int
  521. pam_passthru_add_preop(Slapi_PBlock *pb)
  522. {
  523. return pam_passthru_preop(pb, LDAP_CHANGETYPE_ADD);
  524. }
  525. static int
  526. pam_passthru_mod_preop(Slapi_PBlock *pb)
  527. {
  528. return pam_passthru_preop(pb, LDAP_CHANGETYPE_MODIFY);
  529. }
  530. static int
  531. pam_passthru_del_preop(Slapi_PBlock *pb)
  532. {
  533. return pam_passthru_preop(pb, LDAP_CHANGETYPE_DELETE);
  534. }
  535. static int
  536. pam_passthru_modrdn_preop(Slapi_PBlock *pb)
  537. {
  538. return pam_passthru_preop(pb, LDAP_CHANGETYPE_MODDN);
  539. }
  540. /*
  541. * Post-op callback for dynamic config loading.
  542. */
  543. static int
  544. pam_passthru_postop(Slapi_PBlock *pb)
  545. {
  546. int ret = SLAPI_PLUGIN_SUCCESS;
  547. Slapi_DN *sdn = NULL;
  548. Slapi_DN *new_sdn = NULL;
  549. Slapi_Entry *e = NULL;
  550. int optype = SLAPI_OPERATION_NONE;
  551. int oprc = -1;
  552. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  553. "=> pam_passthru_postop\n");
  554. /* Make sure the operation succeeded and bail if it didn't. */
  555. slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &oprc);
  556. if (oprc != 0) {
  557. ret = oprc;
  558. goto bail;
  559. }
  560. /* Get the target SDN. */
  561. slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
  562. if (!sdn) {
  563. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  564. "pam_passthru_postop - Unable to fetch target SDN.\n");
  565. ret = SLAPI_PLUGIN_FAILURE;
  566. goto bail;
  567. }
  568. /* Check if this is a rename operation.
  569. * If so, we need to get the new DN. */
  570. slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &optype);
  571. if (optype == SLAPI_OPERATION_MODDN) {
  572. slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
  573. if (e) {
  574. new_sdn = slapi_entry_get_sdn(e);
  575. } else {
  576. slapi_log_error(SLAPI_LOG_ERR, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  577. "pam_passthru_postop - Unable to fetch post-op "
  578. "entry for rename operation.\n");
  579. ret = SLAPI_PLUGIN_FAILURE;
  580. goto bail;
  581. }
  582. }
  583. /* Check if the target is a config entry. If so, reload all of the config.
  584. * If this is a rename operation, we also need to see if the new DN is in
  585. * the config scope. */
  586. if (pam_passthru_dn_is_config(sdn) || (new_sdn && pam_passthru_dn_is_config(new_sdn))) {
  587. pam_passthru_load_config(1); /* skip validation, as it was done at preop */
  588. }
  589. slapi_log_error(SLAPI_LOG_TRACE, PAM_PASSTHRU_PLUGIN_SUBSYSTEM,
  590. "<= pam_passthru_postop\n");
  591. bail:
  592. return ret;
  593. }
  594. /*
  595. *
  596. * Deal with config locking
  597. *
  598. */
  599. void pam_passthru_read_lock()
  600. {
  601. slapi_rwlock_rdlock(g_pam_config_lock);
  602. }
  603. void pam_passthru_write_lock()
  604. {
  605. slapi_rwlock_wrlock(g_pam_config_lock);
  606. }
  607. void pam_passthru_unlock()
  608. {
  609. slapi_rwlock_unlock(g_pam_config_lock);
  610. }