Deleted Added
full compact
headers.c (111367) headers.c (111826)
1/*
1/*
2 * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
2 * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#include <sendmail.h>
15
3 * All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#include <sendmail.h>
15
16SM_RCSID("@(#)$Id: headers.c,v 8.266.4.2 2002/09/23 23:42:02 ca Exp $")
16SM_RCSID("@(#)$Id: headers.c,v 8.266.4.4 2003/01/18 00:41:48 gshapiro Exp $")
17
17
18static size_t fix_mime_header __P((char *));
18static size_t fix_mime_header __P((HDR *, ENVELOPE *));
19static int priencode __P((char *));
20static void put_vanilla_header __P((HDR *, char *, MCI *));
21
22/*
23** SETUPHEADERS -- initialize headers in symbol table
24**
25** Parameters:
26** none

--- 644 unchanged lines hidden (view full) ---

671 sm_dprintf("(");
672 xputs(h->h_value);
673 sm_dprintf(") ");
674 }
675 expand(h->h_value, buf, sizeof buf, e);
676 if (buf[0] != '\0')
677 {
678 if (bitset(H_FROM, h->h_flags))
19static int priencode __P((char *));
20static void put_vanilla_header __P((HDR *, char *, MCI *));
21
22/*
23** SETUPHEADERS -- initialize headers in symbol table
24**
25** Parameters:
26** none

--- 644 unchanged lines hidden (view full) ---

671 sm_dprintf("(");
672 xputs(h->h_value);
673 sm_dprintf(") ");
674 }
675 expand(h->h_value, buf, sizeof buf, e);
676 if (buf[0] != '\0')
677 {
678 if (bitset(H_FROM, h->h_flags))
679 expand(crackaddr(buf), buf, sizeof buf,
680 e);
679 expand(crackaddr(buf, e),
680 buf, sizeof buf, e);
681 h->h_value = sm_rpool_strdup_x(e->e_rpool, buf);
682 h->h_flags &= ~H_DEFAULT;
683 }
684 }
685 if (tTd(32, 1))
686 {
687 xputs(h->h_value);
688 sm_dprintf("\n");

--- 304 unchanged lines hidden (view full) ---

993}
994/*
995** CRACKADDR -- parse an address and turn it into a macro
996**
997** This doesn't actually parse the address -- it just extracts
998** it and replaces it with "$g". The parse is totally ad hoc
999** and isn't even guaranteed to leave something syntactically
1000** identical to what it started with. However, it does leave
681 h->h_value = sm_rpool_strdup_x(e->e_rpool, buf);
682 h->h_flags &= ~H_DEFAULT;
683 }
684 }
685 if (tTd(32, 1))
686 {
687 xputs(h->h_value);
688 sm_dprintf("\n");

--- 304 unchanged lines hidden (view full) ---

993}
994/*
995** CRACKADDR -- parse an address and turn it into a macro
996**
997** This doesn't actually parse the address -- it just extracts
998** it and replaces it with "$g". The parse is totally ad hoc
999** and isn't even guaranteed to leave something syntactically
1000** identical to what it started with. However, it does leave
1001** something semantically identical.
1001** something semantically identical if possible, else at least
1002** syntactically correct.
1002**
1003**
1004** For example, it changes "Real Name <real@example.com> (Comment)"
1005** to "Real Name <$g> (Comment)".
1006**
1003** This algorithm has been cleaned up to handle a wider range
1004** of cases -- notably quoted and backslash escaped strings.
1005** This modification makes it substantially better at preserving
1006** the original syntax.
1007**
1008** Parameters:
1009** addr -- the address to be cracked.
1007** This algorithm has been cleaned up to handle a wider range
1008** of cases -- notably quoted and backslash escaped strings.
1009** This modification makes it substantially better at preserving
1010** the original syntax.
1011**
1012** Parameters:
1013** addr -- the address to be cracked.
1014** e -- the current envelope.
1010**
1011** Returns:
1012** a pointer to the new version.
1013**
1014** Side Effects:
1015** none.
1016**
1017** Warning:
1018** The return value is saved in local storage and should
1019** be copied if it is to be reused.
1020*/
1021
1015**
1016** Returns:
1017** a pointer to the new version.
1018**
1019** Side Effects:
1020** none.
1021**
1022** Warning:
1023** The return value is saved in local storage and should
1024** be copied if it is to be reused.
1025*/
1026
1027#define SM_HAVE_ROOM ((bp < buflim) && (buflim <= bufend))
1028
1029/*
1030** Append a character to bp if we have room.
1031** If not, punt and return $g.
1032*/
1033
1034#define SM_APPEND_CHAR(c) \
1035 do \
1036 { \
1037 if (SM_HAVE_ROOM) \
1038 *bp++ = (c); \
1039 else \
1040 goto returng; \
1041 } while (0)
1042
1043#if MAXNAME < 10
1044ERROR MAXNAME must be at least 10
1045#endif /* MAXNAME < 10 */
1046
1022char *
1047char *
1023crackaddr(addr)
1048crackaddr(addr, e)
1024 register char *addr;
1049 register char *addr;
1050 ENVELOPE *e;
1025{
1026 register char *p;
1027 register char c;
1051{
1052 register char *p;
1053 register char c;
1028 int cmtlev;
1029 int realcmtlev;
1030 int anglelev, realanglelev;
1031 int copylev;
1032 int bracklev;
1033 bool qmode;
1034 bool realqmode;
1035 bool skipping;
1036 bool putgmac = false;
1037 bool quoteit = false;
1038 bool gotangle = false;
1039 bool gotcolon = false;
1054 int cmtlev; /* comment level in input string */
1055 int realcmtlev; /* comment level in output string */
1056 int anglelev; /* angle level in input string */
1057 int copylev; /* 0 == in address, >0 copying */
1058 int bracklev; /* bracket level for IPv6 addr check */
1059 bool addangle; /* put closing angle in output */
1060 bool qmode; /* quoting in original string? */
1061 bool realqmode; /* quoting in output string? */
1062 bool putgmac = false; /* already wrote $g */
1063 bool quoteit = false; /* need to quote next character */
1064 bool gotangle = false; /* found first '<' */
1065 bool gotcolon = false; /* found a ':' */
1040 register char *bp;
1041 char *buflim;
1042 char *bufhead;
1043 char *addrhead;
1066 register char *bp;
1067 char *buflim;
1068 char *bufhead;
1069 char *addrhead;
1070 char *bufend;
1044 static char buf[MAXNAME + 1];
1045
1046 if (tTd(33, 1))
1047 sm_dprintf("crackaddr(%s)\n", addr);
1048
1049 /* strip leading spaces */
1050 while (*addr != '\0' && isascii(*addr) && isspace(*addr))
1051 addr++;
1052
1053 /*
1054 ** Start by assuming we have no angle brackets. This will be
1055 ** adjusted later if we find them.
1056 */
1057
1071 static char buf[MAXNAME + 1];
1072
1073 if (tTd(33, 1))
1074 sm_dprintf("crackaddr(%s)\n", addr);
1075
1076 /* strip leading spaces */
1077 while (*addr != '\0' && isascii(*addr) && isspace(*addr))
1078 addr++;
1079
1080 /*
1081 ** Start by assuming we have no angle brackets. This will be
1082 ** adjusted later if we find them.
1083 */
1084
1085 buflim = bufend = &buf[sizeof(buf) - 1];
1058 bp = bufhead = buf;
1086 bp = bufhead = buf;
1059 buflim = &buf[sizeof buf - 7];
1060 p = addrhead = addr;
1087 p = addrhead = addr;
1061 copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
1088 copylev = anglelev = cmtlev = realcmtlev = 0;
1062 bracklev = 0;
1089 bracklev = 0;
1063 qmode = realqmode = false;
1090 qmode = realqmode = addangle = false;
1064
1065 while ((c = *p++) != '\0')
1066 {
1067 /*
1091
1092 while ((c = *p++) != '\0')
1093 {
1094 /*
1068 ** If the buffer is overful, go into a special "skipping"
1069 ** mode that tries to keep legal syntax but doesn't actually
1070 ** output things.
1095 ** Try to keep legal syntax using spare buffer space
1096 ** (maintained by buflim).
1071 */
1072
1097 */
1098
1073 skipping = bp >= buflim;
1099 if (copylev > 0)
1100 SM_APPEND_CHAR(c);
1074
1101
1075 if (copylev > 0 && !skipping)
1076 *bp++ = c;
1077
1078 /* check for backslash escapes */
1079 if (c == '\\')
1080 {
1081 /* arrange to quote the address */
1082 if (cmtlev <= 0 && !qmode)
1083 quoteit = true;
1084
1085 if ((c = *p++) == '\0')
1086 {
1087 /* too far */
1088 p--;
1089 goto putg;
1090 }
1102 /* check for backslash escapes */
1103 if (c == '\\')
1104 {
1105 /* arrange to quote the address */
1106 if (cmtlev <= 0 && !qmode)
1107 quoteit = true;
1108
1109 if ((c = *p++) == '\0')
1110 {
1111 /* too far */
1112 p--;
1113 goto putg;
1114 }
1091 if (copylev > 0 && !skipping)
1092 *bp++ = c;
1115 if (copylev > 0)
1116 SM_APPEND_CHAR(c);
1093 goto putg;
1094 }
1095
1096 /* check for quoted strings */
1097 if (c == '"' && cmtlev <= 0)
1098 {
1099 qmode = !qmode;
1117 goto putg;
1118 }
1119
1120 /* check for quoted strings */
1121 if (c == '"' && cmtlev <= 0)
1122 {
1123 qmode = !qmode;
1100 if (copylev > 0 && !skipping)
1124 if (copylev > 0 && SM_HAVE_ROOM)
1125 {
1126 if (realqmode)
1127 buflim--;
1128 else
1129 buflim++;
1101 realqmode = !realqmode;
1130 realqmode = !realqmode;
1131 }
1102 continue;
1103 }
1104 if (qmode)
1105 goto putg;
1106
1107 /* check for comments */
1108 if (c == '(')
1109 {
1110 cmtlev++;
1111
1112 /* allow space for closing paren */
1132 continue;
1133 }
1134 if (qmode)
1135 goto putg;
1136
1137 /* check for comments */
1138 if (c == '(')
1139 {
1140 cmtlev++;
1141
1142 /* allow space for closing paren */
1113 if (!skipping)
1143 if (SM_HAVE_ROOM)
1114 {
1115 buflim--;
1116 realcmtlev++;
1117 if (copylev++ <= 0)
1118 {
1119 if (bp != bufhead)
1144 {
1145 buflim--;
1146 realcmtlev++;
1147 if (copylev++ <= 0)
1148 {
1149 if (bp != bufhead)
1120 *bp++ = ' ';
1121 *bp++ = c;
1150 SM_APPEND_CHAR(' ');
1151 SM_APPEND_CHAR(c);
1122 }
1123 }
1124 }
1125 if (cmtlev > 0)
1126 {
1127 if (c == ')')
1128 {
1129 cmtlev--;
1130 copylev--;
1152 }
1153 }
1154 }
1155 if (cmtlev > 0)
1156 {
1157 if (c == ')')
1158 {
1159 cmtlev--;
1160 copylev--;
1131 if (!skipping)
1161 if (SM_HAVE_ROOM)
1132 {
1133 realcmtlev--;
1134 buflim++;
1135 }
1136 }
1137 continue;
1138 }
1139 else if (c == ')')
1140 {
1141 /* syntax error: unmatched ) */
1162 {
1163 realcmtlev--;
1164 buflim++;
1165 }
1166 }
1167 continue;
1168 }
1169 else if (c == ')')
1170 {
1171 /* syntax error: unmatched ) */
1142 if (copylev > 0 && !skipping)
1172 if (copylev > 0 && SM_HAVE_ROOM)
1143 bp--;
1144 }
1145
1146 /* count nesting on [ ... ] (for IPv6 domain literals) */
1147 if (c == '[')
1148 bracklev++;
1149 else if (c == ']')
1150 bracklev--;
1151
1152 /* check for group: list; syntax */
1153 if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
1154 !gotcolon && !ColonOkInAddr)
1155 {
1156 register char *q;
1157
1158 /*
1159 ** Check for DECnet phase IV ``::'' (host::user)
1173 bp--;
1174 }
1175
1176 /* count nesting on [ ... ] (for IPv6 domain literals) */
1177 if (c == '[')
1178 bracklev++;
1179 else if (c == ']')
1180 bracklev--;
1181
1182 /* check for group: list; syntax */
1183 if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
1184 !gotcolon && !ColonOkInAddr)
1185 {
1186 register char *q;
1187
1188 /*
1189 ** Check for DECnet phase IV ``::'' (host::user)
1160 ** or ** DECnet phase V ``:.'' syntaxes. The latter
1190 ** or DECnet phase V ``:.'' syntaxes. The latter
1161 ** covers ``user@DEC:.tay.myhost'' and
1162 ** ``DEC:.tay.myhost::user'' syntaxes (bletch).
1163 */
1164
1165 if (*p == ':' || *p == '.')
1166 {
1167 if (cmtlev <= 0 && !qmode)
1168 quoteit = true;
1191 ** covers ``user@DEC:.tay.myhost'' and
1192 ** ``DEC:.tay.myhost::user'' syntaxes (bletch).
1193 */
1194
1195 if (*p == ':' || *p == '.')
1196 {
1197 if (cmtlev <= 0 && !qmode)
1198 quoteit = true;
1169 if (copylev > 0 && !skipping)
1199 if (copylev > 0)
1170 {
1200 {
1171 *bp++ = c;
1172 *bp++ = *p;
1201 SM_APPEND_CHAR(c);
1202 SM_APPEND_CHAR(*p);
1173 }
1174 p++;
1175 goto putg;
1176 }
1177
1178 gotcolon = true;
1179
1180 bp = bufhead;
1181 if (quoteit)
1182 {
1203 }
1204 p++;
1205 goto putg;
1206 }
1207
1208 gotcolon = true;
1209
1210 bp = bufhead;
1211 if (quoteit)
1212 {
1183 *bp++ = '"';
1213 SM_APPEND_CHAR('"');
1184
1185 /* back up over the ':' and any spaces */
1186 --p;
1214
1215 /* back up over the ':' and any spaces */
1216 --p;
1187 while (isascii(*--p) && isspace(*p))
1217 while (p > addr &&
1218 isascii(*--p) && isspace(*p))
1188 continue;
1189 p++;
1190 }
1191 for (q = addrhead; q < p; )
1192 {
1193 c = *q++;
1219 continue;
1220 p++;
1221 }
1222 for (q = addrhead; q < p; )
1223 {
1224 c = *q++;
1194 if (bp < buflim)
1225 if (quoteit && c == '"')
1195 {
1226 {
1196 if (quoteit && c == '"')
1197 *bp++ = '\\';
1198 *bp++ = c;
1227 SM_APPEND_CHAR('\\');
1228 SM_APPEND_CHAR(c);
1199 }
1229 }
1230 else
1231 SM_APPEND_CHAR(c);
1200 }
1201 if (quoteit)
1202 {
1203 if (bp == &bufhead[1])
1204 bp--;
1205 else
1232 }
1233 if (quoteit)
1234 {
1235 if (bp == &bufhead[1])
1236 bp--;
1237 else
1206 *bp++ = '"';
1238 SM_APPEND_CHAR('"');
1207 while ((c = *p++) != ':')
1239 while ((c = *p++) != ':')
1208 {
1209 if (bp < buflim)
1210 *bp++ = c;
1211 }
1212 *bp++ = c;
1240 SM_APPEND_CHAR(c);
1241 SM_APPEND_CHAR(c);
1213 }
1214
1215 /* any trailing white space is part of group: */
1242 }
1243
1244 /* any trailing white space is part of group: */
1216 while (isascii(*p) && isspace(*p) && bp < buflim)
1217 *bp++ = *p++;
1245 while (isascii(*p) && isspace(*p))
1246 {
1247 SM_APPEND_CHAR(*p);
1248 p++;
1249 }
1218 copylev = 0;
1219 putgmac = quoteit = false;
1220 bufhead = bp;
1221 addrhead = p;
1222 continue;
1223 }
1224
1225 if (c == ';' && copylev <= 0 && !ColonOkInAddr)
1250 copylev = 0;
1251 putgmac = quoteit = false;
1252 bufhead = bp;
1253 addrhead = p;
1254 continue;
1255 }
1256
1257 if (c == ';' && copylev <= 0 && !ColonOkInAddr)
1226 {
1227 if (bp < buflim)
1228 *bp++ = c;
1229 }
1258 SM_APPEND_CHAR(c);
1230
1231 /* check for characters that may have to be quoted */
1232 if (strchr(MustQuoteChars, c) != NULL)
1233 {
1234 /*
1235 ** If these occur as the phrase part of a <>
1236 ** construct, but are not inside of () or already
1237 ** quoted, they will have to be quoted. Note that

--- 11 unchanged lines hidden (view full) ---

1249
1250 /* assume first of two angles is bogus */
1251 if (gotangle)
1252 quoteit = true;
1253 gotangle = true;
1254
1255 /* oops -- have to change our mind */
1256 anglelev = 1;
1259
1260 /* check for characters that may have to be quoted */
1261 if (strchr(MustQuoteChars, c) != NULL)
1262 {
1263 /*
1264 ** If these occur as the phrase part of a <>
1265 ** construct, but are not inside of () or already
1266 ** quoted, they will have to be quoted. Note that

--- 11 unchanged lines hidden (view full) ---

1278
1279 /* assume first of two angles is bogus */
1280 if (gotangle)
1281 quoteit = true;
1282 gotangle = true;
1283
1284 /* oops -- have to change our mind */
1285 anglelev = 1;
1257 if (!skipping)
1258 realanglelev = 1;
1286 if (SM_HAVE_ROOM)
1287 {
1288 if (!addangle)
1289 buflim--;
1290 addangle = true;
1291 }
1259
1260 bp = bufhead;
1261 if (quoteit)
1262 {
1292
1293 bp = bufhead;
1294 if (quoteit)
1295 {
1263 *bp++ = '"';
1296 SM_APPEND_CHAR('"');
1264
1265 /* back up over the '<' and any spaces */
1266 --p;
1297
1298 /* back up over the '<' and any spaces */
1299 --p;
1267 while (isascii(*--p) && isspace(*p))
1300 while (p > addr &&
1301 isascii(*--p) && isspace(*p))
1268 continue;
1269 p++;
1270 }
1271 for (q = addrhead; q < p; )
1272 {
1273 c = *q++;
1302 continue;
1303 p++;
1304 }
1305 for (q = addrhead; q < p; )
1306 {
1307 c = *q++;
1274 if (bp < buflim)
1308 if (quoteit && c == '"')
1275 {
1309 {
1276 if (quoteit && c == '"')
1277 *bp++ = '\\';
1278 *bp++ = c;
1310 SM_APPEND_CHAR('\\');
1311 SM_APPEND_CHAR(c);
1279 }
1312 }
1313 else
1314 SM_APPEND_CHAR(c);
1280 }
1281 if (quoteit)
1282 {
1283 if (bp == &buf[1])
1284 bp--;
1285 else
1315 }
1316 if (quoteit)
1317 {
1318 if (bp == &buf[1])
1319 bp--;
1320 else
1286 *bp++ = '"';
1321 SM_APPEND_CHAR('"');
1287 while ((c = *p++) != '<')
1322 while ((c = *p++) != '<')
1288 {
1289 if (bp < buflim)
1290 *bp++ = c;
1291 }
1292 *bp++ = c;
1323 SM_APPEND_CHAR(c);
1324 SM_APPEND_CHAR(c);
1293 }
1294 copylev = 0;
1295 putgmac = quoteit = false;
1296 continue;
1297 }
1298
1299 if (c == '>')
1300 {
1301 if (anglelev > 0)
1302 {
1303 anglelev--;
1325 }
1326 copylev = 0;
1327 putgmac = quoteit = false;
1328 continue;
1329 }
1330
1331 if (c == '>')
1332 {
1333 if (anglelev > 0)
1334 {
1335 anglelev--;
1304 if (!skipping)
1336 if (SM_HAVE_ROOM)
1305 {
1337 {
1306 realanglelev--;
1307 buflim++;
1338 if (addangle)
1339 buflim++;
1340 addangle = false;
1308 }
1309 }
1341 }
1342 }
1310 else if (!skipping)
1343 else if (SM_HAVE_ROOM)
1311 {
1312 /* syntax error: unmatched > */
1313 if (copylev > 0)
1314 bp--;
1315 quoteit = true;
1316 continue;
1317 }
1318 if (copylev++ <= 0)
1344 {
1345 /* syntax error: unmatched > */
1346 if (copylev > 0)
1347 bp--;
1348 quoteit = true;
1349 continue;
1350 }
1351 if (copylev++ <= 0)
1319 *bp++ = c;
1352 SM_APPEND_CHAR(c);
1320 continue;
1321 }
1322
1323 /* must be a real address character */
1324 putg:
1325 if (copylev <= 0 && !putgmac)
1326 {
1353 continue;
1354 }
1355
1356 /* must be a real address character */
1357 putg:
1358 if (copylev <= 0 && !putgmac)
1359 {
1327 if (bp > bufhead && bp[-1] == ')')
1328 *bp++ = ' ';
1329 *bp++ = MACROEXPAND;
1330 *bp++ = 'g';
1360 if (bp > buf && bp[-1] == ')')
1361 SM_APPEND_CHAR(' ');
1362 SM_APPEND_CHAR(MACROEXPAND);
1363 SM_APPEND_CHAR('g');
1331 putgmac = true;
1332 }
1333 }
1334
1335 /* repair any syntactic damage */
1364 putgmac = true;
1365 }
1366 }
1367
1368 /* repair any syntactic damage */
1336 if (realqmode)
1369 if (realqmode && bp < bufend)
1337 *bp++ = '"';
1370 *bp++ = '"';
1338 while (realcmtlev-- > 0)
1371 while (realcmtlev-- > 0 && bp < bufend)
1339 *bp++ = ')';
1372 *bp++ = ')';
1340 while (realanglelev-- > 0)
1373 if (addangle && bp < bufend)
1341 *bp++ = '>';
1374 *bp++ = '>';
1342 *bp++ = '\0';
1375 *bp = '\0';
1376 if (bp < bufend)
1377 goto success;
1343
1378
1379 returng:
1380 /* String too long, punt */
1381 buf[0] = '<';
1382 buf[1] = MACROEXPAND;
1383 buf[2]= 'g';
1384 buf[3] = '>';
1385 buf[4]= '\0';
1386 sm_syslog(LOG_ALERT, e->e_id,
1387 "Dropped invalid comments from header address");
1388
1389 success:
1344 if (tTd(33, 1))
1345 {
1346 sm_dprintf("crackaddr=>`");
1347 xputs(buf);
1348 sm_dprintf("'\n");
1349 }
1390 if (tTd(33, 1))
1391 {
1392 sm_dprintf("crackaddr=>`");
1393 xputs(buf);
1394 sm_dprintf("'\n");
1395 }
1350
1351 return buf;
1352}
1353/*
1354** PUTHEADER -- put the header part of a message from the in-core copy
1355**
1356** Parameters:
1357** mci -- the connection information.
1358** hdr -- the header to put.

--- 48 unchanged lines hidden (view full) ---

1407
1408 /* heuristic shortening of MIME fields to avoid MUA overflows */
1409 if (MaxMimeFieldLength > 0 &&
1410 wordinclass(h->h_field,
1411 macid("{checkMIMEFieldHeaders}")))
1412 {
1413 size_t len;
1414
1396 return buf;
1397}
1398/*
1399** PUTHEADER -- put the header part of a message from the in-core copy
1400**
1401** Parameters:
1402** mci -- the connection information.
1403** hdr -- the header to put.

--- 48 unchanged lines hidden (view full) ---

1452
1453 /* heuristic shortening of MIME fields to avoid MUA overflows */
1454 if (MaxMimeFieldLength > 0 &&
1455 wordinclass(h->h_field,
1456 macid("{checkMIMEFieldHeaders}")))
1457 {
1458 size_t len;
1459
1415 len = fix_mime_header(h->h_value);
1460 len = fix_mime_header(h, e);
1416 if (len > 0)
1417 {
1418 sm_syslog(LOG_ALERT, e->e_id,
1419 "Truncated MIME %s header due to field size (length = %ld) (possible attack)",
1420 h->h_field, (unsigned long) len);
1421 if (tTd(34, 11))
1422 sm_dprintf(" truncated MIME %s header due to field size (length = %ld) (possible attack)\n",
1423 h->h_field,

--- 26 unchanged lines hidden (view full) ---

1450 macid("{checkMIMEHeaders}")))
1451 {
1452 size_t len;
1453
1454 len = strlen(h->h_value);
1455 if (shorten_rfc822_string(h->h_value,
1456 MaxMimeHeaderLength))
1457 {
1461 if (len > 0)
1462 {
1463 sm_syslog(LOG_ALERT, e->e_id,
1464 "Truncated MIME %s header due to field size (length = %ld) (possible attack)",
1465 h->h_field, (unsigned long) len);
1466 if (tTd(34, 11))
1467 sm_dprintf(" truncated MIME %s header due to field size (length = %ld) (possible attack)\n",
1468 h->h_field,

--- 26 unchanged lines hidden (view full) ---

1495 macid("{checkMIMEHeaders}")))
1496 {
1497 size_t len;
1498
1499 len = strlen(h->h_value);
1500 if (shorten_rfc822_string(h->h_value,
1501 MaxMimeHeaderLength))
1502 {
1458 sm_syslog(LOG_ALERT, e->e_id,
1459 "Truncated long MIME %s header (length = %ld) (possible attack)",
1460 h->h_field, (unsigned long) len);
1461 if (tTd(34, 11))
1462 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n",
1463 h->h_field,
1464 (unsigned long) len);
1503 if (len < MaxMimeHeaderLength)
1504 {
1505 /* we only rebalanced a bogus header */
1506 sm_syslog(LOG_ALERT, e->e_id,
1507 "Fixed MIME %s header (possible attack)",
1508 h->h_field);
1509 if (tTd(34, 11))
1510 sm_dprintf(" fixed MIME %s header (possible attack)\n",
1511 h->h_field);
1512 }
1513 else
1514 {
1515 /* we actually shortened header */
1516 sm_syslog(LOG_ALERT, e->e_id,
1517 "Truncated long MIME %s header (length = %ld) (possible attack)",
1518 h->h_field,
1519 (unsigned long) len);
1520 if (tTd(34, 11))
1521 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n",
1522 h->h_field,
1523 (unsigned long) len);
1524 }
1465 }
1466 }
1467
1468 /*
1469 ** Suppress Content-Transfer-Encoding: if we are MIMEing
1470 ** and we are potentially converting from 8 bit to 7 bit
1471 ** MIME. If converting, add a new CTE header in
1472 ** mime8to7().

--- 378 unchanged lines hidden (view full) ---

1851/*
1852** FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
1853**
1854** Run through all of the parameters of a MIME header and
1855** possibly truncate and rebalance the parameter according
1856** to MaxMimeFieldLength.
1857**
1858** Parameters:
1525 }
1526 }
1527
1528 /*
1529 ** Suppress Content-Transfer-Encoding: if we are MIMEing
1530 ** and we are potentially converting from 8 bit to 7 bit
1531 ** MIME. If converting, add a new CTE header in
1532 ** mime8to7().

--- 378 unchanged lines hidden (view full) ---

1911/*
1912** FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
1913**
1914** Run through all of the parameters of a MIME header and
1915** possibly truncate and rebalance the parameter according
1916** to MaxMimeFieldLength.
1917**
1918** Parameters:
1859** string -- the full header
1919** h -- the header to truncate/rebalance
1920** e -- the current envelope
1860**
1861** Returns:
1862** length of last offending field, 0 if all ok.
1863**
1864** Side Effects:
1865** string modified in place
1866*/
1867
1868static size_t
1921**
1922** Returns:
1923** length of last offending field, 0 if all ok.
1924**
1925** Side Effects:
1926** string modified in place
1927*/
1928
1929static size_t
1869fix_mime_header(string)
1870 char *string;
1930fix_mime_header(h, e)
1931 HDR *h;
1932 ENVELOPE *e;
1871{
1933{
1872 char *begin = string;
1934 char *begin = h->h_value;
1873 char *end;
1874 size_t len = 0;
1875 size_t retlen = 0;
1876
1935 char *end;
1936 size_t len = 0;
1937 size_t retlen = 0;
1938
1877 if (string == NULL || *string == '\0')
1939 if (begin == NULL || *begin == '\0')
1878 return 0;
1879
1880 /* Split on each ';' */
1881 while ((end = find_character(begin, ';')) != NULL)
1882 {
1883 char save = *end;
1884 char *bp;
1885
1886 *end = '\0';
1887
1888 len = strlen(begin);
1889
1890 /* Shorten individual parameter */
1891 if (shorten_rfc822_string(begin, MaxMimeFieldLength))
1940 return 0;
1941
1942 /* Split on each ';' */
1943 while ((end = find_character(begin, ';')) != NULL)
1944 {
1945 char save = *end;
1946 char *bp;
1947
1948 *end = '\0';
1949
1950 len = strlen(begin);
1951
1952 /* Shorten individual parameter */
1953 if (shorten_rfc822_string(begin, MaxMimeFieldLength))
1892 retlen = len;
1954 {
1955 if (len < MaxMimeFieldLength)
1956 {
1957 /* we only rebalanced a bogus field */
1958 sm_syslog(LOG_ALERT, e->e_id,
1959 "Fixed MIME %s header field (possible attack)",
1960 h->h_field);
1961 if (tTd(34, 11))
1962 sm_dprintf(" fixed MIME %s header field (possible attack)\n",
1963 h->h_field);
1964 }
1965 else
1966 {
1967 /* we actually shortened the header */
1968 retlen = len;
1969 }
1970 }
1893
1894 /* Collapse the possibly shortened string with rest */
1895 bp = begin + strlen(begin);
1896 if (bp != end)
1897 {
1898 char *ep = end;
1899
1900 *end = save;

--- 17 unchanged lines hidden ---
1971
1972 /* Collapse the possibly shortened string with rest */
1973 bp = begin + strlen(begin);
1974 if (bp != end)
1975 {
1976 char *ep = end;
1977
1978 *end = save;

--- 17 unchanged lines hidden ---