/*************************************************************************** * Copyright (C) 2005 Meni Livne * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * 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. * ***************************************************************************/ #ifdef WIN32 #define close closesocket #include #else #include #include #include #endif #include #include #include #include #include #include "phish_opdb_server.h" #include "phish_util_net.h" #include "phish_util_url.h" #ifdef WIN32 #define ssize_t int #endif #define BUF_SIZE 1024 phish_result_t phish_opdbserver_checkURL(phish_util_url_t *query_url, phish_util_url_t *url, const char *ip, const char *user_agent, phish_url_data_t *results) { #ifdef WIN32 SOCKET sock; #else int sock; #endif char buf[BUF_SIZE]; char *full_query; phish_result_t r; phish_util_http_headers_t headers; full_query = malloc(strlen(query_url->path) + 3 + strlen(url->protocol) + 3 + strlen(ip) + 3 + strlen(url->host) + 3 + strlen(url->path) + 1); if (full_query == NULL) { return PHISH_ERR_MEMORY; } sprintf(full_query, "%s?m=%s&i=%s&s=%s&p=%s", query_url->path, url->protocol, ip, url->host, url->path); /* create socket */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) { return PHISH_ERR_TCP_CONNECT; } /* connect to server */ r = phish_util_tcpConnect(sock, query_url->host, query_url->port); if (r != PHISH_SUCCESS) { return r; } /* send HTTP get request */ r = phish_util_httpGet(sock, full_query, "1.0", query_url->host, user_agent, NULL, NULL, 0); if (r != PHISH_SUCCESS) { return r; } free(full_query); /* parse headers of reply from HTTP server */ r = phish_util_parseHTTPReply(sock, &headers); if (r != PHISH_SUCCESS) { return r; } if (headers.status_code != HTTP_STATUS_OK) { return PHISH_ERR_HTTP_BAD_STATUS; } free(headers.etag); if (phish_util_sockReadLine(sock, buf, BUF_SIZE) != PHISH_SUCCESS) { return PHISH_ERR_SOCK_READ; } /* read results of site query from server */ while (strcmp(buf, "") != 0) { char *field, *content; int i = 0; /* extract field name and field content from reply line */ while (buf[i] != '\0' && buf[i] != ':') i++; if (buf[i] == '\0') return PHISH_ERR_OPDB_BAD_REPLY; field = malloc(i + 1); if (field == NULL) return PHISH_ERR_MEMORY; strncpy(field, buf, i); field[i++] = '\0'; while (buf[i] != '\0' && buf[i] == ' ') i++; if (buf[i] == '\0') { free(field); return PHISH_ERR_OPDB_BAD_REPLY; } content = malloc(strlen(buf + i) + 1); if (content == NULL) { free(field); return PHISH_ERR_MEMORY; } strncpy(content, buf + i, strlen(buf + i)); content[strlen(buf + i)] = '\0'; if (strcmp(field, "IP") == 0) { results->ip = (strcmp(content, "y") == 0) ? 1 : 0; } else if (strcmp(field, "Server") == 0) { results->server = (strcmp(content, "y") == 0) ? 1 : 0; } else if (strcmp(field, "Path") == 0) { results->path = (strcmp(content, "y") == 0) ? 1 : 0; } else if (strcmp(field, "Country") == 0) { strncpy(results->country, content, 2); results->country[2] = '\0'; } else if (strcmp(field, "Comments-Length") == 0) { results->comments_length = atoi(content); } free(field); free(content); if (phish_util_sockReadLine(sock, buf, BUF_SIZE) != PHISH_SUCCESS) { return PHISH_ERR_SOCK_READ; } } /* read comments */ if (results->comments_length > 0) { char *pos; size_t length_remain = results->comments_length; results->comments = malloc(results->comments_length + 1); if (results->comments == NULL) return PHISH_ERR_MEMORY; pos = results->comments; if (phish_util_sockReadLine(sock, buf, BUF_SIZE) != PHISH_SUCCESS) return PHISH_ERR_SOCK_READ; while (length_remain > 0 && (strcmp(buf, "") != 0)) { length_remain -= strlen(buf); strcpy(pos, buf); pos += strlen(buf); if (phish_util_sockReadLine(sock, buf, BUF_SIZE) != PHISH_SUCCESS) { return PHISH_ERR_SOCK_READ; } } } close(sock); return PHISH_SUCCESS; } phish_result_t phish_opdbserver_checkCountry(phish_util_url_t *country_url, const char *ip, const char *user_agent, phish_url_data_t *results) { #ifdef WIN32 SOCKET sock; #else int sock; #endif char buf[BUF_SIZE]; char *full_query; phish_result_t r; phish_util_http_headers_t headers; full_query = malloc(strlen(country_url->path) + 3 + strlen(ip) + 1); if (full_query == NULL) { return PHISH_ERR_MEMORY; } sprintf(full_query, "%s?i=%s", country_url->path, ip); /* create socket */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) { return PHISH_ERR_TCP_CONNECT; } /* connect to server */ r = phish_util_tcpConnect(sock, country_url->host, country_url->port); if (r != PHISH_SUCCESS) { return r; } /* send HTTP get request */ r = phish_util_httpGet(sock, full_query, "1.0", country_url->host, user_agent, NULL, NULL, 0); if (r != PHISH_SUCCESS) { return r; } free(full_query); /* parse headers of reply from HTTP server */ r = phish_util_parseHTTPReply(sock, &headers); if (r != PHISH_SUCCESS) { return r; } if (headers.status_code != HTTP_STATUS_OK) { return PHISH_ERR_HTTP_BAD_STATUS; } free(headers.etag); if (phish_util_sockReadLine(sock, buf, BUF_SIZE) != PHISH_SUCCESS) { return PHISH_ERR_SOCK_READ; } /* read results of site query from server */ while (strcmp(buf, "") != 0) { char *field, *content; int i = 0; /* extract field name and field content from reply line */ while (buf[i] != '\0' && buf[i] != ':') i++; if (buf[i] == '\0') return PHISH_ERR_OPDB_BAD_REPLY; field = malloc(i + 1); if (field == NULL) return PHISH_ERR_MEMORY; strncpy(field, buf, i); field[i++] = '\0'; while (buf[i] != '\0' && buf[i] == ' ') i++; if (buf[i] == '\0') { free(field); return PHISH_ERR_OPDB_BAD_REPLY; } content = malloc(strlen(buf + i) + 1); if (content == NULL) { free(field); return PHISH_ERR_MEMORY; } strncpy(content, buf + i, strlen(buf + i)); content[strlen(buf + i)] = '\0'; if (strcmp(field, "Country") == 0) { strncpy(results->country, content, 2); results->country[2] = '\0'; } free(field); free(content); if (phish_util_sockReadLine(sock, buf, BUF_SIZE) != PHISH_SUCCESS) { return PHISH_ERR_SOCK_READ; } } close(sock); return PHISH_SUCCESS; } phish_result_t phish_opdbserver_downloadDBAsXML(phish_util_url_t *download_url, const char *user_agent, const char *local_file, const char *etag, char **new_etag) { #ifdef WIN32 SOCKET sock; #else int sock; #endif ssize_t bytes_read; char buf[BUF_SIZE]; struct stat sb; phish_result_t r; phish_util_http_headers_t headers; FILE *local_xml; /* if the local XML file doesn't exist, it will be downloaded regardless of the etag */ if (stat(local_file, &sb) == -1 || (sb.st_mode & S_IFREG) == 0) etag = NULL; /* create socket */ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) { return PHISH_ERR_TCP_CONNECT; } /* connect to server */ r = phish_util_tcpConnect(sock, download_url->host, download_url->port); if (r != PHISH_SUCCESS) { return r; } r = phish_util_httpGet(sock, download_url->path, "1.0", download_url->host, user_agent, NULL, etag, 0); if (r != PHISH_SUCCESS) { return r; } r = phish_util_parseHTTPReply(sock, &headers); if (r != PHISH_SUCCESS) { return r; } if (headers.status_code == HTTP_STATUS_NOT_MODIFIED) { /* file wasn't modified, so don't download */ free(headers.etag); close(sock); return PHISH_XML_NOT_MODIFIED; } else if (headers.status_code != HTTP_STATUS_OK) { free(headers.etag); close(sock); return PHISH_ERR_HTTP_BAD_STATUS; } /* set new ETag received */ *new_etag = malloc(strlen(headers.etag) + 1); if (*new_etag == NULL) { free(headers.etag); close(sock); return PHISH_ERR_MEMORY; } strcpy(*new_etag, headers.etag); free(headers.etag); /* download file */ local_xml = fopen(local_file, "w"); if (local_xml == NULL) { close(sock); return PHISH_ERR_FILE; } while ((bytes_read = recv(sock, buf, BUF_SIZE, 0)) > 0) { fwrite(buf, bytes_read, 1, local_xml); } if (bytes_read < 0) { fclose(local_xml); close(sock); return PHISH_ERR_SOCK_READ; } fclose(local_xml); close(sock); return PHISH_SUCCESS; } phish_result_t phish_opdbserver_getReportingURL(phish_util_url_t *reporting_url, const char *client_ua, const char *url, char **result) { *result = malloc(strlen(reporting_url->protocol) + 3 + strlen(reporting_url->host) + strlen(reporting_url->path) + 5 + strlen(url) + 8 + strlen(client_ua) + 1); if (*result == NULL) return PHISH_ERR_MEMORY; sprintf(*result, "%s://%s%s?url=%s&client=%s", reporting_url->protocol, reporting_url->host, reporting_url->path, url, client_ua); return PHISH_SUCCESS; }