/*++
/* NAME
/* dict_nisplus 3
/* SUMMARY
/* dictionary manager interface to NIS+ maps
/* SYNOPSIS
/* #include <dict_nisplus.h>
/*
/* DICT *dict_nisplus_open(map, open_flags, dict_flags)
/* const char *map;
/* int dummy;
/* int dict_flags;
/* DESCRIPTION
/* dict_nisplus_open() makes the specified NIS+ map accessible via
/* the generic dictionary operations described in dict_open(3).
/* The \fIdummy\fR argument is not used.
/* SEE ALSO
/* dict(3) generic dictionary manager
/* DIAGNOSTICS
/* Fatal errors:
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Geoff Gibbs
/* UK-HGMP-RC
/* Hinxton
/* Cambridge
/* CB10 1SB, UK
/*
/* based on the code for dict_nis.c et al by :-
/*
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#ifdef HAS_NISPLUS
#include <rpcsvc/nis.h> /* for nis_list */
#endif
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <vstring.h>
#include <stringops.h>
#include <dict.h>
#include <dict_nisplus.h>
#ifdef HAS_NISPLUS
/* Application-specific. */
typedef struct {
DICT dict; /* generic members */
char *template ; /* parsed query template */
int column; /* NIS+ field number (start at 1) */
} DICT_NISPLUS;
/*
* Begin quote from nis + ( 1 ) :
*
* The following text represents a context - free grammar that defines the
* set of legal NIS + names . The terminals in this grammar are the
* characters ` . ' ( dot ) , ` [ ' ( open bracket ) , ` ] ' ( close bracket ) , ` , '
* ( comma ) , ` = ' ( equals ) and whitespace . Angle brackets ( ` < ' and ` > ' ) ,
* which delineate non - terminals , are not part of the grammar . The
* character ` | ' ( vertical bar ) is used to separate alternate productions
* and should be read as ` ` this production OR this production ' ' .
*
* name : : = . | < simple name > | < indexed name >
*
* simple name : : = < string > . | < string > . < simple name >
*
* indexed name : : = < search criterion > , < simple name >
*
* search criterion : : = [ < attribute list > ]
*
* attribute list : : = < attribute > | < attribute > , < attribute list >
*
* attribute : : = < string > = < string >
*
* string : : = ISO Latin 1 character set except the character
* ' / ' ( slash ) . The initial character may not be a terminal character or
* the characters ' @ ' ( at ) , ' + ' ( plus ) , or ( ` - ' ) hyphen .
*
* Terminals that appear in strings must be quoted with ` " ' ( double quote ) .
* The ` " ' character may be quoted by quoting it with itself ` " " ' .
*
* End quote fron nis + ( 1 ) .
*
* This NIS client always quotes the entire query string ( the value part of
* [ attribute = value ] , file . domain . ) so the issue with initial characters
* should not be applicable . One wonders what restrictions are applicable
* when a string is quoted , but the manual doesn ' t specify what can appear
* between quotes , and we don ' t want to get burned .
*/
/*
* SLMs .
*/
#define STR(x) vstring_str(x)
/* dict_nisplus_lookup - find table entry */
static const char *dict_nisplus_lookup(DICT *dict, const char *key)
{
const char *myname = "dict_nisplus_lookup" ;
DICT_NISPLUS *dict_nisplus = (DICT_NISPLUS *) dict;
static VSTRING *quoted_key;
static VSTRING *query;
static VSTRING *retval;
nis_result *reply;
int count;
const char *cp;
int last_col;
int ch;
dict->error = 0 ;
/*
* Initialize .
*/
if (quoted_key == 0 ) {
query = vstring_alloc(100 );
retval = vstring_alloc(100 );
quoted_key = vstring_alloc(100 );
}
/*
* Optionally fold the key .
*/
if (dict->flags & DICT_FLAG_FOLD_FIX) {
if (dict->fold_buf == 0 )
dict->fold_buf = vstring_alloc(10 );
vstring_strcpy(dict->fold_buf, key);
key = lowercase(vstring_str(dict->fold_buf));
}
/*
* Check that the lookup key does not contain characters disallowed by
* nis + ( 1 ) .
*
* XXX Many client implementations don ' t seem to care about disallowed
* characters .
*/
VSTRING_RESET(quoted_key);
VSTRING_ADDCH(quoted_key, '"' );
for (cp = key; (ch = *(unsigned const char *) cp) != 0 ; cp++) {
if ((ISASCII(ch) && !ISPRINT(ch)) || (ch > 126 && ch < 160 )) {
msg_warn("map %s:%s: lookup key with non-printing character 0x%x:"
" ignoring this request" ,
dict->type, dict->name, ch);
return (0 );
} else if (ch == '"' ) {
VSTRING_ADDCH(quoted_key, '"' );
}
VSTRING_ADDCH(quoted_key, ch);
}
VSTRING_ADDCH(quoted_key, '"' );
VSTRING_TERMINATE(quoted_key);
/*
* Plug the key into the query template , which typically looks something
* like the following : [ alias = % s ] , mail_aliases . org_dir . my . nisplus . domain .
*
* XXX The nis + documentation defines a length limit for simple names like
* a . b . c . , but defines no length limit for ( the components of ) indexed
* names such as [ x = y ] , a . b . c . Our query length is limited because Postfix
* addresses ( in envelopes or in headers ) have a finite length .
*/
vstring_sprintf(query, dict_nisplus->template , STR(quoted_key));
reply = nis_list(STR(query), FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
/*
* When lookup succeeds , the result may be ambiguous , or the requested
* column may not exist .
*/
if (reply->status == NIS_SUCCESS) {
if ((count = NIS_RES_NUMOBJ(reply)) != 1 ) {
msg_warn("ambiguous match (%d results) for %s in NIS+ map %s:"
" ignoring this request" ,
count, key, dict_nisplus->dict.name);
nis_freeresult(reply);
return (0 );
} else {
last_col = NIS_RES_OBJECT(reply)->zo_data
.objdata_u.en_data.en_cols.en_cols_len - 1 ;
if (dict_nisplus->column > last_col)
msg_fatal("requested column %d > max column %d in table %s" ,
dict_nisplus->column, last_col,
dict_nisplus->dict.name);
vstring_strcpy(retval,
NIS_RES_OBJECT(reply)->zo_data.objdata_u
.en_data.en_cols.en_cols_val[dict_nisplus->column]
.ec_value.ec_value_val);
if (msg_verbose)
msg_info("%s: %s, column %d -> %s" , myname, STR(query),
dict_nisplus->column, STR(retval));
nis_freeresult(reply);
return (STR(retval));
}
}
/*
* When the NIS + lookup fails for reasons other than " key not found " ,
* keep logging warnings , and hope that someone will eventually notice
* the problem and fix it .
*/
else {
if (reply->status != NIS_NOTFOUND
&& reply->status != NIS_PARTIAL) {
msg_warn("lookup %s, NIS+ map %s: %s" ,
key, dict_nisplus->dict.name,
nis_sperrno(reply->status));
dict->error = DICT_ERR_RETRY;
} else {
if (msg_verbose)
msg_info("%s: not found: query %s" , myname, STR(query));
}
nis_freeresult(reply);
return (0 );
}
}
/* dict_nisplus_close - close NISPLUS map */
static void dict_nisplus_close(DICT *dict)
{
DICT_NISPLUS *dict_nisplus = (DICT_NISPLUS *) dict;
myfree(dict_nisplus->template );
if (dict->fold_buf)
vstring_free(dict->fold_buf);
dict_free(dict);
}
/* dict_nisplus_open - open NISPLUS map */
DICT *dict_nisplus_open(const char *map, int open_flags, int dict_flags)
{
const char *myname = "dict_nisplus_open" ;
DICT_NISPLUS *dict_nisplus;
char *col_field;
/*
* Sanity check .
*/
if (open_flags != O_RDONLY)
return (dict_surrogate(DICT_TYPE_NISPLUS, map, open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode" ,
DICT_TYPE_NISPLUS, map));
/*
* Initialize . This is a read - only map with fixed strings , not with
* regular expressions .
*/
dict_nisplus = (DICT_NISPLUS *)
dict_alloc(DICT_TYPE_NISPLUS, map, sizeof (*dict_nisplus));
dict_nisplus->dict.lookup = dict_nisplus_lookup;
dict_nisplus->dict.close = dict_nisplus_close;
dict_nisplus->dict.flags = dict_flags | DICT_FLAG_FIXED;
if (dict_flags & DICT_FLAG_FOLD_FIX)
dict_nisplus->dict.fold_buf = vstring_alloc(10 );
dict_nisplus->dict.owner.status = DICT_OWNER_TRUSTED;
/*
* Convert the query template into an indexed name and column number . The
* query template looks like :
*
* [ attribute = % s ; attribute = value . . . ] ; simple . name . : column
*
* One instance of % s gets to be replaced by a version of the lookup key ;
* other attributes must specify fixed values . The reason for using ' ; '
* is that the comma character is special in main . cf . When no column
* number is given at the end of the map name , we use a default column .
*/
dict_nisplus->template = mystrdup(map);
translit(dict_nisplus->template , ";" , "," );
if ((col_field = strstr(dict_nisplus->template , ".:" )) != 0 ) {
col_field[1 ] = 0 ;
col_field += 2 ;
if (!alldig(col_field) || (dict_nisplus->column = atoi(col_field)) < 1 )
msg_fatal("bad column field in NIS+ map name: %s" , map);
} else {
dict_nisplus->column = 1 ;
}
if (msg_verbose)
msg_info("%s: opened NIS+ table %s for column %d" ,
myname, dict_nisplus->template , dict_nisplus->column);
return (&dict_nisplus->dict);
}
#endif
Messung V0.5 in Prozent C=72 H=94 G=83
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.1Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08)
¤
*Bot Zugriff