opnsense-src/contrib/sendmail/libsm/util.c
Gregory Neil Shapiro 58ae50f31e Merge commit '850ef5ae11d69ea3381bd310f564f025fc8caea3'
Merge vendor sendmail 8.18.1 into HEAD

(cherry picked from commit d39bd2c1388b520fcba9abed1932acacead60fba)

Add new source file for sendmail 8.18.1

(cherry picked from commit 19d4fb85bf17579780e8f0c3cbae8a5e92a6922e)

New sendmail 8.18.1 cf file

(cherry picked from commit 1b6a5580c1f999fb1ba5f9860cf63a8aefc55b3c)

Minor change to update these files so new freebsd*.cf files are
generated

(cherry picked from commit 2c191ba6b0b5d1b3729a5ac428d51cfc5d5f3d2e)

Belatedly update version and date for sendmail 8.18.1 upgrade

(cherry picked from commit 31fbc98c949bfca30ab55afef04b4396a61b7e92)

Add a note about sendmail 8.18.1's stricter SMTP protocol enforcement
(akin to commit 21c1f1deb6a3ac6a60e4516261e5264a28e0b7a6 in main)

Update import date for stable/14

Relnotes:	Yes
Security:	CVE-2023-51765
2024-02-07 02:29:43 +00:00

286 lines
5.2 KiB
C

/*
* Copyright (c) 2006 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#include <sm/gen.h>
SM_RCSID("@(#)$Id: util.c,v 1.10 2013-11-22 20:51:44 ca Exp $")
#include <sm/setjmp.h>
#include <sm/conf.h>
#include <sm/assert.h>
#include <sm/heap.h>
#include <sm/string.h>
#include <sm/sendmail.h>
#include <ctype.h>
/*
** STR2PRT -- convert "unprintable" characters in a string to \oct
** (except for some special chars, see below)
**
** Parameters:
** s -- string to convert [A]
**
** Returns:
** converted string [S][U]
** This is a static local buffer, string must be copied
** before this function is called again!
*/
char *
str2prt(s)
char *s;
{
int l;
char c, *h;
bool ok;
static int len = 0;
static char *buf = NULL;
#if _FFR_LOGASIS >= 1
#define BADCHAR(ch) ((unsigned char)(ch) <= 31)
#else
#define BADCHAR(ch) (!(isascii(ch) && isprint(ch)))
#endif
if (s == NULL)
return NULL;
ok = true;
for (h = s, l = 1; *h != '\0'; h++, l++)
{
if (*h == '\\')
{
++l;
ok = false;
}
else if (BADCHAR(*h))
{
l += 3;
ok = false;
}
}
if (ok)
return s;
if (l > len)
{
char *nbuf = sm_pmalloc_x(l);
if (buf != NULL)
sm_free(buf);
len = l;
buf = nbuf;
}
for (h = buf; *s != '\0' && l > 0; s++, l--)
{
c = *s;
if (c != '\\' && !BADCHAR(c))
{
*h++ = c;
}
else
{
*h++ = '\\';
--l;
switch (c)
{
case '\\':
*h++ = '\\';
break;
case '\t':
*h++ = 't';
break;
case '\n':
*h++ = 'n';
break;
case '\r':
*h++ = 'r';
break;
default:
SM_ASSERT(l >= 2);
(void) sm_snprintf(h, l, "%03o",
(unsigned int)((unsigned char) c));
/*
** XXX since l is unsigned this may wrap
** around if the calculation is screwed up...
*/
l -= 2;
h += 3;
break;
}
}
}
*h = '\0';
buf[len - 1] = '\0';
return buf;
}
/*
** QUOTE_INTERNAL_CHARS -- do quoting of internal characters
**
** Necessary to make sure that we don't have metacharacters such
** as the internal versions of "$*" or "$&" in a string.
** The input and output pointers can be the same.
**
** Parameters:
** ibp -- a pointer to the string to translate [x]
** obp -- a pointer to an output buffer [i][m:A]
** bsp -- pointer to the length of the output buffer
** rpool -- rpool for allocations
**
** Returns:
** A possibly new obp (if the buffer needed to grow);
** if it is different, *bsp will updated to the size of
** the new buffer and the caller is responsible for
** freeing the memory.
*/
#define SM_MM_QUOTE(ch) (((ch) & 0377) == METAQUOTE || (((ch) & 0340) == 0200))
char *
#if SM_HEAP_CHECK > 2
quote_internal_chars_tagged
#else
quote_internal_chars
#endif
(ibp, obp, bsp, rpool
#if SM_HEAP_CHECK > 2
, tag, line, group
#endif
)
char *ibp;
char *obp;
int *bsp;
SM_RPOOL_T *rpool;
#if SM_HEAP_CHECK > 2
char *tag;
int line;
int group;
#else
# define tag "quote_internal_chars"
# define line 1
# define group 1
#endif
{
char *ip, *op;
int bufused, olen;
bool buffer_same, needs_quoting;
if (NULL == ibp)
return NULL;
buffer_same = ibp == obp;
SM_REQUIRE(NULL != bsp);
if (NULL == obp)
*bsp = 0;
needs_quoting = false;
/* determine length of output string (starts at 1 for trailing '\0') */
for (ip = ibp, olen = 1; *ip != '\0'; ip++, olen++)
{
if (SM_MM_QUOTE(*ip))
{
olen++;
needs_quoting = true;
}
}
/* is the output buffer big enough? */
if (olen > *bsp)
{
obp = sm_rpool_malloc_tagged_x(rpool, olen, tag, line, group);
buffer_same = false;
*bsp = olen;
}
/*
** shortcut: no change needed?
** Note: we don't check this first as some bozo may use the same
** buffers but restrict the size of the output buffer to less
** than the length of the input buffer in which case we need to
** allocate a new buffer.
*/
if (!needs_quoting)
{
if (!buffer_same)
{
bufused = sm_strlcpy(obp, ibp, *bsp);
SM_ASSERT(bufused <= olen);
}
return obp;
}
if (buffer_same)
{
obp = sm_malloc_tagged_x(olen, tag, line + 1, group);
buffer_same = false;
*bsp = olen;
}
for (ip = ibp, op = obp, bufused = 0; *ip != '\0'; ip++)
{
if (SM_MM_QUOTE(*ip))
{
SM_ASSERT(bufused < olen);
op[bufused++] = METAQUOTE;
}
SM_ASSERT(bufused < olen);
op[bufused++] = *ip;
}
op[bufused] = '\0';
return obp;
}
#if SM_HEAP_CHECK <= 2
# undef tag
# undef line
# undef group
#endif
/*
** DEQUOTE_INTERNAL_CHARS -- undo the effect of quote_internal_chars
**
** Parameters:
** ibp -- a pointer to the string to be translated. [i]
** obp -- a pointer to the output buffer. [x]
** Can be the same as ibp.
** obs -- the size of the output buffer.
**
** Returns:
** number of character added to obp
*/
int
dequote_internal_chars(ibp, obp, obs)
char *ibp;
char *obp;
int obs;
{
char *ip, *op;
int len;
bool quoted;
quoted = false;
len = 0;
for (ip = ibp, op = obp; *ip != '\0'; ip++)
{
if ((*ip & 0377) == METAQUOTE && !quoted)
{
quoted = true;
continue;
}
if (op < &obp[obs - 1])
{
*op++ = *ip;
++len;
}
quoted = false;
}
*op = '\0';
return len;
}