ldapacl.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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. /* #define DBG_PRINT */
  42. #include <netsite.h>
  43. #include <base/rwlock.h>
  44. #include <base/ereport.h>
  45. #include <libaccess/acl.h>
  46. #include "aclpriv.h"
  47. #include <libaccess/aclproto.h>
  48. #include <libaccess/las.h>
  49. #include "aclutil.h"
  50. #include <ldaputil/errors.h>
  51. #include <ldaputil/certmap.h>
  52. #include <ldaputil/ldaputil.h>
  53. #include <ldaputil/dbconf.h>
  54. #include <ldaputil/ldapauth.h>
  55. #include <libaccess/authdb.h>
  56. #include <libaccess/ldapacl.h>
  57. #include <libaccess/usrcache.h>
  58. #include <libaccess/dbtlibaccess.h>
  59. #include <libaccess/aclglobal.h>
  60. #include <libaccess/aclerror.h>
  61. #define BIG_LINE 1024
  62. static int need_ldap_over_ssl = 0;
  63. static RWLOCK ldb_rwlock = (RWLOCK)0;
  64. void init_ldb_rwlock ()
  65. {
  66. ldb_rwlock = rwlock_Init();
  67. }
  68. void ldb_write_rwlock (LDAPDatabase_t *ldb, RWLOCK lock)
  69. {
  70. DBG_PRINT1("ldb_write_rwlock\n");
  71. /* Don't lock for local database -- let ldapsdk handle thread safety*/
  72. if (!ldapu_is_local_db(ldb))
  73. rwlock_WriteLock(lock);
  74. }
  75. void ldb_read_rwlock (LDAPDatabase_t *ldb, RWLOCK lock)
  76. {
  77. DBG_PRINT1("ldb_read_rwlock\n");
  78. /* Don't lock for local database -- let ldapsdk handle thread safety*/
  79. if (!ldapu_is_local_db(ldb))
  80. rwlock_ReadLock(lock);
  81. }
  82. void ldb_unlock_rwlock (LDAPDatabase_t *ldb, RWLOCK lock)
  83. {
  84. DBG_PRINT1("ldb_unlock_rwlock\n");
  85. /* we don't lock for local database */
  86. if (!ldapu_is_local_db(ldb))
  87. rwlock_Unlock(lock);
  88. }
  89. int ACL_NeedLDAPOverSSL ()
  90. {
  91. return need_ldap_over_ssl;
  92. }
  93. NSAPI_PUBLIC int parse_ldap_url (NSErr_t *errp, ACLDbType_t dbtype,
  94. const char *dbname, const char *url,
  95. PList_t plist, void **db)
  96. {
  97. LDAPDatabase_t *ldb;
  98. char *binddn = 0;
  99. char *bindpw = 0;
  100. int rv;
  101. *db = 0;
  102. if (!url || !*url) {
  103. nserrGenerate(errp, ACLERRINVAL, ACLERR5800, ACL_Program, 1, XP_GetAdminStr(DBT_ldapaclDatabaseUrlIsMissing));
  104. return -1;
  105. }
  106. if (!dbname || !*dbname) {
  107. nserrGenerate(errp, ACLERRINVAL, ACLERR5810, ACL_Program, 1, XP_GetAdminStr(DBT_ldapaclDatabaseNameIsMissing));
  108. return -1;
  109. }
  110. /* look for binddn and bindpw in the plist */
  111. if (plist) {
  112. PListFindValue(plist, LDAPU_ATTR_BINDDN, (void **)&binddn, NULL);
  113. PListFindValue(plist, LDAPU_ATTR_BINDPW, (void **)&bindpw, NULL);
  114. }
  115. rv = ldapu_url_parse(url, binddn, bindpw, &ldb);
  116. if (rv != LDAPU_SUCCESS) {
  117. nserrGenerate(errp, ACLERRINVAL, ACLERR5820, ACL_Program, 2, XP_GetAdminStr(DBT_ldapaclErrorParsingLdapUrl), ldapu_err2string(rv));
  118. return -1;
  119. }
  120. /* success */
  121. *db = ldb;
  122. /* Check if we need to do LDAP over SSL */
  123. if (!need_ldap_over_ssl) {
  124. need_ldap_over_ssl = ldb->use_ssl;
  125. }
  126. return 0;
  127. }
  128. int get_is_valid_password_basic_ldap (NSErr_t *errp, PList_t subject,
  129. PList_t resource, PList_t auth_info,
  130. PList_t global_auth, void *unused)
  131. {
  132. /* If the raw-user-name and raw-user-password attributes are present then
  133. * verify the password against the LDAP database.
  134. * Otherwise call AttrGetter for raw-user-name.
  135. */
  136. char *raw_user;
  137. char *raw_pw;
  138. char *userdn = 0;
  139. int rv;
  140. char *dbname;
  141. ACLDbType_t dbtype;
  142. LDAPDatabase_t *ldb;
  143. time_t *req_time = 0;
  144. pool_handle_t *subj_pool = PListGetPool(subject)
  145. DBG_PRINT1("get_is_valid_password_basic_ldap\n");
  146. rv = ACL_GetAttribute(errp, ACL_ATTR_RAW_USER, (void **)&raw_user,
  147. subject, resource, auth_info, global_auth);
  148. if (rv != LAS_EVAL_TRUE) {
  149. return rv;
  150. }
  151. rv = ACL_GetAttribute(errp, ACL_ATTR_RAW_PASSWORD, (void **)&raw_pw,
  152. subject, resource, auth_info, global_auth);
  153. if (rv != LAS_EVAL_TRUE) {
  154. return rv;
  155. }
  156. if (!raw_pw || !*raw_pw) {
  157. /* Null password is not allowed in LDAP since most LDAP servers let
  158. * the bind call succeed as anonymous login (with limited privileges).
  159. */
  160. return LAS_EVAL_FALSE;
  161. }
  162. /* Authenticate the raw_user and raw_pw against LDAP database. */
  163. rv = ACL_AuthInfoGetDbname(auth_info, &dbname);
  164. if (rv < 0) {
  165. char rv_str[16];
  166. sprintf(rv_str, "%d", rv);
  167. nserrGenerate(errp, ACLERRFAIL, ACLERR5830, ACL_Program, 2,
  168. XP_GetAdminStr(DBT_ldapaclUnableToGetDatabaseName), rv_str);
  169. return LAS_EVAL_FAIL;
  170. }
  171. rv = ACL_DatabaseFind(errp, dbname, &dbtype, (void **)&ldb);
  172. if (rv != LAS_EVAL_TRUE) {
  173. nserrGenerate(errp, ACLERRFAIL, ACLERR5840, ACL_Program, 2,
  174. XP_GetAdminStr(DBT_ldapaclUnableToGetParsedDatabaseName), dbname);
  175. return rv;
  176. }
  177. if (acl_usr_cache_enabled()) {
  178. /* avoid unnecessary system call to get time if cache is disabled */
  179. req_time = acl_get_req_time(resource);
  180. /* We have user name and password. */
  181. /* Check the cache to see if the password is valid */
  182. rv = acl_usr_cache_passwd_check(raw_user, dbname, raw_pw, *req_time,
  183. &userdn, subj_pool);
  184. }
  185. else {
  186. rv = LAS_EVAL_FALSE;
  187. }
  188. if (rv != LAS_EVAL_TRUE) {
  189. LDAPMessage *res = 0;
  190. const char *some_attrs[] = { "C", 0 };
  191. LDAP *ld;
  192. char *udn;
  193. /* Not found in the cache */
  194. /* Since we will bind with the user/password and other code relying on
  195. * ldb being bound as ldb->binddn and ldb->bindpw may fail. So block
  196. * them until we are done.
  197. */
  198. ldb_write_rwlock(ldb, ldb_rwlock);
  199. rv = ldapu_ldap_init_and_bind(ldb);
  200. if (rv != LDAPU_SUCCESS) {
  201. ldb_unlock_rwlock(ldb, ldb_rwlock);
  202. nserrGenerate(errp, ACLERRFAIL, ACLERR5850, ACL_Program, 2, XP_GetAdminStr(DBT_ldapaclCoudlntInitializeConnectionToLdap), ldapu_err2string(rv));
  203. return LAS_EVAL_FAIL;
  204. }
  205. /* LDAPU_REQ will reconnect & retry once if LDAP server went down */
  206. ld = ldb->ld;
  207. LDAPU_REQ(rv, ldb, ldapu_find_uid_attrs(ld, raw_user,
  208. ldb->basedn, some_attrs,
  209. 1, &res));
  210. if (rv == LDAPU_SUCCESS) {
  211. LDAPMessage *entry = ldap_first_entry(ld, res);
  212. userdn = ldap_get_dn(ld, entry);
  213. /* LDAPU_REQ will reconnect & retry once if LDAP server went down */
  214. LDAPU_REQ(rv, ldb, ldapu_auth_userdn_password(ld, userdn, raw_pw));
  215. /* Make sure we rebind with the server's DN
  216. * ignore errors from ldapu_ldap_rebind -- we will get the same
  217. * errors in subsequent calls to LDAP. Return status from the
  218. * above call is our only interest now.
  219. */
  220. ldapu_ldap_rebind(ldb);
  221. }
  222. if (res) ldap_msgfree(res);
  223. ldb_unlock_rwlock(ldb, ldb_rwlock);
  224. if (rv == LDAPU_FAILED || rv == LDAP_INVALID_CREDENTIALS) {
  225. /* user entry not found or incorrect password */
  226. if (userdn) ldap_memfree(userdn);
  227. return LAS_EVAL_FALSE;
  228. }
  229. else if (rv != LDAPU_SUCCESS) {
  230. /* some unexpected LDAP error */
  231. nserrGenerate(errp, ACLERRFAIL, ACLERR5860, ACL_Program, 2, XP_GetAdminStr(DBT_ldapaclPassworkCheckLdapError), ldapu_err2string(rv));
  232. if (userdn) ldap_memfree(userdn);
  233. return LAS_EVAL_FAIL;
  234. }
  235. /* Make an entry in the cache */
  236. if (acl_usr_cache_enabled()) {
  237. acl_usr_cache_insert(raw_user, dbname, userdn, raw_pw, 0, 0,
  238. *req_time);
  239. }
  240. udn = pool_strdup(subj_pool, userdn);
  241. ldap_memfree(userdn);
  242. userdn = udn;
  243. }
  244. PListInitProp(subject, ACL_ATTR_IS_VALID_PASSWORD_INDEX, ACL_ATTR_IS_VALID_PASSWORD, raw_user, 0);
  245. PListInitProp(subject, ACL_ATTR_USERDN_INDEX, ACL_ATTR_USERDN, userdn, 0);
  246. return LAS_EVAL_TRUE;
  247. }
  248. static int acl_grpcmpfn (const void *groupids, const char *group,
  249. const int len)
  250. {
  251. const char *token = (const char *)groupids;
  252. int tlen;
  253. char delim = ',';
  254. while((token = acl_next_token_len(token, delim, &tlen)) != NULL) {
  255. if (tlen > 0 && tlen == len && !strncmp(token, group, len))
  256. return LDAPU_SUCCESS;
  257. else if (tlen == 0 || 0 != (token = strchr(token+tlen, delim)))
  258. token++;
  259. else
  260. break;
  261. }
  262. return LDAPU_FAILED;
  263. }
  264. int get_user_ismember_ldap (NSErr_t *errp, PList_t subject,
  265. PList_t resource, PList_t auth_info,
  266. PList_t global_auth, void *unused)
  267. {
  268. int retval;
  269. int rv;
  270. char *userdn;
  271. char *groups;
  272. char *member_of = 0;
  273. LDAPDatabase_t *ldb;
  274. char *dbname;
  275. ACLDbType_t dbtype;
  276. DBG_PRINT1("get_user_ismember_ldap\n");
  277. rv = ACL_GetAttribute(errp, ACL_ATTR_USERDN, (void **)&userdn, subject,
  278. resource, auth_info, global_auth);
  279. if (rv != LAS_EVAL_TRUE) {
  280. return LAS_EVAL_FAIL;
  281. }
  282. rv = ACL_GetAttribute(errp, ACL_ATTR_GROUPS, (void **)&groups, subject,
  283. resource, auth_info, global_auth);
  284. if (rv != LAS_EVAL_TRUE) {
  285. return rv;
  286. }
  287. rv = ACL_AuthInfoGetDbname(auth_info, &dbname);
  288. if (rv < 0) {
  289. char rv_str[16];
  290. sprintf(rv_str, "%d", rv);
  291. nserrGenerate(errp, ACLERRINVAL, ACLERR5900, ACL_Program, 2, XP_GetAdminStr(DBT_GetUserIsMemberLdapUnabelToGetDatabaseName), rv_str);
  292. return rv;
  293. }
  294. rv = ACL_DatabaseFind(errp, dbname, &dbtype, (void **)&ldb);
  295. if (rv != LAS_EVAL_TRUE) {
  296. nserrGenerate(errp, ACLERRINVAL, ACLERR5910, ACL_Program, 2, XP_GetAdminStr(DBT_GetUserIsMemberLdapUnableToGetParsedDatabaseName), dbname);
  297. return rv;
  298. }
  299. ldb_read_rwlock(ldb, ldb_rwlock);
  300. rv = ldapu_ldap_init_and_bind(ldb);
  301. if (rv != LDAPU_SUCCESS) {
  302. ldb_unlock_rwlock(ldb, ldb_rwlock);
  303. nserrGenerate(errp, ACLERRFAIL, ACLERR5930, ACL_Program, 2,
  304. XP_GetAdminStr(DBT_GetUserIsMemberLdapCouldntInitializeConnectionToLdap), ldapu_err2string(rv));
  305. return LAS_EVAL_FAIL;
  306. }
  307. /* check if the user is member of any of the groups */
  308. /* LDAPU_REQ will reconnect & retry once if LDAP server went down */
  309. LDAPU_REQ(rv, ldb, ldapu_auth_userdn_groupids(ldb->ld,
  310. userdn,
  311. groups,
  312. acl_grpcmpfn,
  313. ldb->basedn,
  314. &member_of));
  315. ldb_unlock_rwlock(ldb, ldb_rwlock);
  316. if (rv == LDAPU_SUCCESS) {
  317. /* User is a member of one of the groups */
  318. if (member_of) {
  319. PListInitProp(subject, ACL_ATTR_USER_ISMEMBER_INDEX,
  320. ACL_ATTR_USER_ISMEMBER,
  321. pool_strdup(PListGetPool(subject), member_of), 0);
  322. retval = LAS_EVAL_TRUE;
  323. }
  324. else {
  325. /* This shouldn't happen */
  326. retval = LAS_EVAL_FALSE;
  327. }
  328. }
  329. else if (rv == LDAPU_FAILED) {
  330. /* User is not a member of any of the groups */
  331. retval = LAS_EVAL_FALSE;
  332. }
  333. else {
  334. /* unexpected LDAP error */
  335. nserrGenerate(errp, ACLERRFAIL, ACLERR5950, ACL_Program, 2,
  336. XP_GetAdminStr(DBT_GetUserIsMemberLdapError),
  337. ldapu_err2string(rv));
  338. retval = LAS_EVAL_FAIL;
  339. }
  340. return retval;
  341. }
  342. /* This function returns LDAPU error codes so that the caller can call
  343. * ldapu_err2string to get the error string.
  344. */
  345. int acl_map_cert_to_user (NSErr_t *errp, const char *dbname,
  346. LDAPDatabase_t *ldb, void *cert,
  347. PList_t resource, pool_handle_t *pool,
  348. char **user, char **userdn)
  349. {
  350. int rv;
  351. LDAPMessage *res;
  352. LDAPMessage *entry;
  353. char *uid;
  354. time_t *req_time = 0;
  355. if (acl_usr_cache_enabled()) {
  356. req_time = acl_get_req_time(resource);
  357. rv = acl_cert_cache_get_uid (cert, dbname, *req_time, user, userdn,
  358. pool);
  359. }
  360. else {
  361. rv = LAS_EVAL_FALSE;
  362. }
  363. if (rv != LAS_EVAL_TRUE) {
  364. /* Not found in the cache */
  365. ldb_read_rwlock(ldb, ldb_rwlock);
  366. rv = ldapu_ldap_init_and_bind(ldb);
  367. /* LDAPU_REQ will reconnect & retry once if LDAP server went down */
  368. /* it sets the variable rv */
  369. if (rv == LDAPU_SUCCESS) {
  370. LDAPU_REQ(rv, ldb, ldapu_cert_to_user(cert, ldb->ld, ldb->basedn,
  371. &res, &uid));
  372. if (rv == LDAPU_SUCCESS) {
  373. char *dn;
  374. *user = pool_strdup(pool, uid);
  375. if (!*user) rv = LDAPU_ERR_OUT_OF_MEMORY;
  376. free(uid);
  377. entry = ldap_first_entry(ldb->ld, res);
  378. dn = ldap_get_dn(ldb->ld, entry);
  379. if (acl_usr_cache_enabled()) {
  380. acl_cert_cache_insert (cert, dbname, *user, dn, *req_time);
  381. }
  382. *userdn = dn ? pool_strdup(pool, dn) : 0;
  383. if (!*userdn) rv = LDAPU_ERR_OUT_OF_MEMORY;
  384. ldap_memfree(dn);
  385. }
  386. if (res) ldap_msgfree(res);
  387. }
  388. ldb_unlock_rwlock(ldb, ldb_rwlock);
  389. }
  390. else {
  391. rv = LDAPU_SUCCESS;
  392. }
  393. return rv;
  394. }
  395. /*
  396. * ACL_LDAPDatabaseHandle -
  397. * Finds the internal structure representing the 'dbname'. If it is an LDAP
  398. * database, returns the 'LDAP *ld' pointer. Also, binds to the LDAP server.
  399. * The LDAP *ld handle can be used in calls to LDAP API.
  400. * Returns LAS_EVAL_TRUE if successful, otherwise logs an error in
  401. * LOG_SECURITY and returns LAS_EVAL_FAIL.
  402. */
  403. int ACL_LDAPDatabaseHandle (NSErr_t *errp, const char *dbname, LDAP **ld,
  404. char **basedn)
  405. {
  406. int rv;
  407. ACLDbType_t dbtype;
  408. void *db;
  409. LDAPDatabase_t *ldb;
  410. *ld = 0;
  411. if (!dbname || !*dbname) dbname = DBCONF_DEFAULT_DBNAME;
  412. /* Check if the ldb is already in the ACLUserLdbHash */
  413. ldb = (LDAPDatabase_t *)PR_HashTableLookup(ACLUserLdbHash, dbname);
  414. if (!ldb) {
  415. rv = ACL_DatabaseFind(errp, dbname, &dbtype, &db);
  416. if (rv != LAS_EVAL_TRUE) {
  417. nserrGenerate(errp, ACLERRINVAL, ACLERR6000, ACL_Program, 2, XP_GetAdminStr(DBT_LdapDatabaseHandleNotARegisteredDatabase), dbname);
  418. return LAS_EVAL_FAIL;
  419. }
  420. if (!ACL_DbTypeIsEqual(errp, dbtype, ACL_DbTypeLdap)) {
  421. /* Not an LDAP database -- error */
  422. nserrGenerate(errp, ACLERRINVAL, ACLERR6010, ACL_Program, 2, XP_GetAdminStr(DBT_LdapDatabaseHandleNotAnLdapDatabase), dbname);
  423. return LAS_EVAL_FAIL;
  424. }
  425. ldb = ldapu_copy_LDAPDatabase_t((LDAPDatabase_t *)db);
  426. if (!ldb) {
  427. /* Not an LDAP database -- error */
  428. nserrGenerate(errp, ACLERRNOMEM, ACLERR6020, ACL_Program, 1, XP_GetAdminStr(DBT_LdapDatabaseHandleOutOfMemory));
  429. return LAS_EVAL_FAIL;
  430. }
  431. PR_HashTableAdd(ACLUserLdbHash, PERM_STRDUP(dbname), ldb);
  432. }
  433. if (!ldb->ld) {
  434. rv = ldapu_ldap_init_and_bind(ldb);
  435. if (rv != LDAPU_SUCCESS) {
  436. nserrGenerate(errp, ACLERRFAIL, ACLERR6030, ACL_Program, 2, XP_GetAdminStr(DBT_LdapDatabaseHandleCouldntInitializeConnectionToLdap), ldapu_err2string(rv));
  437. return LAS_EVAL_FAIL;
  438. }
  439. }
  440. /*
  441. * Force the rebind -- we don't know whether the customer has used this ld
  442. * to bind as somebody else. It will also check if the LDAP server is up
  443. * and running, reestablish the connection if the LDAP server has rebooted
  444. * since it was last used.
  445. */
  446. rv = ldapu_ldap_rebind(ldb);
  447. if (rv != LDAPU_SUCCESS) {
  448. nserrGenerate(errp, ACLERRFAIL, ACLERR6040, ACL_Program, 2, XP_GetAdminStr(DBT_LdapDatabaseHandleCouldntBindToLdapServer), ldapu_err2string(rv));
  449. return LAS_EVAL_FAIL;
  450. }
  451. *ld = ldb->ld;
  452. if (basedn) {
  453. /* They asked for the basedn too */
  454. *basedn = PERM_STRDUP(ldb->basedn);
  455. }
  456. return LAS_EVAL_TRUE;
  457. }
  458. int get_userdn_ldap (NSErr_t *errp, PList_t subject,
  459. PList_t resource, PList_t auth_info,
  460. PList_t global_auth, void *unused)
  461. {
  462. char *uid;
  463. char *dbname;
  464. char *userdn;
  465. time_t *req_time = 0;
  466. pool_handle_t *subj_pool = PListGetPool(subject);
  467. int rv;
  468. rv = ACL_GetAttribute(errp, ACL_ATTR_USER, (void **)&uid, subject,
  469. resource, auth_info, global_auth);
  470. if (rv != LAS_EVAL_TRUE) {
  471. return LAS_EVAL_FAIL;
  472. }
  473. /* The getter for ACL_ATTR_USER may have put the USERDN on the PList */
  474. rv = PListGetValue(subject, ACL_ATTR_USERDN_INDEX, (void **)&userdn, NULL);
  475. if (rv >= 0) {
  476. /* Nothing to do */
  477. return LAS_EVAL_TRUE;
  478. }
  479. rv = ACL_AuthInfoGetDbname(auth_info, &dbname);
  480. if (rv < 0) {
  481. char rv_str[16];
  482. sprintf(rv_str, "%d", rv);
  483. nserrGenerate(errp, ACLERRFAIL, ACLERR5830, ACL_Program, 2,
  484. XP_GetAdminStr(DBT_ldapaclUnableToGetDatabaseName), rv_str);
  485. return LAS_EVAL_FAIL;
  486. }
  487. /* Check if the userdn is available in the usr_cache */
  488. if (acl_usr_cache_enabled()) {
  489. /* avoid unnecessary system call to get time if cache is disabled */
  490. req_time = acl_get_req_time(resource);
  491. rv = acl_usr_cache_get_userdn(uid, dbname, *req_time, &userdn,
  492. subj_pool);
  493. }
  494. else {
  495. rv = LAS_EVAL_FALSE;
  496. }
  497. if (rv == LAS_EVAL_TRUE) {
  498. /* Found in the cache */
  499. PListInitProp(subject, ACL_ATTR_USERDN_INDEX, ACL_ATTR_USERDN,
  500. userdn, 0);
  501. }
  502. else {
  503. ACLDbType_t dbtype;
  504. LDAPDatabase_t *ldb = 0;
  505. /* Perform LDAP lookup */
  506. rv = ACL_DatabaseFind(errp, dbname, &dbtype, (void **)&ldb);
  507. if (rv != LAS_EVAL_TRUE) {
  508. nserrGenerate(errp, ACLERRFAIL, ACLERR5840, ACL_Program, 2,
  509. XP_GetAdminStr(DBT_ldapaclUnableToGetParsedDatabaseName), dbname);
  510. return rv;
  511. }
  512. ldb_read_rwlock(ldb, ldb_rwlock);
  513. rv = ldapu_ldap_init_and_bind(ldb);
  514. if (rv != LDAPU_SUCCESS) {
  515. ldb_unlock_rwlock(ldb, ldb_rwlock);
  516. nserrGenerate(errp, ACLERRFAIL, ACLERR5850, ACL_Program, 2, XP_GetAdminStr(DBT_ldapaclCoudlntInitializeConnectionToLdap), ldapu_err2string(rv));
  517. return LAS_EVAL_FAIL;
  518. }
  519. LDAPU_REQ(rv, ldb, ldapu_find_userdn(ldb->ld, uid, ldb->basedn,
  520. &userdn));
  521. ldb_unlock_rwlock(ldb, ldb_rwlock);
  522. if (rv == LDAPU_SUCCESS) {
  523. /* Found it. Store it in the cache also. */
  524. PListInitProp(subject, ACL_ATTR_USERDN_INDEX, ACL_ATTR_USERDN,
  525. pool_strdup(subj_pool, userdn), 0);
  526. if (acl_usr_cache_enabled()) {
  527. acl_usr_cache_set_userdn(uid, dbname, userdn, *req_time);
  528. }
  529. ldapu_free(userdn);
  530. rv = LAS_EVAL_TRUE;
  531. }
  532. else if (rv == LDAPU_FAILED) {
  533. /* Not found but not an error */
  534. rv = LAS_EVAL_FALSE;
  535. }
  536. else {
  537. /* some unexpected LDAP error */
  538. nserrGenerate(errp, ACLERRFAIL, ACLERR5860, ACL_Program, 2, XP_GetAdminStr(DBT_ldapaclPassworkCheckLdapError), ldapu_err2string(rv));
  539. rv = LAS_EVAL_FAIL;
  540. }
  541. }
  542. return rv;
  543. }
  544. /* Attr getter for LDAP database to check if the user exists */
  545. int get_user_exists_ldap (NSErr_t *errp, PList_t subject,
  546. PList_t resource, PList_t auth_info,
  547. PList_t global_auth, void *unused)
  548. {
  549. int rv;
  550. char *user;
  551. char *userdn;
  552. /* See if the userdn is already available */
  553. rv = PListGetValue(subject, ACL_ATTR_USERDN_INDEX, (void **)&userdn, NULL);
  554. if (rv >= 0) {
  555. /* Check if the DN is still valid against the database */
  556. /* Get the database name */
  557. char *dbname;
  558. ACLDbType_t dbtype;
  559. LDAPDatabase_t *ldb = 0;
  560. LDAPMessage *res;
  561. const char *some_attrs[] = { "c", 0 };
  562. rv = ACL_AuthInfoGetDbname(auth_info, &dbname);
  563. if (rv < 0) {
  564. char rv_str[16];
  565. sprintf(rv_str, "%d", rv);
  566. nserrGenerate(errp, ACLERRFAIL, ACLERR5830, ACL_Program, 2,
  567. XP_GetAdminStr(DBT_ldapaclUnableToGetDatabaseName), rv_str);
  568. return LAS_EVAL_FAIL;
  569. }
  570. /* Perform LDAP lookup */
  571. rv = ACL_DatabaseFind(errp, dbname, &dbtype, (void **)&ldb);
  572. if (rv != LAS_EVAL_TRUE) {
  573. nserrGenerate(errp, ACLERRFAIL, ACLERR5840, ACL_Program, 2,
  574. XP_GetAdminStr(DBT_ldapaclUnableToGetParsedDatabaseName), dbname);
  575. return rv;
  576. }
  577. ldb_read_rwlock(ldb, ldb_rwlock);
  578. rv = ldapu_ldap_init_and_bind(ldb);
  579. if (rv != LDAPU_SUCCESS) {
  580. ldb_unlock_rwlock(ldb, ldb_rwlock);
  581. nserrGenerate(errp, ACLERRFAIL, ACLERR5850, ACL_Program, 2, XP_GetAdminStr(DBT_ldapaclCoudlntInitializeConnectionToLdap), ldapu_err2string(rv));
  582. return LAS_EVAL_FAIL;
  583. }
  584. LDAPU_REQ(rv, ldb, ldapu_find (ldb->ld, ldb->basedn, LDAP_SCOPE_BASE,
  585. NULL, some_attrs, 1, &res));
  586. ldb_unlock_rwlock(ldb, ldb_rwlock);
  587. if (rv == LDAPU_SUCCESS) {
  588. /* Found it. */
  589. rv = LAS_EVAL_TRUE;
  590. }
  591. else if (rv == LDAPU_FAILED) {
  592. /* Not found but not an error */
  593. rv = LAS_EVAL_FALSE;
  594. }
  595. else {
  596. /* some unexpected LDAP error */
  597. nserrGenerate(errp, ACLERRFAIL, ACLERR5860, ACL_Program, 2, XP_GetAdminStr(DBT_ldapaclPassworkCheckLdapError), ldapu_err2string(rv));
  598. rv = LAS_EVAL_FAIL;
  599. }
  600. }
  601. else {
  602. /* If the DN doesn't exist, should we just return an error ? */
  603. /* If yes, we don't need rest of the code */
  604. /* If we don't have a DN, we must have a user at least */
  605. rv = PListGetValue(subject, ACL_ATTR_USER_INDEX, (void **)&user, NULL);
  606. if (rv < 0) {
  607. /* We don't even have a user name */
  608. return LAS_EVAL_FAIL;
  609. }
  610. rv = ACL_GetAttribute(errp, ACL_ATTR_USERDN, (void **)&userdn, subject,
  611. resource, auth_info, global_auth);
  612. }
  613. /* If we can get the userdn then the user exists */
  614. if (rv == LAS_EVAL_TRUE) {
  615. PListInitProp(subject, ACL_ATTR_USER_EXISTS_INDEX,
  616. ACL_ATTR_USER_EXISTS, userdn, 0);
  617. }
  618. return rv;
  619. }
  620. /* acl_user_exists - */
  621. /* Function to check if the user still exists */
  622. /* This function works for all kinds of databases */
  623. /* Returns 0 on success and -ve value on failure */
  624. NSAPI_PUBLIC int acl_user_exists (const char *user, const char *userdn,
  625. const char *dbname, const int logerr)
  626. {
  627. NSErr_t err = NSERRINIT;
  628. NSErr_t *errp = &err;
  629. pool_handle_t *pool = 0;
  630. time_t *req_time = 0;
  631. PList_t subject = 0;
  632. PList_t resource = 0;
  633. PList_t auth_info = 0;
  634. PList_t global_auth = NULL;
  635. int rv = 0;
  636. /* Check if the userdn is available in the usr_cache */
  637. if (acl_usr_cache_enabled() && userdn) {
  638. /* avoid unnecessary system call to get time if cache is disabled */
  639. req_time = (time_t *)MALLOC(sizeof(time_t));
  640. if (req_time) {
  641. time(req_time);
  642. rv = acl_usr_cache_userdn_check(user, dbname, userdn, *req_time);
  643. FREE((void *)req_time);
  644. }
  645. if (rv == LAS_EVAL_TRUE)
  646. {
  647. /* Found in the cache with the same DN */
  648. return 0;
  649. }
  650. }
  651. pool = pool_create();
  652. subject = PListCreate(pool, ACL_ATTR_INDEX_MAX, 0, 0);
  653. resource = PListCreate(pool, ACL_ATTR_INDEX_MAX, 0, 0);
  654. auth_info = PListCreate(pool, ACL_ATTR_INDEX_MAX, 0, 0);
  655. if (!pool || !subject || !resource || !auth_info) {
  656. /* ran out of memory */
  657. goto no_mem;
  658. }
  659. /* store a pointer to the user rather than a copy */
  660. rv = PListInitProp(subject, ACL_ATTR_USER_INDEX, ACL_ATTR_USER,
  661. user, 0);
  662. if (rv < 0) { /* Plist error */ goto plist_err; }
  663. if (userdn && *userdn) {
  664. /* store a pointer to the userdn rather than a copy */
  665. rv = PListInitProp(subject, ACL_ATTR_USERDN_INDEX, ACL_ATTR_USERDN,
  666. userdn, 0);
  667. if (rv < 0) { /* Plist error */ goto plist_err; }
  668. }
  669. /* store the cached dbname on auth_info */
  670. rv = ACL_AuthInfoSetDbname(errp, auth_info, dbname);
  671. if (rv < 0) { /* auth_info error */ goto err; }
  672. rv = ACL_GetAttribute(errp, ACL_ATTR_USER_EXISTS, (void **)&user,
  673. subject, resource, auth_info, global_auth);
  674. if (rv == LAS_EVAL_TRUE) {
  675. /* User still exists */
  676. rv = 0;
  677. }
  678. else if (rv == LAS_EVAL_FALSE) {
  679. /* User doesn't exist anymore */
  680. nserrGenerate(errp, ACLERRFAIL, 5880, ACL_Program, 2, XP_GetAdminStr(DBT_AclUserExistsNot), user);
  681. goto err;
  682. }
  683. else {
  684. /* Unexpected error while checking the existence of the user */
  685. goto err;
  686. }
  687. goto done;
  688. plist_err:
  689. nserrGenerate(errp, ACLERRFAIL, 5890, ACL_Program, 1, XP_GetAdminStr(DBT_AclUserPlistError));
  690. goto err;
  691. no_mem:
  692. nserrGenerate(errp, ACLERRNOMEM, 5870, ACL_Program, 1, XP_GetAdminStr(DBT_AclUserExistsOutOfMemory));
  693. goto err;
  694. err:
  695. if (logerr) {
  696. /* Unexpected error while checking the existence of the user */
  697. char buf[BIG_LINE];
  698. /* generate error message (upto depth 6) into buf */
  699. aclErrorFmt(errp, buf, BIG_LINE, 6);
  700. ereport(LOG_SECURITY, "Error while checking the existence of user: %s", buf);
  701. }
  702. nserrDispose(errp);
  703. rv = -1;
  704. done:
  705. /* Destroy the PLists & the pool */
  706. if (subject) PListDestroy(subject);
  707. if (resource) PListDestroy(resource);
  708. if (auth_info) PListDestroy(auth_info);
  709. if (pool) pool_destroy(pool);
  710. return rv;
  711. }