From 26869affd9e594ae71c3a7ad4b7c230c78f4fde2 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Thu, 15 Mar 2012 17:07:44 -0700 Subject: [PATCH] Trac Ticket #307 - htmladmin keeps segfaulting https://fedorahosted.org/389/ticket/307 Fix Description: PR_GetHostByName was used to get PRHostEnt in htmladmin, but it was called only when the first character of host was not digit. The direct cause of the crash was the PRHostEnt variable to fill in in PR_GetHostByName was not initialized, thus if the hostname started with digit, the uninitialized, garbage address in the variable was accessed, which crashed htmladmin. This patch removes the hostname check and replaces PR_GetHostByName with PR_GetAddrInfoByName to support IPv6 environment. Also, to support numerical address, PR_StringToNetAddr is added before trying PR_GetAddrInfoByName. Another cgi statpingserv has the same coding style. It is being fixed, too. --- admserv/cgi-src40/htmladmin.c | 75 +++++++++++++++++++++------------ admserv/cgi-src40/statpingserv.c | 84 ++++++++++++++++++++------------------ 2 files changed, 92 insertions(+), 67 deletions(-) diff --git a/admserv/cgi-src40/htmladmin.c b/admserv/cgi-src40/htmladmin.c index a294766..09d0ad0 100644 --- a/admserv/cgi-src40/htmladmin.c +++ b/admserv/cgi-src40/htmladmin.c @@ -854,6 +854,7 @@ LDAP *server_bind(const char *securitydir, char *host, int port, int security, c return server; } +#if 0 /* NOT USED */ /* rate is specified in seconds */ static int get_topology_refresh_rate(AdmldapInfo admInfo) { @@ -868,7 +869,7 @@ static int get_topology_refresh_rate(AdmldapInfo admInfo) { return rate; } - +#endif /* rate is specified in seconds */ static int get_cgi_timeout_rate(AdmldapInfo admInfo) { @@ -895,38 +896,58 @@ static int get_cgi_timeout_rate(AdmldapInfo admInfo) { * -1 = unknown error */ -int server_status(char *host, int port) { - - PRHostEnt *hstruct; - PRHostEnt hent; - char buf[PR_NETDB_BUF_SIZE]; +int +server_status(char *host, int port) +{ + PRNetAddr *netaddr = NULL; PRStatus err; - PRFileDesc *req_socket= NULL; - int retcode; - PRNetAddr netAddr; - - if(!isdigit(host[0])) { - err = PR_GetHostByName(host, - buf, - PR_NETDB_BUF_SIZE, - &hent); - if(err == PR_FAILURE) - return -1; - } + int retcode = 0; - hstruct = &hent; - PR_InitializeNetAddr(PR_IpAddrNull, (PRUint16)port, &netAddr); - netAddr.inet.ip = *((PRUint32*)hstruct->h_addr_list[0]); - - req_socket = PR_NewTCPSocket(); - retcode = PR_Connect(req_socket, &netAddr, 10000); + if (NULL == host) { + return -1; + } - if(retcode != 0) - return 0; - else - return 1; + netaddr = (PRNetAddr *)calloc(1, sizeof(PRNetAddr)); + if (NULL == netaddr) { + rpt_err(APP_ERROR, "Failed to allocate PRNetAddr", NULL, NULL); + return -1; + } + err = PR_StringToNetAddr(host, netaddr); + if (PR_SUCCESS == err) { + PR_InitializeNetAddr(PR_IpAddrNull, (PRUint16)port, netaddr); + } else { + PRAddrInfo *infop = PR_GetAddrInfoByName(host, + PR_AF_UNSPEC, (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME)); + if (infop) { + void *iter = NULL; + memset( netaddr, 0, sizeof( PRNetAddr )); + /* need just one address */ + iter = PR_EnumerateAddrInfo(iter, infop, (PRUint16)port, netaddr); + if (NULL == iter) { + rpt_err(APP_ERROR, "Failed to enumerate addrinfo", NULL, NULL); + retcode = -1; + } + PR_FreeAddrInfo(infop); + } else { + rpt_err(APP_ERROR, "Failed to get addrinfo", NULL, NULL); + retcode = -1; + } + } + if (retcode < 0) { + free(netaddr); + return retcode; + } else { + req_socket = PR_NewTCPSocket(); + err = PR_Connect(req_socket, netaddr, 10000); + free(netaddr); + if (PR_SUCCESS == err) { + return 1; + } else { + return 0; + } + } } diff --git a/admserv/cgi-src40/statpingserv.c b/admserv/cgi-src40/statpingserv.c index 363eed3..d6e55f7 100644 --- a/admserv/cgi-src40/statpingserv.c +++ b/admserv/cgi-src40/statpingserv.c @@ -59,16 +59,13 @@ int main(int argc, char *argv[]) char *m; char *qs = getenv("QUERY_STRING"); - PRHostEnt hent; - char buf[PR_NETDB_BUF_SIZE]; PRStatus err; char gifbuf[BUFSIZ]; PRInt32 bytes; PRFileDesc *req_socket= NULL; - int retcode; - PRNetAddr netAddr; - + int retcode = 0; + PRNetAddr *netaddr = NULL; char *result; char *host; int port; @@ -79,13 +76,6 @@ int main(int argc, char *argv[]) struct PRFileInfo64 prfileinfo; m = getenv("REQUEST_METHOD"); - /* - { - int d=1; - while(d>0) - {;} - } - */ if(!strcmp(m, "GET")) { if(qs) @@ -93,54 +83,68 @@ int main(int argc, char *argv[]) result = get_cgi_var("result", NULL, NULL); host = get_cgi_var("host", NULL, NULL); - portstr = get_cgi_var("port", NULL, NULL); - if (portstr) { - port = atoi(portstr); - } else { - port = 0; - } + portstr = get_cgi_var("port", NULL, NULL); + if (portstr) { + port = atoi(portstr); + } else { + port = 0; + } if(result && !strcmp(result, "text")) fprintf(stdout, "Content-type: text/html\n"); else fprintf(stdout, "Content-type: image/gif\n"); - if (!host || !port) { - rpt_err(APP_ERROR, "Invalid hostname and/or port number!", NULL, NULL); - } - if(!isdigit(host[0])) { - err = PR_GetHostByName(host, buf, sizeof(buf), &hent); - if(err == PR_FAILURE) { - rpt_err(APP_ERROR, "Cannot resolve host name!", NULL, NULL); - } - - PR_InitializeNetAddr(PR_IpAddrNull, (PRUint16)port, &netAddr); - memcpy((void *) &netAddr.inet.ip, (void const *) hent.h_addr_list[0], sizeof(netAddr.inet.ip)); + if (!host || !port) { + rpt_err(APP_ERROR, "Invalid hostname and/or port number!", NULL, NULL); + return -1; + } + netaddr = (PRNetAddr *)calloc(1, sizeof(PRNetAddr)); + if (NULL == netaddr) { + rpt_err(APP_ERROR, "Failed to allocate PRNetAddr", NULL, NULL); + return -1; + } + err = PR_StringToNetAddr(host, netaddr); + if (PR_SUCCESS == err) { + PR_InitializeNetAddr(PR_IpAddrNull, (PRUint16)port, netaddr); } else { - PR_InitializeNetAddr(PR_IpAddrNull, (PRUint16)port, &netAddr); - err = PR_StringToNetAddr(host, &netAddr); - if(err == PR_FAILURE) { - rpt_err(APP_ERROR, "Cannot parse host address!", NULL, NULL); + PRAddrInfo *infop = PR_GetAddrInfoByName(host, + PR_AF_UNSPEC, (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME)); + if (infop) { + void *iter = NULL; + memset( netaddr, 0, sizeof( PRNetAddr )); + /* need just one address */ + iter = PR_EnumerateAddrInfo(iter, infop, (PRUint16)port, netaddr); + if (NULL == iter) { + rpt_err(APP_ERROR, "Failed to enumerate addrinfo", NULL, NULL); + retcode = -1; + } + PR_FreeAddrInfo(infop); + } else { + rpt_err(APP_ERROR, "Failed to get addrinfo", NULL, NULL); + retcode = -1; } } - req_socket = PR_NewTCPSocket(); - - retcode = PR_Connect(req_socket, &netAddr, 10000); + if (retcode > -1) { + req_socket = PR_NewTCPSocket(); + retcode = PR_Connect(req_socket, netaddr, 10000); + } + free(netaddr); if (retcode != 0) { /* SERVER IS DOWN - output the OFF button */ if(result && !strcmp(result, "text")) { - rpt_success("The server is DOWN."); - return 1; + rpt_success("The server is DOWN."); + return 1; } file = PR_smprintf("%s/togoff.gif", ICONDIR); } else { /* SERVER IS RUNNING - output of ON button */ if(result && !strcmp(result, "text")) { - rpt_success("The server is UP."); - return 1; + rpt_success("The server is UP."); + return 1; } file = PR_smprintf("%s/togon.gif", ICONDIR); } -- 1.7.6.5