📄 util.c
字号:
expand(ProgMailer->m_rootdir, buf, sizeof buf, e);
if (chroot(buf) < 0)
{
syserr("prog_open: cannot chroot(%s)", buf);
exit(EX_TEMPFAIL);
}
if (chdir("/") < 0)
{
syserr("prog_open: cannot chdir(/)");
exit(EX_TEMPFAIL);
}
}
/* run as default user */
endpwent();
if (setgid(DefGid) < 0 && geteuid() == 0)
{
syserr("prog_open: setgid(%ld) failed", (long) DefGid);
exit(EX_TEMPFAIL);
}
if (setuid(DefUid) < 0 && geteuid() == 0)
{
syserr("prog_open: setuid(%ld) failed", (long) DefUid);
exit(EX_TEMPFAIL);
}
/* run in some directory */
if (ProgMailer != NULL)
p = ProgMailer->m_execdir;
else
p = NULL;
for (; p != NULL; p = q)
{
q = strchr(p, ':');
if (q != NULL)
*q = '\0';
expand(p, buf, sizeof buf, e);
if (q != NULL)
*q++ = ':';
if (buf[0] != '\0' && chdir(buf) >= 0)
break;
}
if (p == NULL)
{
/* backup directories */
if (chdir("/tmp") < 0)
(void) chdir("/");
}
/* arrange for all the files to be closed */
for (i = 3; i < DtableSize; i++)
{
register int j;
if ((j = fcntl(i, F_GETFD, 0)) != -1)
(void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
}
/* now exec the process */
(void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron);
/* woops! failed */
save_errno = errno;
syserr("%s: cannot exec", argv[0]);
if (transienterror(save_errno))
_exit(EX_OSERR);
_exit(EX_CONFIG);
return -1; /* avoid compiler warning on IRIX */
}
/*
** GET_COLUMN -- look up a Column in a line buffer
**
** Parameters:
** line -- the raw text line to search.
** col -- the column number to fetch.
** delim -- the delimiter between columns. If null,
** use white space.
** buf -- the output buffer.
** buflen -- the length of buf.
**
** Returns:
** buf if successful.
** NULL otherwise.
*/
char *
get_column(line, col, delim, buf, buflen)
char line[];
int col;
int delim;
char buf[];
int buflen;
{
char *p;
char *begin, *end;
int i;
char delimbuf[4];
if ((char)delim == '\0')
(void) strlcpy(delimbuf, "\n\t ", sizeof delimbuf);
else
{
delimbuf[0] = (char)delim;
delimbuf[1] = '\0';
}
p = line;
if (*p == '\0')
return NULL; /* line empty */
if (*p == (char)delim && col == 0)
return NULL; /* first column empty */
begin = line;
if (col == 0 && (char)delim == '\0')
{
while (*begin != '\0' && isascii(*begin) && isspace(*begin))
begin++;
}
for (i = 0; i < col; i++)
{
if ((begin = strpbrk(begin, delimbuf)) == NULL)
return NULL; /* no such column */
begin++;
if ((char)delim == '\0')
{
while (*begin != '\0' && isascii(*begin) && isspace(*begin))
begin++;
}
}
end = strpbrk(begin, delimbuf);
if (end == NULL)
i = strlen(begin);
else
i = end - begin;
if (i >= buflen)
i = buflen - 1;
(void) strlcpy(buf, begin, i + 1);
return buf;
}
/*
** CLEANSTRCPY -- copy string keeping out bogus characters
**
** Parameters:
** t -- "to" string.
** f -- "from" string.
** l -- length of space available in "to" string.
**
** Returns:
** none.
*/
void
cleanstrcpy(t, f, l)
register char *t;
register char *f;
int l;
{
/* check for newlines and log if necessary */
(void) denlstring(f, TRUE, TRUE);
if (l <= 0)
syserr("!cleanstrcpy: length == 0");
l--;
while (l > 0 && *f != '\0')
{
if (isascii(*f) &&
(isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL))
{
l--;
*t++ = *f;
}
f++;
}
*t = '\0';
}
/*
** DENLSTRING -- convert newlines in a string to spaces
**
** Parameters:
** s -- the input string
** strict -- if set, don't permit continuation lines.
** logattacks -- if set, log attempted attacks.
**
** Returns:
** A pointer to a version of the string with newlines
** mapped to spaces. This should be copied.
*/
char *
denlstring(s, strict, logattacks)
char *s;
bool strict;
bool logattacks;
{
register char *p;
int l;
static char *bp = NULL;
static int bl = 0;
p = s;
while ((p = strchr(p, '\n')) != NULL)
if (strict || (*++p != ' ' && *p != '\t'))
break;
if (p == NULL)
return s;
l = strlen(s) + 1;
if (bl < l)
{
/* allocate more space */
if (bp != NULL)
free(bp);
bp = xalloc(l);
bl = l;
}
(void) strlcpy(bp, s, l);
for (p = bp; (p = strchr(p, '\n')) != NULL; )
*p++ = ' ';
if (logattacks)
{
sm_syslog(LOG_NOTICE, CurEnv->e_id,
"POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
RealHostName == NULL ? "[UNKNOWN]" : RealHostName,
shortenstring(bp, MAXSHORTSTR));
}
return bp;
}
/*
** PATH_IS_DIR -- check to see if file exists and is a directory.
**
** There are some additional checks for security violations in
** here. This routine is intended to be used for the host status
** support.
**
** Parameters:
** pathname -- pathname to check for directory-ness.
** createflag -- if set, create directory if needed.
**
** Returns:
** TRUE -- if the indicated pathname is a directory
** FALSE -- otherwise
*/
int
path_is_dir(pathname, createflag)
char *pathname;
bool createflag;
{
struct stat statbuf;
#if HASLSTAT
if (lstat(pathname, &statbuf) < 0)
#else /* HASLSTAT */
if (stat(pathname, &statbuf) < 0)
#endif /* HASLSTAT */
{
if (errno != ENOENT || !createflag)
return FALSE;
if (mkdir(pathname, 0755) < 0)
return FALSE;
return TRUE;
}
if (!S_ISDIR(statbuf.st_mode))
{
errno = ENOTDIR;
return FALSE;
}
/* security: don't allow writable directories */
if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode))
{
errno = EACCES;
return FALSE;
}
return TRUE;
}
/*
** PROC_LIST_ADD -- add process id to list of our children
**
** Parameters:
** pid -- pid to add to list.
** task -- task of pid.
** type -- type of process.
**
** Returns:
** none
*/
static struct procs *ProcListVec = NULL;
static int ProcListSize = 0;
void
proc_list_add(pid, task, type)
pid_t pid;
char *task;
int type;
{
int i;
for (i = 0; i < ProcListSize; i++)
{
if (ProcListVec[i].proc_pid == NO_PID)
break;
}
if (i >= ProcListSize)
{
/* probe the existing vector to avoid growing infinitely */
proc_list_probe();
/* now scan again */
for (i = 0; i < ProcListSize; i++)
{
if (ProcListVec[i].proc_pid == NO_PID)
break;
}
}
if (i >= ProcListSize)
{
/* grow process list */
struct procs *npv;
npv = (struct procs *) xalloc((sizeof *npv) *
(ProcListSize + PROC_LIST_SEG));
if (ProcListSize > 0)
{
memmove(npv, ProcListVec,
ProcListSize * sizeof (struct procs));
free(ProcListVec);
}
for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++)
{
npv[i].proc_pid = NO_PID;
npv[i].proc_task = NULL;
npv[i].proc_type = PROC_NONE;
}
i = ProcListSize;
ProcListSize += PROC_LIST_SEG;
ProcListVec = npv;
}
ProcListVec[i].proc_pid = pid;
if (ProcListVec[i].proc_task != NULL)
free(ProcListVec[i].proc_task);
ProcListVec[i].proc_task = newstr(task);
ProcListVec[i].proc_type = type;
/* if process adding itself, it's not a child */
if (pid != getpid())
CurChildren++;
}
/*
** PROC_LIST_SET -- set pid task in process list
**
** Parameters:
** pid -- pid to set
** task -- task of pid
**
** Returns:
** none.
*/
void
proc_list_set(pid, task)
pid_t pid;
char *task;
{
int i;
for (i = 0; i < ProcListSize; i++)
{
if (ProcListVec[i].proc_pid == pid)
{
if (ProcListVec[i].proc_task != NULL)
free(ProcListVec[i].proc_task);
ProcListVec[i].proc_task = newstr(task);
break;
}
}
}
/*
** PROC_LIST_DROP -- drop pid from process list
**
** Parameters:
** pid -- pid to drop
**
** Returns:
** type of process
*/
int
proc_list_drop(pid)
pid_t pid;
{
int i;
int type = PROC_NONE;
for (i = 0; i < ProcListSize; i++)
{
if (ProcListVec[i].proc_pid == pid)
{
ProcListVec[i].proc_pid = NO_PID;
type = ProcListVec[i].proc_type;
break;
}
}
if (CurChildren > 0)
CurChildren--;
return type;
}
/*
** PROC_LIST_CLEAR -- clear the process list
**
** Parameters:
** none.
**
** Returns:
** none.
*/
void
proc_list_clear()
{
int i;
/* start from 1 since 0 is the daemon itself */
for (i = 1; i < ProcListSize; i++)
{
ProcListVec[i].proc_pid = NO_PID;
}
CurChildren = 0;
}
/*
** PROC_LIST_PROBE -- probe processes in the list to see if they still exist
**
** Parameters:
** none
**
** Returns:
** none
*/
void
proc_list_probe()
{
int i;
/* start from 1 since 0 is the daemon itself */
for (i = 1; i < ProcListSize; i++)
{
if (ProcListVec[i].proc_pid == NO_PID)
continue;
if (kill(ProcListVec[i].proc_pid, 0) < 0)
{
if (LogLevel > 3)
sm_syslog(LOG_DEBUG, CurEnv->e_id,
"proc_list_probe: lost pid %d",
(int) ProcListVec[i].proc_pid);
ProcListVec[i].proc_pid = NO_PID;
CurChildren--;
}
}
if (CurChildren < 0)
CurChildren = 0;
}
/*
** PROC_LIST_DISPLAY -- display the process list
**
** Parameters:
** out -- output file pointer
**
** Returns:
** none.
*/
void
proc_list_display(out)
FILE *out;
{
int i;
for (i = 0; i < ProcListSize; i++)
{
if (ProcListVec[i].proc_pid == NO_PID)
continue;
fprintf(out, "%d %s%s\n", (int) ProcListVec[i].proc_pid,
ProcListVec[i].proc_task != NULL ?
ProcListVec[i].proc_task : "(unknown)",
(OpMode == MD_SMTP ||
OpMode == MD_DAEMON ||
OpMode == MD_ARPAFTP) ? "\r" : "");
}
}
/*
** SM_STRCASECMP -- 8-bit clean version of strcasecmp
**
** Thank you, vendors, for making this all necessary.
*/
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
#endif /* defined(LIBC_SCCS) && !defined(lint) */
/*
* This array is designed for mapping upper and lower case letter
* together for a case independent comparison. The mappings are
* based upon ascii character sequences.
*/
static const u_char charmap[] = {
0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
};
int
sm_strcasecmp(s1, s2)
const char *s1, *s2;
{
register const u_char *cm = charmap,
*us1 = (const u_char *)s1,
*us2 = (const u_char *)s2;
while (cm[*us1] == cm[*us2++])
if (*us1++ == '\0')
return 0;
return (cm[*us1] - cm[*--us2]);
}
int
sm_strncasecmp(s1, s2, n)
const char *s1, *s2;
register size_t n;
{
if (n != 0) {
register const u_char *cm = charmap,
*us1 = (const u_char *)s1,
*us2 = (const u_char *)s2;
do {
if (cm[*us1] != cm[*us2++])
return (cm[*us1] - cm[*--us2]);
if (*us1++ == '\0')
break;
} while (--n != 0);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -