ldapacl.cpp 23 KB

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