int validate_access(char *client_addr, char *client_name) { int stat = 0; #ifdef HAVE_LIBWRAP int i; if ( use_tcpwrap ) { /* proc ident pattern */ stat = hosts_ctl(ident, client_name, client_addr, STRING_UNKNOWN); /* IP.PORT pattern */ for (i = 0; i < serv_sock_ind; i++) { if (str_serv_sock[i] != NULL && str_serv_sock[i][0] != 0) { stat |= hosts_ctl(str_serv_sock[i], client_name, client_addr, STRING_UNKNOWN); } } } else { #endif /* HAVE_LIBWRAP */ stat = 1; /* allow access un-conditionaly */ #ifdef HAVE_LIBWRAP } #endif /* HAVE_LIBWRAP */ if (stat < 1) { msg_out(warn, "%s[%s] access denied.", client_name, client_addr); } return stat; }
static int check_host (struct sockaddr *sa) { struct sockaddr_in *sin; struct hostent *hp; char *addr; if (sa->sa_family != AF_INET) return 1; sin = (struct sockaddr_in *)sa; hp = gethostbyaddr ((char *)&sin->sin_addr, sizeof (struct in_addr), AF_INET); addr = inet_ntoa (sin->sin_addr); if (hp) { if (!hosts_ctl ("ftpd", hp->h_name, addr, STRING_UNKNOWN)) { syslog (LOG_NOTICE, "tcpwrappers rejected: %s [%s]", hp->h_name, addr); return 0; } } else { if (!hosts_ctl ("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN)) { syslog (LOG_NOTICE, "tcpwrappers rejected: [%s]", addr); return 0; } } return (1); }
static int good_client(struct sockaddr_in *addr) { if (hosts_ctl("portmap", "", inet_ntoa(addr->sin_addr), "")) return 1; #ifdef ENABLE_DNS { struct hostent *hp; char **sp; char *tmpname; /* Check the hostname. */ hp = gethostbyaddr ((const char *) &(addr->sin_addr), sizeof (addr->sin_addr), AF_INET); if (!hp) return 0; /* must make sure the hostent is authoritative. */ tmpname = alloca (strlen (hp->h_name) + 1); strcpy (tmpname, hp->h_name); hp = gethostbyname(tmpname); if (hp) { /* now make sure the "addr->sin_addr" is on the list */ for (sp = hp->h_addr_list ; *sp ; sp++) { if (memcmp(*sp, &(addr->sin_addr), hp->h_length)==0) break; } if (!*sp) /* it was a FAKE. */ return 0; } else /* never heard of it. misconfigured DNS? */ return 0; /* Check the official name first. */ if (hosts_ctl("portmap", "", hp->h_name, "")) return 1; /* Check aliases. */ for (sp = hp->h_aliases; *sp ; sp++) { if (hosts_ctl("portmap", "", *sp, "")) return 1; } } #endif /* ENABLE_DNS */ return 0; }
static int pre_parse(netsnmp_session * session, netsnmp_transport *transport, void *transport_data, int transport_data_length) { #if NETSNMP_USE_LIBWRAP char *addr_string = NULL; if (transport != NULL && transport->f_fmtaddr != NULL) { /* * Okay I do know how to format this address for logging. */ addr_string = transport->f_fmtaddr(transport, transport_data, transport_data_length); /* * Don't forget to free() it. */ } if (addr_string != NULL) { /* Catch udp,udp6,tcp,tcp6 transports using "[" */ char *tcpudpaddr = strstr(addr_string, "["); if ( tcpudpaddr != 0 ) { char sbuf[64]; char *xp; strlcpy(sbuf, tcpudpaddr + 1, sizeof(sbuf)); xp = strstr(sbuf, "]"); if (xp) *xp = '\0'; if (hosts_ctl("snmptrapd", STRING_UNKNOWN, sbuf, STRING_UNKNOWN) == 0) { DEBUGMSGTL(("snmptrapd:libwrap", "%s rejected", addr_string)); SNMP_FREE(addr_string); return 0; } } SNMP_FREE(addr_string); } else { if (hosts_ctl("snmptrapd", STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN) == 0) { DEBUGMSGTL(("snmptrapd:libwrap", "[unknown] rejected")); return 0; } } #endif/* NETSNMP_USE_LIBWRAP */ return 1; }
/********************************************************************** * Do authentication & authorization check **********************************************************************/ int is_authorized(osm_console_t * p_oct) { /* allowed to use the console? */ p_oct->authorized = !is_remote(p_oct->client_type) || hosts_ctl(OSM_DAEMON_NAME, p_oct->client_hn, p_oct->client_ip, "STRING_UNKNOWN"); return p_oct->authorized; }
static int resolve_addr(server_conf_t *conf, req_t *req, int sd) { /* Resolves the network information associated with the * peer at the other end of the socket connection. * Returns 0 if the remote client address is valid, or -1 on error. */ struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); char buf[MAX_LINE]; char *p; int gotHostName = 0; assert(sd >= 0); req->sd = sd; if (getpeername(sd, (struct sockaddr *) &addr, &addrlen) < 0) log_err(errno, "Unable to get address of remote peer"); if (!inet_ntop(AF_INET, &addr.sin_addr, buf, sizeof(buf))) log_err(errno, "Unable to convert network address into string"); req->port = ntohs(addr.sin_port); req->ip = create_string(buf); /* * Attempt to resolve IP address. If it succeeds, buf contains * host string; if it fails, buf is unchanged with IP addr string. * Either way, copy buf to prevent having to code everything as * (req->host ? req->host : req->ip). */ if ((host_addr4_to_name(&addr.sin_addr, buf, sizeof(buf)))) { gotHostName = 1; req->fqdn = create_string(buf); if ((p = strchr(buf, '.'))) *p = '\0'; req->host = create_string(buf); } else { req->fqdn = create_string(buf); req->host = create_string(buf); } #if WITH_TCP_WRAPPERS /* * Check via TCP-Wrappers. */ if (conf->enableTCPWrap) { if (hosts_ctl(CONMAN_DAEMON_NAME, (gotHostName ? req->fqdn : STRING_UNKNOWN), req->ip, STRING_UNKNOWN) == 0) { log_msg(LOG_NOTICE, "TCP-Wrappers rejected connection from <%s:%d>", req->fqdn, req->port); return(-1); } } #endif /* WITH_TCP_WRAPPERS */ return(0); }
/* * check if remote amq is authorized to access this amd. * Returns: 1=allowed, 0=denied. */ static int amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote) { struct hostent *h; char *name = NULL, **ad; int ret = 0; /* default is 0==denied */ /* Check IP address */ if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) { ret = 1; goto out; } /* Get address */ if (!(h = gethostbyaddr((const char *)&(addr->sin_addr), sizeof(addr->sin_addr), AF_INET))) goto out; if (!(name = strdup(h->h_name))) goto out; /* Paranoia check */ if (!(h = gethostbyname(name))) goto out; for (ad = h->h_addr_list; *ad; ad++) if (!memcmp(*ad, &(addr->sin_addr), h->h_length)) break; if (!*ad) goto out; if (hosts_ctl(AMD_SERVICE_NAME, "", h->h_name, "")) { return 1; goto out; } /* Check aliases */ for (ad = h->h_aliases; *ad; ad++) if (hosts_ctl(AMD_SERVICE_NAME, "", *ad, "")) { return 1; goto out; } out: if (name) XFREE(name); return ret; }
/*******************************************************************-o-****** * snmp_check_packet * * Parameters: * session, from * * Returns: * 1 On success. * 0 On error. * * Handler for all incoming messages (a.k.a. packets) for the agent. If using * the libwrap utility, log the connection and deny/allow the access. Print * output when appropriate, and increment the incoming counter. * */ int snmp_check_packet(struct snmp_session *session, snmp_ipaddr from) { struct sockaddr_in *fromIp = (struct sockaddr_in *)&from; #ifdef USE_LIBWRAP const char *addr_string; /* * Log the message and/or dump the message. * Optionally cache the network address of the sender. */ addr_string = inet_ntoa(fromIp->sin_addr); if(!addr_string) { addr_string = STRING_UNKNOWN; } if(hosts_ctl("snmpd", addr_string, addr_string, STRING_UNKNOWN)) { snmp_log(allow_severity, "Connection from %s\n", addr_string); } else { snmp_log(deny_severity, "Connection from %s REFUSED\n", addr_string); return(0); } #endif /* USE_LIBWRAP */ snmp_increment_statistic(STAT_SNMPINPKTS); if (log_addresses || ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)) { int count; for(count = 0; count < ADDRCACHE; count++) { if (addrCache[count].status > UNUSED /* used or old */ && fromIp->sin_addr.s_addr == addrCache[count].addr) break; } if (count >= ADDRCACHE || ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)) { snmp_log(LOG_INFO, "Received SNMP packet(s) from %s\n", inet_ntoa(fromIp->sin_addr)); for(count = 0; count < ADDRCACHE; count++) { if (addrCache[count].status == UNUSED) { addrCache[count].addr = fromIp->sin_addr.s_addr; addrCache[count].status = USED; break; } } } else { addrCache[count].status = USED; } } return ( 1 ); }
/* Accept one connection on a ready fd and pass it on to the npfs 9P engine. */ void diod_sock_accept_one (Npsrv *srv, int fd) { struct sockaddr_storage addr; socklen_t addr_size = sizeof(addr); char host[NI_MAXHOST], ip[NI_MAXHOST], svc[NI_MAXSERV]; int res; fd = accept (fd, (struct sockaddr *)&addr, &addr_size); if (fd < 0) { if (!(errno == EWOULDBLOCK || errno == ECONNABORTED || errno == EPROTO || errno == EINTR)) err ("accept"); return; } if ((res = getnameinfo ((struct sockaddr *)&addr, addr_size, ip, sizeof(ip), svc, sizeof(svc), NI_NUMERICHOST | NI_NUMERICSERV))) { msg ("getnameinfo: %s", gai_strerror(res)); close (fd); return; } if (addr.ss_family != AF_UNIX) { (void)_disable_nagle (fd); (void)_enable_keepalive (fd); } if ((res = getnameinfo ((struct sockaddr *)&addr, addr_size, host, sizeof(host), NULL, 0, 0))) { msg ("getnameinfo: %s", gai_strerror(res)); close (fd); return; } #if HAVE_TCP_WRAPPERS res = hosts_ctl (DAEMON_NAME, host, ip, STRING_UNKNOWN); if (!res) { msg ("connect denied by wrappers: %s:%s", host, svc); close (fd); return; } #endif diod_sock_startfd (srv, fd, fd, strlen(host) > 0 ? host : ip); }
rfbBool rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen) { const int one = 1; int sock = -1; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); if ((sock = accept(rfbScreen->listenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("rfbCheckFds: accept"); return FALSE; } if(!rfbSetNonBlocking(sock)) { closesocket(sock); return FALSE; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbLogPerror("rfbCheckFds: setsockopt"); closesocket(sock); return FALSE; } #ifdef USE_LIBWRAP if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected connection from client %s\n", inet_ntoa(addr.sin_addr)); closesocket(sock); return FALSE; } #endif rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); rfbNewClient(rfbScreen,sock); return TRUE; }
/* * returns nonzero if tcpd/libwrap allows this connection * returns 0 if tcpd/libwrap denies this connection */ int tcpd_allowed(struct svc_req *rqstp) { static char remhost[1024]; int result; assert(rqstp); assert(rqstp->rq_xprt); /* get the hostname from the IP */ result = getnameinfo( (struct sockaddr *) &(rqstp->rq_xprt->xp_raddr), rqstp->rq_xprt->xp_addrlen, remhost,1024, NULL, 0, 0); /* stop here if getnameinfo blew up */ if(result && result != EAI_AGAIN && result != EAI_NONAME) { syslog(LOG_DEBUG,"getnameinfo(%s) failed: %s", inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr), strerror(result)); return 0; } /* do the libwrap check */ result = hosts_ctl(SERVICE_NAME, remhost, inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr), STRING_UNKNOWN); if(result) { return result; } /* report failures */ syslog(LOG_DEBUG,"hosts_ctl(\"%s\",%s,%s) rejected connection", SERVICE_NAME, remhost, inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr)); return 0; }
/* libwrap (tcpd): check the connection is legal. This is necessary because * the actual server will only see a connection coming from localhost and can't * apply the rules itself. * * Returns -1 if access is denied, 0 otherwise */ int check_access_rights(int in_socket, const char* service) { #ifdef LIBWRAP union { struct sockaddr saddr; struct sockaddr_storage ss; } peer; socklen_t size = sizeof(peer); char addr_str[NI_MAXHOST], host[NI_MAXHOST]; int res; res = getpeername(in_socket, &peer.saddr, &size); CHECK_RES_RETURN(res, "getpeername"); /* extract peer address */ res = getnameinfo(&peer.saddr, size, addr_str, sizeof(addr_str), NULL, 0, NI_NUMERICHOST); if (res) { if (verbose) fprintf(stderr, "getnameinfo(NI_NUMERICHOST):%s\n", gai_strerror(res)); strcpy(addr_str, STRING_UNKNOWN); } /* extract peer name */ strcpy(host, STRING_UNKNOWN); if (!numeric) { res = getnameinfo(&peer.saddr, size, host, sizeof(host), NULL, 0, NI_NAMEREQD); if (res) { if (verbose) fprintf(stderr, "getnameinfo(NI_NAMEREQD):%s\n", gai_strerror(res)); } } if (!hosts_ctl(service, host, addr_str, STRING_UNKNOWN)) { if (verbose) fprintf(stderr, "access denied\n"); log_message(LOG_INFO, "connection from %s(%s): access denied", host, addr_str); close(in_socket); return -1; } #endif return 0; }
/* * rpcb_check; the rpcbind/portmap access check function. */ boolean_t rpcb_check(SVCXPRT *transp, rpcproc_t procnum, boolean_t ispmap) { struct netconfig *conf; boolean_t res = B_TRUE; if ((conf = rpcbind_get_conf(transp->xp_netid)) == 0) { syslog(LOG_ERR, "rpcbind_get_conf failed: no client address checks"); return (B_TRUE); } /* * Require IPv4 for pmap calls; they're not defined for anything else. */ if (ispmap && strcmp(conf->nc_protofmly, "inet") != 0) { res = B_FALSE; } else if (strcmp(conf->nc_protofmly, "inet") == 0 || strcmp(conf->nc_protofmly, "inet6") == 0) { const char *addr_string = sgen_toa(svc_getgencaller(transp)); if (!localxprt(transp, ispmap) && (local_only || hosts_ctl("rpcbind", addr_string, addr_string, "") == 0)) { res = B_FALSE; } } out: if (!res) svcerr_auth(transp, AUTH_FAILED); if (verboselog || !res) rpcb_log(res, transp, procnum, 0, ispmap); return (res); }
void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) { int nfds; fd_set fds; struct timeval tv; #ifdef LIBVNCSERVER_IPv6 struct sockaddr_storage addr; #else struct sockaddr_in addr; #endif socklen_t addrlen = sizeof(addr); if (!rfbScreen->httpDir) return; if (rfbScreen->httpListenSock < 0) return; FD_ZERO(&fds); FD_SET(rfbScreen->httpListenSock, &fds); if (rfbScreen->httpListen6Sock >= 0) { FD_SET(rfbScreen->httpListen6Sock, &fds); } if (rfbScreen->httpSock >= 0) { FD_SET(rfbScreen->httpSock, &fds); } tv.tv_sec = 0; tv.tv_usec = 0; nfds = select(max(rfbScreen->httpListen6Sock, max(rfbScreen->httpSock,rfbScreen->httpListenSock)) + 1, &fds, NULL, NULL, &tv); if (nfds == 0) { return; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno != EINTR) rfbLogPerror("httpCheckFds: select"); return; } if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) { httpProcessInput(rfbScreen); } if (FD_ISSET(rfbScreen->httpListenSock, &fds) || FD_ISSET(rfbScreen->httpListen6Sock, &fds)) { if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); if(FD_ISSET(rfbScreen->httpListenSock, &fds)) { if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("httpCheckFds: accept"); return; } } else if(FD_ISSET(rfbScreen->httpListen6Sock, &fds)) { if ((rfbScreen->httpSock = accept(rfbScreen->httpListen6Sock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("httpCheckFds: accept"); return; } } #ifdef USE_LIBWRAP char host[1024]; #ifdef LIBVNCSERVER_IPv6 if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { rfbLogPerror("httpCheckFds: error in getnameinfo"); host[0] = '\0'; } #else memcpy(host, inet_ntoa(addr.sin_addr), sizeof(host)); #endif if(!hosts_ctl("vnc",STRING_UNKNOWN, host, STRING_UNKNOWN)) { rfbLog("Rejected HTTP connection from client %s\n", host); close(rfbScreen->httpSock); rfbScreen->httpSock=-1; return; } #endif if(!rfbSetNonBlocking(rfbScreen->httpSock)) { close(rfbScreen->httpSock); rfbScreen->httpSock=-1; return; } /*AddEnabledDevice(httpSock);*/ } }
int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) { int nfds; fd_set fds; struct timeval tv; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); char buf[6]; const int one = 1; int sock; rfbClientIteratorPtr i; rfbClientPtr cl; struct timeval tv_msg; fd_set fds_msg; int nfds_msg; int result = 0; if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); rfbScreen->inetdInitDone = TRUE; } do { memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set)); tv.tv_sec = 0; tv.tv_usec = usec; nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv); if (nfds == 0) { /* timed out, check for async events */ i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) { if (cl->onHold) continue; if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) rfbSendFileTransferChunk(cl); } rfbReleaseClientIterator(i); return result; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno != EINTR) rfbLogPerror("rfbCheckFds: select"); return -1; } result += nfds; if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) { if ((sock = accept(rfbScreen->listenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("rfbCheckFds: accept"); return -1; } #ifndef WIN32 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { rfbLogPerror("rfbCheckFds: fcntl"); closesocket(sock); return -1; } #endif if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbLogPerror("rfbCheckFds: setsockopt"); closesocket(sock); return -1; } #ifdef USE_LIBWRAP if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected connection from client %s\n", inet_ntoa(addr.sin_addr)); closesocket(sock); return -1; } #endif rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); rfbNewClient(rfbScreen,sock); FD_CLR(rfbScreen->listenSock, &fds); if (--nfds == 0) return result; } if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) { if(!rfbScreen->udpClient) rfbNewUDPClient(rfbScreen); if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK, (struct sockaddr *)&addr, &addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: recvfrom"); rfbDisconnectUDPSock(rfbScreen); rfbScreen->udpSockConnected = FALSE; } else { if (!rfbScreen->udpSockConnected || (memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0)) { /* new remote end */ rfbLog("rfbCheckFds: UDP: got connection\n"); memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen); rfbScreen->udpSockConnected = TRUE; if (connect(rfbScreen->udpSock, (struct sockaddr *)&addr, addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: connect"); rfbDisconnectUDPSock(rfbScreen); return -1; } rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock); } rfbProcessUDPInput(rfbScreen); } FD_CLR(rfbScreen->udpSock, &fds); if (--nfds == 0) return result; } i = rfbGetClientIterator(rfbScreen); while((cl = rfbClientIteratorNext(i))) { if (cl->onHold) continue; if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) { if (FD_ISSET(cl->sock, &fds)) { tv_msg.tv_sec = 0; tv_msg.tv_usec = 0; FD_ZERO(&fds_msg); FD_SET(cl->sock, &fds_msg); do { /* drain all messages, speed up mouse move processing */ rfbProcessClientMessage(cl); nfds_msg = select(cl->sock + 1, &fds_msg, NULL, NULL, &tv_msg); } while (nfds_msg > 0); } else rfbSendFileTransferChunk(cl); } } rfbReleaseClientIterator(i); } while(rfbScreen->handleEventsEagerly); return result; }
void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) { int nfds; fd_set fds; struct timeval tv; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); if (!rfbScreen->httpDir) return; if (rfbScreen->httpListenSock < 0) return; FD_ZERO(&fds); FD_SET(rfbScreen->httpListenSock, &fds); if (rfbScreen->httpSock >= 0) { FD_SET(rfbScreen->httpSock, &fds); } tv.tv_sec = 0; tv.tv_usec = 0; nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv); if (nfds == 0) { return; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno != EINTR) rfbLogPerror("httpCheckFds: select"); return; } if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) { httpProcessInput(rfbScreen); } if (FD_ISSET(rfbScreen->httpListenSock, &fds)) { if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("httpCheckFds: accept"); return; } #ifdef USE_LIBWRAP if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected HTTP connection from client %s\n", inet_ntoa(addr.sin_addr)); close(rfbScreen->httpSock); rfbScreen->httpSock=-1; return; } #endif if(!rfbSetNonBlocking(rfbScreen->httpSock)) { close(rfbScreen->httpSock); rfbScreen->httpSock=-1; return; } /*AddEnabledDevice(httpSock);*/ } }
rfbBool rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen) { const int one = 1; int sock = -1; #ifdef LIBVNCSERVER_IPv6 struct sockaddr_storage addr; #else struct sockaddr_in addr; #endif socklen_t addrlen = sizeof(addr); fd_set listen_fds; int chosen_listen_sock = -1; /* Do another select() call to find out which listen socket has an incoming connection pending. We know that at least one of them has, so this should not block for too long! */ FD_ZERO(&listen_fds); if(rfbScreen->listenSock >= 0) FD_SET(rfbScreen->listenSock, &listen_fds); if(rfbScreen->listen6Sock >= 0) FD_SET(rfbScreen->listen6Sock, &listen_fds); if (select(rfbScreen->maxFd+1, &listen_fds, NULL, NULL, NULL) == -1) { rfbLogPerror("rfbProcessNewConnection: error in select"); return FALSE; } if (rfbScreen->listenSock >= 0 && FD_ISSET(rfbScreen->listenSock, &listen_fds)) chosen_listen_sock = rfbScreen->listenSock; if (rfbScreen->listen6Sock >= 0 && FD_ISSET(rfbScreen->listen6Sock, &listen_fds)) chosen_listen_sock = rfbScreen->listen6Sock; if ((sock = accept(chosen_listen_sock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("rfbCheckFds: accept"); return FALSE; } if(!rfbSetNonBlocking(sock)) { closesocket(sock); return FALSE; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbLogPerror("rfbCheckFds: setsockopt"); closesocket(sock); return FALSE; } #ifdef USE_LIBWRAP if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected connection from client %s\n", inet_ntoa(addr.sin_addr)); closesocket(sock); return FALSE; } #endif #ifdef LIBVNCSERVER_IPv6 { char host[1024]; if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { rfbLogPerror("rfbProcessNewConnection: error in getnameinfo"); } rfbLog("Got connection from client %s\n", host); } #else rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); #endif rfbNewClient(rfbScreen,sock); return TRUE; }
void httpCheckFds(rfbScreenInfoPtr rfbScreen) { int nfds; fd_set fds; struct timeval tv; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); if (!rfbScreen->httpDir) return; FD_ZERO(&fds); FD_SET(rfbScreen->httpListenSock, &fds); if (rfbScreen->httpSock >= 0) { FD_SET(rfbScreen->httpSock, &fds); } tv.tv_sec = 0; tv.tv_usec = 0; nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv); if (nfds == 0) { return; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif rfbLogPerror("httpCheckFds: select"); return; } if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) { httpProcessInput(rfbScreen); } if (FD_ISSET(rfbScreen->httpListenSock, &fds)) { int flags; if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("httpCheckFds: accept"); return; } #ifdef USE_LIBWRAP if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected connection from client %s\n", inet_ntoa(addr.sin_addr)); #else if ((rfbScreen->httpFP = fdopen(rfbScreen->httpSock, "r+")) == NULL) { rfbLogPerror("httpCheckFds: fdopen"); #endif close(rfbScreen->httpSock); rfbScreen->httpSock = -1; return; } flags=fcntl(rfbScreen->httpSock,F_GETFL); if(flags==-1 || fcntl(rfbScreen->httpSock,F_SETFL,flags|O_NONBLOCK)==-1) { rfbLogPerror("httpCheckFds: fcntl"); close(rfbScreen->httpSock); rfbScreen->httpSock=-1; return; } /*AddEnabledDevice(httpSock);*/ } } static void httpCloseSock(rfbScreenInfoPtr rfbScreen) { fclose(rfbScreen->httpFP); rfbScreen->httpFP = NULL; /*RemoveEnabledDevice(httpSock);*/ rfbScreen->httpSock = -1; }
int snmp_read_packet(int sd) { struct sockaddr_in from; int length, out_length, fromlength; u_char packet[1500], outpacket[1500]; #ifdef USE_LIBWRAP char *addr_string; #endif fromlength = sizeof from; length = recvfrom(sd, (char *) packet, 1500, 0, (struct sockaddr *)&from, &fromlength); if (length == -1) perror("recvfrom"); #ifdef USE_LIBWRAP addr_string = inet_ntoa(from.sin_addr); if(!addr_string) { addr_string = STRING_UNKNOWN; } if(hosts_ctl("snmpd", addr_string, addr_string, STRING_UNKNOWN)) { syslog(allow_severity, "Connection from %s", addr_string); } else { syslog(deny_severity, "Connection from %s refused", addr_string); return(0); } #endif #ifdef USING_MIBII_SNMP_MIB_MODULE snmp_inpkts++; #endif if (snmp_dump_packet){ printf("\nreceived %d bytes from %s:\n", length, inet_ntoa(from.sin_addr)); xdump(packet, length, ""); printf("\n"); fflush(stdout); } else if (log_addresses){ int count; for(count = 0; count < ADDRCACHE; count++){ if (addrCache[count].status > UNUSED /* used or old */ && from.sin_addr.s_addr == addrCache[count].addr) break; } if (count >= ADDRCACHE || verbose){ printf("%s Received SNMP packet(s) from %s\n", sprintf_stamp(NULL), inet_ntoa(from.sin_addr)); for(count = 0; count < ADDRCACHE; count++){ if (addrCache[count].status == UNUSED){ addrCache[count].addr = from.sin_addr.s_addr; addrCache[count].status = USED; break; } } } else { addrCache[count].status = USED; } } out_length = 1500; if (snmp_agent_parse(packet, length, outpacket, &out_length, from.sin_addr.s_addr)){ if (snmp_dump_packet){ printf("\nsent %d bytes to %s:\n", out_length, inet_ntoa(from.sin_addr)); xdump(outpacket, out_length, ""); printf("\n"); fflush(stdout); } #ifdef USING_MIBII_SNMP_MIB_MODULE snmp_outpkts++; #endif if (sendto(sd, (char *)outpacket, out_length, 0, (struct sockaddr *)&from, sizeof(from)) < 0){ perror("sendto"); return 0; } } return 1; }
void httpCheckFds() { int nfds, n; fd_set fds; struct timeval tv; struct sockaddr_in addr; int addrlen = sizeof(addr); if (!httpDir) return; FD_ZERO(&fds); FD_SET(httpListenSock, &fds); if (httpSock >= 0) { FD_SET(httpSock, &fds); } tv.tv_sec = 0; tv.tv_usec = 0; nfds = select(max(httpSock,httpListenSock) + 1, &fds, NULL, NULL, &tv); if (nfds == 0) { return; } if (nfds < 0) { rfbLogPerror("httpCheckFds: select"); return; } if ((httpSock >= 0) && FD_ISSET(httpSock, &fds)) { httpProcessInput(); } if (FD_ISSET(httpListenSock, &fds)) { int flags; if (httpSock >= 0) close(httpSock); if ((httpSock = accept(httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("httpCheckFds: accept"); return; } #if USE_LIBWRAP if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected HTTP connection from client %s\n", inet_ntoa(addr.sin_addr)); close(httpSock); httpSock = -1; return; } #endif flags = fcntl (httpSock, F_GETFL); if (flags == -1 || fcntl (httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { rfbLogPerror("httpCheckFds: fcntl"); close (httpSock); httpSock = -1; return; } AddEnabledDevice(httpSock); } }
static void * slapd_daemon_task( void *ptr ) { int l; time_t last_idle_check = 0; struct timeval idle; time( &starttime ); #define SLAPD_IDLE_CHECK_LIMIT 4 if ( global_idletimeout > 0 ) { last_idle_check = slap_get_time(); /* Set the select timeout. * Don't just truncate, preserve the fractions of * seconds to prevent sleeping for zero time. */ idle.tv_sec = global_idletimeout/SLAPD_IDLE_CHECK_LIMIT; idle.tv_usec = global_idletimeout - idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT; idle.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT; } else { idle.tv_sec = 0; idle.tv_usec = 0; } for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; #ifdef LDAP_CONNECTIONLESS /* Since this is connectionless, the data port is the * listening port. The listen() and accept() calls * are unnecessary. */ if ( slap_listeners[l]->sl_is_udp ) { slapd_add( slap_listeners[l]->sl_sd ); continue; } #endif if ( listen( slap_listeners[l]->sl_sd, SLAPD_LISTEN ) == -1 ) { int err = sock_errno(); #ifdef LDAP_PF_INET6 /* If error is EADDRINUSE, we are trying to listen to INADDR_ANY and * we are already listening to in6addr_any, then we want to ignore * this and continue. */ if ( err == EADDRINUSE ) { int i; struct sockaddr_in sa = slap_listeners[l]->sl_sa.sa_in_addr; struct sockaddr_in6 sa6; if ( sa.sin_family == AF_INET && sa.sin_addr.s_addr == htonl(INADDR_ANY) ) { for ( i = 0 ; i < l; i++ ) { sa6 = slap_listeners[i]->sl_sa.sa_in6_addr; if ( sa6.sin6_family == AF_INET6 && !memcmp( &sa6.sin6_addr, &in6addr_any, sizeof(struct in6_addr) ) ) break; } if ( i < l ) { /* We are already listening to in6addr_any */ #ifdef NEW_LOGGING LDAP_LOG(CONNECTION, WARNING, "slapd_daemon_task: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", 0, 0, 0 ); #endif slapd_close( slap_listeners[l]->sl_sd ); slap_listeners[l]->sl_sd = AC_SOCKET_INVALID; continue; } } } #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: listen( %s, 5 ) failed errno=%d (%s)\n", slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "daemon: listen(%s, 5) failed errno=%d (%s)\n", slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); #endif return( (void*)-1 ); } slapd_add( slap_listeners[l]->sl_sd ); } #ifdef HAVE_NT_SERVICE_MANAGER if ( started_event != NULL ) { ldap_pvt_thread_cond_signal( &started_event ); } #endif /* initialization complete. Here comes the loop. */ while ( !slapd_shutdown ) { ber_socket_t i; int ns; int at; ber_socket_t nfds; #define SLAPD_EBADF_LIMIT 16 int ebadf = 0; time_t now; fd_set readfds; fd_set writefds; Sockaddr from; struct timeval tv; struct timeval *tvp; now = slap_get_time(); if( ( global_idletimeout > 0 ) && difftime( last_idle_check + global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) { connections_timeout_idle( now ); last_idle_check = now; } tv = idle; #ifdef SIGHUP if( slapd_gentle_shutdown ) { ber_socket_t active; if( slapd_gentle_shutdown == 1 ) { Debug( LDAP_DEBUG_ANY, "slapd gentle shutdown\n", 0, 0, 0 ); close_listeners( 1 ); global_restrictops |= SLAP_RESTRICT_OP_WRITES; slapd_gentle_shutdown = 2; } ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); active = slap_daemon.sd_nactives; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); if( active == 0 ) { slapd_shutdown = 2; break; } } #endif FD_ZERO( &writefds ); FD_ZERO( &readfds ); at = 0; ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); #ifdef FD_SET_MANUAL_COPY for( s = 0; s < nfds; s++ ) { if(FD_ISSET( &slap_sd_readers, s )) { FD_SET( s, &readfds ); } if(FD_ISSET( &slap_sd_writers, s )) { FD_SET( s, &writefds ); } } #else AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) ); AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) ); #endif assert(!FD_ISSET(wake_sds[0], &readfds)); FD_SET( wake_sds[0], &readfds ); for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; if ( slap_listeners[l]->sl_is_mute ) FD_CLR( slap_listeners[l]->sl_sd, &readfds ); else if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds)) FD_SET( slap_listeners[l]->sl_sd, &readfds ); } #ifndef HAVE_WINSOCK nfds = slap_daemon.sd_nfds; #else nfds = dtblsize; #endif if ( global_idletimeout && slap_daemon.sd_nactives ) at = 1; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); if ( !at ) at = ldap_pvt_thread_pool_backload(&connection_pool); #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS ) tvp = NULL; #else tvp = at ? &tv : NULL; #endif for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID || slap_listeners[l]->sl_is_mute ) continue; #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL1, "slapd_daemon_task: select: listen=%d " "active_threads=%d tvp=%s\n", slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "idle" ); #else Debug( LDAP_DEBUG_CONNS, "daemon: select: listen=%d active_threads=%d tvp=%s\n", slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "idle" ); #endif } switch(ns = select( nfds, &readfds, #ifdef HAVE_WINSOCK /* don't pass empty fd_set */ ( writefds.fd_count > 0 ? &writefds : NULL ), #else &writefds, #endif NULL, tvp )) { case -1: { /* failure - try again */ int err = sock_errno(); if( err == EBADF #ifdef WSAENOTSOCK /* you'd think this would be EBADF */ || err == WSAENOTSOCK #endif ) { if (++ebadf < SLAPD_EBADF_LIMIT) continue; } if( err != EINTR ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slapd_daemon_task: select failed (%d): %s\n", err, sock_errstr(err), 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: select failed (%d): %s\n", err, sock_errstr(err), 0 ); #endif slapd_shutdown = 2; } } continue; case 0: /* timeout - let threads run */ ebadf = 0; #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: select timeout - yielding\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n", 0, 0, 0 ); #endif ldap_pvt_thread_yield(); continue; default: /* something happened - deal with it */ if( slapd_shutdown ) continue; ebadf = 0; #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: activity on %d descriptors\n", ns, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n", ns, 0, 0 ); #endif /* FALL THRU */ } if( FD_ISSET( wake_sds[0], &readfds ) ) { char c[BUFSIZ]; tcp_read( wake_sds[0], c, sizeof(c) ); #if defined(NO_THREADS) || defined(HAVE_GNU_PTH) waking = 0; #endif continue; } for ( l = 0; slap_listeners[l] != NULL; l++ ) { ber_socket_t s; socklen_t len = sizeof(from); long id; slap_ssf_t ssf = 0; char *authid = NULL; #ifdef SLAPD_RLOOKUPS char hbuf[NI_MAXHOST]; #endif char *dnsname = NULL; char *peeraddr = NULL; #ifdef LDAP_PF_LOCAL char peername[MAXPATHLEN + sizeof("PATH=")]; #elif defined(LDAP_PF_INET6) char peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")]; #else char peername[sizeof("IP=255.255.255.255:65336")]; #endif /* LDAP_PF_LOCAL */ peername[0] = '\0'; if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) ) continue; #ifdef LDAP_CONNECTIONLESS if ( slap_listeners[l]->sl_is_udp ) { /* The first time we receive a query, we set this * up as a "connection". It remains open for the life * of the slapd. */ if ( slap_listeners[l]->sl_is_udp < 2 ) { id = connection_init( slap_listeners[l]->sl_sd, slap_listeners[l], "", "", 2, ssf, authid ); slap_listeners[l]->sl_is_udp++; } continue; } #endif /* Don't need to look at this in the data loops */ FD_CLR( slap_listeners[l]->sl_sd, &readfds ); FD_CLR( slap_listeners[l]->sl_sd, &writefds ); s = accept( slap_listeners[l]->sl_sd, (struct sockaddr *) &from, &len ); if ( s == AC_SOCKET_INVALID ) { int err = sock_errno(); if( #ifdef EMFILE err == EMFILE || #endif #ifdef ENFILE err == ENFILE || #endif 0 ) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); emfile++; /* Stop listening until an existing session closes */ slap_listeners[l]->sl_is_mute = 1; ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); } #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n", (long)slap_listeners[l]->sl_sd, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "daemon: accept(%ld) failed errno=%d (%s)\n", (long) slap_listeners[l]->sl_sd, err, sock_errstr(err) ); #endif ldap_pvt_thread_yield(); continue; } #ifndef HAVE_WINSOCK /* make sure descriptor number isn't too great */ if ( s >= dtblsize ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: %ld beyond descriptor table size %ld\n", (long)s, (long)dtblsize, 0 ); #else Debug( LDAP_DEBUG_ANY, "daemon: %ld beyond descriptor table size %ld\n", (long) s, (long) dtblsize, 0 ); #endif slapd_close(s); ldap_pvt_thread_yield(); continue; } #endif #ifdef LDAP_DEBUG ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); /* newly accepted stream should not be in any of the FD SETS */ assert( !FD_ISSET( s, &slap_daemon.sd_actives) ); assert( !FD_ISSET( s, &slap_daemon.sd_readers) ); assert( !FD_ISSET( s, &slap_daemon.sd_writers) ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); #endif #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) #ifdef LDAP_PF_LOCAL /* for IPv4 and IPv6 sockets only */ if ( from.sa_addr.sa_family != AF_LOCAL ) #endif /* LDAP_PF_LOCAL */ { int rc; int tmp; #ifdef SO_KEEPALIVE /* enable keep alives */ tmp = 1; rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: setsockopt( %ld, SO_KEEPALIVE)" " failed errno=%d (%s)\n", (long)s, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(SO_KEEPALIVE) failed " "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); #endif } #endif #ifdef TCP_NODELAY /* enable no delay */ tmp = 1; rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, ERR, "slapd_daemon_task: setsockopt( %ld, " "TCP_NODELAY) failed errno=%d (%s)\n", (long)s, err, sock_errstr(err) ); #else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(TCP_NODELAY) failed " "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); #endif } #endif } #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL1, "slapd_daemon_task: new connection on %ld\n", (long)s, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n", (long) s, 0, 0 ); #endif switch ( from.sa_addr.sa_family ) { # ifdef LDAP_PF_LOCAL case AF_LOCAL: sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path ); ssf = LDAP_PVT_SASL_LOCAL_SSF; { uid_t uid; gid_t gid; if( getpeereid( s, &uid, &gid ) == 0 ) { authid = ch_malloc( sizeof("uidnumber=4294967295+gidnumber=4294967295," "cn=peercred,cn=external,cn=auth")); sprintf(authid, "uidnumber=%d+gidnumber=%d," "cn=peercred,cn=external,cn=auth", (int) uid, (int) gid); } } dnsname = "local"; break; #endif /* LDAP_PF_LOCAL */ # ifdef LDAP_PF_INET6 case AF_INET6: if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) { peeraddr = inet_ntoa( *((struct in_addr *) &from.sa_in6_addr.sin6_addr.s6_addr[12]) ); sprintf( peername, "IP=%s:%d", peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); } else { char addr[INET6_ADDRSTRLEN]; peeraddr = (char *) inet_ntop( AF_INET6, &from.sa_in6_addr.sin6_addr, addr, sizeof addr ); sprintf( peername, "IP=%s %d", peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); } break; # endif /* LDAP_PF_INET6 */ case AF_INET: peeraddr = inet_ntoa( from.sa_in_addr.sin_addr ); sprintf( peername, "IP=%s:%d", peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, (unsigned) ntohs( from.sa_in_addr.sin_port ) ); break; default: slapd_close(s); continue; } if ( ( from.sa_addr.sa_family == AF_INET ) #ifdef LDAP_PF_INET6 || ( from.sa_addr.sa_family == AF_INET6 ) #endif ) { #ifdef SLAPD_RLOOKUPS if ( use_reverse_lookup ) { char *herr; if (ldap_pvt_get_hname( (const struct sockaddr *)&from, len, hbuf, sizeof(hbuf), &herr ) == 0) { ldap_pvt_str2lower( hbuf ); dnsname = hbuf; } } #else dnsname = NULL; #endif /* SLAPD_RLOOKUPS */ #ifdef HAVE_TCPD if ( !hosts_ctl("slapd", dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, SLAP_STRING_UNKNOWN )) { /* DENY ACCESS */ Statslog( LDAP_DEBUG_STATS, "fd=%ld DENIED from %s (%s)\n", (long) s, dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, 0, 0 ); slapd_close(s); continue; } #endif /* HAVE_TCPD */ } id = connection_init(s, slap_listeners[l], dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, peername, #ifdef HAVE_TLS slap_listeners[l]->sl_is_tls, #else 0, #endif ssf, authid ); if( authid ) ch_free(authid); if( id < 0 ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, INFO, "slapd_daemon_task: " "connection_init(%ld, %s, %s) " "failed.\n", (long)s, peername, slap_listeners[l]->sl_name.bv_val ); #else Debug( LDAP_DEBUG_ANY, "daemon: connection_init(%ld, %s, %s) " "failed.\n", (long) s, peername, slap_listeners[l]->sl_name.bv_val ); #endif slapd_close(s); continue; } Statslog( LDAP_DEBUG_STATS, "conn=%ld fd=%ld ACCEPT from %s (%s)\n", id, (long) s, peername, slap_listeners[l]->sl_name.bv_val, 0 ); slapd_add( s ); continue; } #ifdef LDAP_DEBUG #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: activity on ", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 ); #endif #ifdef HAVE_WINSOCK for ( i = 0; i < readfds.fd_count; i++ ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, " %d%s", readfds.fd_array[i], "r", 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, " %d%s", readfds.fd_array[i], "r", 0 ); #endif } for ( i = 0; i < writefds.fd_count; i++ ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, " %d%s", writefds.fd_array[i], "w" , 0 ); #else Debug( LDAP_DEBUG_CONNS, " %d%s", writefds.fd_array[i], "w", 0 ); #endif } #else for ( i = 0; i < nfds; i++ ) { int r, w; r = FD_ISSET( i, &readfds ); w = FD_ISSET( i, &writefds ); if ( r || w ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, " %d%s%s", i, r ? "r" : "", w ? "w" : "" ); #else Debug( LDAP_DEBUG_CONNS, " %d%s%s", i, r ? "r" : "", w ? "w" : "" ); #endif } } #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 ); #endif #endif /* loop through the writers */ #ifdef HAVE_WINSOCK for ( i = 0; i < writefds.fd_count; i++ ) #else for ( i = 0; i < nfds; i++ ) #endif { ber_socket_t wd; #ifdef HAVE_WINSOCK wd = writefds.fd_array[i]; #else if( ! FD_ISSET( i, &writefds ) ) { continue; } wd = i; #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: write active on %d\n", wd, 0, 0 ); #else Debug( LDAP_DEBUG_CONNS, "daemon: write active on %d\n", wd, 0, 0 ); #endif /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. * connection_write() must valid the stream is still * active. */ if ( connection_write( wd ) < 0 ) { FD_CLR( (unsigned) wd, &readfds ); slapd_close( wd ); } } #ifdef HAVE_WINSOCK for ( i = 0; i < readfds.fd_count; i++ ) #else for ( i = 0; i < nfds; i++ ) #endif { ber_socket_t rd; #ifdef HAVE_WINSOCK rd = readfds.fd_array[i]; #else if( ! FD_ISSET( i, &readfds ) ) { continue; } rd = i; #endif #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, DETAIL2, "slapd_daemon_task: read activity on %d\n", rd, 0, 0 ); #else Debug ( LDAP_DEBUG_CONNS, "daemon: read activity on %d\n", rd, 0, 0 ); #endif /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. * connection_read() must valid the stream is still * active. */ if ( connection_read( rd ) < 0 ) { slapd_close( rd ); } } ldap_pvt_thread_yield(); } if( slapd_shutdown == 1 ) { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: shutdown requested and initiated.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: shutdown requested and initiated.\n", 0, 0, 0 ); #endif } else if ( slapd_shutdown == 2 ) { #ifdef HAVE_NT_SERVICE_MANAGER #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: shutdown initiated by Service Manager.\n", 0, 0, 0); #else Debug( LDAP_DEBUG_TRACE, "daemon: shutdown initiated by Service Manager.\n", 0, 0, 0); #endif #else /* !HAVE_NT_SERVICE_MANAGER */ #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: abnormal condition, " "shutdown initiated.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: abnormal condition, shutdown initiated.\n", 0, 0, 0 ); #endif #endif /* !HAVE_NT_SERVICE_MANAGER */ } else { #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: no active streams, shutdown initiated.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "daemon: no active streams, shutdown initiated.\n", 0, 0, 0 ); #endif } if( slapd_gentle_shutdown != 2 ) { close_listeners ( 0 ); } free ( slap_listeners ); slap_listeners = NULL; if( !slapd_gentle_shutdown ) { connections_shutdown(); } #ifdef NEW_LOGGING LDAP_LOG( CONNECTION, CRIT, "slapd_daemon_task: shutdown waiting for %d threads to terminate.\n", ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "slapd shutdown: waiting for %d threads to terminate\n", ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 ); #endif ldap_pvt_thread_pool_destroy(&connection_pool, 1); return NULL; }
void rfbCheckFds() { int nfds; fd_set fds; struct timeval tv; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); char addrStr[INET6_ADDRSTRLEN]; char buf[6]; const int one = 1; int sock; rfbClientPtr cl; static Bool inetdInitDone = FALSE; if (!inetdInitDone && inetdSock != -1) { rfbNewClientConnection(inetdSock); inetdInitDone = TRUE; } memcpy((char *)&fds, (char *)&allFds, sizeof(fd_set)); tv.tv_sec = 0; tv.tv_usec = 0; nfds = select(maxFd + 1, &fds, NULL, NULL, &tv); if (nfds == 0) { return; } if (nfds < 0) { rfbLogPerror("rfbCheckFds: select"); return; } if (rfbListenSock != -1 && FD_ISSET(rfbListenSock, &fds)) { if ((sock = accept(rfbListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("rfbCheckFds: accept"); return; } if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { rfbLogPerror("rfbCheckFds: fcntl"); close(sock); return; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbLogPerror("rfbCheckFds: setsockopt"); close(sock); return; } fprintf(stderr, "\n"); #if USE_LIBWRAP if (!hosts_ctl("Xvnc", STRING_UNKNOWN, sockaddr_string(&addr, addrStr, INET6_ADDRSTRLEN), STRING_UNKNOWN)) { rfbLog("Rejected connection from client %s\n", sockaddr_string(&addr, addrStr, INET6_ADDRSTRLEN)) close(sock); return; } #endif rfbLog("Got connection from client %s\n", sockaddr_string(&addr, addrStr, INET6_ADDRSTRLEN)); AddEnabledDevice(sock); FD_SET(sock, &allFds); maxFd = max(sock, maxFd); rfbNewClientConnection(sock); FD_CLR(rfbListenSock, &fds); if (--nfds == 0) return; } if ((udpSock != -1) && FD_ISSET(udpSock, &fds)) { if (recvfrom(udpSock, buf, 1, MSG_PEEK, (struct sockaddr *)&addr, &addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: recvfrom"); rfbDisconnectUDPSock(); } else { if (!udpSockConnected || (memcmp(&addr, &udpRemoteAddr, addrlen) != 0)) { /* new remote end */ rfbLog("rfbCheckFds: UDP: got connection\n"); memcpy(&udpRemoteAddr, &addr, addrlen); udpSockConnected = TRUE; if (connect(udpSock, (struct sockaddr *)&addr, addrlen) < 0) { rfbLogPerror("rfbCheckFds: UDP: connect"); rfbDisconnectUDPSock(); return; } rfbNewUDPConnection(udpSock); } rfbProcessUDPInput(udpSock); } FD_CLR(udpSock, &fds); if (--nfds == 0) return; } for (cl = rfbClientHead; cl; cl = cl->next) { if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &allFds)) { rfbClientPtr cl2; #if USETLS do { rfbProcessClientMessage(cl); /* Make sure cl hasn't been freed */ for (cl2 = rfbClientHead; cl2; cl2 = cl2->next) { if (cl2 == cl) break; } if (cl2 == NULL) return; } while (cl->sslctx && rfbssl_pending(cl) > 0); #else rfbProcessClientMessage(cl); for (cl2 = rfbClientHead; cl2; cl2 = cl2->next) { if (cl2 == cl) break; } if (cl2 == NULL) return; #endif } } }
void server(int lpnumber) { struct rlimit resourcelimit; #ifdef USE_GETPROTOBYNAME struct protoent *proto; #endif int netfd = -1, fd, lp, one = 1; int open_sleep = 10; socklen_t clientlen; struct sockaddr_storage client; struct addrinfo hints, *res, *ressave; char pidfilename[sizeof(PIDFILE)]; char service[10]; // 9100 (65535 max) FILE *f; const int bufsiz = 65536; #ifndef TESTING if (!log_to_stdout) { switch (fork()) { case -1: dolog(LOGOPTS, "fork: %m\n"); exit(1); case 0: /* child */ break; default: /* parent */ exit(0); } /* Now in child process */ resourcelimit.rlim_max = 0; if (getrlimit(RLIMIT_NOFILE, &resourcelimit) < 0) { dolog(LOGOPTS, "getrlimit: %m\n"); exit(1); } for (fd = 0; fd < resourcelimit.rlim_max; ++fd) (void)close(fd); if (setsid() < 0) { dolog(LOGOPTS, "setsid: %m\n"); exit(1); } (void)chdir("/"); (void)umask(022); fd = open("/dev/null", O_RDWR); /* stdin */ (void)dup(fd); /* stdout */ (void)dup(fd); /* stderr */ (void)snprintf(pidfilename, sizeof(pidfilename), PIDFILE, lpnumber); if ((f = fopen(pidfilename, "w")) == NULL) { dolog(LOGOPTS, "%s: %m\n", pidfilename); exit(1); } (void)fprintf(f, "%d\n", getpid()); (void)fclose(f); } if (get_lock(lpnumber) == 0) exit(1); #endif memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; (void)snprintf(service, sizeof(service), "%hu", (BASEPORT + lpnumber - '0')); if (getaddrinfo(bindaddr, service, &hints, &res) != 0) { dolog(LOGOPTS, "getaddr: %m\n"); exit(1); } ressave = res; while (res) { #ifdef USE_GETPROTOBYNAME if ((proto = getprotobyname("tcp6")) == NULL) { if ((proto = getprotobyname("tcp")) == NULL) { dolog(LOGOPTS, "Cannot find protocol for TCP!\n"); exit(1); } } if ((netfd = socket(res->ai_family, res->ai_socktype, proto->p_proto)) < 0) #else if ((netfd = socket(res->ai_family, res->ai_socktype, IPPROTO_IP)) < 0) #endif { dolog(LOGOPTS, "socket: %m\n"); close(netfd); res = res->ai_next; continue; } if (setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)) < 0) { dolog(LOGOPTS, "setsocketopt: SO_RCVBUF: %m\n"); /* not fatal if it fails */ } if (setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)) < 0) { dolog(LOGOPTS, "setsocketopt: SO_SNDBUF: %m\n"); /* not fatal if it fails */ } if (setsockopt(netfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { dolog(LOGOPTS, "setsocketopt: SO_REUSEADDR: %m\n"); close(netfd); res = res->ai_next; continue; } if (bind(netfd, res->ai_addr, res->ai_addrlen) < 0) { dolog(LOGOPTS, "bind: %m\n"); close(netfd); res = res->ai_next; continue; } if (listen(netfd, 5) < 0) { dolog(LOGOPTS, "listen: %m\n"); close(netfd); res = res->ai_next; continue; } break; } freeaddrinfo(ressave); clientlen = sizeof(client); memset(&client, 0, sizeof(client)); while ((fd = accept(netfd, (struct sockaddr *)&client, &clientlen)) >= 0) { char host[INET6_ADDRSTRLEN]; #ifdef USE_LIBWRAP if (hosts_ctl("p910nd", STRING_UNKNOWN, get_ip_str((struct sockaddr *)&client, host, sizeof(host)), STRING_UNKNOWN) == 0) { dolog(LOGOPTS, "Connection from %s port %hu rejected\n", get_ip_str((struct sockaddr *)&client, host, sizeof(host)), get_port((struct sockaddr *)&client)); close(fd); continue; } #endif dolog(LOG_NOTICE, "Connection from %s port %hu accepted\n", get_ip_str((struct sockaddr *)&client, host, sizeof(host)), get_port((struct sockaddr *)&client)); /*write(fd, "Printing", 8); */ /* Make sure lp device is open... */ while ((lp = open_printer(lpnumber)) == -1) { sleep(open_sleep); if (open_sleep < 320) /* ~5 min interval to avoid spam in syslog */ open_sleep *= 2; } open_sleep = 10; if (copy_stream(fd, lp) < 0) dolog(LOGOPTS, "copy_stream: %m\n"); (void)close(fd); (void)close(lp); } dolog(LOGOPTS, "accept: %m\n"); free_lock(); exit(1); }
void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) { int nfds; fd_set fds; struct timeval tv; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); if (!rfbScreen->httpDir) return; if (rfbScreen->httpListenSock < 0) return; FD_ZERO(&fds); FD_SET(rfbScreen->httpListenSock, &fds); if (rfbScreen->httpSock >= 0) { FD_SET(rfbScreen->httpSock, &fds); } tv.tv_sec = 0; tv.tv_usec = 0; nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv); if (nfds == 0) { return; } if (nfds < 0) { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno != EINTR) rfbLogPerror("httpCheckFds: select"); return; } if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) { httpProcessInput(rfbScreen); } if (FD_ISSET(rfbScreen->httpListenSock, &fds)) { int flags; if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) { rfbLogPerror("httpCheckFds: accept"); return; } #ifdef __MINGW32__ rfbErr("O_NONBLOCK on MinGW32 NOT IMPLEMENTED"); #else #ifdef USE_LIBWRAP if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) { rfbLog("Rejected HTTP connection from client %s\n", inet_ntoa(addr.sin_addr)); #else flags = fcntl(rfbScreen->httpSock, F_GETFL); if (flags < 0 || fcntl(rfbScreen->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { rfbLogPerror("httpCheckFds: fcntl"); #endif close(rfbScreen->httpSock); rfbScreen->httpSock = -1; return; } flags=fcntl(rfbScreen->httpSock,F_GETFL); if(flags==-1 || fcntl(rfbScreen->httpSock,F_SETFL,flags|O_NONBLOCK)==-1) { rfbLogPerror("httpCheckFds: fcntl"); close(rfbScreen->httpSock); rfbScreen->httpSock=-1; return; } #endif /*AddEnabledDevice(httpSock);*/ } } static void httpCloseSock(rfbScreenInfoPtr rfbScreen) { close(rfbScreen->httpSock); rfbScreen->httpSock = -1; buf_filled = 0; }
/* * We will eventually be called from inetd or via the rc scripts directly * Parse arguments and act appropiately. */ int main(int argc, char **argv) { extern char *optarg; FILE *fp; int c, *s, ns; struct pollfd *pfds; #if PROFILE moncontrol(0); #endif if ((progname = strrchr(*argv, '/')) != NULL) { progname++; } else progname = *argv; /* initialise global session data */ memset(&session, 0, sizeof(session)); session.peer = tac_strdup("unknown"); if (argc <= 1) { usage(); tac_exit(1); } while ((c = getopt(argc, argv, "B:C:d:hiPp:tGgvSsLw:u:")) != EOF) switch (c) { case 'B': /* bind() address*/ bind_address = optarg; break; case 'L': /* lookup peer names via DNS */ lookup_peer = 1; break; case 's': /* don't respond to sendpass */ sendauth_only = 1; break; case 'v': /* print version and exit */ vers(); tac_exit(1); case 't': console = 1; /* log to console too */ break; case 'P': /* Parse config file only */ parse_only = 1; break; case 'G': /* foreground */ opt_G = 1; break; case 'g': /* single threaded */ single = 1; break; case 'p': /* port */ port = atoi(optarg); portstr = optarg; break; case 'd': /* debug */ debug |= atoi(optarg); break; case 'C': /* config file name */ session.cfgfile = tac_strdup(optarg); break; case 'h': /* usage */ usage(); tac_exit(0); case 'i': /* inetd mode */ standalone = 0; break; case 'S': /* enable single-connection */ opt_S = 1; break; #ifdef MAXSESS case 'w': /* wholog file */ wholog = tac_strdup(optarg); break; #endif case 'u': wtmpfile = tac_strdup(optarg); break; default: fprintf(stderr, "%s: bad switch %c\n", progname, c); usage(); tac_exit(1); } parser_init(); /* read the configuration/etc */ init(); #if defined(REAPCHILD) && defined(REAPSIGIGN) client_count_init(); #endif open_logfile(); signal(SIGUSR1, handler); signal(SIGHUP, handler); signal(SIGUSR2, dump_clients_handler); signal(SIGTERM, die); signal(SIGPIPE, SIG_IGN); if (parse_only) tac_exit(0); if (debug) report(LOG_DEBUG, "tac_plus server %s starting", version); if (!standalone) { /* running under inetd */ char host[NI_MAXHOST]; int on; #ifdef IPV6 struct sockaddr_in6 name; #else struct sockaddr_in name; #endif socklen_t name_len; name_len = sizeof(name); session.flags |= SESS_NO_SINGLECONN; session.sock = 0; #ifdef IPV6 if (getpeername(session.sock, (struct sockaddr6 *)&name, &name_len)) { report(LOG_ERR, "getpeername failure %s", strerror(errno)); #else if (getpeername(session.sock, (struct sockaddr *)&name, &name_len)) { report(LOG_ERR, "getpeername failure %s", strerror(errno)); #endif } else { if (lookup_peer) on = 0; else on = NI_NUMERICHOST; #ifdef IPV6 if (getnameinfo((struct sockaddr6 *)&name, name_len, host, 128, NULL, 0, on)) { #else if (getnameinfo((struct sockaddr *)&name, name_len, host, 128, NULL, 0, on)) { #endif strncpy(host, "unknown", NI_MAXHOST - 1); host[NI_MAXHOST - 1] = '\0'; } if (session.peer) free(session.peer); session.peer = tac_strdup(host); if (session.peerip) free(session.peerip); #ifdef IPV6 session.peerip = tac_strdup((char *)inet_ntop(name.sin6_family, &name.sin6_addr, host, name_len)); #else session.peerip = tac_strdup((char *)inet_ntop(name.sin_family, &name.sin_addr, host, name_len)); #endif if (debug & DEBUG_AUTHEN_FLAG) report(LOG_INFO, "session.peerip is %s", session.peerip); } #ifdef FIONBIO on = 1; if (ioctl(session.sock, FIONBIO, &on) < 0) { report(LOG_ERR, "ioctl(FIONBIO) %s", strerror(errno)); tac_exit(1); } #endif start_session(); tac_exit(0); } if (single) { session.flags |= SESS_NO_SINGLECONN; } else { /* * Running standalone; background ourselves and release controlling * tty, unless -G option was specified to keep the parent in the * foreground. */ #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif if (!opt_S) session.flags |= SESS_NO_SINGLECONN; if (!opt_G) { if ((childpid = fork()) < 0) report(LOG_ERR, "Can't fork first child"); else if (childpid > 0) exit(0); /* parent */ if (debug) report(LOG_DEBUG, "Backgrounded"); #if SETPGRP_VOID if (setpgrp() == -1) #else if (setpgrp(0, getpid()) == -1) #endif /* SETPGRP_VOID */ report(LOG_ERR, "Can't change process group: %s", strerror(errno)); /* XXX What does "REAPCHILD" have to do with TIOCNOTTY? */ #ifndef REAPCHILD c = open("/dev/tty", O_RDWR); if (c >= 0) { ioctl(c, TIOCNOTTY, (char *)0); (void) close(c); } #else /* REAPCHILD */ if ((childpid = fork()) < 0) report(LOG_ERR, "Can't fork second child"); else if (childpid > 0) exit(0); if (debug & DEBUG_FORK_FLAG) report(LOG_DEBUG, "Forked grandchild"); #endif /* REAPCHILD */ /* some systems require this */ closelog(); for (c = getdtablesize(); c >= 0; c--) (void)close(c); /* * make sure we can still log to syslog now that we have closed * everything */ open_logfile(); } } #if REAPCHILD #if REAPSIGIGN signal(SIGCHLD, reapchild); #else signal(SIGCHLD, SIG_IGN); #endif #endif ostream = NULL; /* chdir("/"); */ umask(022); errno = 0; get_socket(&s, &ns); #ifndef SOMAXCONN #define SOMAXCONN 5 #endif for (c = 0; c < ns; c++) { if (listen(s[c], SOMAXCONN) < 0) { console = 1; report(LOG_ERR, "listen: %s", strerror(errno)); tac_exit(1); } } if (port == TAC_PLUS_PORT) { if (bind_address == NULL) { strncpy(pidfilebuf, TACPLUS_PIDFILE, PIDSZ); if (pidfilebuf[PIDSZ - 1] != '\0') c = PIDSZ; else c = PIDSZ - 1; } else c = snprintf(pidfilebuf, PIDSZ, "%s.%s", TACPLUS_PIDFILE, bind_address); } else { if (bind_address == NULL) c = snprintf(pidfilebuf, PIDSZ, "%s.%d", TACPLUS_PIDFILE, port); else c = snprintf(pidfilebuf, PIDSZ, "%s.%s.%d", TACPLUS_PIDFILE, bind_address, port); } if (c >= PIDSZ) { pidfilebuf[PIDSZ - 1] = '\0'; report(LOG_ERR, "pid filename truncated: %s", pidfilebuf); childpid = 0; } else { /* write process id to pidfile */ if ((fp = fopen(pidfilebuf, "w")) != NULL) { fprintf(fp, "%d\n", (int)getpid()); fclose(fp); /* * After forking to disassociate; make sure we know we're the * mother so that we remove our pid file upon exit in die(). */ childpid = 1; } else { report(LOG_ERR, "Cannot write pid to %s %s", pidfilebuf, strerror(errno)); childpid = 0; } } #ifdef TACPLUS_GROUPID if (setgid(TACPLUS_GROUPID)) report(LOG_ERR, "Cannot set group id to %d %s", TACPLUS_GROUPID, strerror(errno)); #endif #ifdef TACPLUS_USERID if (setuid(TACPLUS_USERID)) report(LOG_ERR, "Cannot set user id to %d %s", TACPLUS_USERID, strerror(errno)); #endif #ifdef MAXSESS maxsess_loginit(); #endif /* MAXSESS */ report(LOG_DEBUG, "uid=%d euid=%d gid=%d egid=%d s=%d", getuid(), geteuid(), getgid(), getegid(), s); pfds = malloc(sizeof(struct pollfd) * ns); if (pfds == NULL) { report(LOG_ERR, "malloc failure: %s", strerror(errno)); tac_exit(1); } for (c = 0; c < ns; c++) { pfds[c].fd = s[c]; pfds[c].events = POLLIN | POLLERR | POLLHUP | POLLNVAL; } for (;;) { #if HAVE_PID_T pid_t pid; #else int pid; #endif char host[NI_MAXHOST]; #ifdef IPV6 struct sockaddr_in6 from; #else struct sockaddr_in from; #endif socklen_t from_len; int newsockfd, status; int flags; int procs_for_client; #if defined(REAPCHILD) && defined(REAPSIGIGN) if (reap_children) reapchildren(); #endif if (reinitialize) init(); if (dump_client_table) { report(LOG_ALERT, "Dumping Client Tables"); dump_client_tables(); dump_client_table = 0; } status = poll(pfds, ns, cfg_get_accepttimeout() * 1000); if (status == 0) continue; if (status == -1) if (errno == EINTR) continue; from_len = sizeof(from); memset((char *)&from, 0, from_len); for (c = 0; c < ns; c++) { if (pfds[c].revents & POLLIN) #ifdef IPV6 newsockfd = accept(s[c], (struct sockaddr6 *)&from, &from_len); #else newsockfd = accept(s[c], (struct sockaddr *)&from, &from_len); #endif else if (pfds[c].revents & (POLLERR | POLLHUP | POLLNVAL)) { report(LOG_ERR, "exception on listen FD %d", s[c]); tac_exit(1); } } if (newsockfd < 0) { if (errno == EINTR) continue; report(LOG_ERR, "accept: %s", strerror(errno)); continue; } if (lookup_peer) flags = 0; else flags = NI_NUMERICHOST; #ifdef IPV6 if (getnameinfo((struct sockaddr_in6 *)&from, from_len, host, 128, NULL, 0, flags)) { #else if (getnameinfo((struct sockaddr_in *)&from, from_len, host, 128, NULL, 0, flags)) { #endif strncpy(host, "unknown", NI_MAXHOST - 1); host[NI_MAXHOST - 1] = '\0'; } if (session.peer) free(session.peer); session.peer = tac_strdup(host); if (session.peerip) free(session.peerip); #ifdef IPV6 session.peerip = tac_strdup((char *)inet_ntop(from.sin6_family, &from.sin6_addr, host, INET6_ADDRSTRLEN)); #else session.peerip = tac_strdup((char *)inet_ntop(from.sin_family, &from.sin_addr, host, INET_ADDRSTRLEN)); #endif if (debug & DEBUG_PACKET_FLAG) report(LOG_DEBUG, "session request from %s sock=%d", session.peer, newsockfd); if (!single) { #if defined(REAPCHILD) && defined(REAPSIGIGN) /* first we check the tocal process count to see if we are at the limit */ if (total_child_count >= cfg_get_maxprocs()) { report(LOG_ALERT, "refused connection from %s [%s] at global max procs [%d]", session.peer, session.peerip, total_child_count); shutdown(newsockfd, 2); close(newsockfd); continue; } /* no we check the process count per client */ procs_for_client = get_client_count(session.peerip); report(LOG_ALERT, "connection [%d] from %s [%s]", procs_for_client + 1, session.peer, session.peerip); if (procs_for_client >= cfg_get_maxprocsperclt()) { report(LOG_ALERT, "refused connection from %s [%s] at client max procs [%d]", session.peer, session.peerip, procs_for_client); shutdown(newsockfd, 2); close(newsockfd); continue; } #endif pid = fork(); if (pid < 0) { report(LOG_ERR, "fork error"); tac_exit(1); } } else { pid = 0; } if (pid == 0) { /* child */ if (!single) { if (ns > 1) { for (c = 0; c < ns; c++) { close(s[c]); } } } session.sock = newsockfd; #ifdef LIBWRAP if (! hosts_ctl(progname,session.peer,session.peerip,progname)) { report(LOG_ALERT, "refused connection from %s [%s]", session.peer, session.peerip); shutdown(session.sock, 2); close(session.sock); if (!single) { tac_exit(0); } else { close(session.sock); continue; } } if (debug) report(LOG_DEBUG, "connect from %s [%s]", session.peer, session.peerip); #endif #if PROFILE moncontrol(1); #endif start_session(); shutdown(session.sock, 2); close(session.sock); if (!single) tac_exit(0); } else { /* parent */ #if defined(REAPCHILD) && defined(REAPSIGIGN) total_child_count++; procs_for_client = increment_client_count_for_proc(pid, session.peerip); snprintf(msgbuf, MSGBUFSZ, "forked %lu for %s, procs %d, procs for client %d", (long)pid, session.peerip, total_child_count, procs_for_client); report(LOG_DEBUG, msgbuf); #endif close(newsockfd); } } }