whois.c | 145 ++++++++++++++++++++++++++++++++++++++++----------------------- whois.h | 13 ++++- 2 files changed, 102 insertions(+), 56 deletions(-) diff --git a/whois.c b/whois.c index a8be51b..6f85038 100644 --- a/whois.c +++ b/whois.c @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) /* RIPE flags */ if (strchr(ripeflags, ch)) { for (p = fstring; *p; p++); - sprintf(p--, "-%c ", ch); + snprintf(p--, sizeof(fstring), "-%c ", ch); continue; } if (strchr(ripeflagsp, ch)) { @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) /* program flags */ switch (ch) { case 'h': - server = strdup(optarg); + server = xstrdup(optarg); break; case 'V': client_tag = optarg; @@ -107,7 +107,7 @@ int main(int argc, char *argv[]) hide_discl = HIDE_UNSTARTED; /* enable disclaimers hiding */ break; case 'p': - port = strdup(optarg); + port = xstrdup(optarg); break; case 2: verb = 1; @@ -131,7 +131,7 @@ int main(int argc, char *argv[]) usage(); /* On some systems realloc only works on non-NULL buffers */ - qstring = malloc(64); + qstring = xmalloc(64); *qstring = '\0'; /* parse other parameters, if any */ @@ -140,11 +140,11 @@ int main(int argc, char *argv[]) while (1) { qslen += strlen(*argv) + 1 + 1; - qstring = realloc(qstring, qslen); - strcat(qstring, *argv++); + qstring = xrealloc(qstring, qslen); + strncat(qstring, *argv++, qslen-1); if (argc == 1) break; - strcat(qstring, " "); + strncat(qstring, " ", qslen-1); argc--; } } @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) /* -v or -t has been used */ if (!server && !*qstring) - server = strdup("whois.ripe.net"); + server = xstrdup("whois.ripe.net"); #ifdef CONFIG_FILE if (!server) { @@ -191,12 +191,13 @@ const char *handle_query(const char *hserver, const char *hport, { const char *server = NULL, *port = NULL; char *p; + size_t buflen = 0; if (hport) { - server = strdup(hserver); - port = strdup(hport); + server = xstrdup(hserver); + port = xstrdup(hport); } else if (hserver[0] < ' ') - server = strdup(hserver); + server = xstrdup(hserver); else split_server_port(hserver, &server, &port); @@ -261,7 +262,7 @@ const char *handle_query(const char *hserver, const char *hport, if (!server) return NULL; - p = queryformat(server, fstring, qstring); + p = queryformat(server, fstring, qstring, &buflen); if (verb) { printf(_("Using server %s.\n"), server); printf(_("Query string: \"%s\"\n\n"), p); @@ -269,7 +270,7 @@ const char *handle_query(const char *hserver, const char *hport, sockfd = openconn(server, port); - strcat(p, "\r\n"); + strncat(p, "\r\n", buflen-1); server = do_query(sockfd, p); /* recursion is fun */ @@ -333,7 +334,7 @@ const char *match_config_file(const char *s) i = regexec(&re, s, 0, NULL, 0); if (i == 0) { regfree(&re); - return strdup(server); + return xstrdup(server); } if (i != REG_NOMATCH) { char m[1024]; @@ -343,7 +344,7 @@ const char *match_config_file(const char *s) regfree(&re); #else if (domcmp(s, pattern)) - return strdup(server); + return xstrdup(server); #endif } return NULL; @@ -439,26 +440,27 @@ const char *whereas(const unsigned short asn) return "\x06"; } -char *queryformat(const char *server, const char *flags, const char *query) +char *queryformat(const char *server, const char *flags, const char *query, size_t *buflen) { char *buf, *p; int i, isripe = 0; /* 64 bytes reserved for server-specific flags added later */ - buf = malloc(strlen(flags) + strlen(query) + strlen(client_tag) + 64); + *buflen = strlen(flags) + strlen(query) + strlen(client_tag) + 64; + buf = xmalloc(*buflen); *buf = '\0'; for (i = 0; ripe_servers[i]; i++) if (streq(server, ripe_servers[i])) { - strcat(buf, "-V "); - strcat(buf, client_tag); - strcat(buf, " "); + strncat(buf, "-V ", *buflen - 1); + strncat(buf, client_tag, *buflen - 1); + strncat(buf, " ", *buflen - 1); isripe = 1; break; } if (*flags) { if (!isripe && !streq(server, "whois.corenic.net")) puts(_("Warning: RIPE flags used with a traditional server.")); - strcat(buf, flags); + strncat(buf, flags, *buflen - 1); } #ifdef HAVE_LIBIDN @@ -467,33 +469,33 @@ char *queryformat(const char *server, const char *flags, const char *query) */ if (streq(server, "whois.denic.de") && domcmp(query, ".de") && !strchr(query, ' ') && !*flags) - sprintf(buf, "-T dn,ace -C US-ASCII %s", query); + snprintf(buf, *buflen, "-T dn,ace -C US-ASCII %s", query); else /* here we have another registrar who could not make things simple * -C sets the language for both input and output */ if (!isripe && streq(server, "whois.cat") && domcmp(query, ".cat") && !strchr(query, ' ')) - sprintf(buf, "-C US-ASCII ace %s", query); + snprintf(buf, *buflen, "-C US-ASCII ace %s", query); else #endif if (!isripe && (streq(server, "whois.nic.mil") || streq(server, "whois.nic.ad.jp")) && strncasecmp(query, "AS", 2) == 0 && isasciidigit(query[2])) /* FIXME: /e is not applied to .JP ASN */ - sprintf(buf, "AS %s", query + 2); /* fix query for DDN */ + snprintf(buf, *buflen, "AS %s", query + 2); /* fix query for DDN */ else if (!isripe && (streq(server, "whois.nic.ad.jp") || streq(server, "whois.jprs.jp"))) { char *lang = getenv("LANG"); /* not a perfect check, but... */ if (!lang || !strneq(lang, "ja", 2)) - sprintf(buf, "%s/e", query); /* ask for english text */ + snprintf(buf, *buflen, "%s/e", query); /* ask for english text */ else - strcat(buf, query); + strncat(buf, query, *buflen - 1); } else if (!isripe && streq(server, "whois.arin.net") && (p = strrchr(query, '/'))) { strncat(buf, query, p - query); /* strip CIDR */ } else - strcat(buf, query); + strncat(buf, query, *buflen - 1); return buf; } @@ -559,8 +561,7 @@ const char *do_query(const int sock, const char *query) if (sscanf(buf, REFERTO_FORMAT, nh, np, nq) == 3) { /* XXX we are ignoring the new query string */ - referral_server = malloc(300); - sprintf(referral_server, "%s:%s", nh, np); + xasprintf(&referral_server, "%s:%s", nh, np); } } @@ -573,9 +574,9 @@ const char *do_query(const int sock, const char *query) q = strstr(buf, "rwhois://"); if ((q = strstr(buf, "rwhois://"))) - referral_server = strdup(q + 9); + referral_server = xstrdup(q + 9); else if ((q = strstr(buf, "whois://"))) - referral_server = strdup(q + 8); + referral_server = xstrdup(q + 8); if (referral_server) { if ((q = strchr(referral_server, '/')) || (q = strchr(referral_server, '\n'))) @@ -608,10 +609,7 @@ const char *query_crsnic(const int sock, const char *query) int hide = hide_discl; int state = 0; - temp = malloc(strlen(query) + 1 + 2 + 1); - *temp = '='; - strcpy(temp + 1, query); - strcat(temp, "\r\n"); + xasprintf(&temp, "=%s\r\n", query); fi = fdopen(sock, "r"); if (write(sock, temp, strlen(temp)) < 0) @@ -626,7 +624,7 @@ const char *query_crsnic(const int sock, const char *query) for (p = buf; *p != ':'; p++); /* skip until colon */ for (p++; *p == ' '; p++); /* skip colon and spaces */ - ret = malloc(strlen(p) + 1); + ret = xmalloc(strlen(p) + 1); for (q = ret; *p != '\n' && *p != '\r' && *p != ' '; *q++ = *p++) ; /*copy data*/ *q = '\0'; @@ -651,10 +649,7 @@ const char *query_pir(const int sock, const char *query) int hide = hide_discl; int state = 0; - temp = malloc(strlen(query) + 5 + 2 + 1); - strcpy(temp, "FULL "); - strcat(temp, query); - strcat(temp, "\r\n"); + xasprintf(&temp, "FULL %s\r\n", query); fi = fdopen(sock, "r"); if (write(sock, temp, strlen(temp)) < 0) @@ -672,7 +667,7 @@ const char *query_pir(const int sock, const char *query) for (p = buf; *p != ':'; p++); /* skip until colon */ for (p++; *p != ':'; p++); /* skip until 2nd colon */ for (p++; *p == ' '; p++); /* skip colon and spaces */ - ret = malloc(strlen(p) + 1); + ret = xmalloc(strlen(p) + 1); for (q = ret; *p != '\n' && *p != '\r'; *q++ = *p++); /*copy data*/ *q = '\0'; state = 2; @@ -779,7 +774,7 @@ char *normalize_domain(const char *dom) { char *p, *ret; - ret = strdup(dom); + ret = xstrdup(dom); for (p = ret; *p; p++); p--; /* move to the last char */ for (; *p == '.' || p == ret; p--) /* eat trailing dots */ *p = '\0'; @@ -806,29 +801,29 @@ void split_server_port(const char *const input, char *s; int len = p - input - 1; - *server = s = malloc(len + 1); + *server = s = xmalloc(len + 1); memcpy(s, input + 1, len); *(s + len) = '\0'; p = strchr(p, ':'); if (p && *(p + 1) != '\0') - *port = strdup(p + 1); /* IPv6 + port */ + *port = xstrdup(p + 1); /* IPv6 + port */ } else if ((p = strchr(input, ':')) && /* IPv6, no port */ strchr(p + 1, ':')) { /* and no brackets */ - *server = strdup(input); + *server = xstrdup(input); } else if ((p = strchr(input, ':'))) { /* IPv4 + port */ char *s; int len = p - input; - *server = s = malloc(len + 1); + *server = s = xmalloc(len + 1); memcpy(s, input, len); *(s + len) = '\0'; p++; if (*p != '\0') - *port = strdup(p); + *port = xstrdup(p); } else { /* IPv4, no port */ - *server = strdup(input); + *server = xstrdup(input); } /* change the server name to lower case */ @@ -838,19 +833,20 @@ void split_server_port(const char *const input, char *convert_6to4(const char *s) { - char *new = malloc(sizeof("255.255.255.255")); + char *new = xmalloc(sizeof("255.255.255.255")); unsigned int a, b; if (sscanf(s, "2002:%x:%x:", &a, &b) != 2) return (char *) "0.0.0.0"; - sprintf(new, "%d.%d.%d.%d", a >> 8, a & 0xff, b >> 8, b & 0xff); + sprintf(new, "%d.%d.%d.%d", + (a >> 8) & 0xff, a & 0xff, (b >> 8) & 0xff, b & 0xff); return new; } char *convert_teredo(const char *s) { - char *new = malloc(sizeof("255.255.255.255")); + char *new = xmalloc(sizeof("255.255.255.255")); unsigned int a, b; if (sscanf(s, "2001:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%x:%x", &a, &b) != 2) @@ -858,7 +854,8 @@ char *convert_teredo(const char *s) a ^= 0xffff; b ^= 0xffff; - sprintf(new, "%d.%d.%d.%d", a >> 8, a & 0xff, b >> 8, b & 0xff); + sprintf(new, "%d.%d.%d.%d", + (a >> 8) & 0xff, a & 0xff, (b >> 8) & 0xff, b & 0xff); return new; } @@ -917,6 +914,48 @@ void usage(void) } +/* Memory allocation routines */ +void *xmalloc(size_t size) +{ + void *ptr; + + if ((ptr = malloc(size)) == NULL) + err_sys("malloc"); + + return ptr; +} + +void *xrealloc(void *ptr, size_t size) +{ + if ((ptr = realloc(ptr, size)) == NULL) + err_sys("realloc"); + + return ptr; +} + +char *xstrdup (const char *s) +{ + char *r = strdup (s); + + if (!r) + err_sys("strdup"); + + return r; +} + +char * +xasprintf(char **ptr, const char *fmt, ...) +{ + va_list arg; + + va_start(arg, fmt); + if (vasprintf(ptr, fmt, arg) < 0) + err_sys("vasprintf"); + va_end(arg); + + return *ptr; +} + /* Error routines */ void err_sys(const char *fmt, ...) { @@ -924,7 +963,7 @@ void err_sys(const char *fmt, ...) va_start(ap, fmt); vfprintf(stderr, fmt, ap); - fprintf(stderr, ": %s\n", strerror(errno)); + fprintf(stderr, ": %m\n"); va_end(ap); exit(2); } diff --git a/whois.h b/whois.h index 7fe800b..a476afc 100644 --- a/whois.h +++ b/whois.h @@ -12,7 +12,7 @@ const char *whichwhois(const char *); const char *match_config_file(const char *); const char *whereas(const unsigned short); -char *queryformat(const char *, const char *, const char *); +char *queryformat(const char *, const char *, const char *, size_t *); int hide_line(int *hiding, const char *const line); const char *do_query(const int, const char *); const char *query_crsnic(const int, const char *); @@ -33,8 +33,15 @@ const char *handle_query(const char *server, const char *port, void split_server_port(const char *const input, const char **server, const char **port); -void err_quit(const char *,...); -void err_sys(const char *,...); +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +char *xstrdup(const char *s); +char *xasprintf(char **ptr, const char *fmt, ...) + __attribute__ ((__format__(__printf__, 2, 3))); +void err_quit(const char *,...) + __attribute__ ((__format__ (__printf__, 1, 2))); +void err_sys(const char *,...) + __attribute__ ((__format__ (__printf__, 1, 2))); /* flags for RIPE-like servers */