root/honeytrap/trunk/src/response.c

Revision 1355, 5.7 kB (checked in by till, 1 year ago)

- fix: corrected error in logical expression when searching for default responses
- fix: passing errors to errno when a non-blocking connect fails
- switched to the more flexible sigaction() instead of signal()
- improved ngrie's performance: reallocating arrays as trie nodes seems to be a fast solution

Line 
1 /* response.c
2  * Copyright (C) 2006-2007 Tillmann Werner <tillmann.werner@gmx.de>
3  *
4  * This file is free software; as a special exception the author gives
5  * unlimited permission to copy and/or distribute it, with or without
6  * modifications, as long as this notice is preserved.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
10  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * This code is based on an OpenSSL-compatible implementation of the RSA
13  * Data Security, * Inc. MD5 Message-Digest Algorithm, written by Solar
14  * Designer <solar at openwall.com> in 2001, and placed in the public
15  * domain. There's absolutely no warranty.
16  *
17  * This implementation is meant to be fast, but not as fast as possible.
18  * Some known optimizations are not included to reduce source code size
19  * and avoid compile-time configuration.
20  */
21
22 #include <dirent.h>
23 #include <errno.h>
24 #include <fnmatch.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30
31 #include "honeytrap.h"
32 #include "tcpip.h"
33 #include "logging.h"
34 #include "response.h"
35
36
37 void unload_default_responses(void) {
38         def_resp *cur_response;
39        
40         while(response_list) {
41                 cur_response = response_list->next;
42                 free(response_list->response);
43                 free(response_list);
44                 response_list = cur_response;
45         }
46         return;
47 }
48
49 int prepare_default_response(char *filename, uint16_t port, uint16_t proto) {
50         int answer_fd, ccopy;
51         u_char buffer[100];
52         FILE* answer_file = NULL;
53         def_resp *last_response, *new_response;
54
55         /* allocate memory for new response */
56         if ((new_response = (def_resp *) malloc(sizeof(struct def_resp))) == NULL) {
57                 perror("  Error - Unable to allocate memory");
58                 return(-1);
59         } else {
60                 new_response->port      = port;
61                 new_response->proto     = proto;
62                 new_response->size      = 0;
63                 new_response->response  = NULL;
64                 new_response->next      = NULL;
65         }
66         if (!response_list) response_list = new_response;
67         else {
68                 /* spool to end of the list and attach new response */
69                 last_response = response_list;
70                 while (last_response->next) last_response = last_response->next;
71                 last_response->next = new_response;
72         }
73
74         /* read response */
75         if ((proto != TCP) && (proto != UDP)) {
76                 fprintf(stderr, "  Error - Protocol %u is not supported.\n", proto);
77                 return(-1);
78         }
79         DEBUG_FPRINTF(stdout, "  Loading default response for port %u/%s.\n", port, PROTO(proto));
80         if (((answer_fd = open(filename, O_NOCTTY | O_RDONLY, 0640)) == -1) || (!(answer_file = fopen(filename, "rb")))) {
81                 DEBUG_FPRINTF(stdout, "  Warning - Unable to open file '%s'\n", filename);
82         } else {
83                 ccopy           = 0;
84                 while((ccopy = fread(buffer, 1, 100, answer_file))) {
85                         if ((new_response->response = (u_char *) realloc(new_response->response, new_response->size + ccopy)) == NULL) {
86                                 perror("  Error - Unable to allocate memory");
87                                 return(-1);
88                         } else {
89                                 memcpy(new_response->response + new_response->size, buffer, ccopy);
90                                 new_response->size += ccopy;
91                         }
92                 }
93                 if (new_response->size != 0) {
94                         DEBUG_FPRINTF(stdout, "  Default response string for port %u/%s successfully loaded.\n",
95                                 port, PROTO(proto));
96                 } else DEBUG_FPRINTF(stdout, "  Warning - Default response file '%s' is empty.\n", filename);
97         }
98         fclose(answer_file);
99         close(answer_fd);
100         return(0);
101 }
102
103
104 int load_default_responses(char *dir) {
105         struct stat statbuf;
106         struct dirent **namelist;
107         int n;
108         uint16_t port;
109         char *full_path;
110         DIR *respdir;
111
112         full_path = NULL;
113
114         if ((respdir = opendir(dir)) == NULL) {
115                 perror("  Error - Unable to open response directory");
116                 exit(EXIT_FAILURE);
117         }
118        
119         DEBUG_FPRINTF(stdout, "  Searching for response files in %s\n", dir);
120         if ((n = scandir(dir, &namelist, 0, alphasort)) < 0) {
121                 perror("  Error - Unable to scan response directory");
122                 exit(EXIT_FAILURE);
123         } else while(n--) {
124                 stat(namelist[n]->d_name, &statbuf);
125                 if ((fnmatch("*_tcp", namelist[n]->d_name, 0) == 0) || (fnmatch("*_udp", namelist[n]->d_name, 0) == 0)) {
126                         /* found a default response file */
127                         if ((full_path = (char *) malloc(strlen(dir) + strlen(namelist[n]->d_name) + 2)) == NULL) {
128                                 perror("  Error - Unable to allocate memory");
129                                 exit(EXIT_FAILURE);
130                         }
131                         snprintf(full_path, strlen(dir)+strlen(namelist[n]->d_name)+2, "%s/%s", dir, namelist[n]->d_name);
132                         DEBUG_FPRINTF(stdout, "  Response file found: %s\n", full_path);
133                         port = atoi(namelist[n]->d_name);
134                         if (fnmatch("*_tcp", namelist[n]->d_name, 0) == 0)
135                                 prepare_default_response(full_path, port, TCP);
136                         else if (fnmatch("*_udp", namelist[n]->d_name, 0) == 0)
137                                 prepare_default_response(full_path, port, UDP);
138                 }
139                 free(namelist[n]);
140         }
141         free(namelist);
142        
143         return(0);
144 }
145
146
147 int send_default_response(int connection_fd, uint16_t port, uint16_t proto, u_char timeout) {
148         def_resp *cur_response = NULL;
149
150         if ((proto != TCP) && (proto != UDP)) {
151                 fprintf(stderr, "  Error - Protocol %u is not supported.\n", proto);
152                 return(-1);
153         }
154
155         logmsg(LOG_DEBUG, 1, "Searching for default response for port %s.\n", portstr);
156        
157         /* advance through list to find response for port */
158         cur_response = response_list;
159         while(cur_response && ((cur_response->port != port) || (cur_response->proto != proto)))
160                 cur_response = cur_response->next;
161        
162         if (cur_response && (cur_response->port == port) && (cur_response->proto == proto)) {
163                 /* default response for port found */
164                 logmsg(LOG_NOISY, 1, "   %s  No data for %u second(s), sending default response.\n",
165                         portstr, (u_char) timeout);
166
167                 if (!(write(connection_fd, cur_response->response, cur_response->size))) return(-1);
168         } else {
169                 logmsg(LOG_NOISY, 1, "   %s  No data for %d second(s), sending '\\n'.\n", portstr, timeout);
170                 if (!(write(connection_fd, "\n", 1))) return(-1);
171         }
172         return(0);
173 }
174
Note: See TracBrowser for help on using the browser.