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 --- |