|
Packit |
6bd9ab |
/*
|
|
Packit |
6bd9ab |
common.h - common functions for NSS lookups
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
Copyright (C) 2006 West Consulting
|
|
Packit |
6bd9ab |
Copyright (C) 2006-2015 Arthur de Jong
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
This library is free software; you can redistribute it and/or
|
|
Packit |
6bd9ab |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6bd9ab |
License as published by the Free Software Foundation; either
|
|
Packit |
6bd9ab |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
This library is distributed in the hope that it will be useful,
|
|
Packit |
6bd9ab |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6bd9ab |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6bd9ab |
Lesser General Public License for more details.
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6bd9ab |
License along with this library; if not, write to the Free Software
|
|
Packit |
6bd9ab |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
6bd9ab |
02110-1301 USA
|
|
Packit |
6bd9ab |
*/
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#ifndef NSS__COMMON_H
|
|
Packit |
6bd9ab |
#define NSS__COMMON_H 1
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#include <stdio.h>
|
|
Packit |
6bd9ab |
#include <stdlib.h>
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#include "nslcd.h"
|
|
Packit |
6bd9ab |
#include "common/nslcd-prot.h"
|
|
Packit |
6bd9ab |
#include "compat/attrs.h"
|
|
Packit |
6bd9ab |
#include "compat/nss_compat.h"
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#ifdef NSS_FLAVOUR_SOLARIS
|
|
Packit |
6bd9ab |
#include "solnss.h"
|
|
Packit |
6bd9ab |
#endif /* NSS_FLAVOUR_SOLARIS */
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* If not TLS (thread local storage) is available on the platform
|
|
Packit |
6bd9ab |
don't use it. This should not be a problem on most platforms because
|
|
Packit |
6bd9ab |
get*ent() is not expected to be thread-safe (at least not on Glibc). */
|
|
Packit |
6bd9ab |
#ifndef TLS
|
|
Packit |
6bd9ab |
#define TLS
|
|
Packit |
6bd9ab |
#endif /* not TLS */
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* skip timeout determines the maximum time to wait when closing the
|
|
Packit |
6bd9ab |
connection and reading whatever data that is available */
|
|
Packit |
6bd9ab |
#define SKIP_TIMEOUT 500
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* These are macros for handling read and write problems, they are
|
|
Packit |
6bd9ab |
NSS specific due to the return code so are defined here. They
|
|
Packit |
6bd9ab |
genrally close the open file, set an error code and return with
|
|
Packit |
6bd9ab |
an error status. */
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* Macro is called to handle errors in opening a client connection. */
|
|
Packit |
6bd9ab |
#define ERROR_OUT_OPENERROR \
|
|
Packit |
6bd9ab |
*errnop = ENOENT; \
|
|
Packit |
6bd9ab |
return (errno == EAGAIN) ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* Macro is called to handle errors on read operations. */
|
|
Packit |
6bd9ab |
#define ERROR_OUT_READERROR(fp) \
|
|
Packit |
6bd9ab |
(void)tio_close(fp); \
|
|
Packit |
6bd9ab |
fp = NULL; \
|
|
Packit |
6bd9ab |
*errnop = ENOENT; \
|
|
Packit |
6bd9ab |
return NSS_STATUS_UNAVAIL;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* Macro is called to handle problems with too small a buffer.
|
|
Packit |
6bd9ab |
This triggers the caller to call the function with a larger
|
|
Packit |
6bd9ab |
buffer (see NSS_GETENT below). */
|
|
Packit |
6bd9ab |
#define ERROR_OUT_BUFERROR(fp) \
|
|
Packit |
6bd9ab |
*errnop = ERANGE; \
|
|
Packit |
6bd9ab |
return NSS_STATUS_TRYAGAIN;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* This macro is called if there was a problem with a write
|
|
Packit |
6bd9ab |
operation. */
|
|
Packit |
6bd9ab |
#define ERROR_OUT_WRITEERROR(fp) \
|
|
Packit |
6bd9ab |
ERROR_OUT_READERROR(fp)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* This macro is called if the read status code is not
|
|
Packit |
6bd9ab |
NSLCD_RESULT_BEGIN. */
|
|
Packit |
6bd9ab |
#define ERROR_OUT_NOSUCCESS(fp) \
|
|
Packit |
6bd9ab |
(void)tio_close(fp); \
|
|
Packit |
6bd9ab |
fp = NULL; \
|
|
Packit |
6bd9ab |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* These are some general macros that are used to build parts of the
|
|
Packit |
6bd9ab |
genral macros below. */
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* check to see if we should answer NSS requests */
|
|
Packit |
6bd9ab |
#define NSS_AVAILCHECK \
|
|
Packit |
6bd9ab |
if (!NSS_NAME(enablelookups)) \
|
|
Packit |
6bd9ab |
return NSS_STATUS_UNAVAIL;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#ifdef NSS_FLAVOUR_GLIBC
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* extra definitions we need (nothing for Glibc) */
|
|
Packit |
6bd9ab |
#define NSS_EXTRA_DEFS ;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* check validity of passed buffer (Glibc flavour) */
|
|
Packit |
6bd9ab |
#define NSS_BUFCHECK \
|
|
Packit |
6bd9ab |
if (buffer == NULL) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
*errnop = EINVAL; \
|
|
Packit |
6bd9ab |
return NSS_STATUS_UNAVAIL; \
|
|
Packit |
6bd9ab |
} \
|
|
Packit |
6bd9ab |
if (buflen == 0) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
*errnop = ERANGE; \
|
|
Packit |
6bd9ab |
return NSS_STATUS_TRYAGAIN; \
|
|
Packit |
6bd9ab |
}
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#endif /* NSS_FLAVOUR_GLIBC */
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* The following macros to automatically generate get..byname(),
|
|
Packit |
6bd9ab |
get..bynumber(), setent(), getent() and endent() function
|
|
Packit |
6bd9ab |
bodies. These functions have very common code so this can
|
|
Packit |
6bd9ab |
easily be reused. */
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* This is a generic get..by..() generation macro. The action
|
|
Packit |
6bd9ab |
parameter is the NSLCD_ACTION_.. action, the writefn is the
|
|
Packit |
6bd9ab |
operation for writing the parameters and readfn is the function
|
|
Packit |
6bd9ab |
name for reading a single result entry. The function is assumed
|
|
Packit |
6bd9ab |
to have result, buffer, buflen and errnop parameters that define
|
|
Packit |
6bd9ab |
the result structure, the user buffer with length and the
|
|
Packit |
6bd9ab |
errno to return. This macro should be called through some of
|
|
Packit |
6bd9ab |
the customized ones below. */
|
|
Packit |
6bd9ab |
#define NSS_GETONE(action, writefn, readfn) \
|
|
Packit |
6bd9ab |
TFILE *fp; \
|
|
Packit |
6bd9ab |
int32_t tmpint32; \
|
|
Packit |
6bd9ab |
nss_status_t retv; \
|
|
Packit |
6bd9ab |
NSS_EXTRA_DEFS; \
|
|
Packit |
6bd9ab |
NSS_AVAILCHECK; \
|
|
Packit |
6bd9ab |
NSS_BUFCHECK; \
|
|
Packit |
6bd9ab |
/* open socket and write request */ \
|
|
Packit |
6bd9ab |
NSLCD_REQUEST(fp, action, writefn); \
|
|
Packit |
6bd9ab |
/* read response */ \
|
|
Packit |
6bd9ab |
READ_RESPONSE_CODE(fp); \
|
|
Packit |
6bd9ab |
retv = readfn; \
|
|
Packit |
6bd9ab |
/* close socket and we're done */ \
|
|
Packit |
6bd9ab |
if ((retv == NSS_STATUS_SUCCESS) || (retv == NSS_STATUS_TRYAGAIN)) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
(void)tio_skipall(fp, SKIP_TIMEOUT); \
|
|
Packit |
6bd9ab |
(void)tio_close(fp); \
|
|
Packit |
6bd9ab |
} \
|
|
Packit |
6bd9ab |
return retv;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* This macro generates a simple setent() function body. This closes any
|
|
Packit |
6bd9ab |
open streams so that NSS_GETENT() can open a new file. */
|
|
Packit |
6bd9ab |
#define NSS_SETENT(fp) \
|
|
Packit |
6bd9ab |
NSS_AVAILCHECK; \
|
|
Packit |
6bd9ab |
if (fp != NULL) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
(void)tio_close(fp); \
|
|
Packit |
6bd9ab |
fp = NULL; \
|
|
Packit |
6bd9ab |
} \
|
|
Packit |
6bd9ab |
return NSS_STATUS_SUCCESS;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* This macro generates a getent() function body. If the stream is not yet
|
|
Packit |
6bd9ab |
open, a new one is opened, a request is written and a check is done for
|
|
Packit |
6bd9ab |
a response header. A single entry is read with the readfn() function. */
|
|
Packit |
6bd9ab |
#define NSS_GETENT(fp, action, readfn) \
|
|
Packit |
6bd9ab |
int32_t tmpint32; \
|
|
Packit |
6bd9ab |
nss_status_t retv; \
|
|
Packit |
6bd9ab |
NSS_EXTRA_DEFS; \
|
|
Packit |
6bd9ab |
NSS_AVAILCHECK; \
|
|
Packit |
6bd9ab |
NSS_BUFCHECK; \
|
|
Packit |
6bd9ab |
/* check that we have a valid file descriptor */ \
|
|
Packit |
6bd9ab |
if (fp == NULL) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
/* open a new stream and write the request */ \
|
|
Packit |
6bd9ab |
NSLCD_REQUEST(fp, action, /* no writefn */ ;); \
|
|
Packit |
6bd9ab |
} \
|
|
Packit |
6bd9ab |
/* prepare for buffer errors */ \
|
|
Packit |
6bd9ab |
tio_mark(fp); \
|
|
Packit |
6bd9ab |
/* read a response */ \
|
|
Packit |
6bd9ab |
READ_RESPONSE_CODE(fp); \
|
|
Packit |
6bd9ab |
retv = readfn; \
|
|
Packit |
6bd9ab |
/* check read result */ \
|
|
Packit |
6bd9ab |
if (retv == NSS_STATUS_TRYAGAIN) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
/* if we have a full buffer try to reset the stream */ \
|
|
Packit |
6bd9ab |
if (tio_reset(fp)) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
/* reset failed, we close and give up with a permanent error \
|
|
Packit |
6bd9ab |
because we cannot retry just the getent() call because it \
|
|
Packit |
6bd9ab |
may not be only the first entry that failed */ \
|
|
Packit |
6bd9ab |
tio_close(fp); \
|
|
Packit |
6bd9ab |
fp = NULL; \
|
|
Packit |
6bd9ab |
*errnop = EINVAL; \
|
|
Packit |
6bd9ab |
return NSS_STATUS_UNAVAIL; \
|
|
Packit |
6bd9ab |
} \
|
|
Packit |
6bd9ab |
} \
|
|
Packit |
6bd9ab |
else if (retv != NSS_STATUS_SUCCESS) \
|
|
Packit |
6bd9ab |
fp = NULL; /* file should be closed by now */ \
|
|
Packit |
6bd9ab |
return retv;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
/* This macro generates an endent() function body. This just closes
|
|
Packit |
6bd9ab |
the stream. */
|
|
Packit |
6bd9ab |
#define NSS_ENDENT(fp) \
|
|
Packit |
6bd9ab |
NSS_AVAILCHECK; \
|
|
Packit |
6bd9ab |
if (fp != NULL) \
|
|
Packit |
6bd9ab |
{ \
|
|
Packit |
6bd9ab |
(void)tio_skipall(fp, SKIP_TIMEOUT); \
|
|
Packit |
6bd9ab |
(void)tio_close(fp); \
|
|
Packit |
6bd9ab |
fp = NULL; \
|
|
Packit |
6bd9ab |
} \
|
|
Packit |
6bd9ab |
return NSS_STATUS_SUCCESS;
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
#endif /* not NSS__COMMON_H */
|