mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-24 00:29:35 -05:00
ITS#8097 nssov: update nss-pam-ldapd files to 0.9.4
This commit is contained in:
parent
25bbf116ad
commit
6a28f3dc20
6 changed files with 569 additions and 520 deletions
|
|
@ -1,4 +1,4 @@
|
|||
These files were pulled from the nss-pam-ldapd project version 0.8.12.
|
||||
These files were pulled from the nss-pam-ldapd project version 0.9.4.
|
||||
Copyright notices are in the individual files.
|
||||
|
||||
This is not the full distribution of nss-pam-ldapd, and does not
|
||||
|
|
@ -10,6 +10,6 @@ If your system already has the nss-pam-ldapd stub libraries
|
|||
installed, make sure the versions match the version number
|
||||
shown above. Otherwise, there may be incompatible differences in
|
||||
the protocols being used. Currently nssov requires at least
|
||||
version 0.8.11. If your system's version is older, you will need
|
||||
version 0.9.0. If your system's version is older, you will need
|
||||
to install the client-side stubs from source.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
attrs.h - wrapper macros for the gcc __attribute__(()) directive
|
||||
|
||||
Copyright (C) 2007, 2008 Arthur de Jong
|
||||
Copyright (C) 2007, 2008, 2012 Arthur de Jong
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
#define COMPAT__ATTRS_H 1
|
||||
|
||||
/* macro for testing the version of GCC */
|
||||
#define GCC_VERSION(major,minor) \
|
||||
#define GCC_VERSION(major, minor) \
|
||||
((__GNUC__ > (major)) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
|
||||
|
||||
/* These are macros to use some gcc-specific flags in case the're available
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
/* this is used to flag function parameters that are not used in the function
|
||||
body. */
|
||||
#if GCC_VERSION(3,0)
|
||||
#if GCC_VERSION(3, 0)
|
||||
#define UNUSED(x) x __attribute__((__unused__))
|
||||
#else
|
||||
#define UNUSED(x) x
|
||||
|
|
@ -42,16 +42,16 @@
|
|||
|
||||
/* this is used to add extra format checking to the function calls as if this
|
||||
was a printf()-like function */
|
||||
#if GCC_VERSION(3,0)
|
||||
#define LIKE_PRINTF(format_idx,arg_idx) \
|
||||
__attribute__((__format__(__printf__,format_idx,arg_idx)))
|
||||
#if GCC_VERSION(3, 0)
|
||||
#define LIKE_PRINTF(format_idx, arg_idx) \
|
||||
__attribute__((__format__(__printf__, format_idx, arg_idx)))
|
||||
#else
|
||||
#define LIKE_PRINTF(format_idx,arg_idx) /* no attribute */
|
||||
#define LIKE_PRINTF(format_idx, arg_idx) /* no attribute */
|
||||
#endif
|
||||
|
||||
/* indicates that the function is "pure": it's result is purely based on
|
||||
/* indicates that the function is "pure": its result is purely based on
|
||||
the parameters and has no side effects or used static data */
|
||||
#if GCC_VERSION(3,0)
|
||||
#if GCC_VERSION(3, 0)
|
||||
#define PURE __attribute__((__pure__))
|
||||
#else
|
||||
#define PURE /* no attribute */
|
||||
|
|
@ -59,21 +59,21 @@
|
|||
|
||||
/* the function returns a new data structure that has been freshly
|
||||
allocated */
|
||||
#if GCC_VERSION(3,0)
|
||||
#if GCC_VERSION(3, 0)
|
||||
#define LIKE_MALLOC __attribute__((__malloc__))
|
||||
#else
|
||||
#define LIKE_MALLOC /* no attribute */
|
||||
#endif
|
||||
|
||||
/* the function's return value should be used by the caller */
|
||||
#if GCC_VERSION(3,4)
|
||||
#if GCC_VERSION(3, 4)
|
||||
#define MUST_USE __attribute__((__warn_unused_result__))
|
||||
#else
|
||||
#define MUST_USE /* no attribute */
|
||||
#endif
|
||||
|
||||
/* the function's return value should be used by the caller */
|
||||
#if GCC_VERSION(2,5)
|
||||
#if GCC_VERSION(2, 5)
|
||||
#define NORETURN __attribute__((__noreturn__))
|
||||
#else
|
||||
#define NORETURN /* no attribute */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
nslcd-prot.h - helper macros for reading and writing in protocol streams
|
||||
|
||||
Copyright (C) 2006 West Consulting
|
||||
Copyright (C) 2006, 2007, 2009 Arthur de Jong
|
||||
Copyright (C) 2006-2014 Arthur de Jong
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -23,6 +23,9 @@
|
|||
#ifndef COMMON__NSLCD_PROT_H
|
||||
#define COMMON__NSLCD_PROT_H 1
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "tio.h"
|
||||
|
||||
/* If you use these macros you should define the following macros to
|
||||
|
|
@ -42,11 +45,12 @@
|
|||
/* define a debugging macro to output logging */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#define DEBUG_PRINT(fmt,arg) \
|
||||
fprintf(stderr,"%s:%d:%s: " fmt "\n",__FILE__,__LINE__,__PRETTY_FUNCTION__,arg);
|
||||
#define DEBUG_PRINT(fmt, arg) \
|
||||
fprintf(stderr, "%s:%d:%s: " fmt "\n", __FILE__, __LINE__, \
|
||||
__PRETTY_FUNCTION__, arg);
|
||||
#else /* DEBUG_PROT */
|
||||
/* define an empty debug macro to disable logging */
|
||||
#define DEBUG_PRINT(fmt,arg)
|
||||
#define DEBUG_PRINT(fmt, arg)
|
||||
#endif /* not DEBUG_PROT */
|
||||
|
||||
#ifdef DEBUG_PROT_DUMP
|
||||
|
|
@ -54,19 +58,19 @@
|
|||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif /* HAVE_STDINT_H */
|
||||
static void debug_dump(const void *ptr,size_t size)
|
||||
static void debug_dump(const void *ptr, size_t size)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<size;i++)
|
||||
fprintf(stderr," %02x",((const uint8_t *)ptr)[i]);
|
||||
fprintf(stderr,"\n");
|
||||
for (i = 0; i < size; i++)
|
||||
fprintf(stderr, " %02x", ((const uint8_t *)ptr)[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#define DEBUG_DUMP(ptr,size) \
|
||||
fprintf(stderr,"%s:%d:%s:",__FILE__,__LINE__,__PRETTY_FUNCTION__); \
|
||||
debug_dump(ptr,size);
|
||||
#define DEBUG_DUMP(ptr, size) \
|
||||
fprintf(stderr, "%s:%d:%s:", __FILE__, __LINE__, __PRETTY_FUNCTION__); \
|
||||
debug_dump(ptr, size);
|
||||
#else /* DEBUG_PROT_DUMP */
|
||||
/* define an empty debug macro to disable logging */
|
||||
#define DEBUG_DUMP(ptr,size)
|
||||
#define DEBUG_DUMP(ptr, size)
|
||||
#endif /* not DEBUG_PROT_DUMP */
|
||||
|
||||
|
||||
|
|
@ -77,76 +81,76 @@ static void debug_dump(const void *ptr,size_t size)
|
|||
int32_t tmpint32; - temporary variable
|
||||
*/
|
||||
|
||||
#define WRITE(fp,ptr,size) \
|
||||
DEBUG_PRINT("WRITE : var="__STRING(ptr)" size=%d",(int)size); \
|
||||
DEBUG_DUMP(ptr,size); \
|
||||
if (tio_write(fp,ptr,(size_t)size)) \
|
||||
{ \
|
||||
DEBUG_PRINT("WRITE : var="__STRING(ptr)" error: %s",strerror(errno)); \
|
||||
ERROR_OUT_WRITEERROR(fp); \
|
||||
#define WRITE(fp, ptr, size) \
|
||||
DEBUG_PRINT("WRITE : var="__STRING(ptr)" size=%d", (int)size); \
|
||||
DEBUG_DUMP(ptr, size); \
|
||||
if (tio_write(fp, ptr, (size_t)size)) \
|
||||
{ \
|
||||
DEBUG_PRINT("WRITE : var="__STRING(ptr)" error: %s", \
|
||||
strerror(errno)); \
|
||||
ERROR_OUT_WRITEERROR(fp); \
|
||||
}
|
||||
|
||||
#define WRITE_TYPE(fp,field,type) \
|
||||
WRITE(fp,&(field),sizeof(type))
|
||||
#define WRITE_INT32(fp, i) \
|
||||
DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%08x", (int)i); \
|
||||
tmpint32 = htonl((int32_t)(i)); \
|
||||
WRITE(fp, &tmpint32, sizeof(int32_t))
|
||||
|
||||
#define WRITE_INT32(fp,i) \
|
||||
DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%d",(int)i); \
|
||||
tmpint32=(int32_t)(i); \
|
||||
WRITE_TYPE(fp,tmpint32,int32_t)
|
||||
|
||||
#define WRITE_STRING(fp,str) \
|
||||
DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"",(str)); \
|
||||
if ((str)==NULL) \
|
||||
{ \
|
||||
WRITE_INT32(fp,0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
WRITE_INT32(fp,strlen(str)); \
|
||||
if (tmpint32>0) \
|
||||
{ WRITE(fp,(str),tmpint32); } \
|
||||
#define WRITE_STRING(fp, str) \
|
||||
DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"", (str)); \
|
||||
if ((str) == NULL) \
|
||||
{ \
|
||||
WRITE_INT32(fp, 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
WRITE_INT32(fp, strlen(str)); \
|
||||
tmpint32 = ntohl(tmpint32); \
|
||||
if (tmpint32 > 0) \
|
||||
{ \
|
||||
WRITE(fp, (str), tmpint32); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define WRITE_STRINGLIST(fp,arr) \
|
||||
if ((arr)==NULL) \
|
||||
{ \
|
||||
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",0); \
|
||||
WRITE_INT32(fp,0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* first determin length of array */ \
|
||||
for (tmp3int32=0;(arr)[tmp3int32]!=NULL;tmp3int32++) \
|
||||
/*noting*/ ; \
|
||||
/* write number of strings */ \
|
||||
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
|
||||
WRITE_TYPE(fp,tmp3int32,int32_t); \
|
||||
/* write strings */ \
|
||||
for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
|
||||
{ \
|
||||
WRITE_STRING(fp,(arr)[tmp2int32]); \
|
||||
} \
|
||||
#define WRITE_STRINGLIST(fp, arr) \
|
||||
if ((arr) == NULL) \
|
||||
{ \
|
||||
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", 0); \
|
||||
WRITE_INT32(fp, 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* first determine length of array */ \
|
||||
for (tmp3int32 = 0; (arr)[tmp3int32] != NULL; tmp3int32++) \
|
||||
/* noting */ ; \
|
||||
/* write number of strings */ \
|
||||
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32); \
|
||||
WRITE_INT32(fp, tmp3int32); \
|
||||
/* write strings */ \
|
||||
for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++) \
|
||||
{ \
|
||||
WRITE_STRING(fp, (arr)[tmp2int32]); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define WRITE_STRINGLIST_EXCEPT(fp,arr,not) \
|
||||
/* first determin length of array */ \
|
||||
tmp3int32=0; \
|
||||
for (tmp2int32=0;(arr)[tmp2int32]!=NULL;tmp2int32++) \
|
||||
if (strcmp((arr)[tmp2int32],(not))!=0) \
|
||||
tmp3int32++; \
|
||||
/* write number of strings (mius one because we intend to skip one) */ \
|
||||
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
|
||||
WRITE_TYPE(fp,tmp3int32,int32_t); \
|
||||
/* write strings */ \
|
||||
for (tmp2int32=0;(arr)[tmp2int32]!=NULL;tmp2int32++) \
|
||||
{ \
|
||||
if (strcmp((arr)[tmp2int32],(not))!=0) \
|
||||
{ \
|
||||
WRITE_STRING(fp,(arr)[tmp2int32]); \
|
||||
} \
|
||||
#define WRITE_STRINGLIST_EXCEPT(fp, arr, not) \
|
||||
/* first determine length of array */ \
|
||||
tmp3int32 = 0; \
|
||||
for (tmp2int32 = 0; (arr)[tmp2int32] != NULL; tmp2int32++) \
|
||||
if (strcmp((arr)[tmp2int32], (not)) != 0) \
|
||||
tmp3int32++; \
|
||||
/* write number of strings (mius one because we intend to skip one) */ \
|
||||
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32); \
|
||||
WRITE_INT32(fp, tmp3int32); \
|
||||
/* write strings */ \
|
||||
for (tmp2int32 = 0; (arr)[tmp2int32] != NULL; tmp2int32++) \
|
||||
{ \
|
||||
if (strcmp((arr)[tmp2int32], (not)) != 0) \
|
||||
{ \
|
||||
WRITE_STRING(fp, (arr)[tmp2int32]); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* READ macros, used for reading data, on read error they will
|
||||
call the ERROR_OUT_READERROR or ERROR_OUT_BUFERROR macro
|
||||
these macros may require the availability of the following
|
||||
|
|
@ -154,42 +158,43 @@ static void debug_dump(const void *ptr,size_t size)
|
|||
int32_t tmpint32; - temporary variable
|
||||
*/
|
||||
|
||||
#define READ(fp,ptr,size) \
|
||||
if (tio_read(fp,ptr,(size_t)size)) \
|
||||
{ \
|
||||
DEBUG_PRINT("READ : var="__STRING(ptr)" error: %s",strerror(errno)); \
|
||||
ERROR_OUT_READERROR(fp); \
|
||||
} \
|
||||
DEBUG_PRINT("READ : var="__STRING(ptr)" size=%d",(int)size); \
|
||||
DEBUG_DUMP(ptr,size);
|
||||
#define READ(fp, ptr, size) \
|
||||
if (tio_read(fp, ptr, (size_t)size)) \
|
||||
{ \
|
||||
DEBUG_PRINT("READ : var="__STRING(ptr)" error: %s", \
|
||||
strerror(errno)); \
|
||||
ERROR_OUT_READERROR(fp); \
|
||||
} \
|
||||
DEBUG_PRINT("READ : var="__STRING(ptr)" size=%d", (int)(size)); \
|
||||
DEBUG_DUMP(ptr, size);
|
||||
|
||||
#define READ_TYPE(fp,field,type) \
|
||||
READ(fp,&(field),sizeof(type))
|
||||
|
||||
#define READ_INT32(fp,i) \
|
||||
READ_TYPE(fp,tmpint32,int32_t); \
|
||||
i=tmpint32; \
|
||||
DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32=%d",(int)i);
|
||||
#define READ_INT32(fp, i) \
|
||||
READ(fp, &tmpint32, sizeof(int32_t)); \
|
||||
(i) = (int32_t)ntohl(tmpint32); \
|
||||
DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32==%08x", (int)(i));
|
||||
|
||||
/* read a string in a fixed-size "normal" buffer */
|
||||
#define READ_STRING(fp,buffer) \
|
||||
/* read the size of the string */ \
|
||||
READ_TYPE(fp,tmpint32,int32_t); \
|
||||
DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d",tmpint32); \
|
||||
/* check if read would fit */ \
|
||||
if (((size_t)tmpint32)>=sizeof(buffer)) \
|
||||
{ \
|
||||
/* will not fit */ \
|
||||
tmpint32=(tmpint32-sizeof(buffer))+1; \
|
||||
DEBUG_PRINT("READ : buffer %d bytes too small",tmpint32); \
|
||||
ERROR_OUT_BUFERROR(fp); \
|
||||
} \
|
||||
/* read string from the stream */ \
|
||||
if (tmpint32>0) \
|
||||
{ READ(fp,buffer,(size_t)tmpint32); } \
|
||||
/* null-terminate string in buffer */ \
|
||||
buffer[tmpint32]='\0'; \
|
||||
DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"",buffer);
|
||||
#define READ_STRING(fp, buffer) \
|
||||
/* read the size of the string */ \
|
||||
READ(fp, &tmpint32, sizeof(int32_t)); \
|
||||
tmpint32 = ntohl(tmpint32); \
|
||||
DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d", tmpint32); \
|
||||
/* check if read would fit */ \
|
||||
if (((size_t)tmpint32) >= sizeof(buffer)) \
|
||||
{ \
|
||||
/* will not fit */ \
|
||||
tmpint32 = (tmpint32 - sizeof(buffer)) + 1; \
|
||||
DEBUG_PRINT("READ : buffer %d bytes too small", tmpint32); \
|
||||
ERROR_OUT_BUFERROR(fp); \
|
||||
} \
|
||||
/* read string from the stream */ \
|
||||
if (tmpint32 > 0) \
|
||||
{ \
|
||||
READ(fp, buffer, (size_t)tmpint32); \
|
||||
} \
|
||||
/* null-terminate string in buffer */ \
|
||||
buffer[tmpint32] = '\0'; \
|
||||
DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"", buffer);
|
||||
|
||||
|
||||
/* READ BUF macros that read data into a pre-allocated buffer.
|
||||
|
|
@ -202,116 +207,123 @@ static void debug_dump(const void *ptr,size_t size)
|
|||
*/
|
||||
|
||||
/* current position in the buffer */
|
||||
#define BUF_CUR \
|
||||
(buffer+bufptr)
|
||||
#define BUF_CUR \
|
||||
(buffer + bufptr)
|
||||
|
||||
/* check that the buffer has sz bytes left in it */
|
||||
#define BUF_CHECK(fp,sz) \
|
||||
if ((bufptr+(size_t)(sz))>buflen) \
|
||||
{ \
|
||||
/* will not fit */ \
|
||||
tmpint32=bufptr+(sz)-(buflen); \
|
||||
DEBUG_PRINT("READ : buffer %d bytes too small",tmpint32); \
|
||||
ERROR_OUT_BUFERROR(fp); \
|
||||
#define BUF_CHECK(fp, sz) \
|
||||
if ((bufptr + (size_t)(sz)) > buflen) \
|
||||
{ \
|
||||
/* will not fit */ \
|
||||
tmpint32 = bufptr + (sz) - (buflen); \
|
||||
DEBUG_PRINT("READ : buffer %d bytes too small", tmpint32); \
|
||||
ERROR_OUT_BUFERROR(fp); \
|
||||
}
|
||||
|
||||
/* move the buffer pointer */
|
||||
#define BUF_SKIP(sz) \
|
||||
bufptr+=(size_t)(sz);
|
||||
#define BUF_SKIP(sz) \
|
||||
bufptr += (size_t)(sz);
|
||||
|
||||
/* move BUF_CUR foreward so that it is aligned to the specified
|
||||
type width */
|
||||
#define BUF_ALIGN(fp,type) \
|
||||
/* figure out number of bytes to skip foreward */ \
|
||||
tmp2int32=(sizeof(type)-((BUF_CUR-(char *)NULL)%sizeof(type)))%sizeof(type); \
|
||||
/* check and skip */ \
|
||||
BUF_CHECK(fp,tmp2int32); \
|
||||
#define BUF_ALIGN(fp, type) \
|
||||
/* figure out number of bytes to skip foreward */ \
|
||||
tmp2int32 = (sizeof(type) - ((BUF_CUR - (char *)NULL) % sizeof(type))) \
|
||||
% sizeof(type); \
|
||||
/* check and skip */ \
|
||||
BUF_CHECK(fp, tmp2int32); \
|
||||
BUF_SKIP(tmp2int32);
|
||||
|
||||
/* allocate a piece of the buffer to store an array in */
|
||||
#define BUF_ALLOC(fp,ptr,type,num) \
|
||||
/* align to the specified type width */ \
|
||||
BUF_ALIGN(fp,type); \
|
||||
/* check that we have enough room */ \
|
||||
BUF_CHECK(fp,(size_t)(num)*sizeof(type)); \
|
||||
/* store the pointer */ \
|
||||
(ptr)=(type *)BUF_CUR; \
|
||||
/* reserve the space */ \
|
||||
BUF_SKIP((size_t)(num)*sizeof(type));
|
||||
#define BUF_ALLOC(fp, ptr, type, num) \
|
||||
/* align to the specified type width */ \
|
||||
BUF_ALIGN(fp, type); \
|
||||
/* check that we have enough room */ \
|
||||
BUF_CHECK(fp, (size_t)(num) * sizeof(type)); \
|
||||
/* store the pointer */ \
|
||||
(ptr) = (type *)BUF_CUR; \
|
||||
/* reserve the space */ \
|
||||
BUF_SKIP((size_t)(num) * sizeof(type));
|
||||
|
||||
/* read a binary blob into the buffer */
|
||||
#define READ_BUF(fp,ptr,sz) \
|
||||
/* check that there is enough room and read */ \
|
||||
BUF_CHECK(fp,sz); \
|
||||
READ(fp,BUF_CUR,(size_t)sz); \
|
||||
/* store pointer and skip */ \
|
||||
(ptr)=BUF_CUR; \
|
||||
#define READ_BUF(fp, ptr, sz) \
|
||||
/* check that there is enough room and read */ \
|
||||
BUF_CHECK(fp, sz); \
|
||||
READ(fp, BUF_CUR, (size_t)sz); \
|
||||
/* store pointer and skip */ \
|
||||
(ptr) = BUF_CUR; \
|
||||
BUF_SKIP(sz);
|
||||
|
||||
/* read string in the buffer (using buffer, buflen and bufptr)
|
||||
and store the actual location of the string in field */
|
||||
#define READ_BUF_STRING(fp,field) \
|
||||
/* read the size of the string */ \
|
||||
READ_TYPE(fp,tmpint32,int32_t); \
|
||||
DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" strlen=%d",tmpint32); \
|
||||
/* check if read would fit */ \
|
||||
BUF_CHECK(fp,tmpint32+1); \
|
||||
/* read string from the stream */ \
|
||||
if (tmpint32>0) \
|
||||
{ READ(fp,BUF_CUR,(size_t)tmpint32); } \
|
||||
/* null-terminate string in buffer */ \
|
||||
BUF_CUR[tmpint32]='\0'; \
|
||||
DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" string=\"%s\"",BUF_CUR); \
|
||||
/* prepare result */ \
|
||||
(field)=BUF_CUR; \
|
||||
BUF_SKIP(tmpint32+1);
|
||||
#define READ_BUF_STRING(fp, field) \
|
||||
/* read the size of the string */ \
|
||||
READ(fp, &tmpint32, sizeof(int32_t)); \
|
||||
tmpint32 = ntohl(tmpint32); \
|
||||
DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" strlen=%d", tmpint32); \
|
||||
/* check if read would fit */ \
|
||||
BUF_CHECK(fp, tmpint32 + 1); \
|
||||
/* read string from the stream */ \
|
||||
if (tmpint32 > 0) \
|
||||
{ \
|
||||
READ(fp, BUF_CUR, (size_t)tmpint32); \
|
||||
} \
|
||||
/* null-terminate string in buffer */ \
|
||||
BUF_CUR[tmpint32] = '\0'; \
|
||||
DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" string=\"%s\"", BUF_CUR); \
|
||||
/* prepare result */ \
|
||||
(field) = BUF_CUR; \
|
||||
BUF_SKIP(tmpint32 + 1);
|
||||
|
||||
/* read an array from a stram and store it as a null-terminated
|
||||
array list (size for the array is allocated) */
|
||||
#define READ_BUF_STRINGLIST(fp,arr) \
|
||||
/* read the number of entries */ \
|
||||
READ_TYPE(fp,tmp3int32,int32_t); \
|
||||
DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
|
||||
/* allocate room for *char[num+1] */ \
|
||||
BUF_ALLOC(fp,arr,char *,tmp3int32+1); \
|
||||
/* read all entries */ \
|
||||
for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
|
||||
{ \
|
||||
READ_BUF_STRING(fp,(arr)[tmp2int32]); \
|
||||
} \
|
||||
/* set last entry to NULL */ \
|
||||
(arr)[tmp2int32]=NULL;
|
||||
#define READ_BUF_STRINGLIST(fp, arr) \
|
||||
/* read the number of entries */ \
|
||||
READ(fp, &tmp3int32, sizeof(int32_t)); \
|
||||
tmp3int32 = ntohl(tmp3int32); \
|
||||
DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d", (int)tmp3int32); \
|
||||
/* allocate room for *char[num + 1] */ \
|
||||
BUF_ALLOC(fp, arr, char *, tmp3int32 + 1); \
|
||||
/* read all entries */ \
|
||||
for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++) \
|
||||
{ \
|
||||
READ_BUF_STRING(fp, (arr)[tmp2int32]); \
|
||||
} \
|
||||
/* set last entry to NULL */ \
|
||||
(arr)[tmp2int32] = NULL;
|
||||
|
||||
|
||||
/* SKIP macros for skipping over certain parts of the protocol stream. */
|
||||
|
||||
/* skip a number of bytes foreward */
|
||||
#define SKIP(fp,sz) \
|
||||
DEBUG_PRINT("READ : skip %d bytes",(int)(sz)); \
|
||||
/* read (skip) the specified number of bytes */ \
|
||||
if (tio_skip(fp,sz)) \
|
||||
{ \
|
||||
DEBUG_PRINT("READ : skip error: %s",strerror(errno)); \
|
||||
ERROR_OUT_READERROR(fp); \
|
||||
#define SKIP(fp, sz) \
|
||||
DEBUG_PRINT("READ : skip %d bytes", (int)(sz)); \
|
||||
/* read (skip) the specified number of bytes */ \
|
||||
if (tio_skip(fp, sz)) \
|
||||
{ \
|
||||
DEBUG_PRINT("READ : skip error: %s", strerror(errno)); \
|
||||
ERROR_OUT_READERROR(fp); \
|
||||
}
|
||||
|
||||
/* read a string from the stream but don't do anything with the result */
|
||||
#define SKIP_STRING(fp) \
|
||||
/* read the size of the string */ \
|
||||
READ_TYPE(fp,tmpint32,int32_t); \
|
||||
DEBUG_PRINT("READ_STRING: skip %d bytes",(int)tmpint32); \
|
||||
/* read (skip) the specified number of bytes */ \
|
||||
SKIP(fp,tmpint32);
|
||||
#define SKIP_STRING(fp) \
|
||||
/* read the size of the string */ \
|
||||
READ(fp, &tmpint32, sizeof(int32_t)); \
|
||||
tmpint32 = ntohl(tmpint32); \
|
||||
DEBUG_PRINT("READ_STRING: skip %d bytes", (int)tmpint32); \
|
||||
/* read (skip) the specified number of bytes */ \
|
||||
SKIP(fp, tmpint32);
|
||||
|
||||
/* skip a list of strings */
|
||||
#define SKIP_STRINGLIST(fp) \
|
||||
/* read the number of entries */ \
|
||||
READ_TYPE(fp,tmp3int32,int32_t); \
|
||||
DEBUG_PRINT("READ_STRLST: skip %d strings",(int)tmp3int32); \
|
||||
/* read all entries */ \
|
||||
for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
|
||||
{ \
|
||||
SKIP_STRING(fp); \
|
||||
#define SKIP_STRINGLIST(fp) \
|
||||
/* read the number of entries */ \
|
||||
READ(fp, &tmp3int32, sizeof(int32_t)); \
|
||||
tmp3int32 = ntohl(tmp3int32); \
|
||||
DEBUG_PRINT("READ_STRLST: skip %d strings", (int)tmp3int32); \
|
||||
/* read all entries */ \
|
||||
for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++) \
|
||||
{ \
|
||||
SKIP_STRING(fp); \
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -324,35 +336,46 @@ TFILE *nslcd_client_open(void)
|
|||
MUST_USE;
|
||||
|
||||
/* generic request code */
|
||||
#define NSLCD_REQUEST(fp,action,writefn) \
|
||||
/* open a client socket */ \
|
||||
if ((fp=nslcd_client_open())==NULL) \
|
||||
{ ERROR_OUT_OPENERROR } \
|
||||
/* write a request header with a request code */ \
|
||||
WRITE_INT32(fp,(int32_t)NSLCD_VERSION) \
|
||||
WRITE_INT32(fp,(int32_t)action) \
|
||||
/* write the request parameters (if any) */ \
|
||||
writefn; \
|
||||
/* flush the stream */ \
|
||||
if (tio_flush(fp)<0) \
|
||||
{ \
|
||||
DEBUG_PRINT("WRITE_FLUSH : error: %s",strerror(errno)); \
|
||||
ERROR_OUT_WRITEERROR(fp); \
|
||||
} \
|
||||
/* read and check response version number */ \
|
||||
READ_TYPE(fp,tmpint32,int32_t); \
|
||||
if (tmpint32!=(int32_t)NSLCD_VERSION) \
|
||||
{ ERROR_OUT_READERROR(fp) } \
|
||||
/* read and check response request number */ \
|
||||
READ_TYPE(fp,tmpint32,int32_t); \
|
||||
if (tmpint32!=(int32_t)(action)) \
|
||||
{ ERROR_OUT_READERROR(fp) }
|
||||
#define NSLCD_REQUEST(fp, action, writefn) \
|
||||
/* open a client socket */ \
|
||||
if ((fp = nslcd_client_open()) == NULL) \
|
||||
{ \
|
||||
ERROR_OUT_OPENERROR; \
|
||||
} \
|
||||
/* write a request header with a request code */ \
|
||||
WRITE_INT32(fp, (int32_t)NSLCD_VERSION) \
|
||||
WRITE_INT32(fp, (int32_t)action) \
|
||||
/* write the request parameters (if any) */ \
|
||||
writefn; \
|
||||
/* flush the stream */ \
|
||||
if (tio_flush(fp) < 0) \
|
||||
{ \
|
||||
DEBUG_PRINT("WRITE_FLUSH : error: %s", strerror(errno)); \
|
||||
ERROR_OUT_WRITEERROR(fp); \
|
||||
} \
|
||||
/* read and check response version number */ \
|
||||
READ(fp, &tmpint32, sizeof(int32_t)); \
|
||||
tmpint32 = ntohl(tmpint32); \
|
||||
if (tmpint32 != (int32_t)NSLCD_VERSION) \
|
||||
{ \
|
||||
ERROR_OUT_READERROR(fp); \
|
||||
} \
|
||||
/* read and check response request number */ \
|
||||
READ(fp, &tmpint32, sizeof(int32_t)); \
|
||||
tmpint32 = ntohl(tmpint32); \
|
||||
if (tmpint32 != (int32_t)(action)) \
|
||||
{ \
|
||||
ERROR_OUT_READERROR(fp); \
|
||||
}
|
||||
|
||||
/* Read the response code (the result code of the query) from
|
||||
the stream. */
|
||||
#define READ_RESPONSE_CODE(fp) \
|
||||
READ_TYPE(fp,tmpint32,int32_t); \
|
||||
if (tmpint32!=(int32_t)NSLCD_RESULT_BEGIN) \
|
||||
{ ERROR_OUT_NOSUCCESS(fp) }
|
||||
#define READ_RESPONSE_CODE(fp) \
|
||||
READ(fp, &tmpint32, sizeof(int32_t)); \
|
||||
tmpint32 = ntohl(tmpint32); \
|
||||
if (tmpint32 != (int32_t)NSLCD_RESULT_BEGIN) \
|
||||
{ \
|
||||
ERROR_OUT_NOSUCCESS(fp); \
|
||||
}
|
||||
|
||||
#endif /* not COMMON__NSLCD_PROT_H */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
nslcd.h - file describing client/server protocol
|
||||
|
||||
Copyright (C) 2006 West Consulting
|
||||
Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012 Arthur de Jong
|
||||
Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012, 2013 Arthur de Jong
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -59,122 +59,130 @@
|
|||
Furthermore the ADDRESS compound data type is defined as:
|
||||
INT32 type of address: e.g. AF_INET or AF_INET6
|
||||
INT32 lenght of address
|
||||
RAW the address itself in network byte order
|
||||
RAW the address itself
|
||||
With the ADDRESSLIST using the same construct as with STRINGLIST.
|
||||
|
||||
The protocol uses host-byte order for all types (except in the raw
|
||||
address above).
|
||||
The protocol uses network byte order for all types.
|
||||
*/
|
||||
|
||||
/* The current version of the protocol. Note that version 1
|
||||
is experimental and this version will be used until a
|
||||
1.0 release of nss-pam-ldapd is made. */
|
||||
#define NSLCD_VERSION 1
|
||||
/* The current version of the protocol. This protocol should only be
|
||||
updated with major backwards-incompatible changes. */
|
||||
#define NSLCD_VERSION 0x00000002
|
||||
|
||||
/* Get a NSLCD configuration option. There is one request parameter:
|
||||
INT32 NSLCD_CONFIG_*
|
||||
the result value is:
|
||||
STRING value, interpretation depending on request */
|
||||
#define NSLCD_ACTION_CONFIG_GET 20006
|
||||
#define NSLCD_ACTION_CONFIG_GET 0x00010001
|
||||
|
||||
/* return the message, if any, that is presented to the user when password
|
||||
modification through PAM is prohibited */
|
||||
#define NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE 852
|
||||
#define NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE 1
|
||||
|
||||
/* Email alias (/etc/aliases) NSS requests. The result values for a
|
||||
single entry are:
|
||||
STRING alias name
|
||||
STRINGLIST alias rcpts */
|
||||
#define NSLCD_ACTION_ALIAS_BYNAME 4001
|
||||
#define NSLCD_ACTION_ALIAS_ALL 4002
|
||||
#define NSLCD_ACTION_ALIAS_BYNAME 0x00020001
|
||||
#define NSLCD_ACTION_ALIAS_ALL 0x00020008
|
||||
|
||||
/* Ethernet address/name mapping NSS requests. The result values for a
|
||||
single entry are:
|
||||
STRING ether name
|
||||
TYPE(uint8_t[6]) ether address */
|
||||
#define NSLCD_ACTION_ETHER_BYNAME 3001
|
||||
#define NSLCD_ACTION_ETHER_BYETHER 3002
|
||||
#define NSLCD_ACTION_ETHER_ALL 3005
|
||||
#define NSLCD_ACTION_ETHER_BYNAME 0x00030001
|
||||
#define NSLCD_ACTION_ETHER_BYETHER 0x00030002
|
||||
#define NSLCD_ACTION_ETHER_ALL 0x00030008
|
||||
|
||||
/* Group and group membership related NSS requests. The result values
|
||||
for a single entry are:
|
||||
STRING group name
|
||||
STRING group password
|
||||
TYPE(gid_t) group id
|
||||
INT32 group id
|
||||
STRINGLIST members (usernames) of the group
|
||||
(not that the BYMEMER call returns an emtpy members list) */
|
||||
#define NSLCD_ACTION_GROUP_BYNAME 5001
|
||||
#define NSLCD_ACTION_GROUP_BYGID 5002
|
||||
#define NSLCD_ACTION_GROUP_BYMEMBER 5003
|
||||
#define NSLCD_ACTION_GROUP_ALL 5004
|
||||
#define NSLCD_ACTION_GROUP_BYNAME 0x00040001
|
||||
#define NSLCD_ACTION_GROUP_BYGID 0x00040002
|
||||
#define NSLCD_ACTION_GROUP_BYMEMBER 0x00040006
|
||||
#define NSLCD_ACTION_GROUP_ALL 0x00040008
|
||||
|
||||
/* Hostname (/etc/hosts) lookup NSS requests. The result values
|
||||
for an entry are:
|
||||
STRING host name
|
||||
STRINGLIST host aliases
|
||||
ADDRESSLIST host addresses */
|
||||
#define NSLCD_ACTION_HOST_BYNAME 6001
|
||||
#define NSLCD_ACTION_HOST_BYADDR 6002
|
||||
#define NSLCD_ACTION_HOST_ALL 6005
|
||||
#define NSLCD_ACTION_HOST_BYNAME 0x00050001
|
||||
#define NSLCD_ACTION_HOST_BYADDR 0x00050002
|
||||
#define NSLCD_ACTION_HOST_ALL 0x00050008
|
||||
|
||||
/* Netgroup NSS request return a number of results. Result values
|
||||
can be either a reference to another netgroup:
|
||||
/* Netgroup NSS result entries contain a number of parts. A result entry
|
||||
starts with:
|
||||
STRING netgroup name
|
||||
followed by zero or more references to other netgroups or netgroup
|
||||
triples. A reference to another netgroup looks like:
|
||||
INT32 NSLCD_NETGROUP_TYPE_NETGROUP
|
||||
STRING other netgroup name
|
||||
or a netgroup triple:
|
||||
A a netgroup triple looks like:
|
||||
INT32 NSLCD_NETGROUP_TYPE_TRIPLE
|
||||
STRING host
|
||||
STRING user
|
||||
STRING domain */
|
||||
#define NSLCD_ACTION_NETGROUP_BYNAME 12001
|
||||
#define NSLCD_NETGROUP_TYPE_NETGROUP 123
|
||||
#define NSLCD_NETGROUP_TYPE_TRIPLE 456
|
||||
STRING domain
|
||||
A netgroup result entry is terminated by:
|
||||
INT32 NSLCD_NETGROUP_TYPE_END
|
||||
*/
|
||||
#define NSLCD_ACTION_NETGROUP_BYNAME 0x00060001
|
||||
#define NSLCD_ACTION_NETGROUP_ALL 0x00060008
|
||||
#define NSLCD_NETGROUP_TYPE_NETGROUP 1
|
||||
#define NSLCD_NETGROUP_TYPE_TRIPLE 2
|
||||
#define NSLCD_NETGROUP_TYPE_END 3
|
||||
|
||||
/* Network name (/etc/networks) NSS requests. Result values for a single
|
||||
entry are:
|
||||
STRING network name
|
||||
STRINGLIST network aliases
|
||||
ADDRESSLIST network addresses */
|
||||
#define NSLCD_ACTION_NETWORK_BYNAME 8001
|
||||
#define NSLCD_ACTION_NETWORK_BYADDR 8002
|
||||
#define NSLCD_ACTION_NETWORK_ALL 8005
|
||||
#define NSLCD_ACTION_NETWORK_BYNAME 0x00070001
|
||||
#define NSLCD_ACTION_NETWORK_BYADDR 0x00070002
|
||||
#define NSLCD_ACTION_NETWORK_ALL 0x00070008
|
||||
|
||||
/* User account (/etc/passwd) NSS requests. Result values are:
|
||||
STRING user name
|
||||
STRING user password
|
||||
TYPE(uid_t) user id
|
||||
TYPE(gid_t) group id
|
||||
INT32 user id
|
||||
INT32 group id
|
||||
STRING gecos information
|
||||
STRING home directory
|
||||
STRING login shell */
|
||||
#define NSLCD_ACTION_PASSWD_BYNAME 1001
|
||||
#define NSLCD_ACTION_PASSWD_BYUID 1002
|
||||
#define NSLCD_ACTION_PASSWD_ALL 1004
|
||||
#define NSLCD_ACTION_PASSWD_BYNAME 0x00080001
|
||||
#define NSLCD_ACTION_PASSWD_BYUID 0x00080002
|
||||
#define NSLCD_ACTION_PASSWD_ALL 0x00080008
|
||||
|
||||
/* Protocol information requests. Result values are:
|
||||
STRING protocol name
|
||||
STRINGLIST protocol aliases
|
||||
INT32 protocol number */
|
||||
#define NSLCD_ACTION_PROTOCOL_BYNAME 9001
|
||||
#define NSLCD_ACTION_PROTOCOL_BYNUMBER 9002
|
||||
#define NSLCD_ACTION_PROTOCOL_ALL 9003
|
||||
#define NSLCD_ACTION_PROTOCOL_BYNAME 0x00090001
|
||||
#define NSLCD_ACTION_PROTOCOL_BYNUMBER 0x00090002
|
||||
#define NSLCD_ACTION_PROTOCOL_ALL 0x00090008
|
||||
|
||||
/* RPC information requests. Result values are:
|
||||
STRING rpc name
|
||||
STRINGLIST rpc aliases
|
||||
INT32 rpc number */
|
||||
#define NSLCD_ACTION_RPC_BYNAME 10001
|
||||
#define NSLCD_ACTION_RPC_BYNUMBER 10002
|
||||
#define NSLCD_ACTION_RPC_ALL 10003
|
||||
#define NSLCD_ACTION_RPC_BYNAME 0x000a0001
|
||||
#define NSLCD_ACTION_RPC_BYNUMBER 0x000a0002
|
||||
#define NSLCD_ACTION_RPC_ALL 0x000a0008
|
||||
|
||||
/* Service (/etc/services) information requests. Result values are:
|
||||
/* Service (/etc/services) information requests. The BYNAME and BYNUMBER
|
||||
requests contain an extra protocol string in the request which, if not
|
||||
blank, will filter the services by this protocol. Result values are:
|
||||
STRING service name
|
||||
STRINGLIST service aliases
|
||||
INT32 service (port) number
|
||||
STRING service protocol */
|
||||
#define NSLCD_ACTION_SERVICE_BYNAME 11001
|
||||
#define NSLCD_ACTION_SERVICE_BYNUMBER 11002
|
||||
#define NSLCD_ACTION_SERVICE_ALL 11005
|
||||
#define NSLCD_ACTION_SERVICE_BYNAME 0x000b0001
|
||||
#define NSLCD_ACTION_SERVICE_BYNUMBER 0x000b0002
|
||||
#define NSLCD_ACTION_SERVICE_ALL 0x000b0008
|
||||
|
||||
/* Extended user account (/etc/shadow) information requests. Result
|
||||
values for a single entry are:
|
||||
|
|
@ -187,69 +195,95 @@
|
|||
INT32 inact
|
||||
INT32 expire
|
||||
INT32 flag */
|
||||
#define NSLCD_ACTION_SHADOW_BYNAME 2001
|
||||
#define NSLCD_ACTION_SHADOW_ALL 2005
|
||||
#define NSLCD_ACTION_SHADOW_BYNAME 0x000c0001
|
||||
#define NSLCD_ACTION_SHADOW_ALL 0x000c0008
|
||||
|
||||
/* PAM-related requests. The request parameters for all these requests
|
||||
begin with:
|
||||
STRING user name
|
||||
STRING DN (if value is known already, otherwise empty)
|
||||
STRING service name
|
||||
all requests, except the SESSION requests start the result value with:
|
||||
STRING user name (cannonical name)
|
||||
STRING DN (can be used to speed up requests)
|
||||
Some functions may return an authorisation message. This message, if
|
||||
supplied will be used by the PAM module instead of a message that is
|
||||
generated by the PAM module itself. */
|
||||
STRING ruser
|
||||
STRING rhost
|
||||
STRING tty
|
||||
If the user is not known in LDAP no result may be returned (immediately
|
||||
return NSLCD_RESULT_END instead of a PAM error code). */
|
||||
|
||||
/* PAM authentication check request. The extra request values are:
|
||||
STRING password
|
||||
and the result value ends with:
|
||||
and the result value consists of:
|
||||
INT32 authc NSLCD_PAM_* result code
|
||||
STRING user name (the cannonical user name)
|
||||
INT32 authz NSLCD_PAM_* result code
|
||||
STRING authorisation error message
|
||||
If the username is empty in this request an attempt is made to
|
||||
authenticate as the administrator (set using rootpwmoddn). The returned DN
|
||||
is that of the administrator. */
|
||||
#define NSLCD_ACTION_PAM_AUTHC 20001
|
||||
authenticate as the administrator (set using rootpwmoddn).
|
||||
Some authorisation checks are already done during authentication so the
|
||||
response also includes authorisation information. */
|
||||
#define NSLCD_ACTION_PAM_AUTHC 0x000d0001
|
||||
|
||||
/* PAM authorisation check request. The extra request values are:
|
||||
STRING ruser
|
||||
STRING rhost
|
||||
STRING tty
|
||||
and the result value ends with:
|
||||
/* PAM authorisation check request. The result value consists of:
|
||||
INT32 authz NSLCD_PAM_* result code
|
||||
STRING authorisation error message */
|
||||
#define NSLCD_ACTION_PAM_AUTHZ 20002
|
||||
STRING authorisation error message
|
||||
The authentication check may have already returned some authorisation
|
||||
information. The authorisation error message, if supplied, will be used
|
||||
by the PAM module instead of a message that is generated by the PAM
|
||||
module itself. */
|
||||
#define NSLCD_ACTION_PAM_AUTHZ 0x000d0002
|
||||
|
||||
/* PAM session open and close requests. These requests have the following
|
||||
extra request values:
|
||||
STRING tty
|
||||
STRING rhost
|
||||
STRING ruser
|
||||
INT32 session id (ignored for SESS_O)
|
||||
and these calls only return the session ID:
|
||||
INT32 session id
|
||||
The SESS_C must contain the ID that is retured by SESS_O to close the
|
||||
correct session. */
|
||||
#define NSLCD_ACTION_PAM_SESS_O 20003
|
||||
#define NSLCD_ACTION_PAM_SESS_C 20004
|
||||
/* PAM session open request. The result value consists of:
|
||||
STRING session id
|
||||
This session id may be used to close this session with. */
|
||||
#define NSLCD_ACTION_PAM_SESS_O 0x000d0003
|
||||
|
||||
/* PAM session close request. This request has the following
|
||||
extra request value:
|
||||
STRING session id
|
||||
and this calls only returns an empty response value. */
|
||||
#define NSLCD_ACTION_PAM_SESS_C 0x000d0004
|
||||
|
||||
/* PAM password modification request. This requests has the following extra
|
||||
request values:
|
||||
STRING old password
|
||||
STRING new password
|
||||
INT32 asroot: 0=oldpasswd is user passwd, 1=oldpasswd is root passwd
|
||||
STRING old password
|
||||
STRING new password
|
||||
and returns there extra result values:
|
||||
INT32 authz NSLCD_PAM_* result code
|
||||
STRING authorisation error message
|
||||
In this request the DN may be set to the administrator's DN. In this
|
||||
case old password should be the administrator's password. This allows
|
||||
the administrator to change any user's password. */
|
||||
#define NSLCD_ACTION_PAM_PWMOD 20005
|
||||
INT32 NSLCD_PAM_* result code
|
||||
STRING error message */
|
||||
#define NSLCD_ACTION_PAM_PWMOD 0x000d0005
|
||||
|
||||
/* User information change request. This request allows one to change
|
||||
their full name and other information. The request parameters for this
|
||||
request are:
|
||||
STRING user name
|
||||
INT32 asroot: 0=passwd is user passwd, 1=passwd is root passwd
|
||||
STRING password
|
||||
followed by one or more of the below, terminated by NSLCD_USERMOD_END
|
||||
INT32 NSLCD_USERMOD_*
|
||||
STRING new value
|
||||
the response consists of one or more of the entries below, terminated
|
||||
by NSLCD_USERMOD_END:
|
||||
INT32 NSLCD_USERMOD_*
|
||||
STRING response
|
||||
(if the response is blank, the change went OK, otherwise the string
|
||||
contains an error message)
|
||||
*/
|
||||
#define NSLCD_ACTION_USERMOD 0x000e0001
|
||||
|
||||
/* These are the possible values for the NSLCD_ACTION_USERMOD operation
|
||||
above. */
|
||||
#define NSLCD_USERMOD_END 0 /* end of change values */
|
||||
#define NSLCD_USERMOD_RESULT 1 /* global result value */
|
||||
#define NSLCD_USERMOD_FULLNAME 2 /* full name */
|
||||
#define NSLCD_USERMOD_ROOMNUMBER 3 /* room number */
|
||||
#define NSLCD_USERMOD_WORKPHONE 4 /* office phone number */
|
||||
#define NSLCD_USERMOD_HOMEPHONE 5 /* home phone number */
|
||||
#define NSLCD_USERMOD_OTHER 6 /* other info */
|
||||
#define NSLCD_USERMOD_HOMEDIR 7 /* home directory */
|
||||
#define NSLCD_USERMOD_SHELL 8 /* login shell */
|
||||
|
||||
/* Request result codes. */
|
||||
#define NSLCD_RESULT_BEGIN 0
|
||||
#define NSLCD_RESULT_END 3
|
||||
#define NSLCD_RESULT_BEGIN 1
|
||||
#define NSLCD_RESULT_END 2
|
||||
|
||||
/* Partial list of PAM result codes. */
|
||||
#define NSLCD_PAM_SUCCESS 0 /* everything ok */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
tio.c - timed io functions
|
||||
This file is part of the nss-pam-ldapd library.
|
||||
|
||||
Copyright (C) 2007, 2008, 2010, 2011, 2012 Arthur de Jong
|
||||
Copyright (C) 2007-2014 Arthur de Jong
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -20,7 +20,6 @@
|
|||
02110-1301 USA
|
||||
*/
|
||||
|
||||
//#include "config.h"
|
||||
#include "portable.h"
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
|
|
@ -37,6 +36,7 @@
|
|||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tio.h"
|
||||
|
||||
|
|
@ -76,124 +76,117 @@ struct tio_fileinfo {
|
|||
#endif /* DEBUG_TIO_STATS */
|
||||
};
|
||||
|
||||
/* build a timeval for comparison to when the operation should be finished */
|
||||
static inline void tio_get_deadline(struct timeval *deadline,int timeout)
|
||||
{
|
||||
if (gettimeofday(deadline,NULL))
|
||||
{
|
||||
/* just blank it in case of errors */
|
||||
deadline->tv_sec=0;
|
||||
deadline->tv_usec=0;
|
||||
return;
|
||||
}
|
||||
deadline->tv_sec+=timeout/1000;
|
||||
deadline->tv_sec+=(timeout%1000)*1000;
|
||||
}
|
||||
/* some older versions of Solaris don't provide CLOCK_MONOTONIC but do have
|
||||
a CLOCK_HIGHRES that has the same properties we need */
|
||||
#ifndef CLOCK_MONOTONIC
|
||||
#ifdef CLOCK_HIGHRES
|
||||
#define CLOCK_MONOTONIC CLOCK_HIGHRES
|
||||
#endif /* CLOCK_HIGHRES */
|
||||
#endif /* not CLOCK_MONOTONIC */
|
||||
|
||||
/* update the timeout to the value that is remaining before deadline
|
||||
returns non-zero if there is no more time before the deadline */
|
||||
static inline int tio_time_remaining(const struct timeval *deadline)
|
||||
/* update the timeout to the value that is remaining before the deadline
|
||||
returns the number of milliseconds before the deadline (or a negative
|
||||
value of the deadline has expired) */
|
||||
static inline int tio_time_remaining(struct timespec *deadline, int timeout)
|
||||
{
|
||||
struct timeval tv;
|
||||
/* get the current time */
|
||||
if (gettimeofday(&tv,NULL))
|
||||
struct timespec tv;
|
||||
/* if this is the first call, set the deadline and return the full time */
|
||||
if ((deadline->tv_sec == 0) && (deadline->tv_nsec == 0))
|
||||
{
|
||||
/* 1 second default if gettimeofday() is broken */
|
||||
return 1000;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, deadline) == 0)
|
||||
{
|
||||
deadline->tv_sec += timeout / 1000;
|
||||
deadline->tv_nsec += (timeout % 1000) * 1000000;
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
/* calculate time remaining in miliseconds */
|
||||
return (deadline->tv_sec-tv.tv_sec)*1000 + (deadline->tv_usec-tv.tv_usec)/1000;
|
||||
/* get the current time (fall back to full time on error) */
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tv))
|
||||
return timeout;
|
||||
/* calculate time remaining in milliseconds */
|
||||
return (deadline->tv_sec - tv.tv_sec) * 1000 +
|
||||
(deadline->tv_nsec - tv.tv_nsec) / 1000000;
|
||||
}
|
||||
|
||||
/* open a new TFILE based on the file descriptor */
|
||||
TFILE *tio_fdopen(int fd,int readtimeout,int writetimeout,
|
||||
size_t initreadsize,size_t maxreadsize,
|
||||
size_t initwritesize,size_t maxwritesize)
|
||||
TFILE *tio_fdopen(int fd, int readtimeout, int writetimeout,
|
||||
size_t initreadsize, size_t maxreadsize,
|
||||
size_t initwritesize, size_t maxwritesize)
|
||||
{
|
||||
struct tio_fileinfo *fp;
|
||||
fp=(struct tio_fileinfo *)malloc(sizeof(struct tio_fileinfo));
|
||||
if (fp==NULL)
|
||||
fp = (struct tio_fileinfo *)malloc(sizeof(struct tio_fileinfo));
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
fp->fd=fd;
|
||||
fp->fd = fd;
|
||||
/* initialize read buffer */
|
||||
fp->readbuffer.buffer=(uint8_t *)malloc(initreadsize);
|
||||
if (fp->readbuffer.buffer==NULL)
|
||||
fp->readbuffer.buffer = (uint8_t *)malloc(initreadsize);
|
||||
if (fp->readbuffer.buffer == NULL)
|
||||
{
|
||||
free(fp);
|
||||
return NULL;
|
||||
}
|
||||
fp->readbuffer.size=initreadsize;
|
||||
fp->readbuffer.maxsize=maxreadsize;
|
||||
fp->readbuffer.start=0;
|
||||
fp->readbuffer.len=0;
|
||||
fp->readbuffer.size = initreadsize;
|
||||
fp->readbuffer.maxsize = maxreadsize;
|
||||
fp->readbuffer.start = 0;
|
||||
fp->readbuffer.len = 0;
|
||||
/* initialize write buffer */
|
||||
fp->writebuffer.buffer=(uint8_t *)malloc(initwritesize);
|
||||
if (fp->writebuffer.buffer==NULL)
|
||||
fp->writebuffer.buffer = (uint8_t *)malloc(initwritesize);
|
||||
if (fp->writebuffer.buffer == NULL)
|
||||
{
|
||||
free(fp->readbuffer.buffer);
|
||||
free(fp);
|
||||
return NULL;
|
||||
}
|
||||
fp->writebuffer.size=initwritesize;
|
||||
fp->writebuffer.maxsize=maxwritesize;
|
||||
fp->writebuffer.start=0;
|
||||
fp->writebuffer.len=0;
|
||||
fp->writebuffer.size = initwritesize;
|
||||
fp->writebuffer.maxsize = maxwritesize;
|
||||
fp->writebuffer.start = 0;
|
||||
fp->writebuffer.len = 0;
|
||||
/* initialize other attributes */
|
||||
fp->readtimeout=readtimeout;
|
||||
fp->writetimeout=writetimeout;
|
||||
fp->read_resettable=0;
|
||||
fp->readtimeout = readtimeout;
|
||||
fp->writetimeout = writetimeout;
|
||||
fp->read_resettable = 0;
|
||||
#ifdef DEBUG_TIO_STATS
|
||||
fp->byteswritten=0;
|
||||
fp->bytesread=0;
|
||||
fp->byteswritten = 0;
|
||||
fp->bytesread = 0;
|
||||
#endif /* DEBUG_TIO_STATS */
|
||||
return fp;
|
||||
}
|
||||
|
||||
/* wait for any activity on the specified file descriptor using
|
||||
the specified deadline */
|
||||
static int tio_wait(TFILE *fp,int readfd,const struct timeval *deadline)
|
||||
static int tio_wait(int fd, short events, int timeout,
|
||||
struct timespec *deadline)
|
||||
{
|
||||
int timeout;
|
||||
int t;
|
||||
struct pollfd fds[1];
|
||||
int rv;
|
||||
while (1)
|
||||
{
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = events;
|
||||
/* figure out the time we need to wait */
|
||||
if ((timeout=tio_time_remaining(deadline))<0)
|
||||
if ((t = tio_time_remaining(deadline, timeout)) < 0)
|
||||
{
|
||||
errno=ETIME;
|
||||
errno = ETIME;
|
||||
return -1;
|
||||
}
|
||||
/* sanitiy check for moving clock */
|
||||
if (t > timeout)
|
||||
t = timeout;
|
||||
/* wait for activity */
|
||||
if (readfd)
|
||||
{
|
||||
fds[0].fd=fp->fd;
|
||||
fds[0].events=POLLIN;
|
||||
/* santiy check for moving clock */
|
||||
if (timeout>fp->readtimeout)
|
||||
timeout=fp->readtimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
fds[0].fd=fp->fd;
|
||||
fds[0].events=POLLOUT;
|
||||
/* santiy check for moving clock */
|
||||
if (timeout>fp->writetimeout)
|
||||
timeout=fp->writetimeout;
|
||||
}
|
||||
rv=poll(fds,1,timeout);
|
||||
if (rv>0)
|
||||
rv = poll(fds, 1, t);
|
||||
if (rv > 0)
|
||||
return 0; /* we have activity */
|
||||
else if (rv==0)
|
||||
else if (rv == 0)
|
||||
{
|
||||
/* no file descriptors were available within the specified time */
|
||||
errno=ETIME;
|
||||
errno = ETIME;
|
||||
return -1;
|
||||
}
|
||||
else if (errno!=EINTR)
|
||||
else if ((errno != EINTR) && (errno != EAGAIN))
|
||||
/* some error ocurred */
|
||||
return -1;
|
||||
/* we just try again on EINTR */
|
||||
/* we just try again on EINTR or EAGAIN */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,93 +194,92 @@ static int tio_wait(TFILE *fp,int readfd,const struct timeval *deadline)
|
|||
if no data was read in the specified time an error is returned */
|
||||
int tio_read(TFILE *fp, void *buf, size_t count)
|
||||
{
|
||||
struct timeval deadline;
|
||||
struct timespec deadline = {0, 0};
|
||||
int rv;
|
||||
uint8_t *tmp;
|
||||
size_t newsz;
|
||||
size_t len;
|
||||
/* have a more convenient storage type for the buffer */
|
||||
uint8_t *ptr=(uint8_t *)buf;
|
||||
/* build a time by which we should be finished */
|
||||
tio_get_deadline(&deadline,fp->readtimeout);
|
||||
uint8_t *ptr = (uint8_t *)buf;
|
||||
/* loop until we have returned all the needed data */
|
||||
while (1)
|
||||
{
|
||||
/* check if we have enough data in the buffer */
|
||||
if (fp->readbuffer.len >= count)
|
||||
{
|
||||
if (count>0)
|
||||
if (count > 0)
|
||||
{
|
||||
if (ptr!=NULL)
|
||||
memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,count);
|
||||
if (ptr != NULL)
|
||||
memcpy(ptr, fp->readbuffer.buffer + fp->readbuffer.start, count);
|
||||
/* adjust buffer position */
|
||||
fp->readbuffer.start+=count;
|
||||
fp->readbuffer.len-=count;
|
||||
fp->readbuffer.start += count;
|
||||
fp->readbuffer.len -= count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* empty what we have and continue from there */
|
||||
if (fp->readbuffer.len>0)
|
||||
if (fp->readbuffer.len > 0)
|
||||
{
|
||||
if (ptr!=NULL)
|
||||
if (ptr != NULL)
|
||||
{
|
||||
memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.len);
|
||||
ptr+=fp->readbuffer.len;
|
||||
memcpy(ptr, fp->readbuffer.buffer + fp->readbuffer.start,
|
||||
fp->readbuffer.len);
|
||||
ptr += fp->readbuffer.len;
|
||||
}
|
||||
count-=fp->readbuffer.len;
|
||||
fp->readbuffer.start+=fp->readbuffer.len;
|
||||
fp->readbuffer.len=0;
|
||||
count -= fp->readbuffer.len;
|
||||
fp->readbuffer.start += fp->readbuffer.len;
|
||||
fp->readbuffer.len = 0;
|
||||
}
|
||||
/* after this point until the read fp->readbuffer.len is 0 */
|
||||
if (!fp->read_resettable)
|
||||
{
|
||||
/* the stream is not resettable, re-use the buffer */
|
||||
fp->readbuffer.start=0;
|
||||
fp->readbuffer.start = 0;
|
||||
}
|
||||
else if (fp->readbuffer.start>=(fp->readbuffer.size-4))
|
||||
else if (fp->readbuffer.start >= (fp->readbuffer.size - 4))
|
||||
{
|
||||
/* buffer is running empty, try to grow buffer */
|
||||
if (fp->readbuffer.size<fp->readbuffer.maxsize)
|
||||
if (fp->readbuffer.size < fp->readbuffer.maxsize)
|
||||
{
|
||||
newsz=fp->readbuffer.size*2;
|
||||
if (newsz>fp->readbuffer.maxsize)
|
||||
newsz=fp->readbuffer.maxsize;
|
||||
tmp=realloc(fp->readbuffer.buffer,newsz);
|
||||
if (tmp!=NULL)
|
||||
newsz = fp->readbuffer.size * 2;
|
||||
if (newsz > fp->readbuffer.maxsize)
|
||||
newsz = fp->readbuffer.maxsize;
|
||||
tmp = realloc(fp->readbuffer.buffer, newsz);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
fp->readbuffer.buffer=tmp;
|
||||
fp->readbuffer.size=newsz;
|
||||
fp->readbuffer.buffer = tmp;
|
||||
fp->readbuffer.size = newsz;
|
||||
}
|
||||
}
|
||||
/* if buffer still does not contain enough room, clear resettable */
|
||||
if (fp->readbuffer.start>=(fp->readbuffer.size-4))
|
||||
if (fp->readbuffer.start >= (fp->readbuffer.size - 4))
|
||||
{
|
||||
fp->readbuffer.start=0;
|
||||
fp->read_resettable=0;
|
||||
fp->readbuffer.start = 0;
|
||||
fp->read_resettable = 0;
|
||||
}
|
||||
}
|
||||
/* wait until we have input */
|
||||
if (tio_wait(fp,1,&deadline))
|
||||
if (tio_wait(fp->fd, POLLIN, fp->readtimeout, &deadline))
|
||||
return -1;
|
||||
/* read the input in the buffer */
|
||||
len=fp->readbuffer.size-fp->readbuffer.start;
|
||||
len = fp->readbuffer.size - fp->readbuffer.start;
|
||||
#ifdef SSIZE_MAX
|
||||
if (len>SSIZE_MAX)
|
||||
len=SSIZE_MAX;
|
||||
if (len > SSIZE_MAX)
|
||||
len = SSIZE_MAX;
|
||||
#endif /* SSIZE_MAX */
|
||||
rv=read(fp->fd,fp->readbuffer.buffer+fp->readbuffer.start,len);
|
||||
rv = read(fp->fd, fp->readbuffer.buffer + fp->readbuffer.start, len);
|
||||
/* check for errors */
|
||||
if (rv==0)
|
||||
if (rv == 0)
|
||||
{
|
||||
errno=ECONNRESET;
|
||||
errno = ECONNRESET;
|
||||
return -1;
|
||||
}
|
||||
else if ((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN))
|
||||
return -1; /* something went wrong with the read */
|
||||
/* skip the read part in the buffer */
|
||||
fp->readbuffer.len=rv;
|
||||
else if ((rv < 0) && (errno != EINTR) && (errno != EAGAIN))
|
||||
return -1; /* something went wrong with the read */
|
||||
else if (rv > 0)
|
||||
fp->readbuffer.len = rv; /* skip the read part in the buffer */
|
||||
#ifdef DEBUG_TIO_STATS
|
||||
fp->bytesread+=rv;
|
||||
fp->bytesread += rv;
|
||||
#endif /* DEBUG_TIO_STATS */
|
||||
}
|
||||
}
|
||||
|
|
@ -295,45 +287,37 @@ int tio_read(TFILE *fp, void *buf, size_t count)
|
|||
/* Read and discard the specified number of bytes from the stream. */
|
||||
int tio_skip(TFILE *fp, size_t count)
|
||||
{
|
||||
return tio_read(fp,NULL,count);
|
||||
return tio_read(fp, NULL, count);
|
||||
}
|
||||
|
||||
/* Read all available data from the stream and empty the read buffer. */
|
||||
int tio_skipall(TFILE *fp)
|
||||
int tio_skipall(TFILE *fp, int timeout)
|
||||
{
|
||||
struct pollfd fds[1];
|
||||
struct timespec deadline = {0, 0};
|
||||
int rv;
|
||||
size_t len;
|
||||
/* clear the read buffer */
|
||||
fp->readbuffer.start=0;
|
||||
fp->readbuffer.len=0;
|
||||
fp->read_resettable=0;
|
||||
fp->readbuffer.start = 0;
|
||||
fp->readbuffer.len = 0;
|
||||
fp->read_resettable = 0;
|
||||
/* read until we can't read no more */
|
||||
len=fp->readbuffer.size;
|
||||
len = fp->readbuffer.size;
|
||||
#ifdef SSIZE_MAX
|
||||
if (len>SSIZE_MAX)
|
||||
len=SSIZE_MAX;
|
||||
if (len > SSIZE_MAX)
|
||||
len = SSIZE_MAX;
|
||||
#endif /* SSIZE_MAX */
|
||||
while (1)
|
||||
{
|
||||
/* see if any data is available */
|
||||
fds[0].fd=fp->fd;
|
||||
fds[0].events=POLLIN;
|
||||
rv=poll(fds,1,0);
|
||||
/* check the poll() result */
|
||||
if (rv==0)
|
||||
return 0; /* no file descriptor ready */
|
||||
if ((rv<0)&&((errno==EINTR)||(errno==EAGAIN)))
|
||||
continue; /* interrupted, try again */
|
||||
if (rv<0)
|
||||
return -1; /* something went wrong */
|
||||
/* wait until we have input */
|
||||
if (tio_wait(fp->fd, POLLIN, timeout, &deadline))
|
||||
return -1;
|
||||
/* read data from the stream */
|
||||
rv=read(fp->fd,fp->readbuffer.buffer,len);
|
||||
if (rv==0)
|
||||
rv = read(fp->fd, fp->readbuffer.buffer, len);
|
||||
if (rv == 0)
|
||||
return 0; /* end-of-file */
|
||||
if ((rv<0)&&(errno==EWOULDBLOCK))
|
||||
if ((rv < 0) && (errno == EWOULDBLOCK))
|
||||
return 0; /* we've ready everything we can without blocking */
|
||||
if ((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN))
|
||||
if ((rv < 0) && (errno != EINTR) && (errno != EAGAIN))
|
||||
return -1; /* something went wrong with the read */
|
||||
}
|
||||
}
|
||||
|
|
@ -345,46 +329,50 @@ static int tio_writebuf(TFILE *fp)
|
|||
int rv;
|
||||
/* write the buffer */
|
||||
#ifdef MSG_NOSIGNAL
|
||||
rv=send(fp->fd,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len,MSG_NOSIGNAL);
|
||||
rv = send(fp->fd, fp->writebuffer.buffer + fp->writebuffer.start,
|
||||
fp->writebuffer.len, MSG_NOSIGNAL);
|
||||
#else /* not MSG_NOSIGNAL */
|
||||
/* on platforms that cannot use send() with masked signals, we change the
|
||||
signal mask and change it back after the write (note that there is a
|
||||
race condition here) */
|
||||
struct sigaction act,oldact;
|
||||
struct sigaction act, oldact;
|
||||
/* set up sigaction */
|
||||
memset(&act,0,sizeof(struct sigaction));
|
||||
act.sa_sigaction=NULL;
|
||||
act.sa_handler=SIG_IGN;
|
||||
memset(&act, 0, sizeof(struct sigaction));
|
||||
act.sa_sigaction = NULL;
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags=SA_RESTART;
|
||||
act.sa_flags = SA_RESTART;
|
||||
/* ignore SIGPIPE */
|
||||
if (sigaction(SIGPIPE,&act,&oldact)!=0)
|
||||
if (sigaction(SIGPIPE, &act, &oldact) != 0)
|
||||
return -1; /* error setting signal handler */
|
||||
/* write the buffer */
|
||||
rv=write(fp->fd,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len);
|
||||
rv = write(fp->fd, fp->writebuffer.buffer + fp->writebuffer.start,
|
||||
fp->writebuffer.len);
|
||||
/* restore the old handler for SIGPIPE */
|
||||
if (sigaction(SIGPIPE,&oldact,NULL)!=0)
|
||||
if (sigaction(SIGPIPE, &oldact, NULL) != 0)
|
||||
return -1; /* error restoring signal handler */
|
||||
#endif
|
||||
/* check for errors */
|
||||
if ((rv==0)||((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN)))
|
||||
if ((rv == 0) || ((rv < 0) && (errno != EINTR) && (errno != EAGAIN)))
|
||||
return -1; /* something went wrong with the write */
|
||||
/* skip the written part in the buffer */
|
||||
if (rv>0)
|
||||
if (rv > 0)
|
||||
{
|
||||
fp->writebuffer.start+=rv;
|
||||
fp->writebuffer.len-=rv;
|
||||
fp->writebuffer.start += rv;
|
||||
fp->writebuffer.len -= rv;
|
||||
#ifdef DEBUG_TIO_STATS
|
||||
fp->byteswritten+=rv;
|
||||
fp->byteswritten += rv;
|
||||
#endif /* DEBUG_TIO_STATS */
|
||||
/* reset start if len is 0 */
|
||||
if (fp->writebuffer.len==0)
|
||||
fp->writebuffer.start=0;
|
||||
if (fp->writebuffer.len == 0)
|
||||
fp->writebuffer.start = 0;
|
||||
/* move contents of the buffer to the front if it will save enough room */
|
||||
if (fp->writebuffer.start>=(fp->writebuffer.size/4))
|
||||
if (fp->writebuffer.start >= (fp->writebuffer.size / 4))
|
||||
{
|
||||
memmove(fp->writebuffer.buffer,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len);
|
||||
fp->writebuffer.start=0;
|
||||
memmove(fp->writebuffer.buffer,
|
||||
fp->writebuffer.buffer + fp->writebuffer.start,
|
||||
fp->writebuffer.len);
|
||||
fp->writebuffer.start = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -393,14 +381,12 @@ static int tio_writebuf(TFILE *fp)
|
|||
/* write all the data in the buffer to the stream */
|
||||
int tio_flush(TFILE *fp)
|
||||
{
|
||||
struct timeval deadline;
|
||||
/* build a time by which we should be finished */
|
||||
tio_get_deadline(&deadline,fp->writetimeout);
|
||||
struct timespec deadline = {0, 0};
|
||||
/* loop until we have written our buffer */
|
||||
while (fp->writebuffer.len > 0)
|
||||
{
|
||||
/* wait until we can write */
|
||||
if (tio_wait(fp,0,&deadline))
|
||||
if (tio_wait(fp->fd, POLLOUT, fp->writetimeout, &deadline))
|
||||
return -1;
|
||||
/* write one block */
|
||||
if (tio_writebuf(fp))
|
||||
|
|
@ -415,16 +401,16 @@ static int tio_flush_nonblock(TFILE *fp)
|
|||
{
|
||||
struct pollfd fds[1];
|
||||
int rv;
|
||||
/* wait for activity */
|
||||
fds[0].fd=fp->fd;
|
||||
fds[0].events=POLLOUT;
|
||||
rv=poll(fds,1,0);
|
||||
/* see if we can write without blocking */
|
||||
fds[0].fd = fp->fd;
|
||||
fds[0].events = POLLOUT;
|
||||
rv = poll(fds, 1, 0);
|
||||
/* check if any file descriptors were ready (timeout) or we were
|
||||
interrupted */
|
||||
if ((rv==0)||((rv<0)&&(errno==EINTR)))
|
||||
if ((rv == 0) || ((rv < 0) && ((errno == EINTR) || (errno == EAGAIN))))
|
||||
return 0;
|
||||
/* any other errors? */
|
||||
if (rv<0)
|
||||
if (rv < 0)
|
||||
return -1;
|
||||
/* so file descriptor will accept writes */
|
||||
return tio_writebuf(fp);
|
||||
|
|
@ -435,44 +421,46 @@ int tio_write(TFILE *fp, const void *buf, size_t count)
|
|||
size_t fr;
|
||||
uint8_t *tmp;
|
||||
size_t newsz;
|
||||
const uint8_t *ptr=(const uint8_t *)buf;
|
||||
const uint8_t *ptr = (const uint8_t *)buf;
|
||||
/* keep filling the buffer until we have bufferred everything */
|
||||
while (count>0)
|
||||
while (count > 0)
|
||||
{
|
||||
/* figure out free size in buffer */
|
||||
fr=fp->writebuffer.size-(fp->writebuffer.start+fp->writebuffer.len);
|
||||
fr = fp->writebuffer.size - (fp->writebuffer.start + fp->writebuffer.len);
|
||||
if (count <= fr)
|
||||
{
|
||||
/* the data fits in the buffer */
|
||||
memcpy(fp->writebuffer.buffer+fp->writebuffer.start+fp->writebuffer.len,ptr,count);
|
||||
fp->writebuffer.len+=count;
|
||||
memcpy(fp->writebuffer.buffer + fp->writebuffer.start +
|
||||
fp->writebuffer.len, ptr, count);
|
||||
fp->writebuffer.len += count;
|
||||
return 0;
|
||||
}
|
||||
else if (fr > 0)
|
||||
{
|
||||
/* fill the buffer with data that will fit */
|
||||
memcpy(fp->writebuffer.buffer+fp->writebuffer.start+fp->writebuffer.len,ptr,fr);
|
||||
fp->writebuffer.len+=fr;
|
||||
ptr+=fr;
|
||||
count-=fr;
|
||||
memcpy(fp->writebuffer.buffer + fp->writebuffer.start +
|
||||
fp->writebuffer.len, ptr, fr);
|
||||
fp->writebuffer.len += fr;
|
||||
ptr += fr;
|
||||
count -= fr;
|
||||
}
|
||||
/* try to flush some of the data that is in the buffer */
|
||||
if (tio_flush_nonblock(fp))
|
||||
return -1;
|
||||
/* if we have room now, try again */
|
||||
if (fp->writebuffer.size>(fp->writebuffer.start+fp->writebuffer.len))
|
||||
if (fp->writebuffer.size > (fp->writebuffer.start + fp->writebuffer.len))
|
||||
continue;
|
||||
/* try to grow the buffer */
|
||||
if (fp->writebuffer.size<fp->writebuffer.maxsize)
|
||||
if (fp->writebuffer.size < fp->writebuffer.maxsize)
|
||||
{
|
||||
newsz=fp->writebuffer.size*2;
|
||||
if (newsz>fp->writebuffer.maxsize)
|
||||
newsz=fp->writebuffer.maxsize;
|
||||
tmp=realloc(fp->writebuffer.buffer,newsz);
|
||||
if (tmp!=NULL)
|
||||
newsz = fp->writebuffer.size * 2;
|
||||
if (newsz > fp->writebuffer.maxsize)
|
||||
newsz = fp->writebuffer.maxsize;
|
||||
tmp = realloc(fp->writebuffer.buffer, newsz);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
fp->writebuffer.buffer=tmp;
|
||||
fp->writebuffer.size=newsz;
|
||||
fp->writebuffer.buffer = tmp;
|
||||
fp->writebuffer.size = newsz;
|
||||
continue; /* try again */
|
||||
}
|
||||
}
|
||||
|
|
@ -487,15 +475,18 @@ int tio_close(TFILE *fp)
|
|||
{
|
||||
int retv;
|
||||
/* write any buffered data */
|
||||
retv=tio_flush(fp);
|
||||
retv = tio_flush(fp);
|
||||
#ifdef DEBUG_TIO_STATS
|
||||
/* dump statistics to stderr */
|
||||
fprintf(stderr,"DEBUG_TIO_STATS READ=%d WRITTEN=%d\n",fp->bytesread,fp->byteswritten);
|
||||
fprintf(stderr, "DEBUG_TIO_STATS READ=%d WRITTEN=%d\n", fp->bytesread,
|
||||
fp->byteswritten);
|
||||
#endif /* DEBUG_TIO_STATS */
|
||||
/* close file descriptor */
|
||||
if (close(fp->fd))
|
||||
retv=-1;
|
||||
retv = -1;
|
||||
/* free any allocated buffers */
|
||||
memset(fp->readbuffer.buffer, 0, fp->readbuffer.size);
|
||||
memset(fp->writebuffer.buffer, 0, fp->writebuffer.size);
|
||||
free(fp->readbuffer.buffer);
|
||||
free(fp->writebuffer.buffer);
|
||||
/* free the tio struct itself */
|
||||
|
|
@ -507,13 +498,14 @@ int tio_close(TFILE *fp)
|
|||
void tio_mark(TFILE *fp)
|
||||
{
|
||||
/* move any data in the buffer to the start of the buffer */
|
||||
if ((fp->readbuffer.start>0)&&(fp->readbuffer.len>0))
|
||||
if ((fp->readbuffer.start > 0) && (fp->readbuffer.len > 0))
|
||||
{
|
||||
memmove(fp->readbuffer.buffer,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.len);
|
||||
fp->readbuffer.start=0;
|
||||
memmove(fp->readbuffer.buffer,
|
||||
fp->readbuffer.buffer + fp->readbuffer.start, fp->readbuffer.len);
|
||||
fp->readbuffer.start = 0;
|
||||
}
|
||||
/* mark the stream as resettable */
|
||||
fp->read_resettable=1;
|
||||
fp->read_resettable = 1;
|
||||
}
|
||||
|
||||
int tio_reset(TFILE *fp)
|
||||
|
|
@ -522,7 +514,7 @@ int tio_reset(TFILE *fp)
|
|||
if (!fp->read_resettable)
|
||||
return -1;
|
||||
/* reset the buffer */
|
||||
fp->readbuffer.len+=fp->readbuffer.start;
|
||||
fp->readbuffer.start=0;
|
||||
fp->readbuffer.len += fp->readbuffer.start;
|
||||
fp->readbuffer.start = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
tio.h - timed io functions
|
||||
This file is part of the nss-pam-ldapd library.
|
||||
|
||||
Copyright (C) 2007, 2008, 2010, 2012 Arthur de Jong
|
||||
Copyright (C) 2007, 2008, 2010, 2012, 2013 Arthur de Jong
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -47,22 +47,22 @@ typedef struct tio_fileinfo TFILE;
|
|||
|
||||
/* Open a new TFILE based on the file descriptor. The timeout is set for any
|
||||
operation (value in milliseconds). */
|
||||
TFILE *tio_fdopen(int fd,int readtimeout,int writetimeout,
|
||||
size_t initreadsize,size_t maxreadsize,
|
||||
size_t initwritesize,size_t maxwritesize)
|
||||
TFILE *tio_fdopen(int fd, int readtimeout, int writetimeout,
|
||||
size_t initreadsize, size_t maxreadsize,
|
||||
size_t initwritesize, size_t maxwritesize)
|
||||
LIKE_MALLOC MUST_USE;
|
||||
|
||||
/* Read the specified number of bytes from the stream. */
|
||||
int tio_read(TFILE *fp,void *buf,size_t count);
|
||||
int tio_read(TFILE *fp, void *buf, size_t count);
|
||||
|
||||
/* Read and discard the specified number of bytes from the stream. */
|
||||
int tio_skip(TFILE *fp,size_t count);
|
||||
int tio_skip(TFILE *fp, size_t count);
|
||||
|
||||
/* Read all available data from the stream and empty the read buffer. */
|
||||
int tio_skipall(TFILE *fp);
|
||||
int tio_skipall(TFILE *fp, int timeout);
|
||||
|
||||
/* Write the specified buffer to the stream. */
|
||||
int tio_write(TFILE *fp,const void *buf,size_t count);
|
||||
int tio_write(TFILE *fp, const void *buf, size_t count);
|
||||
|
||||
/* Write out all buffered data to the stream. */
|
||||
int tio_flush(TFILE *fp);
|
||||
|
|
|
|||
Loading…
Reference in a new issue