ldapacl.cpp 25 KB

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