/*
* System Security Services Daemon. NSS client interface
*
* Copyright (C) Simo Sorce 2007
*
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* GROUP database NSS interface */
#include <nss.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "sss_cli.h"
#include "nss_mc.h"
#include "nss_common.h"
static struct sss_nss_getgrent_data {
static void sss_nss_getgrent_data_clean(void)
{
}
sss_nss_getgrent_data.len = 0;
sss_nss_getgrent_data.ptr = 0;
}
enum sss_nss_gr_type {
};
static struct sss_nss_getgr_data {
union {
char *grname;
} id;
{
}
if (freebuf) {
}
}
enum sss_nss_gr_type type,
int *errnop)
{
bool freebuf = true;
int ret = 0;
goto done;
}
switch (type) {
case GETGR_NAME:
if (ret != 0) {
goto done;
}
break;
case GETGR_GID:
goto done;
}
break;
default:
goto done;
}
/* ok we have it, remove from cache and pass back to the caller */
/* prevent _clean() from freeing the buffer */
freebuf = false;
done:
return status;
}
/* this function always takes ownership of repbuf and NULLs it before
* returning */
enum sss_nss_gr_type type,
{
int ret = 0;
switch (type) {
case GETGR_NAME:
goto done;
}
goto done;
}
break;
case GETGR_GID:
if (gid == 0) {
goto done;
}
break;
default:
goto done;
}
done:
if (ret) {
sss_nss_getgr_data_clean(true);
}
}
/* GETGRNAM Request:
*
* 0-X: string with name
*
* GERTGRGID Request:
*
* 0-7: 32bit number with gid
*
* INITGROUPS Request:
*
* 0-3: 32bit number with gid
* 4-7: 32bit unsigned with max num of entries
*
* Replies:
*
* 0-3: 32bit unsigned number of results
* For each result (64bit padded?):
* 0-3: 32bit number gid
* 4-7: 32bit unsigned number of members
* 8-X: sequence of 0 terminated strings (name, passwd, mem..)
*
* FIXME: do we need to pad so that each result is 32 bit aligned?
*/
{
char *sbuf;
uint32_t c;
return EBADMSG;
}
i = 0;
NULL);
NULL);
/* Make sure pr->buffer[i+pad] is aligned to sizeof(char *) */
pad = PADDING_SIZE(i, char *);
/* now members */
return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */
}
ptmem += i;
for (l = 0; l < mem_num; l++) {
&glen);
}
return 0;
}
/* INITGROUP Reply:
*
* 0-3: 32bit unsigned number of results
* For each result:
* 0-4: 32bit number with gid
*/
int *errnop)
{
long int l, max_ret;
int ret;
if (ret != 0) {
return NSS_STATUS_NOTFOUND;
}
switch (ret) {
case 0:
*errnop = 0;
return NSS_STATUS_SUCCESS;
case ERANGE:
return NSS_STATUS_TRYAGAIN;
case ENOENT:
/* fall through, we need to actively ask the parent
* if no entry is found */
break;
default:
/* if using the mmapped cache failed,
* fall back to socket based comms */
break;
}
sss_nss_lock();
/* previous thread might already initialize entry in mmap cache */
switch (ret) {
case 0:
*errnop = 0;
goto out;
case ERANGE:
goto out;
case ENOENT:
/* fall through, we need to actively ask the parent
* if no entry is found */
break;
default:
/* if using the mmapped cache failed,
* fall back to socket based comms */
break;
}
if (nret != NSS_STATUS_SUCCESS) {
goto out;
}
/* no results if not found */
if (num_ret == 0) {
goto out;
}
/* check we have enough space in the buffer */
long int newsize;
}
if (!newgroups) {
goto out;
}
}
/* Skip first two 32 bit values (number of results and
* reserved padding) */
for (l = 0; l < max_ret; l++) {
&buf_index);
*start += 1;
}
out:
return nret;
}
{
int ret;
/* Caught once glibc passing in buffer == 0x0 */
return NSS_STATUS_TRYAGAIN;
}
if (ret != 0) {
return NSS_STATUS_NOTFOUND;
}
switch (ret) {
case 0:
*errnop = 0;
return NSS_STATUS_SUCCESS;
case ERANGE:
return NSS_STATUS_TRYAGAIN;
case ENOENT:
/* fall through, we need to actively ask the parent
* if no entry is found */
break;
default:
/* if using the mmapped cache failed,
* fall back to socket based comms */
break;
}
sss_nss_lock();
/* previous thread might already initialize entry in mmap cache */
switch (ret) {
case 0:
*errnop = 0;
goto out;
case ERANGE:
goto out;
case ENOENT:
/* fall through, we need to actively ask the parent
* if no entry is found */
break;
default:
/* if using the mmapped cache failed,
* fall back to socket based comms */
break;
}
if (nret == NSS_STATUS_NOTFOUND) {
}
if (nret != NSS_STATUS_SUCCESS) {
goto out;
}
/* Get number of results from repbuf. */
/* no results if not found */
if (num_results == 0) {
goto out;
}
/* only 1 result is accepted for this function */
if (num_results != 1) {
goto out;
}
} else {
}
if (ret) {
goto out;
}
out:
return nret;
}
{
int ret;
/* Caught once glibc passing in buffer == 0x0 */
return NSS_STATUS_TRYAGAIN;
}
switch (ret) {
case 0:
*errnop = 0;
return NSS_STATUS_SUCCESS;
case ERANGE:
return NSS_STATUS_TRYAGAIN;
case ENOENT:
/* fall through, we need to actively ask the parent
* if no entry is found */
break;
default:
/* if using the mmapped cache failed,
* fall back to socket based comms */
break;
}
sss_nss_lock();
/* previous thread might already initialize entry in mmap cache */
switch (ret) {
case 0:
*errnop = 0;
goto out;
case ERANGE:
goto out;
case ENOENT:
/* fall through, we need to actively ask the parent
* if no entry is found */
break;
default:
/* if using the mmapped cache failed,
* fall back to socket based comms */
break;
}
if (nret == NSS_STATUS_NOTFOUND) {
}
if (nret != NSS_STATUS_SUCCESS) {
goto out;
}
/* Get number of results from repbuf. */
/* no results if not found */
if (num_results == 0) {
goto out;
}
/* only 1 result is accepted for this function */
if (num_results != 1) {
goto out;
}
} else {
}
if (ret) {
goto out;
}
out:
return nret;
}
{
int errnop;
sss_nss_lock();
/* make sure we do not have leftovers, and release memory */
if (nret != NSS_STATUS_SUCCESS) {
}
return nret;
}
int *errnop)
{
int ret;
/* Caught once glibc passing in buffer == 0x0 */
return NSS_STATUS_TRYAGAIN;
}
/* if there are leftovers return the next one */
if (ret) {
return NSS_STATUS_TRYAGAIN;
}
/* advance buffer pointer */
return NSS_STATUS_SUCCESS;
}
/* release memory if any */
/* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */
if (nret != NSS_STATUS_SUCCESS) {
return nret;
}
/* Get number of results from repbuf. */
/* no results if not found */
return NSS_STATUS_NOTFOUND;
}
/* call again ourselves, this will return the first result */
}
{
sss_nss_lock();
return nret;
}
{
int errnop;
sss_nss_lock();
/* make sure we do not have leftovers, and release memory */
if (nret != NSS_STATUS_SUCCESS) {
}
return nret;
}