nss_mc_common.c revision 0ed6114c6b2cc9d7e0c09842d19f0987e9ebbb4a
e9458b1a7a19a63aa4c179f9ab20f4d50681c168Jens Elkner * System Security Services Daemon. NSS client interface
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer * Copyright (C) Simo Sorce 2011
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer * This program is free software; you can redistribute it and/or modify
2eeec5240b424984e3ee26296da1eeab6c6d739eChristian Maeder * it under the terms of the GNU Lesser General Public License as
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer * published by the Free Software Foundation; either version 2.1 of the
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer * License, or (at your option) any later version.
7520452bb30b5abbd471f82352fc4c1c937e02c5Till Mossakowski * This program is distributed in the hope that it will be useful,
7520452bb30b5abbd471f82352fc4c1c937e02c5Till Mossakowski * but WITHOUT ANY WARRANTY; without even the implied warranty of
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer * GNU Lesser General Public License for more details.
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer * You should have received a copy of the GNU Lesser General Public License
d7aa4e1cbe00f7f3add4da911673b3b176b140c3Thiemo Wiedemeyer * along with this program. If not, see <http://www.gnu.org/licenses/>.
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer/* NSS interfaces to mmap cache */
aa21e7aa42fef563dea0cc77edbde76f66cdbe88Thiemo Wiedemeyer/* FIXME: hook up to library destructor to avoid leaks */
aa21e7aa42fef563dea0cc77edbde76f66cdbe88Thiemo Wiedemeyer/* FIXME: temporarily open passwd file on our own, later we will probably
8836fa284a241af325aa6f41234b5130b26ec4f9Thiemo Wiedemeyer * use socket passing from the main process */
8836fa284a241af325aa6f41234b5130b26ec4f9Thiemo Wiedemeyer/* FIXME: handle name upper/lower casing ? Maybe a flag passed down by
331603b37dec12e37e2e1df9634ef0f2c5c73ddfThiemo Wiedemeyer * sssd or a flag in sss_mc_header ? per domain ? */
1a389234e68da7c3d087b038307ed8c66fc6dc32Thiemo Wiedemeyer#define MEMCPY_WITH_BARRIERS(res, dest, src, len) \
f7b9d64160c23654b7288a3b0ee3e2b95af3e752Thiemo Wiedemeyererrno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx)
f7b9d64160c23654b7288a3b0ee3e2b95af3e752Thiemo Wiedemeyer /* retry barrier protected reading max 5 times then give up */
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyer sizeof(struct sss_mc_header));
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer /* record is consistent so we can proceed */
a7e5c17a679fa2dae5998cd04c7e9e06c05c8164Christian Maeder /* couldn't successfully read header we have to give up */
f7b9d64160c23654b7288a3b0ee3e2b95af3e752Thiemo Wiedemeyer /* first time we check the header, let's fill our own struct */
f7b9d64160c23654b7288a3b0ee3e2b95af3e752Thiemo Wiedemeyer ctx->data_table = MC_PTR_ADD(ctx->mmap_base, h.data_table);
0d0278c34a374b29c2d6c58b39b8b56e283d48e8Christian Maeder ctx->hash_table = MC_PTR_ADD(ctx->mmap_base, h.hash_table);
ddc662fdf0207eae2034d7b68ae5e2225c575207Thiemo Wiedemeyer ctx->data_table != MC_PTR_ADD(ctx->mmap_base, h.data_table) ||
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer ctx->hash_table != MC_PTR_ADD(ctx->mmap_base, h.hash_table) ||
d7aa4e1cbe00f7f3add4da911673b3b176b140c3Thiemo Wiedemeyerstatic void sss_nss_mc_destroy_ctx(struct sss_cli_mc_ctx *ctx)
32d98ca5e560cf6c1062a0463be4c350af32bed5Thiemo Wiedemeyer if ((ctx->mmap_base != NULL) && (ctx->mmap_size != 0)) {
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer memset(ctx, 0, sizeof(struct sss_cli_mc_ctx));
d7aa4e1cbe00f7f3add4da911673b3b176b140c3Thiemo Wiedemeyerstatic errno_t sss_nss_mc_init_ctx(const char *name,
d7aa4e1cbe00f7f3add4da911673b3b176b140c3Thiemo Wiedemeyer /* check if ctx is initialised by previous thread. */
0b8b26a22f136a9b2a8e99d655f6fe6b0b96008cThiemo Wiedemeyer ret = asprintf(&file, "%s/%s", SSS_NSS_MCACHE_DIR, name);
788bd3c33ec5aaeb90a1932c341ff837116410cfThiemo Wiedemeyer ctx->fd = sss_open_cloexec(file, O_RDONLY, &ret);
ea76e25262c3325f293fbdd6560f180ca18f9be4Thiemo Wiedemeyer ctx->mmap_base = mmap(NULL, ctx->mmap_size,
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyererrno_t sss_nss_mc_get_ctx(const char *name, struct sss_cli_mc_ctx *ctx)
aa21e7aa42fef563dea0cc77edbde76f66cdbe88Thiemo Wiedemeyer if (envval && strcasecmp(envval, "NO") == 0) {
92e96be605537638d75e9d3023ab698bd89cf889Thiemo Wiedemeyer __sync_add_and_fetch(&ctx->active_threads, 1);
92e96be605537638d75e9d3023ab698bd89cf889Thiemo Wiedemeyer __sync_add_and_fetch(&ctx->active_threads, 1);
aa21e7aa42fef563dea0cc77edbde76f66cdbe88Thiemo Wiedemeyer /* we need to safely destroy memory cache */
d9f20cf968e246ec283f0c09f60af4b47b174398Thiemo Wiedemeyer if (ctx->initialized == RECYCLED && ctx->active_threads == 0) {
239991d3955da0cfb760af4d506069446e1676b7Christian Maeder /* just one thread should call munmap */
39a2520d13a7d43f0c0fa71b94255c3f7c500005Christian Maeder /* In case of error, we will not touch mmapped area => decrement */
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyer __sync_sub_and_fetch(&ctx->active_threads, 1);
4014fb09362f3e38a91d7bb11b1484a4790e9297Thiemo Wiedemeyeruint32_t sss_nss_mc_hash(struct sss_cli_mc_ctx *ctx,
3e3efd4ce838940032e875e6d08712a177c9c1d0Thiemo Wiedemeyer return murmurhash3(key, len, ctx->seed) % MC_HT_ELEMS(ctx->ht_size);
239991d3955da0cfb760af4d506069446e1676b7Christian Maedererrno_t sss_nss_mc_get_record(struct sss_cli_mc_ctx *ctx,
788bd3c33ec5aaeb90a1932c341ff837116410cfThiemo Wiedemeyer /* try max 5 times */
788bd3c33ec5aaeb90a1932c341ff837116410cfThiemo Wiedemeyer rec = MC_SLOT_TO_PTR(ctx->data_table, slot, struct sss_mc_rec);
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyer /* fetch record length */
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyer /* record is inconsistent, retry */
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyer /* record has invalid length */
32d98ca5e560cf6c1062a0463be4c350af32bed5Thiemo Wiedemeyer /* we cannot access data directly, we must copy data and then
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyer * access the copy */
239991d3955da0cfb760af4d506069446e1676b7Christian Maeder MEMCPY_WITH_BARRIERS(copy_ok, copy_rec, rec, rec_len);
66fd8f017efdb8a6c862c3f1856dfaef90865dd5Thiemo Wiedemeyer /* we must check data is consistent again after the copy */
84ba39232a012abf2085c8a421ebce6abc52d56eThiemo Wiedemeyer /* record is consistent, use it */
84ba39232a012abf2085c8a421ebce6abc52d56eThiemo Wiedemeyer /* couldn't successfully read header we have to give up */
71654489020a03cf6ce9f2947f3da26a996f9c32Razvan Pascanu * returns strings froma a buffer.
71654489020a03cf6ce9f2947f3da26a996f9c32Razvan Pascanu * Call first time with *cookie set to null, then call again
44c1fff98bd6c54db237bef5030657d3f47058a5Thiemo Wiedemeyer * with the returned cookie.
1a389234e68da7c3d087b038307ed8c66fc6dc32Thiemo Wiedemeyer * On the last string the cookie will be reset to null and
1a389234e68da7c3d087b038307ed8c66fc6dc32Thiemo Wiedemeyer * all strings will have been returned.
8836fa284a241af325aa6f41234b5130b26ec4f9Thiemo Wiedemeyer * In case the last string is not zero terminated EINVAL is returned.
8836fa284a241af325aa6f41234b5130b26ec4f9Thiemo Wiedemeyererrno_t sss_nss_str_ptr_from_buffer(char **str, void **cookie,
a4e6fb26100f53e3b1e9f5b97c2e0a0c129294e5Christian Maeder p = *((char **)cookie);
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyer while (p < max) {
109b67ffce2bad83667e2f4a319d2d7f380f91afThiemo Wiedemeyer if (*p == '\0') {
53e76316f409f6b1b57ed3d2e5cb9cfe1cb511e5Thiemo Wiedemeyeruint32_t sss_nss_mc_next_slot_with_hash(struct sss_mc_rec *rec,
f7b9d64160c23654b7288a3b0ee3e2b95af3e752Thiemo Wiedemeyer /* it should never happen. */