Lines 765-771
Link Here
|
765 |
} |
765 |
} |
766 |
|
766 |
|
767 |
static int |
767 |
static int |
768 |
_handle_spamd_header(struct message *m, int flags, char *buf, int len) |
768 |
_handle_spamd_header(struct message *m, int flags, char *buf, int len, |
|
|
769 |
int *islearned) |
769 |
{ |
770 |
{ |
770 |
char is_spam[6]; |
771 |
char is_spam[6]; |
771 |
char s_str[21], t_str[21]; |
772 |
char s_str[21], t_str[21]; |
Lines 818-827
Link Here
|
818 |
} |
819 |
} |
819 |
else if (sscanf(buf, "Learned: %3s", is_learned) == 1) { |
820 |
else if (sscanf(buf, "Learned: %3s", is_learned) == 1) { |
820 |
if(strcmp(is_learned, "yes") == 0 || strcmp(is_learned, "Yes") == 0) { |
821 |
if(strcmp(is_learned, "yes") == 0 || strcmp(is_learned, "Yes") == 0) { |
821 |
m->is_learned = 1; |
822 |
*islearned = 1; |
822 |
} |
823 |
} |
823 |
else if(strcmp(is_learned, "no") == 0 || strcmp(is_learned, "No") == 0) { |
824 |
else if(strcmp(is_learned, "no") == 0 || strcmp(is_learned, "No") == 0) { |
824 |
m->is_learned = 0; |
825 |
*islearned = 0; |
825 |
} |
826 |
} |
826 |
else { |
827 |
else { |
827 |
libspamc_log(flags, LOG_ERR, "spamd responded with bad Learned-state '%s'", |
828 |
libspamc_log(flags, LOG_ERR, "spamd responded with bad Learned-state '%s'", |
Lines 835-842
Link Here
|
835 |
return EX_PROTOCOL; |
836 |
return EX_PROTOCOL; |
836 |
} |
837 |
} |
837 |
|
838 |
|
838 |
int message_filter(struct transport *tp, const char *username, int learntype, |
839 |
int message_filter(struct transport *tp, const char *username, |
839 |
int flags, struct message *m) |
840 |
int flags, struct message *m) |
840 |
{ |
841 |
{ |
841 |
char buf[8192]; |
842 |
char buf[8192]; |
842 |
size_t bufsiz = (sizeof(buf) / sizeof(*buf)) - 4; /* bit of breathing room */ |
843 |
size_t bufsiz = (sizeof(buf) / sizeof(*buf)) - 4; /* bit of breathing room */ |
Lines 844-850
Link Here
|
844 |
int sock = -1; |
845 |
int sock = -1; |
845 |
int rc; |
846 |
int rc; |
846 |
char versbuf[20]; |
847 |
char versbuf[20]; |
847 |
char strlearntype[1]; |
|
|
848 |
float version; |
848 |
float version; |
849 |
int response; |
849 |
int response; |
850 |
int failureval; |
850 |
int failureval; |
Lines 876-882
Link Here
|
876 |
m->out_len = 0; |
876 |
m->out_len = 0; |
877 |
|
877 |
|
878 |
/* Build spamd protocol header */ |
878 |
/* Build spamd protocol header */ |
879 |
if(flags & SPAMC_CHECK_ONLY) |
879 |
if (flags & SPAMC_CHECK_ONLY) |
880 |
strcpy(buf, "CHECK "); |
880 |
strcpy(buf, "CHECK "); |
881 |
else if (flags & SPAMC_REPORT_IFSPAM) |
881 |
else if (flags & SPAMC_REPORT_IFSPAM) |
882 |
strcpy(buf, "REPORT_IFSPAM "); |
882 |
strcpy(buf, "REPORT_IFSPAM "); |
Lines 884-891
Link Here
|
884 |
strcpy(buf, "REPORT "); |
884 |
strcpy(buf, "REPORT "); |
885 |
else if (flags & SPAMC_SYMBOLS) |
885 |
else if (flags & SPAMC_SYMBOLS) |
886 |
strcpy(buf, "SYMBOLS "); |
886 |
strcpy(buf, "SYMBOLS "); |
887 |
else if (flags & SPAMC_LEARN ) |
|
|
888 |
strcpy(buf, "LEARN "); |
889 |
else |
887 |
else |
890 |
strcpy(buf, "PROCESS "); |
888 |
strcpy(buf, "PROCESS "); |
891 |
|
889 |
|
Lines 899-919
Link Here
|
899 |
strcat(buf, "\r\n"); |
897 |
strcat(buf, "\r\n"); |
900 |
len = strlen(buf); |
898 |
len = strlen(buf); |
901 |
|
899 |
|
902 |
|
|
|
903 |
if (flags & SPAMC_LEARN) { |
904 |
if ((learntype > 2) | (learntype < 0 )) { |
905 |
free(m->out); |
906 |
m->out = m->msg; |
907 |
m->out_len = m->msg_len; |
908 |
return EX_OSERR; |
909 |
} |
910 |
sprintf(strlearntype,"%d",learntype); |
911 |
strcpy(buf + len, "Learn-type: "); |
912 |
strcat(buf + len, strlearntype); |
913 |
strcat(buf + len, "\r\n"); |
914 |
len += strlen(buf + len); |
915 |
} |
916 |
|
917 |
if (username != NULL) { |
900 |
if (username != NULL) { |
918 |
if (strlen(username) + 8 >= (bufsiz - len)) { |
901 |
if (strlen(username) + 8 >= (bufsiz - len)) { |
919 |
_use_msg_for_out(m); |
902 |
_use_msg_for_out(m); |
Lines 988-994
Link Here
|
988 |
m->score = 0; |
971 |
m->score = 0; |
989 |
m->threshold = 0; |
972 |
m->threshold = 0; |
990 |
m->is_spam = EX_TOOBIG; |
973 |
m->is_spam = EX_TOOBIG; |
991 |
m->is_learned = 0; |
|
|
992 |
while (1) { |
974 |
while (1) { |
993 |
failureval = |
975 |
failureval = |
994 |
_spamc_read_full_line(m, flags, ssl, sock, buf, &len, bufsiz); |
976 |
_spamc_read_full_line(m, flags, ssl, sock, buf, &len, bufsiz); |
Lines 999-1006
Link Here
|
999 |
if (len == 0 && buf[0] == '\0') { |
981 |
if (len == 0 && buf[0] == '\0') { |
1000 |
break; /* end of headers */ |
982 |
break; /* end of headers */ |
1001 |
} |
983 |
} |
1002 |
|
984 |
int throwaway; |
1003 |
if (_handle_spamd_header(m, flags, buf, len) < 0) { |
985 |
if (_handle_spamd_header(m, flags, buf, len, &throwaway) < 0) { |
1004 |
failureval = EX_PROTOCOL; |
986 |
failureval = EX_PROTOCOL; |
1005 |
goto failure; |
987 |
goto failure; |
1006 |
} |
988 |
} |
Lines 1018-1029
Link Here
|
1018 |
} |
1000 |
} |
1019 |
return EX_OK; |
1001 |
return EX_OK; |
1020 |
} |
1002 |
} |
1021 |
else if (flags & SPAMC_LEARN) { |
|
|
1022 |
shutdown(sock, SHUT_RD); |
1023 |
closesocket(sock); |
1024 |
sock = -1; |
1025 |
return EX_OK; |
1026 |
} |
1027 |
else { |
1003 |
else { |
1028 |
if (m->content_length < 0) { |
1004 |
if (m->content_length < 0) { |
1029 |
/* should have got a length too. */ |
1005 |
/* should have got a length too. */ |
Lines 1093-1099
Link Here
|
1093 |
} |
1069 |
} |
1094 |
|
1070 |
|
1095 |
|
1071 |
|
1096 |
int message_process(struct transport *trans, char *username, int learntype, int max_size, |
1072 |
int message_process(struct transport *trans, char *username, int max_size, |
1097 |
int in_fd, int out_fd, const int flags) |
1073 |
int in_fd, int out_fd, const int flags) |
1098 |
{ |
1074 |
{ |
1099 |
int ret; |
1075 |
int ret; |
Lines 1105-1111
Link Here
|
1105 |
ret = message_read(in_fd, flags, &m); |
1081 |
ret = message_read(in_fd, flags, &m); |
1106 |
if (ret != EX_OK) |
1082 |
if (ret != EX_OK) |
1107 |
goto FAIL; |
1083 |
goto FAIL; |
1108 |
ret = message_filter(trans, username, learntype, flags, &m); |
1084 |
ret = message_filter(trans, username, flags, &m); |
1109 |
if (ret != EX_OK) |
1085 |
if (ret != EX_OK) |
1110 |
goto FAIL; |
1086 |
goto FAIL; |
1111 |
if (message_write(out_fd, &m) < 0) |
1087 |
if (message_write(out_fd, &m) < 0) |
Lines 1130-1136
Link Here
|
1130 |
} |
1106 |
} |
1131 |
} |
1107 |
} |
1132 |
|
1108 |
|
|
|
1109 |
int message_learn(struct transport *tp, const char *username, int flags, |
1110 |
struct message *m, int learntype, int *islearned) |
1111 |
{ |
1112 |
char buf[8192]; |
1113 |
size_t bufsiz = (sizeof(buf) / sizeof(*buf)) - 4; /* bit of breathing room */ |
1114 |
size_t len; |
1115 |
int sock = -1; |
1116 |
int rc; |
1117 |
char versbuf[20]; |
1118 |
char strlearntype[1]; |
1119 |
float version; |
1120 |
int response; |
1121 |
int failureval; |
1122 |
SSL_CTX *ctx = NULL; |
1123 |
SSL *ssl = NULL; |
1124 |
SSL_METHOD *meth; |
1133 |
|
1125 |
|
|
|
1126 |
if (flags & SPAMC_USE_SSL) { |
1127 |
#ifdef SPAMC_SSL |
1128 |
SSLeay_add_ssl_algorithms(); |
1129 |
meth = SSLv2_client_method(); |
1130 |
SSL_load_error_strings(); |
1131 |
ctx = SSL_CTX_new(meth); |
1132 |
#else |
1133 |
UNUSED_VARIABLE(ssl); |
1134 |
UNUSED_VARIABLE(meth); |
1135 |
UNUSED_VARIABLE(ctx); |
1136 |
libspamc_log(flags, LOG_ERR, "spamc not built with SSL support"); |
1137 |
return EX_SOFTWARE; |
1138 |
#endif |
1139 |
} |
1140 |
|
1141 |
m->is_spam = EX_TOOBIG; |
1142 |
if ((m->outbuf = malloc(m->max_len + EXPANSION_ALLOWANCE + 1)) == NULL) { |
1143 |
failureval = EX_OSERR; |
1144 |
goto failure; |
1145 |
} |
1146 |
m->out = m->outbuf; |
1147 |
m->out_len = 0; |
1148 |
|
1149 |
/* Build spamd protocol header */ |
1150 |
strcpy(buf, "LEARN "); |
1151 |
|
1152 |
len = strlen(buf); |
1153 |
if (len + strlen(PROTOCOL_VERSION) + 2 >= bufsiz) { |
1154 |
_use_msg_for_out(m); |
1155 |
return EX_OSERR; |
1156 |
} |
1157 |
|
1158 |
strcat(buf, PROTOCOL_VERSION); |
1159 |
strcat(buf, "\r\n"); |
1160 |
len = strlen(buf); |
1161 |
|
1162 |
if ((learntype > 2) | (learntype < 0 )) { |
1163 |
free(m->out); |
1164 |
m->out = m->msg; |
1165 |
m->out_len = m->msg_len; |
1166 |
return EX_OSERR; |
1167 |
} |
1168 |
sprintf(strlearntype,"%d",learntype); |
1169 |
strcpy(buf + len, "Learn-type: "); |
1170 |
strcat(buf + len, strlearntype); |
1171 |
strcat(buf + len, "\r\n"); |
1172 |
len += strlen(buf + len); |
1173 |
|
1174 |
if (username != NULL) { |
1175 |
if (strlen(username) + 8 >= (bufsiz - len)) { |
1176 |
_use_msg_for_out(m); |
1177 |
return EX_OSERR; |
1178 |
} |
1179 |
strcpy(buf + len, "User: "); |
1180 |
strcat(buf + len, username); |
1181 |
strcat(buf + len, "\r\n"); |
1182 |
len += strlen(buf + len); |
1183 |
} |
1184 |
if ((m->msg_len > 9999999) || ((len + 27) >= (bufsiz - len))) { |
1185 |
_use_msg_for_out(m); |
1186 |
return EX_OSERR; |
1187 |
} |
1188 |
len += sprintf(buf + len, "Content-length: %d\r\n\r\n", m->msg_len); |
1189 |
|
1190 |
libspamc_timeout = m->timeout; |
1191 |
|
1192 |
if (tp->socketpath) |
1193 |
rc = _try_to_connect_unix(tp, &sock); |
1194 |
else |
1195 |
rc = _try_to_connect_tcp(tp, &sock); |
1196 |
|
1197 |
if (rc != EX_OK) { |
1198 |
_use_msg_for_out(m); |
1199 |
return rc; /* use the error code try_to_connect_*() gave us. */ |
1200 |
} |
1201 |
|
1202 |
if (flags & SPAMC_USE_SSL) { |
1203 |
#ifdef SPAMC_SSL |
1204 |
ssl = SSL_new(ctx); |
1205 |
SSL_set_fd(ssl, sock); |
1206 |
SSL_connect(ssl); |
1207 |
#endif |
1208 |
} |
1209 |
|
1210 |
/* Send to spamd */ |
1211 |
if (flags & SPAMC_USE_SSL) { |
1212 |
#ifdef SPAMC_SSL |
1213 |
SSL_write(ssl, buf, len); |
1214 |
SSL_write(ssl, m->msg, m->msg_len); |
1215 |
#endif |
1216 |
} |
1217 |
else { |
1218 |
full_write(sock, 0, buf, len); |
1219 |
full_write(sock, 0, m->msg, m->msg_len); |
1220 |
shutdown(sock, SHUT_WR); |
1221 |
} |
1222 |
|
1223 |
/* ok, now read and parse it. SPAMD/1.2 line first... */ |
1224 |
failureval = |
1225 |
_spamc_read_full_line(m, flags, ssl, sock, buf, &len, bufsiz); |
1226 |
if (failureval != EX_OK) { |
1227 |
goto failure; |
1228 |
} |
1229 |
|
1230 |
if (sscanf(buf, "SPAMD/%18s %d %*s", versbuf, &response) != 2) { |
1231 |
libspamc_log(flags, LOG_ERR, "spamd responded with bad string '%s'", buf); |
1232 |
failureval = EX_PROTOCOL; |
1233 |
goto failure; |
1234 |
} |
1235 |
|
1236 |
versbuf[19] = '\0'; |
1237 |
version = _locale_safe_string_to_float(versbuf, 20); |
1238 |
if (version < 1.0) { |
1239 |
libspamc_log(flags, LOG_ERR, "spamd responded with bad version string '%s'", |
1240 |
versbuf); |
1241 |
failureval = EX_PROTOCOL; |
1242 |
goto failure; |
1243 |
} |
1244 |
|
1245 |
m->score = 0; |
1246 |
m->threshold = 0; |
1247 |
m->is_spam = EX_TOOBIG; |
1248 |
*islearned = 0; |
1249 |
while (1) { |
1250 |
failureval = |
1251 |
_spamc_read_full_line(m, flags, ssl, sock, buf, &len, bufsiz); |
1252 |
if (failureval != EX_OK) { |
1253 |
goto failure; |
1254 |
} |
1255 |
|
1256 |
if (len == 0 && buf[0] == '\0') { |
1257 |
break; /* end of headers */ |
1258 |
} |
1259 |
|
1260 |
if (_handle_spamd_header(m, flags, buf, len, islearned) < 0) { |
1261 |
failureval = EX_PROTOCOL; |
1262 |
goto failure; |
1263 |
} |
1264 |
} |
1265 |
|
1266 |
len = 0; /* overwrite those headers */ |
1267 |
|
1268 |
shutdown(sock, SHUT_RD); |
1269 |
closesocket(sock); |
1270 |
sock = -1; |
1271 |
return EX_OK; |
1272 |
|
1273 |
libspamc_timeout = 0; |
1274 |
|
1275 |
if (m->out_len != m->content_length) { |
1276 |
libspamc_log(flags, LOG_ERR, |
1277 |
"failed sanity check, %d bytes claimed, %d bytes seen", |
1278 |
m->content_length, m->out_len); |
1279 |
failureval = EX_PROTOCOL; |
1280 |
goto failure; |
1281 |
} |
1282 |
|
1283 |
return EX_OK; |
1284 |
|
1285 |
failure: |
1286 |
_use_msg_for_out(m); |
1287 |
if (sock != -1) { |
1288 |
closesocket(sock); |
1289 |
} |
1290 |
libspamc_timeout = 0; |
1291 |
|
1292 |
if (flags & SPAMC_USE_SSL) { |
1293 |
#ifdef SPAMC_SSL |
1294 |
SSL_free(ssl); |
1295 |
SSL_CTX_free(ctx); |
1296 |
#endif |
1297 |
} |
1298 |
return failureval; |
1299 |
} |
1300 |
|
1134 |
void message_cleanup(struct message *m) |
1301 |
void message_cleanup(struct message *m) |
1135 |
{ |
1302 |
{ |
1136 |
if (m->outbuf) |
1303 |
if (m->outbuf) |
Lines 1143-1151
Link Here
|
1143 |
} |
1310 |
} |
1144 |
|
1311 |
|
1145 |
/* Aug 14, 2002 bj: Obsolete! */ |
1312 |
/* Aug 14, 2002 bj: Obsolete! */ |
1146 |
int process_message(struct transport *tp, char *username, int learntype, |
1313 |
int process_message(struct transport *tp, char *username, int max_size, |
1147 |
int max_size, int in_fd, int out_fd, |
1314 |
int in_fd, int out_fd, const int my_check_only, |
1148 |
const int my_check_only, const int my_safe_fallback) |
1315 |
const int my_safe_fallback) |
1149 |
{ |
1316 |
{ |
1150 |
int flags; |
1317 |
int flags; |
1151 |
|
1318 |
|
Lines 1155-1161
Link Here
|
1155 |
if (my_safe_fallback) |
1322 |
if (my_safe_fallback) |
1156 |
flags |= SPAMC_SAFE_FALLBACK; |
1323 |
flags |= SPAMC_SAFE_FALLBACK; |
1157 |
|
1324 |
|
1158 |
return message_process(tp, username, learntype, max_size, in_fd, out_fd, flags); |
1325 |
return message_process(tp, username, max_size, in_fd, out_fd, flags); |
1159 |
} |
1326 |
} |
1160 |
|
1327 |
|
1161 |
/* |
1328 |
/* |