/* dnsdcc.c - MessageWall DNS DCC definitions Copyright (C) 2002 Ian Gulliver This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include "messagewall.h" #include "md5.h" #include "mime.h" #include "smtp.h" #include "dnsdcc.h" static const char tagstring[] = "$Id: dnsdcc.c,v 1.20 2002/07/15 17:48:26 ian Exp $"; char *dnsdcc_checksum_aa(struct firestring_estr_t *chunk) { /* * this is a standard boring md5 */ static char ret[33]; md5_state_t state; md5_byte_t digest[16]; int i; md5_init(&state); md5_append(&state, (unsigned char *) chunk->s, chunk->l); md5_finish(&state, digest); /* * we know the maximum size of the object we're printing (1 byte), so this sprintf is safe */ for (i = 0; i < 16; i++) sprintf(ret + i * 2, "%02x", digest[i]); /* ITS4: ignore sprintf */ return ret; } char *dnsdcc_checksum_ba(struct firestring_estr_t *chunk) { /* * mad crazy linguistic "the" hook checksum */ static struct firestring_estr_t line = {0}; int i = 0; int words = 0; if (line.a == 0) firestring_estr_alloc(&line,DNSDCC_BA_MAXLEN); line.l = 0; while (words < 10) { i = firestring_estr_stristr(chunk,"the",i); if (i == -1) break; i += 3; if (chunk->l <= i) break; if (strchr(DNSDCC_WHITESPACE,chunk->s[i]) == NULL) continue; while (strchr(DNSDCC_WHITESPACE,chunk->s[i]) != NULL) { i++; if (chunk->l <= i) goto dnsdcc_ba_out; } while (strchr(DNSDCC_WHITESPACE,chunk->s[i]) == NULL) { /* * check for space in line */ if (line.l >= line.a - 1) goto dnsdcc_ba_out; /* * check for end of source */ if (i == chunk->l - 1) goto dnsdcc_ba_out; line.s[line.l++] = tolower(chunk->s[i]); i++; } line.s[line.l++] = ' '; words++; } dnsdcc_ba_out: if (words < 5) return NULL; return dnsdcc_checksum_aa(&line); } int dnsdcc_clear_queries(int client) { time(&clients[client].dnsdcc_send); clients[client].resent_dnsdcc = 0; clients[client].num_parts = 0; return 0; } int dnsdcc_send_queries(int client, int part, char *(*check)(struct firestring_estr_t *), struct firestring_estr_t *chunk) { struct messagewall_dnsdcc_global_t *dnsdcc; char *res; char query[256]; clients[client].resent_dnsdcc = 0; res = check(chunk); if (res == NULL) return 0; dnsdcc = dnsdcc_head; while (dnsdcc != NULL) { if (dnsdcc->check != check) { dnsdcc = dnsdcc->next; continue; } firestring_snprintf(query,256,"%s.%e",res,&dnsdcc->dnsdcc); clients[client].dnsdcc_fd[part][dnsdcc->i] = firedns_gettxt(query); dnsdcc = dnsdcc->next; } clients[client].num_parts = max(clients[client].num_parts,part); return 0; } int dnsdcc_resend_queries(int client) { struct messagewall_dnsdcc_global_t *dnsdcc; char query[256]; int i; dnsdcc = dnsdcc_head; while (dnsdcc != NULL) { for (i = 0; i < clients[client].num_parts; i++) if (clients[client].dnsdcc_fd[i][dnsdcc->i] >= 0) { firedns_getresult(clients[client].dnsdcc_fd[i][dnsdcc->i]); firestring_snprintf(query,256,"%s.%s",dnsdcc->check(&clients[client].parts[i].message.body),&dnsdcc->dnsdcc); clients[client].dnsdcc_fd[i][dnsdcc->i] = firedns_gettxt(query); } dnsdcc = dnsdcc->next; } return 0; } int dnsdcc_response(int client, int part, int dnsdcc) { char *ret; ret = firedns_getresult(clients[client].dnsdcc_fd[part][dnsdcc]); if (ret == NULL) clients[client].dnsdcc_fd[part][dnsdcc] = -1; else clients[client].dnsdcc_fd[part][dnsdcc] = -2; return 0; } int dnsdcc_check_profile(int client, int force) { struct messagewall_dnsdcc_profile_t *iter; int i; iter = clients[client].profile->dnsdcc; while (iter != NULL) { for (i = 0; i <= clients[client].num_parts; i++) { if (clients[client].dnsdcc_fd[i][iter->global->i] == -2) { if (force == 1) { if (smtp_reject(client,"DNSDCC","%e: checksum is listed",SMTP_DNSDCC,iter->score,0,&iter->global->dnsdcc,NULL) == 1) return 1; } else return 1; } if (clients[client].dnsdcc_fd[i][iter->global->i] >= 0) { if (force == 1) continue; else return -1; } } iter = iter->next; } return 0; }