📄 map.c
字号:
(void) strlcpy(host_record, vp, sizeof host_record);
free(vp);
if (tTd(38, 44))
dprintf("got record `%s'\n", host_record);
if (!extract_canonname(nbuf, host_record, cbuf, sizeof cbuf))
{
/* this should not happen, but.... */
*statp = EX_NOHOST;
return FALSE;
}
if (hbsize < strlen(cbuf))
{
*statp = EX_UNAVAILABLE;
return FALSE;
}
(void) strlcpy(name, cbuf, hbsize);
*statp = EX_OK;
return TRUE;
}
#endif /* NIS */
/*
** NISPLUS Modules
**
** This code donated by Sun Microsystems.
*/
#ifdef NISPLUS
# undef NIS /* symbol conflict in nis.h */
# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */
# include <rpcsvc/nis.h>
# include <rpcsvc/nislib.h>
# define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
# define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
# define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
# define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.')
/*
** NISPLUS_MAP_OPEN -- open nisplus table
*/
bool
nisplus_map_open(map, mode)
MAP *map;
int mode;
{
nis_result *res = NULL;
int retry_cnt, max_col, i;
char qbuf[MAXLINE + NIS_MAXNAMELEN];
if (tTd(38, 2))
dprintf("nisplus_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
errno = EPERM;
return FALSE;
}
if (*map->map_file == '\0')
map->map_file = "mail_aliases.org_dir";
if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
{
/* set default NISPLUS Domain to $m */
map->map_domain = newstr(nisplus_default_domain());
if (tTd(38, 2))
dprintf("nisplus_map_open(%s): using domain %s\n",
map->map_file, map->map_domain);
}
if (!PARTIAL_NAME(map->map_file))
{
map->map_domain = newstr("");
snprintf(qbuf, sizeof qbuf, "%s", map->map_file);
}
else
{
/* check to see if this map actually exists */
snprintf(qbuf, sizeof qbuf, "%s.%s",
map->map_file, map->map_domain);
}
retry_cnt = 0;
while (res == NULL || res->status != NIS_SUCCESS)
{
res = nis_lookup(qbuf, FOLLOW_LINKS);
switch (res->status)
{
case NIS_SUCCESS:
break;
case NIS_TRYAGAIN:
case NIS_RPCERROR:
case NIS_NAMEUNREACHABLE:
if (retry_cnt++ > 4)
{
errno = EAGAIN;
return FALSE;
}
/* try not to overwhelm hosed server */
sleep(2);
break;
default: /* all other nisplus errors */
# if 0
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("421 4.0.0 Cannot find table %s.%s: %s",
map->map_file, map->map_domain,
nis_sperrno(res->status));
# endif /* 0 */
errno = EAGAIN;
return FALSE;
}
}
if (NIS_RES_NUMOBJ(res) != 1 ||
(NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
{
if (tTd(38, 10))
dprintf("nisplus_map_open: %s is not a table\n", qbuf);
# if 0
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("421 4.0.0 %s.%s: %s is not a table",
map->map_file, map->map_domain,
nis_sperrno(res->status));
# endif /* 0 */
errno = EBADF;
return FALSE;
}
/* default key column is column 0 */
if (map->map_keycolnm == NULL)
map->map_keycolnm = newstr(COL_NAME(res,0));
max_col = COL_MAX(res);
/* verify the key column exist */
for (i = 0; i< max_col; i++)
{
if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0)
break;
}
if (i == max_col)
{
if (tTd(38, 2))
dprintf("nisplus_map_open(%s): can not find key column %s\n",
map->map_file, map->map_keycolnm);
errno = ENOENT;
return FALSE;
}
/* default value column is the last column */
if (map->map_valcolnm == NULL)
{
map->map_valcolno = max_col - 1;
return TRUE;
}
for (i = 0; i< max_col; i++)
{
if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
{
map->map_valcolno = i;
return TRUE;
}
}
if (tTd(38, 2))
dprintf("nisplus_map_open(%s): can not find column %s\n",
map->map_file, map->map_keycolnm);
errno = ENOENT;
return FALSE;
}
/*
** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
*/
char *
nisplus_map_lookup(map, name, av, statp)
MAP *map;
char *name;
char **av;
int *statp;
{
char *p;
auto int vsize;
char *skp;
int skleft;
char search_key[MAXNAME + 4];
char qbuf[MAXLINE + NIS_MAXNAMELEN];
nis_result *result;
if (tTd(38, 20))
dprintf("nisplus_map_lookup(%s, %s)\n",
map->map_mname, name);
if (!bitset(MF_OPEN, map->map_mflags))
{
if (nisplus_map_open(map, O_RDONLY))
{
map->map_mflags |= MF_OPEN;
map->map_pid = getpid();
}
else
{
*statp = EX_UNAVAILABLE;
return NULL;
}
}
/*
** Copy the name to the key buffer, escaping double quote characters
** by doubling them and quoting "]" and "," to avoid having the
** NIS+ parser choke on them.
*/
skleft = sizeof search_key - 4;
skp = search_key;
for (p = name; *p != '\0' && skleft > 0; p++)
{
switch (*p)
{
case ']':
case ',':
/* quote the character */
*skp++ = '"';
*skp++ = *p;
*skp++ = '"';
skleft -= 3;
break;
case '"':
/* double the quote */
*skp++ = '"';
skleft--;
/* FALLTHROUGH */
default:
*skp++ = *p;
skleft--;
break;
}
}
*skp = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(search_key);
/* construct the query */
if (PARTIAL_NAME(map->map_file))
snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s",
map->map_keycolnm, search_key, map->map_file,
map->map_domain);
else
snprintf(qbuf, sizeof qbuf, "[%s=%s],%s",
map->map_keycolnm, search_key, map->map_file);
if (tTd(38, 20))
dprintf("qbuf=%s\n", qbuf);
result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
if (result->status == NIS_SUCCESS)
{
int count;
char *str;
if ((count = NIS_RES_NUMOBJ(result)) != 1)
{
if (LogLevel > 10)
sm_syslog(LOG_WARNING, CurEnv->e_id,
"%s: lookup error, expected 1 entry, got %d",
map->map_file, count);
/* ignore second entry */
if (tTd(38, 20))
dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
name, count);
}
p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
/* set the length of the result */
if (p == NULL)
p = "";
vsize = strlen(p);
if (tTd(38, 20))
dprintf("nisplus_map_lookup(%s), found %s\n",
name, p);
if (bitset(MF_MATCHONLY, map->map_mflags))
str = map_rewrite(map, name, strlen(name), NULL);
else
str = map_rewrite(map, p, vsize, av);
nis_freeresult(result);
*statp = EX_OK;
return str;
}
else
{
if (result->status == NIS_NOTFOUND)
*statp = EX_NOTFOUND;
else if (result->status == NIS_TRYAGAIN)
*statp = EX_TEMPFAIL;
else
{
*statp = EX_UNAVAILABLE;
map->map_mflags &= ~(MF_VALID|MF_OPEN);
}
}
if (tTd(38, 20))
dprintf("nisplus_map_lookup(%s), failed\n", name);
nis_freeresult(result);
return NULL;
}
/*
** NISPLUS_GETCANONNAME -- look up canonical name in NIS+
*/
static bool
nisplus_getcanonname(name, hbsize, statp)
char *name;
int hbsize;
int *statp;
{
char *vp;
auto int vsize;
nis_result *result;
char *p;
char nbuf[MAXNAME + 1];
char qbuf[MAXLINE + NIS_MAXNAMELEN];
if (strlen(name) >= sizeof nbuf)
{
*statp = EX_UNAVAILABLE;
return FALSE;
}
(void) strlcpy(nbuf, name, sizeof nbuf);
shorten_hostname(nbuf);
p = strchr(nbuf, '.');
if (p == NULL)
{
/* single token */
snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir", nbuf);
}
else if (p[1] != '\0')
{
/* multi token -- take only first token in nbuf */
*p = '\0';
snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir.%s",
nbuf, &p[1]);
}
else
{
*statp = EX_NOHOST;
return FALSE;
}
if (tTd(38, 20))
dprintf("\nnisplus_getcanoname(%s), qbuf=%s\n",
name, qbuf);
result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH,
NULL, NULL);
if (result->status == NIS_SUCCESS)
{
int count;
char *domain;
if ((count = NIS_RES_NUMOBJ(result)) != 1)
{
if (LogLevel > 10)
sm_syslog(LOG_WARNING, CurEnv->e_id,
"nisplus_getcanonname: lookup error, expected 1 entry, got %d",
count);
/* ignore second entry */
if (tTd(38, 20))
dprintf("nisplus_getcanoname(%s), got %d entries, all but first ignored\n",
name, count);
}
if (tTd(38, 20))
dprintf("nisplus_getcanoname(%s), found in directory \"%s\"\n",
name, (NIS_RES_OBJECT(result))->zo_domain);
vp = ((NIS_RES_OBJECT(result))->EN_col(0));
vsize = strlen(vp);
if (tTd(38, 20))
dprintf("nisplus_getcanonname(%s), found %s\n",
name, vp);
if (strchr(vp, '.') != NULL)
{
domain = "";
}
else
{
domain = macvalue('m', CurEnv);
if (domain == NULL)
domain = "";
}
if (hbsize > vsize + (int) strlen(domain) + 1)
{
if (domain[0] == '\0')
(void) strlcpy(name, vp, hbsize);
else
snprintf(name, hbsize, "%s.%s", vp, domain);
*statp = EX_OK;
}
else
*statp = EX_NOHOST;
nis_freeresult(result);
return TRUE;
}
else
{
if (result->status == NIS_NOTFOUND)
*statp = EX_NOHOST;
else if (result->status == NIS_TRYAGAIN)
*statp = EX_TEMPFAIL;
else
*statp = EX_UNAVAILABLE;
}
if (tTd(38, 20))
dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
name, result->status, *statp);
nis_freeresult(result);
return FALSE;
}
char *
nisplus_default_domain()
{
static char default_domain[MAXNAME + 1] = "";
char *p;
if (default_domain[0] != '\0')
return default_domain;
p = nis_local_directory();
snprintf(default_domain, sizeof default_domain, "%s", p);
return default_domain;
}
#endif /* NISPLUS */
/*
** LDAP Modules
*/
/*
** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs
*/
#if defined(LDAPMAP) || defined(PH_MAP)
# ifdef PH_MAP
# define ph_map_dequote ldapmap_dequote
# endif /* PH_MAP */
char *
ldapmap_dequote(str)
char *str;
{
char *p;
char *start;
if (str == NULL)
return NULL;
p = str;
if (*p == '"')
{
/* Should probably swallow initial whitespace here */
start = ++p;
}
else
return str;
while (*p != '"' && *p != '\0')
p++;
if (*p != '\0')
*p = '\0';
return start;
}
#endif /* defined(LDAPMAP) || defined(PH_MAP) */
#ifdef LDAPMAP
LDAPMAP_STRUCT *LDAPDefaults = NULL;
/*
** LDAPMAP_OPEN -- open LDAP map
**
** Connect to the LDAP server. Re-use existing connections since a
** single server connection to a host (with the same host, port,
** bind DN, and secret) can answer queries for multiple maps.
*/
bool
ldapmap_open(map, mode)
MAP *map;
int mode;
{
LDAPMAP_STRUCT *lmap;
STAB *s;
if (tTd(38, 2))
dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode);
mode &= O_ACCMODE;
/* sendmail doesn't have the ability to write to LDAP (yet) */
if (mode != O_RDONLY)
{
/* issue a pseudo-error message */
# ifdef ENOSYS
errno = ENOSYS;
# else /* ENOSYS */
# ifdef EFTYPE
errno = EFTYPE;
# else /* EFTYPE */
errno = ENXIO;
# endif /* EFTYPE */
# endif /* ENOSYS */
return FALSE;
}
/* Comma separate if used as an alias file */
if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags))
map->map_coldelim = ',';
lmap = (LDAPMAP_STRUCT *) map->map_db1;
s = ldapmap_findconn(lmap);
if (s->s_ldap != NULL)
{
/* Already have a connection open to this LDAP server */
lmap->ldap_ld = s->s_ldap;
if (tTd(38, 2))
dprintf("using cached connection\n");
return TRUE;
}
if (tTd(38, 2))
dprintf("opening new connection\n");
/* No connection yet, connect */
if (!ldapmap_start(map))
return FALSE;
/* Save connection for reuse */
s->s_ldap = lmap->ldap_ld;
return TRUE;
}
/*
** LDAPMAP_START -- actually connect to an LDAP server
**
** Parameters:
** map -- the map being opened.
**
** Returns:
** TRUE if connection is successful, FALSE otherwise.
**
** Side Effects:
** Populates lmap->ldap_ld.
*/
static
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -