/* ************************************************************* RWhois Software Copyright (c) 1994 Scott Williamson and Mark Kosters Copyright (c) 1996-2000 Network Solutions, Inc. See the file LICENSE for conditions of use and distribution. **************************************************************** */ /* This set of routines provides a (very) limited set of WHOIS (not RWhois) client routines, provided so that there is at least some support for following whois referrals. Note that since WHOIS is largely unstandardized, these routines are not guaranteed to work against all deployed WHOIS server. In fact, it is not guaranteed to work with any of them. */ #include "whoisquery.h" #include "rwhois.h" #include "strutils.h" char *whois_keyword_allowed_domains[] = { "networksolutions.com", "internic.net", NULL }; char *rwhois_keyword_list[] = { "domain", "host", "contact", "network", "server", NULL }; static int is_keyword_ok_host(char *host) { char *k; int i = 0; while ((k = whois_keyword_allowed_domains[i]) != NULL) { if (strSTR(host, k)) { return TRUE; } i++; } return FALSE; } /* query can be one of the following forms, really: value (e.g, "example.com", "host-org", "ns21.worldnic.com") attribute = value (e.g., "domain-name=example.com", "tech-contact = host-org", etc.) keyword value (e.g., "domain netsol.com") keyword attribute = value plus, AND and OR clauses. We won't deal with multi clause rwhois queries. We will just split into keyword, attribute name, and value */ static int split_rwhois_non_keyword_fragment(char *frag, char **attr, char **value) { char *p; /* we have attr = value (with or without whitespace) */ if ((p = strchr(frag, '='))) { *p = '\0'; *attr = frag; *value = p + 1; return RW_OK; } /* otherwise, we just have value */ *value = frag; return RW_OK; } static int split_rwhois_query(char *query, char **keyword, char **attr, char **value) { char *p; int i; assert(keyword); assert(attr); assert(value); if (NOT_STR_EXISTS(query)) { return RW_ERROR; } *keyword = NULL; *attr = NULL; *value = NULL; /* remove leading and trailing whitespace */ trim(query); /* if there is no whitespace, then there is no keyword */ if (count_spaces(query) <= 0) { return split_rwhois_non_keyword_fragment(query, attr, value); } /* we have whitespace, so there might be a keyword */ /* change sequences of whitespace to one to simplify matters */ compact_whitespace(query); i = 0; while ( rwhois_keyword_list[i] ) { /* we found a keyword */ if (strSTR(query, rwhois_keyword_list[i]) && (p = strchr(query, ' '))) { *p = '\0'; p++; *keyword = query; return split_rwhois_non_keyword_fragment(p, attr, value); } i++; } /* no keyword */ return split_rwhois_non_keyword_fragment(query, attr, value); } /* do some simplistic "corrections" to an rwhois query. Realistically, this should use regular expressions, or a full rwhois query parser. */ char * rwhois_correct_whois_query(rw_server_struct *server, char *rwhois_query) { char *keyword; char *attr; char *value; char *query_copy; char *query_result; int query_result_len; assert(server); if (NOT_STR_EXISTS(rwhois_query)) { return NULL; } if (NOT_STR_EXISTS(server->host)) { return NULL; } query_copy = STRDUP(rwhois_query); if (split_rwhois_query(query_copy, &keyword, &attr, &value) < 0) { FREE(query_copy); return STRDUP(rwhois_query); } query_result_len = 0; /* if we allow keywords, then result query is "keyword value" */ if (is_keyword_ok_host(server->host) && STR_EXISTS(keyword) && STR_EXISTS(value)) { query_result_len = strlen(keyword) + strlen(value) + 2; query_result = (char *) CALLOC(1, query_result_len); strcpy(query_result, keyword); strcat(query_result, " "); strcat(query_result, value); FREE(query_copy); return query_result; } /* otherwise, result query is just "value" */ if (STR_EXISTS(value)) { query_result = STRDUP(value); FREE(query_copy); return query_result; } FREE(query_copy); return NULL; } static rw_whois_result_struct * read_whois_response(rw_server_struct *server, rw_response_struct *response) { char line[MAXBUFFER]; char *buffer; rw_whois_result_struct *result; size_t buffer_size; size_t buffer_len; size_t line_length; assert(server); assert(response); result = (rw_whois_result_struct *) CALLOC(1, sizeof(*result)); buffer = (char *) CALLOC(1, MAXBUFFER); buffer_size = MAXBUFFER; buffer_len = 0; while ( (rwhois_read(server, line, sizeof(line))) > 0 ) { if (NOT_STR_EXISTS(line)) { continue; } if (strSTR(line, "Registrant:") && ( line[0] == 'R' || line[0] == 'r') ) { result->separator = STRDUP(line); if (buffer_len > 0) { result->disclaimer = buffer; buffer = (char *) CALLOC(1, MAXBUFFER); buffer_size = MAXBUFFER; buffer_len = 0; } continue; } line_length = strlen(line); /* see if we need to grow the buffer */ if ( (buffer_len + line_length + 2) > buffer_size && buffer_size < (5 * MAXBUFFER)) { buffer = (char *) REALLOC(buffer, buffer_size + MAXBUFFER); buffer_size += MAXBUFFER; } strcat(buffer, line); buffer_len += line_length; strcat(buffer, "\n"); buffer_len++; } result->text = buffer; return result; } rw_whois_result_struct * rwhois_query_whois_server(rw_server_struct *server, char *rwhois_query, rw_response_struct *response) { rw_whois_result_struct *result; char *actual_query; assert(server); assert(response); if (NOT_STR_EXISTS(rwhois_query)) { rwhois_set_response(response, RW_ERROR, "Null query"); return NULL; } /* open the connection to the whois server, if we haven't already */ if (!rwhois_is_open(server)) { if (rwhois_whoisconnect(server, response) < 0) { return NULL; } } /* calulate the real query */ actual_query = rwhois_correct_whois_query(server, rwhois_query); if (NOT_STR_EXISTS(actual_query)) { rwhois_set_response(response, RW_ERROR, "Error transforming rwhois query to whois query"); return NULL; } if (rwhois_write(server, actual_query, strlen(actual_query)) <= 0) { rwhois_set_response(response, RW_ERROR, "Write error occured in whois query"); FREE(actual_query); return NULL; } FREE(actual_query); result = read_whois_response(server, response); rwhois_close(server); return result; } rw_whois_result_struct * rwhois_query_whois_referral(rw_referral_struct *referral, char *rwhois_query, int debug_level, rw_response_struct *response) { rw_server_struct whois_server; assert(response); assert(referral); if (NOT_STR_EXISTS(referral->scheme) || !STR_EQ(referral->scheme, "whois")) { return NULL; } memset(&whois_server, 0, sizeof(whois_server)); whois_server.host = referral->host; whois_server.port = referral->port; whois_server.debug_level = debug_level; return rwhois_query_whois_server(&whois_server, rwhois_query, response); } int destroy_rw_whois_result_struct(rw_whois_result_struct *res) { if (!res) return TRUE; if (res->disclaimer) FREE(res->disclaimer); if (res->separator) FREE(res->separator); if (res->text) FREE(res->text); FREE(res); return TRUE; }