X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Fhttp-addr.c;h=677c7a682483c28db1d5d25670ad27383d6b0e20;hb=f518bf7ea19de7d9ddc79ffe2d4d0556145adbec;hp=d80bb8d017641b3ae19b1960c0705513463ab8d0;hpb=3dd9c340583c44d4dcb7223efbd0a815e0027ff7;p=thirdparty%2Fcups.git diff --git a/cups/http-addr.c b/cups/http-addr.c index d80bb8d01..677c7a682 100644 --- a/cups/http-addr.c +++ b/cups/http-addr.c @@ -1,29 +1,10 @@ /* - * "$Id: http-addr.c 7910 2008-09-06 00:25:17Z mike $" + * HTTP address routines for CUPS. * - * HTTP address routines for CUPS. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * httpAddrAny() - Check for the "any" address. - * httpAddrEqual() - Compare two addresses. - * httpAddrLocalhost() - Check for the local loopback address. - * httpAddrLookup() - Lookup the hostname associated with the address. - * _httpAddrPort() - Get the port number associated with an address. - * _httpAddrSetPort() - Set the port number associated with an address. - * httpAddrString() - Convert an IP address to a dotted string. - * httpGetHostByName() - Lookup a hostname or IP address, and return - * address records for the specified name. - * httpGetHostname() - Get the FQDN for the local system. + * Licensed under Apache License v2.0. See the file "LICENSE" for more information. */ /* @@ -31,6 +12,8 @@ */ #include "cups-private.h" +#include "debug-internal.h" +#include #ifdef HAVE_RESOLV_H # include #endif /* HAVE_RESOLV_H */ @@ -43,7 +26,7 @@ /* * 'httpAddrAny()' - Check for the "any" address. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 1 if "any", 0 otherwise */ @@ -66,10 +49,41 @@ httpAddrAny(const http_addr_t *addr) /* I - Address to check */ } +/* + * 'httpAddrClose()' - Close a socket created by @link httpAddrConnect@ or + * @link httpAddrListen@. + * + * Pass @code NULL@ for sockets created with @link httpAddrConnect2@ and the + * listen address for sockets created with @link httpAddrListen@. This function + * ensures that domain sockets are removed when closed. + * + * @since CUPS 2.0/OS 10.10@ + */ + +int /* O - 0 on success, -1 on failure */ +httpAddrClose(http_addr_t *addr, /* I - Listen address or @code NULL@ */ + int fd) /* I - Socket file descriptor */ +{ +#ifdef _WIN32 + if (closesocket(fd)) +#else + if (close(fd)) +#endif /* _WIN32 */ + return (-1); + +#ifdef AF_LOCAL + if (addr && addr->addr.sa_family == AF_LOCAL) + return (unlink(addr->un.sun_path)); +#endif /* AF_LOCAL */ + + return (0); +} + + /* * 'httpAddrEqual()' - Compare two addresses. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 1 if equal, 0 if not */ @@ -102,7 +116,7 @@ httpAddrEqual(const http_addr_t *addr1, /* I - First address */ /* * 'httpAddrLength()' - Return the length of the address in bytes. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - Length in bytes */ @@ -118,8 +132,7 @@ httpAddrLength(const http_addr_t *addr) /* I - Address */ #endif /* AF_INET6 */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) - return (offsetof(struct sockaddr_un, sun_path) + - strlen(addr->un.sun_path) + 1); + return ((int)(offsetof(struct sockaddr_un, sun_path) + strlen(addr->un.sun_path) + 1)); else #endif /* AF_LOCAL */ if (addr->addr.sa_family == AF_INET) @@ -130,10 +143,137 @@ httpAddrLength(const http_addr_t *addr) /* I - Address */ } +/* + * 'httpAddrListen()' - Create a listening socket bound to the specified + * address and port. + * + * @since CUPS 1.7/macOS 10.9@ + */ + +int /* O - Socket or -1 on error */ +httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ + int port) /* I - Port number to bind to */ +{ + int fd = -1, /* Socket */ + val, /* Socket value */ + status; /* Bind status */ + + + /* + * Range check input... + */ + + if (!addr || port < 0) + return (-1); + + /* + * Create the socket and set options... + */ + + if ((fd = socket(addr->addr.sa_family, SOCK_STREAM, 0)) < 0) + { + _cupsSetHTTPError(HTTP_STATUS_ERROR); + return (-1); + } + + val = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, CUPS_SOCAST &val, sizeof(val)); + +#ifdef IPV6_V6ONLY + if (addr->addr.sa_family == AF_INET6) + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, CUPS_SOCAST &val, sizeof(val)); +#endif /* IPV6_V6ONLY */ + + /* + * Bind the socket... + */ + +#ifdef AF_LOCAL + if (addr->addr.sa_family == AF_LOCAL) + { + mode_t mask; /* Umask setting */ + + /* + * Remove any existing domain socket file... + */ + + unlink(addr->un.sun_path); + + /* + * Save the current umask and set it to 0 so that all users can access + * the domain socket... + */ + + mask = umask(0); + + /* + * Bind the domain socket... + */ + + status = bind(fd, (struct sockaddr *)addr, (socklen_t)httpAddrLength(addr)); + + /* + * Restore the umask and fix permissions... + */ + + umask(mask); + chmod(addr->un.sun_path, 0140777); + } + else +#endif /* AF_LOCAL */ + { + _httpAddrSetPort(addr, port); + + status = bind(fd, (struct sockaddr *)addr, (socklen_t)httpAddrLength(addr)); + } + + if (status) + { + _cupsSetHTTPError(HTTP_STATUS_ERROR); + + close(fd); + + return (-1); + } + + /* + * Listen... + */ + + if (listen(fd, 5)) + { + _cupsSetHTTPError(HTTP_STATUS_ERROR); + + close(fd); + + return (-1); + } + + /* + * Close on exec... + */ + +#ifndef _WIN32 + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); +#endif /* !_WIN32 */ + +#ifdef SO_NOSIGPIPE + /* + * Disable SIGPIPE for this socket. + */ + + val = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val)); +#endif /* SO_NOSIGPIPE */ + + return (fd); +} + + /* * 'httpAddrLocalhost()' - Check for the local loopback address. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ int /* O - 1 if local host, 0 otherwise */ @@ -165,7 +305,7 @@ httpAddrLocalhost( /* * 'httpAddrLookup()' - Lookup the hostname associated with the address. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ char * /* O - Host name */ @@ -178,8 +318,7 @@ httpAddrLookup( /* Global data */ - DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)", addr, name, - namelen)); + DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)", (void *)addr, (void *)name, namelen)); /* * Range check input... @@ -196,7 +335,7 @@ httpAddrLookup( #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) { - strlcpy(name, addr->un.sun_path, namelen); + strlcpy(name, addr->un.sun_path, (size_t)namelen); return (name); } #endif /* AF_LOCAL */ @@ -207,7 +346,7 @@ httpAddrLookup( if (httpAddrLocalhost(addr)) { - strlcpy(name, "localhost", namelen); + strlcpy(name, "localhost", (size_t)namelen); return (name); } @@ -242,8 +381,7 @@ httpAddrLookup( * do... */ - int error = getnameinfo(&addr->addr, httpAddrLength(addr), name, namelen, - NULL, 0, 0); + int error = getnameinfo(&addr->addr, (socklen_t)httpAddrLength(addr), name, (socklen_t)namelen, NULL, 0, 0); if (error) { @@ -279,7 +417,7 @@ httpAddrLookup( return (httpAddrString(addr, name, namelen)); } - strlcpy(name, host->h_name, namelen); + strlcpy(name, host->h_name, (size_t)namelen); } #endif /* HAVE_GETNAMEINFO */ @@ -290,14 +428,30 @@ httpAddrLookup( /* - * '_httpAddrPort()' - Get the port number associated with an address. + * 'httpAddrFamily()' - Get the address family of an address. + */ + +int /* O - Address family */ +httpAddrFamily(http_addr_t *addr) /* I - Address */ +{ + if (addr) + return (addr->addr.sa_family); + else + return (0); +} + + +/* + * 'httpAddrPort()' - Get the port number associated with an address. + * + * @since CUPS 1.7/macOS 10.9@ */ int /* O - Port number */ -_httpAddrPort(http_addr_t *addr) /* I - Address */ +httpAddrPort(http_addr_t *addr) /* I - Address */ { if (!addr) - return (ippPort()); + return (-1); #ifdef AF_INET6 else if (addr->addr.sa_family == AF_INET6) return (ntohs(addr->ipv6.sin6_port)); @@ -305,7 +459,7 @@ _httpAddrPort(http_addr_t *addr) /* I - Address */ else if (addr->addr.sa_family == AF_INET) return (ntohs(addr->ipv4.sin_port)); else - return (ippPort()); + return (0); } @@ -333,7 +487,7 @@ _httpAddrSetPort(http_addr_t *addr, /* I - Address */ /* * 'httpAddrString()' - Convert an address to a numeric string. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ char * /* O - Numeric address string */ @@ -341,7 +495,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ char *s, /* I - String buffer */ int slen) /* I - Length of string */ { - DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)", addr, s, slen)); + DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)", (void *)addr, (void *)s, slen)); /* * Range check input... @@ -359,9 +513,9 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ if (addr->addr.sa_family == AF_LOCAL) { if (addr->un.sun_path[0] == '/') - strlcpy(s, addr->un.sun_path, slen); + strlcpy(s, addr->un.sun_path, (size_t)slen); else - strlcpy(s, "localhost", slen); + strlcpy(s, "localhost", (size_t)slen); } else #endif /* AF_LOCAL */ @@ -369,10 +523,9 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ { unsigned temp; /* Temporary address */ - temp = ntohl(addr->ipv4.sin_addr.s_addr); - snprintf(s, slen, "%d.%d.%d.%d", (temp >> 24) & 255, + snprintf(s, (size_t)slen, "%d.%d.%d.%d", (temp >> 24) & 255, (temp >> 16) & 255, (temp >> 8) & 255, temp & 255); } #ifdef AF_INET6 @@ -382,8 +535,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ temps[64]; /* Temporary string for address */ # ifdef HAVE_GETNAMEINFO - if (getnameinfo(&addr->addr, httpAddrLength(addr), temps, sizeof(temps), - NULL, 0, NI_NUMERICHOST)) + if (getnameinfo(&addr->addr, (socklen_t)httpAddrLength(addr), temps, sizeof(temps), NULL, 0, NI_NUMERICHOST)) { /* * If we get an error back, then the address type is not supported @@ -414,8 +566,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ { temp = ntohl(addr->ipv6.sin6_addr.s6_addr32[i]); - snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix, - (temp >> 16) & 0xffff); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, (temp >> 16) & 0xffff); prefix = ":"; sptr += strlen(sptr); @@ -423,7 +574,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ if (temp || i == 3 || addr->ipv6.sin6_addr.s6_addr32[i + 1]) { - snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix, temp); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, temp); sptr += strlen(sptr); } } @@ -435,7 +586,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ if (i < 4) { - snprintf(sptr, sizeof(temps) - (sptr - temps), "%s:", prefix); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s:", prefix); prefix = ":"; sptr += strlen(sptr); @@ -446,13 +597,11 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ if ((temp & 0xffff0000) || (i > 0 && addr->ipv6.sin6_addr.s6_addr32[i - 1])) { - snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix, - (temp >> 16) & 0xffff); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, (temp >> 16) & 0xffff); sptr += strlen(sptr); } - snprintf(sptr, sizeof(temps) - (sptr - temps), "%s%x", prefix, - temp & 0xffff); + snprintf(sptr, sizeof(temps) - (size_t)(sptr - temps), "%s%x", prefix, temp & 0xffff); sptr += strlen(sptr); } } @@ -470,7 +619,7 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ * Empty at end... */ - strlcpy(sptr, "::", sizeof(temps) - (sptr - temps)); + strlcpy(sptr, "::", sizeof(temps) - (size_t)(sptr - temps)); } } # endif /* HAVE_GETNAMEINFO */ @@ -479,11 +628,11 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ * Add "[v1." and "]" around IPv6 address to convert to URI form. */ - snprintf(s, slen, "[v1.%s]", temps); + snprintf(s, (size_t)slen, "[v1.%s]", temps); } #endif /* AF_INET6 */ else - strlcpy(s, "UNKNOWN", slen); + strlcpy(s, "UNKNOWN", (size_t)slen); DEBUG_printf(("1httpAddrString: returning \"%s\"...", s)); @@ -491,11 +640,33 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */ } +/* + * 'httpGetAddress()' - Get the address of the connected peer of a connection. + * + * For connections created with @link httpConnect2@, the address is for the + * server. For connections created with @link httpAccept@, the address is for + * the client. + * + * Returns @code NULL@ if the socket is currently unconnected. + * + * @since CUPS 2.0/OS 10.10@ + */ + +http_addr_t * /* O - Connected address or @code NULL@ */ +httpGetAddress(http_t *http) /* I - HTTP connection */ +{ + if (http) + return (http->hostaddr); + else + return (NULL); +} + + /* * 'httpGetHostByName()' - Lookup a hostname or IPv4 address, and return * address records for the specified name. * - * @deprecated@ + * @deprecated@ @exclude all@ */ struct hostent * /* O - Host entry */ @@ -540,7 +711,7 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ cg->hostent.h_name = (char *)name; cg->hostent.h_aliases = NULL; cg->hostent.h_addrtype = AF_LOCAL; - cg->hostent.h_length = strlen(name) + 1; + cg->hostent.h_length = (int)strlen(name) + 1; cg->hostent.h_addr_list = cg->ip_ptrs; cg->ip_ptrs[0] = (char *)name; cg->ip_ptrs[1] = NULL; @@ -566,8 +737,9 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255) return (NULL); /* Invalid byte ranges! */ - cg->ip_addr = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | - ip[3])); + cg->ip_addr = htonl((((((((unsigned)ip[0] << 8) | (unsigned)ip[1]) << 8) | + (unsigned)ip[2]) << 8) | + (unsigned)ip[3])); /* * Fill in the host entry and return it... @@ -603,11 +775,12 @@ httpGetHostByName(const char *name) /* I - Hostname or IP address */ * 'httpGetHostname()' - Get the FQDN for the connection or local system. * * When "http" points to a connected socket, return the hostname or - * address that was used in the call to httpConnect() or httpConnectEncrypt(). + * address that was used in the call to httpConnect() or httpConnectEncrypt(), + * or the address of the client for the connection from httpAcceptConnection(). * Otherwise, return the FQDN for the local system using both gethostname() * and gethostbyname() to get the local hostname with domain. * - * @since CUPS 1.2/OS X 10.5@ + * @since CUPS 1.2/macOS 10.5@ */ const char * /* O - FQDN for connection or system */ @@ -615,15 +788,19 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ char *s, /* I - String buffer for name */ int slen) /* I - Size of buffer */ { - if (!s || slen <= 1) - return (NULL); - if (http) { - if (http->hostname[0] == '/') - strlcpy(s, "localhost", slen); + if (!s || slen <= 1) + { + if (http->hostname[0] == '/') + return ("localhost"); + else + return (http->hostname); + } + else if (http->hostname[0] == '/') + strlcpy(s, "localhost", (size_t)slen); else - strlcpy(s, http->hostname, slen); + strlcpy(s, http->hostname, (size_t)slen); } else { @@ -631,8 +808,11 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ * Get the hostname... */ - if (gethostname(s, slen) < 0) - strlcpy(s, "localhost", slen); + if (!s || slen <= 1) + return (NULL); + + if (gethostname(s, (size_t)slen) < 0) + strlcpy(s, "localhost", (size_t)slen); if (!strchr(s, '.')) { @@ -656,7 +836,7 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ * Append ".local." to the hostname we get... */ - snprintf(s, slen, "%s.local.", localStr); + snprintf(s, (size_t)slen, "%s.local.", localStr); } if (local) @@ -677,10 +857,29 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ * Use the resolved hostname... */ - strlcpy(s, host->h_name, slen); + strlcpy(s, host->h_name, (size_t)slen); } #endif /* HAVE_SCDYNAMICSTORECOPYCOMPUTERNAME */ } + + /* + * Make sure .local hostnames end with a period... + */ + + if (strlen(s) > 6 && !strcmp(s + strlen(s) - 6, ".local")) + strlcat(s, ".", (size_t)slen); + } + + /* + * Convert the hostname to lowercase as needed... + */ + + if (s[0] != '/') + { + char *ptr; /* Pointer into string */ + + for (ptr = s; *ptr; ptr ++) + *ptr = (char)_cups_tolower((int)*ptr); } /* @@ -692,5 +891,41 @@ httpGetHostname(http_t *http, /* I - HTTP connection or NULL */ /* - * End of "$Id: http-addr.c 7910 2008-09-06 00:25:17Z mike $". + * 'httpResolveHostname()' - Resolve the hostname of the HTTP connection + * address. + * + * @since CUPS 2.0/OS 10.10@ */ + +const char * /* O - Resolved hostname or @code NULL@ */ +httpResolveHostname(http_t *http, /* I - HTTP connection */ + char *buffer, /* I - Hostname buffer */ + size_t bufsize) /* I - Size of buffer */ +{ + if (!http) + return (NULL); + + if (isdigit(http->hostname[0] & 255) || http->hostname[0] == '[') + { + char temp[1024]; /* Temporary string */ + + if (httpAddrLookup(http->hostaddr, temp, sizeof(temp))) + strlcpy(http->hostname, temp, sizeof(http->hostname)); + else + return (NULL); + } + + if (buffer) + { + if (http->hostname[0] == '/') + strlcpy(buffer, "localhost", bufsize); + else + strlcpy(buffer, http->hostname, bufsize); + + return (buffer); + } + else if (http->hostname[0] == '/') + return ("localhost"); + else + return (http->hostname); +}