1d0cef73dSGregory Neil Shapiro /* 2*5dd76dd0SGregory Neil Shapiro * Copyright (c) 2006 Proofpoint, Inc. and its suppliers. 3d0cef73dSGregory Neil Shapiro * All rights reserved. 4d0cef73dSGregory Neil Shapiro * 5d0cef73dSGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 6d0cef73dSGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 7d0cef73dSGregory Neil Shapiro * the sendmail distribution. 8d0cef73dSGregory Neil Shapiro * 9d0cef73dSGregory Neil Shapiro */ 10d0cef73dSGregory Neil Shapiro 11d0cef73dSGregory Neil Shapiro #include <sm/gen.h> 12d0cef73dSGregory Neil Shapiro 13*5dd76dd0SGregory Neil Shapiro SM_RCSID("@(#)$Id: util.c,v 1.10 2013/11/22 20:51:44 ca Exp $") 14d0cef73dSGregory Neil Shapiro #include <sm/setjmp.h> 15d0cef73dSGregory Neil Shapiro #include <sm/conf.h> 16d0cef73dSGregory Neil Shapiro #include <sm/assert.h> 17d0cef73dSGregory Neil Shapiro #include <sm/heap.h> 18d0cef73dSGregory Neil Shapiro #include <sm/string.h> 19d0cef73dSGregory Neil Shapiro #include <sm/sendmail.h> 20d0cef73dSGregory Neil Shapiro #include <ctype.h> 21d0cef73dSGregory Neil Shapiro 22d0cef73dSGregory Neil Shapiro /* 23d0cef73dSGregory Neil Shapiro ** STR2PRT -- convert "unprintable" characters in a string to \oct 24d0cef73dSGregory Neil Shapiro ** 25d0cef73dSGregory Neil Shapiro ** Parameters: 26d0cef73dSGregory Neil Shapiro ** s -- string to convert 27d0cef73dSGregory Neil Shapiro ** 28d0cef73dSGregory Neil Shapiro ** Returns: 29d0cef73dSGregory Neil Shapiro ** converted string. 30d0cef73dSGregory Neil Shapiro ** This is a static local buffer, string must be copied 31d0cef73dSGregory Neil Shapiro ** before this function is called again! 32d0cef73dSGregory Neil Shapiro */ 33d0cef73dSGregory Neil Shapiro 34d0cef73dSGregory Neil Shapiro char * 35d0cef73dSGregory Neil Shapiro str2prt(s) 36d0cef73dSGregory Neil Shapiro char *s; 37d0cef73dSGregory Neil Shapiro { 38d0cef73dSGregory Neil Shapiro int l; 39d0cef73dSGregory Neil Shapiro char c, *h; 40d0cef73dSGregory Neil Shapiro bool ok; 41d0cef73dSGregory Neil Shapiro static int len = 0; 42d0cef73dSGregory Neil Shapiro static char *buf = NULL; 43d0cef73dSGregory Neil Shapiro 44d0cef73dSGregory Neil Shapiro if (s == NULL) 45d0cef73dSGregory Neil Shapiro return NULL; 46d0cef73dSGregory Neil Shapiro ok = true; 47d0cef73dSGregory Neil Shapiro for (h = s, l = 1; *h != '\0'; h++, l++) 48d0cef73dSGregory Neil Shapiro { 49d0cef73dSGregory Neil Shapiro if (*h == '\\') 50d0cef73dSGregory Neil Shapiro { 51d0cef73dSGregory Neil Shapiro ++l; 52d0cef73dSGregory Neil Shapiro ok = false; 53d0cef73dSGregory Neil Shapiro } 54d0cef73dSGregory Neil Shapiro else if (!(isascii(*h) && isprint(*h))) 55d0cef73dSGregory Neil Shapiro { 56d0cef73dSGregory Neil Shapiro l += 3; 57d0cef73dSGregory Neil Shapiro ok = false; 58d0cef73dSGregory Neil Shapiro } 59d0cef73dSGregory Neil Shapiro } 60d0cef73dSGregory Neil Shapiro if (ok) 61d0cef73dSGregory Neil Shapiro return s; 62d0cef73dSGregory Neil Shapiro if (l > len) 63d0cef73dSGregory Neil Shapiro { 64d0cef73dSGregory Neil Shapiro char *nbuf = sm_pmalloc_x(l); 65d0cef73dSGregory Neil Shapiro 66d0cef73dSGregory Neil Shapiro if (buf != NULL) 67d0cef73dSGregory Neil Shapiro sm_free(buf); 68d0cef73dSGregory Neil Shapiro len = l; 69d0cef73dSGregory Neil Shapiro buf = nbuf; 70d0cef73dSGregory Neil Shapiro } 71d0cef73dSGregory Neil Shapiro for (h = buf; *s != '\0' && l > 0; s++, l--) 72d0cef73dSGregory Neil Shapiro { 73d0cef73dSGregory Neil Shapiro c = *s; 74d0cef73dSGregory Neil Shapiro if (isascii(c) && isprint(c) && c != '\\') 75d0cef73dSGregory Neil Shapiro { 76d0cef73dSGregory Neil Shapiro *h++ = c; 77d0cef73dSGregory Neil Shapiro } 78d0cef73dSGregory Neil Shapiro else 79d0cef73dSGregory Neil Shapiro { 80d0cef73dSGregory Neil Shapiro *h++ = '\\'; 81d0cef73dSGregory Neil Shapiro --l; 82d0cef73dSGregory Neil Shapiro switch (c) 83d0cef73dSGregory Neil Shapiro { 84d0cef73dSGregory Neil Shapiro case '\\': 85d0cef73dSGregory Neil Shapiro *h++ = '\\'; 86d0cef73dSGregory Neil Shapiro break; 87d0cef73dSGregory Neil Shapiro case '\t': 88d0cef73dSGregory Neil Shapiro *h++ = 't'; 89d0cef73dSGregory Neil Shapiro break; 90d0cef73dSGregory Neil Shapiro case '\n': 91d0cef73dSGregory Neil Shapiro *h++ = 'n'; 92d0cef73dSGregory Neil Shapiro break; 93d0cef73dSGregory Neil Shapiro case '\r': 94d0cef73dSGregory Neil Shapiro *h++ = 'r'; 95d0cef73dSGregory Neil Shapiro break; 96d0cef73dSGregory Neil Shapiro default: 97d0cef73dSGregory Neil Shapiro SM_ASSERT(l >= 2); 98d0cef73dSGregory Neil Shapiro (void) sm_snprintf(h, l, "%03o", 99d0cef73dSGregory Neil Shapiro (unsigned int)((unsigned char) c)); 100d0cef73dSGregory Neil Shapiro 101d0cef73dSGregory Neil Shapiro /* 102d0cef73dSGregory Neil Shapiro ** XXX since l is unsigned this may 103d0cef73dSGregory Neil Shapiro ** wrap around if the calculation is screwed 104d0cef73dSGregory Neil Shapiro ** up... 105d0cef73dSGregory Neil Shapiro */ 106d0cef73dSGregory Neil Shapiro 107d0cef73dSGregory Neil Shapiro l -= 2; 108d0cef73dSGregory Neil Shapiro h += 3; 109d0cef73dSGregory Neil Shapiro break; 110d0cef73dSGregory Neil Shapiro } 111d0cef73dSGregory Neil Shapiro } 112d0cef73dSGregory Neil Shapiro } 113d0cef73dSGregory Neil Shapiro *h = '\0'; 114d0cef73dSGregory Neil Shapiro buf[len - 1] = '\0'; 115d0cef73dSGregory Neil Shapiro return buf; 116d0cef73dSGregory Neil Shapiro } 117d0cef73dSGregory Neil Shapiro 118d0cef73dSGregory Neil Shapiro /* 119d0cef73dSGregory Neil Shapiro ** QUOTE_INTERNAL_CHARS -- do quoting of internal characters 120d0cef73dSGregory Neil Shapiro ** 121d0cef73dSGregory Neil Shapiro ** Necessary to make sure that we don't have metacharacters such 122d0cef73dSGregory Neil Shapiro ** as the internal versions of "$*" or "$&" in a string. 123d0cef73dSGregory Neil Shapiro ** The input and output pointers can be the same. 124d0cef73dSGregory Neil Shapiro ** 125d0cef73dSGregory Neil Shapiro ** Parameters: 126d0cef73dSGregory Neil Shapiro ** ibp -- a pointer to the string to translate 127d0cef73dSGregory Neil Shapiro ** obp -- a pointer to an output buffer 128d0cef73dSGregory Neil Shapiro ** bsp -- pointer to the length of the output buffer 129d0cef73dSGregory Neil Shapiro ** 130d0cef73dSGregory Neil Shapiro ** Returns: 131d0cef73dSGregory Neil Shapiro ** A possibly new bp (if the buffer needed to grow); if 132d0cef73dSGregory Neil Shapiro ** it is different, *bsp will updated to the size of 133d0cef73dSGregory Neil Shapiro ** the new buffer and the caller is responsible for 134d0cef73dSGregory Neil Shapiro ** freeing the memory. 135d0cef73dSGregory Neil Shapiro */ 136d0cef73dSGregory Neil Shapiro 137d0cef73dSGregory Neil Shapiro #define SM_MM_QUOTE(ch) (((ch) & 0377) == METAQUOTE || (((ch) & 0340) == 0200)) 138d0cef73dSGregory Neil Shapiro 139d0cef73dSGregory Neil Shapiro char * 140d0cef73dSGregory Neil Shapiro quote_internal_chars(ibp, obp, bsp) 141d0cef73dSGregory Neil Shapiro char *ibp; 142d0cef73dSGregory Neil Shapiro char *obp; 143d0cef73dSGregory Neil Shapiro int *bsp; 144d0cef73dSGregory Neil Shapiro { 145d0cef73dSGregory Neil Shapiro char *ip, *op; 146d0cef73dSGregory Neil Shapiro int bufused, olen; 147d0cef73dSGregory Neil Shapiro bool buffer_same, needs_quoting; 148d0cef73dSGregory Neil Shapiro 149d0cef73dSGregory Neil Shapiro buffer_same = ibp == obp; 150d0cef73dSGregory Neil Shapiro needs_quoting = false; 151d0cef73dSGregory Neil Shapiro 152d0cef73dSGregory Neil Shapiro /* determine length of output string (starts at 1 for trailing '\0') */ 153d0cef73dSGregory Neil Shapiro for (ip = ibp, olen = 1; *ip != '\0'; ip++, olen++) 154d0cef73dSGregory Neil Shapiro { 155d0cef73dSGregory Neil Shapiro if (SM_MM_QUOTE(*ip)) 156d0cef73dSGregory Neil Shapiro { 157d0cef73dSGregory Neil Shapiro olen++; 158d0cef73dSGregory Neil Shapiro needs_quoting = true; 159d0cef73dSGregory Neil Shapiro } 160d0cef73dSGregory Neil Shapiro } 161d0cef73dSGregory Neil Shapiro 162d0cef73dSGregory Neil Shapiro /* is the output buffer big enough? */ 163d0cef73dSGregory Neil Shapiro if (olen > *bsp) 164d0cef73dSGregory Neil Shapiro { 165d0cef73dSGregory Neil Shapiro obp = sm_malloc_x(olen); 166d0cef73dSGregory Neil Shapiro buffer_same = false; 167d0cef73dSGregory Neil Shapiro *bsp = olen; 168d0cef73dSGregory Neil Shapiro } 169d0cef73dSGregory Neil Shapiro 170d0cef73dSGregory Neil Shapiro /* 171d0cef73dSGregory Neil Shapiro ** shortcut: no change needed? 172d0cef73dSGregory Neil Shapiro ** Note: we don't check this first as some bozo may use the same 173d0cef73dSGregory Neil Shapiro ** buffers but restrict the size of the output buffer to less 174d0cef73dSGregory Neil Shapiro ** than the length of the input buffer in which case we need to 175d0cef73dSGregory Neil Shapiro ** allocate a new buffer. 176d0cef73dSGregory Neil Shapiro */ 177d0cef73dSGregory Neil Shapiro 178d0cef73dSGregory Neil Shapiro if (!needs_quoting) 179d0cef73dSGregory Neil Shapiro { 180d0cef73dSGregory Neil Shapiro if (!buffer_same) 181d0cef73dSGregory Neil Shapiro { 182d0cef73dSGregory Neil Shapiro bufused = sm_strlcpy(obp, ibp, *bsp); 183d0cef73dSGregory Neil Shapiro SM_ASSERT(bufused <= olen); 184d0cef73dSGregory Neil Shapiro } 185d0cef73dSGregory Neil Shapiro return obp; 186d0cef73dSGregory Neil Shapiro } 187d0cef73dSGregory Neil Shapiro 188d0cef73dSGregory Neil Shapiro if (buffer_same) 189d0cef73dSGregory Neil Shapiro { 190d0cef73dSGregory Neil Shapiro obp = sm_malloc_x(olen); 191d0cef73dSGregory Neil Shapiro buffer_same = false; 192d0cef73dSGregory Neil Shapiro *bsp = olen; 193d0cef73dSGregory Neil Shapiro } 194d0cef73dSGregory Neil Shapiro 195d0cef73dSGregory Neil Shapiro for (ip = ibp, op = obp, bufused = 0; *ip != '\0'; ip++) 196d0cef73dSGregory Neil Shapiro { 197d0cef73dSGregory Neil Shapiro if (SM_MM_QUOTE(*ip)) 198d0cef73dSGregory Neil Shapiro { 199d0cef73dSGregory Neil Shapiro SM_ASSERT(bufused < olen); 200d0cef73dSGregory Neil Shapiro op[bufused++] = METAQUOTE; 201d0cef73dSGregory Neil Shapiro } 202d0cef73dSGregory Neil Shapiro SM_ASSERT(bufused < olen); 203d0cef73dSGregory Neil Shapiro op[bufused++] = *ip; 204d0cef73dSGregory Neil Shapiro } 205d0cef73dSGregory Neil Shapiro op[bufused] = '\0'; 206d0cef73dSGregory Neil Shapiro return obp; 207d0cef73dSGregory Neil Shapiro } 208d0cef73dSGregory Neil Shapiro 209d0cef73dSGregory Neil Shapiro /* 210d0cef73dSGregory Neil Shapiro ** DEQUOTE_INTERNAL_CHARS -- undo the effect of quote_internal_chars 211d0cef73dSGregory Neil Shapiro ** 212d0cef73dSGregory Neil Shapiro ** Parameters: 213d0cef73dSGregory Neil Shapiro ** ibp -- a pointer to the string to be translated. 214d0cef73dSGregory Neil Shapiro ** obp -- a pointer to the output buffer. Can be the 215d0cef73dSGregory Neil Shapiro ** same as ibp. 216d0cef73dSGregory Neil Shapiro ** obs -- the size of the output buffer. 217d0cef73dSGregory Neil Shapiro ** 218d0cef73dSGregory Neil Shapiro ** Returns: 219d0cef73dSGregory Neil Shapiro ** number of character added to obp 220d0cef73dSGregory Neil Shapiro */ 221d0cef73dSGregory Neil Shapiro 222d0cef73dSGregory Neil Shapiro int 223d0cef73dSGregory Neil Shapiro dequote_internal_chars(ibp, obp, obs) 224d0cef73dSGregory Neil Shapiro char *ibp; 225d0cef73dSGregory Neil Shapiro char *obp; 226d0cef73dSGregory Neil Shapiro int obs; 227d0cef73dSGregory Neil Shapiro { 228d0cef73dSGregory Neil Shapiro char *ip, *op; 229d0cef73dSGregory Neil Shapiro int len; 230d0cef73dSGregory Neil Shapiro bool quoted; 231d0cef73dSGregory Neil Shapiro 232d0cef73dSGregory Neil Shapiro quoted = false; 233d0cef73dSGregory Neil Shapiro len = 0; 234d0cef73dSGregory Neil Shapiro for (ip = ibp, op = obp; *ip != '\0'; ip++) 235d0cef73dSGregory Neil Shapiro { 236d0cef73dSGregory Neil Shapiro if ((*ip & 0377) == METAQUOTE && !quoted) 237d0cef73dSGregory Neil Shapiro { 238d0cef73dSGregory Neil Shapiro quoted = true; 239d0cef73dSGregory Neil Shapiro continue; 240d0cef73dSGregory Neil Shapiro } 241d0cef73dSGregory Neil Shapiro if (op < &obp[obs - 1]) 242d0cef73dSGregory Neil Shapiro { 243d0cef73dSGregory Neil Shapiro *op++ = *ip; 244d0cef73dSGregory Neil Shapiro ++len; 245d0cef73dSGregory Neil Shapiro } 246d0cef73dSGregory Neil Shapiro quoted = false; 247d0cef73dSGregory Neil Shapiro } 248d0cef73dSGregory Neil Shapiro *op = '\0'; 249d0cef73dSGregory Neil Shapiro return len; 250d0cef73dSGregory Neil Shapiro } 251