static int check(char *name, int fd) { struct request_info request; request_init(&request, RQ_DAEMON, name, RQ_FILE, fd, 0); fromhost(&request); return hosts_access(&request); }
bool socket_tcpwrap(int fd, const char *name) { #ifdef HAVE_LIBWRAP struct request_info req; union { struct sockaddr sa; struct sockaddr_in in; struct sockaddr_in6 in6; struct sockaddr_un un; struct sockaddr_storage storage; } sa_union; socklen_t l = sizeof(sa_union); if (getsockname(fd, &sa_union.sa, &l) < 0) return true; if (sa_union.sa.sa_family != AF_INET && sa_union.sa.sa_family != AF_INET6) return true; request_init(&req, RQ_DAEMON, name, RQ_FILE, fd, NULL); fromhost(&req); if (!hosts_access(&req)) { log_warning("Connection refused by tcpwrap."); return false; } log_debug("Connection accepted by tcpwrap."); #endif return true; }
static gboolean afsocket_sd_process_connection(AFSocketSourceDriver *self, GSockAddr *client_addr, GSockAddr *local_addr, gint fd) { gchar buf[MAX_SOCKADDR_STRING], buf2[MAX_SOCKADDR_STRING]; #if SYSLOG_NG_ENABLE_TCP_WRAPPER if (client_addr && (client_addr->sa.sa_family == AF_INET #if SYSLOG_NG_ENABLE_IPV6 || client_addr->sa.sa_family == AF_INET6 #endif )) { struct request_info req; request_init(&req, RQ_DAEMON, "syslog-ng", RQ_FILE, fd, 0); fromhost(&req); if (hosts_access(&req) == 0) { msg_error("Syslog connection rejected by tcpd", evt_tag_str("client", g_sockaddr_format(client_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(local_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); return FALSE; } } #endif if (self->num_connections >= self->max_connections) { msg_error("Number of allowed concurrent connections reached, rejecting connection", evt_tag_str("client", g_sockaddr_format(client_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(local_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_int("max", self->max_connections), NULL); return FALSE; } else { AFSocketSourceConnection *conn; conn = afsocket_sc_new(client_addr, fd, self->super.super.super.cfg); afsocket_sc_set_owner(conn, self); if (log_pipe_init(&conn->super)) { afsocket_sd_add_connection(self, conn); self->num_connections++; log_pipe_append(&conn->super, &self->super.super.super); } else { log_pipe_unref(&conn->super); return FALSE; } } return TRUE; }
int peer_ok(char *prog, int sd) { struct request_info request; request_init(&request, RQ_DAEMON, prog, RQ_FILE, sd, 0); fromhost(&request); if (!hosts_access(&request)) return 0; else return 1; }
static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_socket_server *s = userdata; pa_iochannel *io; int nfd; pa_assert(s); pa_assert(PA_REFCNT_VALUE(s) >= 1); pa_assert(s->mainloop == mainloop); pa_assert(s->io_event == e); pa_assert(e); pa_assert(fd >= 0); pa_assert(fd == s->fd); pa_socket_server_ref(s); if ((nfd = pa_accept_cloexec(fd, NULL, NULL)) < 0) { pa_log("accept(): %s", pa_cstrerror(errno)); goto finish; } if (!s->on_connection) { pa_close(nfd); goto finish; } #ifdef HAVE_LIBWRAP if (s->tcpwrap_service) { struct request_info req; request_init(&req, RQ_DAEMON, s->tcpwrap_service, RQ_FILE, nfd, NULL); fromhost(&req); if (!hosts_access(&req)) { pa_log_warn("TCP connection refused by tcpwrap."); pa_close(nfd); goto finish; } pa_log_info("TCP connection accepted by tcpwrap."); } #endif /* There should be a check for socket type here */ if (s->type == SOCKET_SERVER_IPV4) pa_make_tcp_socket_low_delay(fd); else pa_make_socket_low_delay(fd); pa_assert_se(io = pa_iochannel_new(s->mainloop, nfd, nfd)); s->on_connection(s, io, s->userdata); finish: pa_socket_server_unref(s); }
static void httpd_listen_in_event(int fd, const struct sockaddr *address, size_t address_length, G_GNUC_UNUSED int uid, void *ctx) { struct httpd_output *httpd = ctx; /* the listener socket has become readable - a client has connected */ #ifdef HAVE_LIBWRAP if (address->sa_family != AF_UNIX) { char *hostaddr = sockaddr_to_string(address, address_length, NULL); const char *progname = g_get_prgname(); struct request_info req; request_init(&req, RQ_FILE, fd, RQ_DAEMON, progname, 0); fromhost(&req); if (!hosts_access(&req)) { /* tcp wrappers says no */ g_warning("libwrap refused connection (libwrap=%s) from %s", progname, hostaddr); g_free(hostaddr); close_socket(fd); g_mutex_unlock(httpd->mutex); return; } g_free(hostaddr); } #else (void)address; (void)address_length; #endif /* HAVE_WRAP */ g_mutex_lock(httpd->mutex); if (fd >= 0) { /* can we allow additional client */ if (httpd->open && (httpd->clients_max == 0 || httpd->clients_cnt < httpd->clients_max)) httpd_client_add(httpd, fd); else close_socket(fd); } else if (fd < 0 && errno != EINTR) { g_warning("accept() failed: %s", g_strerror(errno)); } g_mutex_unlock(httpd->mutex); }
static int tcpd_auth(int connfd) { struct request_info request; int rc; request_init(&request, RQ_DAEMON, PROGNAME, RQ_FILE, connfd, 0); fromhost(&request); rc = hosts_access(&request); if (rc == 0) return -1; return 0; }
void aha1542a_device::device_add_mconfig(machine_config &config) { i8085a_cpu_device &localcpu(I8085A(config, m_localcpu, 10'000'000)); localcpu.set_addrmap(AS_PROGRAM, &aha1542a_device::i8085_map); generic_latch_8_device &fromhost(GENERIC_LATCH_8(config, "fromhost")); fromhost.data_pending_callback().set_inputline(m_localcpu, I8085_RST55_LINE); GENERIC_LATCH_8(config, "tohost"); scsi_add(config); DP8473(config, m_fdc, 24_MHz_XTAL); }
static int auth_libwrap(CLI *c) { #ifdef USE_LIBWRAP struct request_info request; int fd[2]; int result=0; /* deny by default */ if(pipe(fd)<0) { ioerror("pipe"); return -1; } if(alloc_fd(fd[0]) || alloc_fd(fd[1])) return -1; switch(fork()) { case -1: /* error */ close(fd[0]); close(fd[1]); ioerror("fork"); return -1; case 0: /* child */ close(fd[0]); /* read side */ request_init(&request, RQ_DAEMON, c->opt->servname, RQ_FILE, c->local_rfd.fd, 0); fromhost(&request); result=hosts_access(&request); write_blocking(c, fd[1], (u8 *)&result, sizeof(result)); /* ignore the returned error */ close(fd[1]); /* write side */ _exit(0); default: /* parent */ close(fd[1]); /* write side */ read_blocking(c, fd[0], (u8 *)&result, sizeof(result)); /* ignore the returned error */ close(fd[0]); /* read side */ /* no need to wait() for zombies here: * - in UCONTEXT/PTHREAD mode they're removed using the signal pipe * - in FORK mode they're removed with the client process */ } if(!result) { s_log(LOG_WARNING, "Connection from %s REFUSED by libwrap", c->accepting_address); s_log(LOG_DEBUG, "See hosts_access(5) manual for details"); return -1; /* FAILED */ } s_log(LOG_DEBUG, "Connection from %s permitted by libwrap", c->accepting_address); #endif return 0; /* OK */ }
static int tcpd_auth(int csock) { int ret; struct request_info request; request_init(&request, RQ_DAEMON, "usbipd", RQ_FILE, csock, 0); fromhost(&request); ret = hosts_access(&request); if (!ret) return -1; return 0; }
static void tcpwrap_client_handle(struct tcpwrap_client *client, int check_fd, const char *daemon_name) { struct request_info request; request_init(&request, RQ_DAEMON, daemon_name, RQ_FILE, check_fd, 0); fromhost(&request); if (!hosts_access(&request)) (void)write_full(client->fd, "0\n", 2); else (void)write_full(client->fd, "1\n", 2); exit(0); }
static int tcpd_auth(server_generic_client_t *cdata, int clnt_sock) { int ret; struct request_info request; request_init(&request, RQ_DAEMON, "prelude-manager", RQ_FILE, clnt_sock, 0); fromhost(&request); ret = hosts_access(&request); if ( ! ret ) { server_generic_log_client(cdata, PRELUDE_LOG_WARN, "tcp wrapper refused connection.\n"); return -1; } return 0; }
/* * send_stats: * Accept a connection to the statistics port, and emit * the stats. */ static void send_stats(void) { FILE *fp; int s; struct sockaddr_in sockstruct; socklen_t socklen; struct request_info ri; int flags; /* Accept a connection to the statistics socket: */ socklen = sizeof sockstruct; s = accept(Status, (struct sockaddr *) &sockstruct, &socklen); if (s < 0) { if (errno == EINTR) return; logx(LOG_ERR, "accept"); return; } /* Check for access permissions: */ request_init(&ri, RQ_DAEMON, "huntd", RQ_FILE, s, 0); fromhost(&ri); if (hosts_access(&ri) == 0) { logx(LOG_INFO, "rejected connection from %s", eval_client(&ri)); close(s); return; } /* Don't allow the writes to block: */ flags = fcntl(s, F_GETFL, 0); flags |= O_NDELAY; (void) fcntl(s, F_SETFL, flags); fp = fdopen(s, "w"); if (fp == NULL) { logit(LOG_ERR, "fdopen"); (void) close(s); return; } print_stats(fp); (void) fclose(fp); }
static int auth_libwrap(CLI *c) { #ifdef USE_LIBWRAP struct request_info request; int result; enter_critical_section(CRIT_NTOA); /* libwrap is not mt-safe */ request_init(&request, RQ_DAEMON, c->opt->servname, RQ_FILE, c->local_rfd.fd, 0); fromhost(&request); result=hosts_access(&request); leave_critical_section(CRIT_NTOA); if (!result) { log(LOG_WARNING, "Connection from %s:%d REFUSED by libwrap", c->accepting_address, ntohs(c->addr.sin_port)); log(LOG_DEBUG, "See hosts_access(5) for details"); return -1; /* FAILED */ } #endif return 0; /* OK */ }
int TcpAcceptConnection(int sock, struct sockaddr_storage *addr, int block) { int new_sock; socklen_t size = sizeof(struct sockaddr_storage); /* Accept incoming connection */ memset(addr, 0, sizeof(*addr)); if ((new_sock = accept(sock, (struct sockaddr *)addr, &size)) < 0) { Perror("%s: accept", __FUNCTION__); return (-1); } #ifdef USE_WRAP if (Enabled(&gGlobalConf.options, GLOBAL_CONF_TCPWRAPPER)) { struct request_info req; request_init(&req, RQ_DAEMON, "mpd", RQ_FILE, new_sock, NULL); fromhost(&req); if (!hosts_access(&req)) { Log(LG_ERR, ("refused connection (tcp-wrapper) from %s", eval_client(&req))); close(new_sock); return (-1); } } #endif if (!block) { (void)fcntl(new_sock, F_SETFD, 1); if (fcntl(new_sock, F_SETFL, O_NONBLOCK) < 0) { Perror("%s: fcntl", __FUNCTION__); return (-1); } } /* Done */ return (new_sock); }
void answer_first() { struct sockaddr sockstruct; int newsock; socklen_t socklen; int flags; struct request_info ri; struct spawn *sp; /* Answer the call to hunt: */ socklen = sizeof sockstruct; newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen); if (newsock < 0) { logit(LOG_ERR, "accept"); return; } /* Check for access permissions: */ request_init(&ri, RQ_DAEMON, "huntd", RQ_FILE, newsock, 0); fromhost(&ri); if (hosts_access(&ri) == 0) { logx(LOG_INFO, "rejected connection from %s", eval_client(&ri)); close(newsock); return; } /* Remember this spawning connection: */ sp = (struct spawn *)malloc(sizeof *sp); if (sp == NULL) { logit(LOG_ERR, "malloc"); close(newsock); return; } memset(sp, '\0', sizeof *sp); /* Keep the calling machine's source addr for ident purposes: */ memcpy(&sp->source, &sockstruct, sizeof sp->source); sp->sourcelen = socklen; /* Warn if we lose connection info: */ if (socklen > sizeof Spawn->source) logx(LOG_WARNING, "struct sockaddr is not big enough! (%d > %zu)", socklen, sizeof Spawn->source); /* * Turn off blocking I/O, so a slow or dead terminal won't stop * the game. All subsequent reads check how many bytes they read. */ flags = fcntl(newsock, F_GETFL, 0); flags |= O_NDELAY; (void) fcntl(newsock, F_SETFL, flags); /* Start listening to the spawning connection */ sp->fd = newsock; FD_SET(sp->fd, &Fds_mask); if (sp->fd >= Num_fds) Num_fds = sp->fd + 1; sp->reading_msg = 0; sp->inlen = 0; /* Add to the spawning list */ if ((sp->next = Spawn) != NULL) Spawn->prevnext = &sp->next; sp->prevnext = &Spawn; Spawn = sp; }
void my_fromhost(struct request_info *req) { fromhost(req); }
int mqtt3_socket_accept(struct _mosquitto_db *db, int listensock) { int i; int j; int new_sock = -1; struct mosquitto **tmp_contexts = NULL; struct mosquitto *new_context; int opt = 1; #ifdef WITH_TLS BIO *bio; int rc; #endif #ifdef WITH_WRAP struct request_info wrap_req; #endif new_sock = accept(listensock, NULL, 0); if(new_sock == INVALID_SOCKET) return -1; #ifndef WIN32 /* Set non-blocking */ opt = fcntl(new_sock, F_GETFL, 0); if(opt == -1 || fcntl(new_sock, F_SETFL, opt | O_NONBLOCK) == -1){ /* If either fcntl fails, don't want to allow this client to connect. */ close(new_sock); return -1; } #else if(ioctlsocket(new_sock, FIONBIO, &opt)){ closesocket(new_sock); return INVALID_SOCKET; } #endif #ifdef WITH_WRAP /* Use tcpd / libwrap to determine whether a connection is allowed. */ request_init(&wrap_req, RQ_FILE, new_sock, RQ_DAEMON, "mosquitto", 0); fromhost(&wrap_req); if(!hosts_access(&wrap_req)){ /* Access is denied */ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client connection denied access by tcpd."); COMPAT_CLOSE(new_sock); return -1; }else{ #endif new_context = mqtt3_context_init(new_sock); if(!new_context){ COMPAT_CLOSE(new_sock); return -1; } for(i=0; i<db->config->listener_count; i++){ for(j=0; j<db->config->listeners[i].sock_count; j++){ if(db->config->listeners[i].socks[j] == listensock){ new_context->listener = &db->config->listeners[i]; break; } } } if(!new_context->listener){ COMPAT_CLOSE(new_sock); return -1; } if(new_context->listener->max_connections > 0 && new_context->listener->client_count >= new_context->listener->max_connections){ COMPAT_CLOSE(new_sock); return -1; } _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New connection from %s.", new_context->address); for(i=0; i<db->context_count; i++){ if(db->contexts[i] == NULL){ db->contexts[i] = new_context; break; } } if(i==db->context_count){ tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(struct mosquitto*)*(db->context_count+1)); if(tmp_contexts){ db->context_count++; db->contexts = tmp_contexts; db->contexts[db->context_count-1] = new_context; }else{ mqtt3_context_cleanup(NULL, new_context, true); } } new_context->listener->client_count++; #ifdef WITH_TLS /* TLS init */ for(i=0; i<db->config->listener_count; i++){ for(j=0; j<db->config->listeners[i].sock_count; j++){ if(db->config->listeners[i].socks[j] == listensock){ if(db->config->listeners[i].ssl_ctx){ new_context->ssl = SSL_new(db->config->listeners[i].ssl_ctx); if(!new_context->ssl){ COMPAT_CLOSE(new_sock); return -1; } SSL_set_ex_data(new_context->ssl, tls_ex_index_context, new_context); SSL_set_ex_data(new_context->ssl, tls_ex_index_listener, &db->config->listeners[i]); new_context->want_read = true; new_context->want_write = true; bio = BIO_new_socket(new_sock, BIO_NOCLOSE); SSL_set_bio(new_context->ssl, bio, bio); rc = SSL_accept(new_context->ssl); if(rc != 1){ rc = SSL_get_error(new_context->ssl, rc); if(rc == SSL_ERROR_WANT_READ){ new_context->want_read = true; }else if(rc == SSL_ERROR_WANT_WRITE){ new_context->want_write = true; } } } } } } #endif #ifdef WITH_WRAP } #endif return new_sock; }
int main(int argc, char *argv[]) { struct request_info request; char path[MAXPATHNAMELEN]; /* Attempt to prevent the creation of world-writable files. */ #ifdef DAEMON_UMASK umask(DAEMON_UMASK); #endif /* * If argv[0] is an absolute path name, ignore REAL_DAEMON_DIR, and strip * argv[0] to its basename. */ if (argv[0][0] == '/') { strlcpy(path, argv[0], sizeof path); argv[0] = strrchr(argv[0], '/') + 1; } else { snprintf(path, sizeof path, "%s/%s", REAL_DAEMON_DIR, argv[0]); } /* * Open a channel to the syslog daemon. Older versions of openlog() * require only two arguments. */ #ifdef LOG_MAIL (void) openlog(argv[0], LOG_PID, FACILITY); #else (void) openlog(argv[0], LOG_PID); #endif /* * Find out the endpoint addresses of this conversation. Host name * lookups and double checks will be done on demand. */ request_init(&request, RQ_DAEMON, argv[0], RQ_FILE, STDIN_FILENO, 0); fromhost(&request); /* * Optionally look up and double check the remote host name. Sites * concerned with security may choose to refuse connections from hosts * that pretend to have someone elses host name. */ #ifdef PARANOID if (STR_EQ(eval_hostname(request.client), paranoid)) refuse(&request); #endif /* * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow * socket options at the IP level. They do so for a good reason. * Unfortunately, we cannot use this with SunOS 4.1.x because the * getsockopt() system call can panic the system. */ #ifdef KILL_IP_OPTIONS fix_options(&request); #endif /* * Check whether this host can access the service in argv[0]. The * access-control code invokes optional shell commands as specified in * the access-control tables. */ #ifdef HOSTS_ACCESS if (!hosts_access(&request)) refuse(&request); #endif /* Report request and invoke the real daemon program. */ syslog(allow_severity, "connect from %s", eval_client(&request)); closelog(); (void) execv(path, argv); syslog(LOG_ERR, "error: cannot execute %s: %m", path); clean_exit(&request); /* NOTREACHED */ }
/* * Handle a UDP packet sent to the well known port. */ static void handle_wkport(int fd) { struct sockaddr fromaddr; socklen_t fromlen; u_int16_t query; u_int16_t response; struct request_info ri; request_init(&ri, RQ_DAEMON, "huntd", RQ_FILE, fd, 0); fromhost(&ri); fromlen = sizeof fromaddr; if (recvfrom(fd, &query, sizeof query, 0, &fromaddr, &fromlen) == -1) { logit(LOG_WARNING, "recvfrom"); return; } #ifdef DEBUG fprintf(stderr, "query %d (%s) from %s:%d\n", query, query == C_MESSAGE ? "C_MESSAGE" : query == C_SCORES ? "C_SCORES" : query == C_PLAYER ? "C_PLAYER" : query == C_MONITOR ? "C_MONITOR" : "?", inet_ntoa(((struct sockaddr_in *)&fromaddr)->sin_addr), ntohs(((struct sockaddr_in *)&fromaddr)->sin_port)); #endif /* Do we allow access? */ if (hosts_access(&ri) == 0) { logx(LOG_INFO, "rejected connection from %s", eval_client(&ri)); return; } query = ntohs(query); switch (query) { case C_MESSAGE: if (Nplayer <= 0) /* Don't bother replying if nobody to talk to: */ return; /* Return the number of people playing: */ response = Nplayer; break; case C_SCORES: /* Someone wants the statistics port: */ response = stat_port; break; case C_PLAYER: case C_MONITOR: /* Someone wants to play or watch: */ if (query == C_MONITOR && Nplayer <= 0) /* Don't bother replying if there's nothing to watch: */ return; /* Otherwise, tell them how to get to the game: */ response = sock_port; break; default: logit(LOG_INFO, "unknown udp query %d", query); return; } response = ntohs(response); if (sendto(fd, &response, sizeof response, 0, &fromaddr, sizeof fromaddr) == -1) logit(LOG_WARNING, "sendto"); }
int quendi_dp_connect(void) { int dsock; int i; char buffer[QUENDI_RESPONSE_LENGTH]; struct sockaddr_in addr; socklen_t addrlen; struct request_info req; fd_set sock_set; struct timeval timeout; dsock = quendi_dp_open(); if (dsock < 1) { quendi_respond(QUENYA_RESPONSE_OPEN_ERROR, NULL); return -1; } addrlen = sizeof(addr); getsockname(dsock, (struct sockaddr*)&addr, &addrlen); snprintf(buffer, QUENDI_RESPONSE_LENGTH - 1, "%i@%s:%i Listening on Port", 1, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); quendi_respond(QUENYA_RESPONSE_LISTENING, buffer); if (listen(dsock, 1)) { syslog(LOG_WARNING, "dp listen: %m"); return 0; } FD_ZERO(&sock_set); FD_SET(dsock, &sock_set); timeout.tv_sec = 60; timeout.tv_usec = 0; i = select(dsock + 1, &sock_set, NULL, NULL, &timeout); if (i == -1) syslog(LOG_WARNING, "dp select: %m"); else if (FD_ISSET(dsock, &sock_set)) { i = accept(dsock, (struct sockaddr*)&addr, &addrlen); if (i == -1) syslog(LOG_WARNING, "dp accept: %m"); } else { close(dsock); return -2; /* timeout */ } if (i == -1) { close(dsock); return -1; /* select or accept error */ } /* tcp wrapper check */ request_init(&req, RQ_DAEMON, quendi_server_data->server_name, RQ_FILE, quendi_server_data->csock, 0); fromhost(&req); if (!hosts_access(&req)) { close(dsock); return -3; /* host access error */ } close(dsock); return i; }
void ssh_channel_ftcp_incoming_connection(SshIpError error, SshStream stream, void *context) { SshRemoteTcpForward fwd = (SshRemoteTcpForward)context; char ip[20], port[20]; SshBuffer buffer; SSH_DEBUG(5, ("connection to forwarded TCP/IP port")); /* We should only receive new connection notifications. */ if (error != SSH_IP_NEW_CONNECTION) ssh_fatal("ssh_channel_ftcp_incoming_connection: error %d", (int)error); /* Get remote ip address and port. */ if (!ssh_tcp_get_remote_address(stream, ip, sizeof(ip))) strcpy(ip, "UNKNOWN"); if (!ssh_tcp_get_remote_port(stream, port, sizeof(port))) strcpy(port, "UNKNOWN"); SSH_TRACE(0, ("Connection to forwarded port %s from %s:%s", fwd->port, ip, port)); ssh_log_event(fwd->common->config->log_facility, SSH_LOG_INFORMATIONAL, "Connection to forwarded port %s from %s:%s", fwd->port, fwd->common->remote_host, port); /* XXXXXXXX */ #ifdef HAVE_LIBWRAP { struct request_info req; struct servent *serv; char fwdportname[32]; void *old_handler; old_handler = signal(SIGCHLD, SIG_DFL); /* try to find port's name in /etc/services */ serv = getservbyport(atoi(fwd->port), "tcp"); if (serv == NULL) { /* not found (or faulty getservbyport) - use the number as a name */ snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%s", fwd->port); } else { snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%.20s", serv->s_name); } /* fill req struct with port name and fd number */ request_init(&req, RQ_DAEMON, fwdportname, RQ_FILE, ssh_stream_fd_get_readfd(stream), NULL); fromhost(&req); if (!hosts_access(&req)) { ssh_conn_send_debug(fwd->common->conn, TRUE, "Fwd connection from %.500s to local port " \ "%s refused by tcp_wrappers.", eval_client(&req), fwdportname); ssh_stream_destroy(stream); signal(SIGCHLD, old_handler); return; } signal(SIGCHLD, old_handler); ssh_log_event(fwd->common->config->log_facility, SSH_LOG_INFORMATIONAL, "Remote fwd connect from %.500s to local port %s", eval_client(&req), fwdportname); } #endif /* HAVE_LIBWRAP */ /* Register that we have an open channel. */ ssh_common_new_channel(fwd->common); /* Send a request to open a channel and connect it to the given port. */ ssh_buffer_init(&buffer); ssh_encode_buffer(&buffer, SSH_FORMAT_UINT32_STR, fwd->address_to_bind, strlen(fwd->address_to_bind), SSH_FORMAT_UINT32, (SshUInt32) atol(fwd->port), SSH_FORMAT_UINT32_STR, ip, strlen(ip), SSH_FORMAT_UINT32, (SshUInt32) atol(port), SSH_FORMAT_END); ssh_conn_send_channel_open(fwd->common->conn, "forwarded-tcpip", stream, TRUE, FALSE, SSH_TCPIP_WINDOW, SSH_TCPIP_PACKET_SIZE, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer), NULL, ssh_channel_tcp_connection_destroy, (void *)fwd->common, NULL, NULL); ssh_buffer_uninit(&buffer); }
int main(int argc, char *argv[]) { int new_fd; struct sockaddr_in server_addr, conn_addr; int sin_size; int c; char isdaemon = 0; /* check parameters */ while (( c = getopt(argc, argv, "Dv")) != -1) switch(c) { case 'D': isdaemon = 1; break; case 'v': showversion(); exit(0); break; case '?': return 1; default: abort(); } if (isdaemon) run_as_daemon(); /* initialize the error logging */ error_init("nettrafd", isdaemon); /* initialize the nettraf library - used to fetch information from the system */ if (!nettraf_init()) error_exit("Cannot initialize nettraf library"); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { error_sys_exit("socket"); } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(NETTRAFD_PORT); server_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { error_sys_exit("bind"); } if (listen(sockfd, 10) == -1) { error_sys_exit("listen"); } signal(SIGINT, (void *)&sighandler); while (1) { sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&conn_addr, &sin_size)) == -1) { error_sys_report("accept"); continue; } #ifdef DEBUG printf("server: got connection from %s\n", inet_ntoa(conn_addr.sin_addr)); #endif #ifdef USE_LIBWRAP request_init(&request, RQ_DAEMON, "nettraf", RQ_FILE, 0, 0); fromhost(&request); if (! hosts_access(&request)) { char text[256]; sprintf(text, "Connection from %s:%d REFUSED by LIBWRAP", inet_ntoa(conn_addr.sin_addr), ntohs(conn_addr.sin_port)); error_report(text); close(new_fd); } else #endif ntd_newconnection(new_fd, conn_addr); } /* should never reach this... */ do_cleanup(); exit(0); }
/* accept the socket and do a little sanity checking */ static int dsi_tcp_open(DSI *dsi) { pid_t pid; SOCKLEN_T len; len = sizeof(dsi->client); dsi->socket = accept(dsi->serversock, (struct sockaddr *) &dsi->client, &len); #ifdef TCPWRAP { struct request_info req; request_init(&req, RQ_DAEMON, dsi->program, RQ_FILE, dsi->socket, NULL); fromhost(&req); if (!hosts_access(&req)) { LOG(deny_severity, logtype_dsi, "refused connect from %s", eval_client(&req)); close(dsi->socket); errno = ECONNREFUSED; dsi->socket = -1; } } #endif /* TCPWRAP */ if (dsi->socket < 0) return -1; getitimer(ITIMER_PROF, &itimer); if (0 == (pid = fork()) ) { /* child */ static struct itimerval timer = {{0, 0}, {DSI_TCPTIMEOUT, 0}}; struct sigaction newact, oldact; u_int8_t block[DSI_BLOCKSIZ]; size_t stored; /* Immediateyl mark globally that we're a child now */ parent_or_child = 1; /* reset signals */ server_reset_signal(); #ifndef DEBUGGING /* install an alarm to deal with non-responsive connections */ newact.sa_handler = timeout_handler; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigemptyset(&oldact.sa_mask); oldact.sa_flags = 0; setitimer(ITIMER_PROF, &itimer, NULL); if ((sigaction(SIGALRM, &newact, &oldact) < 0) || (setitimer(ITIMER_REAL, &timer, NULL) < 0)) { LOG(log_error, logtype_dsi, "dsi_tcp_open: %s", strerror(errno)); exit(EXITERR_SYS); } #endif /* read in commands. this is similar to dsi_receive except * for the fact that we do some sanity checking to prevent * delinquent connections from causing mischief. */ /* read in the first two bytes */ len = dsi_stream_read(dsi, block, 2); if (!len ) { /* connection already closed, don't log it (normal OSX 10.3 behaviour) */ exit(EXITERR_CLNT); } if (len < 2 || (block[0] > DSIFL_MAX) || (block[1] > DSIFUNC_MAX)) { LOG(log_error, logtype_dsi, "dsi_tcp_open: invalid header"); exit(EXITERR_CLNT); } /* read in the rest of the header */ stored = 2; while (stored < DSI_BLOCKSIZ) { len = dsi_stream_read(dsi, block + stored, sizeof(block) - stored); if (len > 0) stored += len; else { LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno)); exit(EXITERR_CLNT); } } dsi->header.dsi_flags = block[0]; dsi->header.dsi_command = block[1]; memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID)); memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code)); memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len)); memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved)); dsi->clientID = ntohs(dsi->header.dsi_requestID); /* make sure we don't over-write our buffers. */ dsi->cmdlen = min(ntohl(dsi->header.dsi_len), DSI_CMDSIZ); stored = 0; while (stored < dsi->cmdlen) { len = dsi_stream_read(dsi, dsi->commands + stored, dsi->cmdlen - stored); if (len > 0) stored += len; else { LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno)); exit(EXITERR_CLNT); } } /* stop timer and restore signal handler */ #ifndef DEBUGGING memset(&timer, 0, sizeof(timer)); setitimer(ITIMER_REAL, &timer, NULL); sigaction(SIGALRM, &oldact, NULL); #endif LOG(log_info, logtype_dsi, "AFP/TCP session from %s:%u", getip_string((struct sockaddr *)&dsi->client), getip_port((struct sockaddr *)&dsi->client)); } /* send back our pid */ return pid; }
int main(int argc, char *argv[]) { socklen_t opt_len; struct sockaddr_in name, newname; socklen_t newnamelen; long bufsize = 0; /* use default */ long bufsizea = 0; /* actual bufsize */ long bufsizea2 = 0; int result; int sock, newsock; pid_t pid; int port = TPORT; int errflg = 0; char host[256]; int client = 0; int maxbuf = 0; int timeout = 0; int daemon = 0; int c; while ((c = getopt(argc, argv, "h?p:b:Bc:t:Dm:")) != -1) { switch (c) { case 'h': case '?': errflg++; break; case 'p': port = atoi(optarg); break; case 'b': if (maxbuf != 0) errflg++; bufsize = atoi(optarg); break; case 'B': if (bufsize != 0) errflg++; maxbuf = 1; break; case 'c': strncpy(host, optarg, 255); host[255] = '\0'; client = 1; break; case 't': timeout = atoi(optarg); break; case 'D': daemon = 1; break; case 'm': child_avail = atoi(optarg); break; default: errflg++; break; } } // For backword compatibility; bufsize given as an arg if (optind == argc - 1) bufsize = atoi(argv[optind]); if (errflg) { usage(argv[0]); exit(2); } /* * Create a socket to test with */ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("Couldn't create a socket"); exit(-1); } /* * Set the buffer size, if specified */ opt_len = sizeof(bufsize); if (bufsize) { if (setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (void *) &bufsize, opt_len)) { perror("Couldn't set receive socket buffer size"); exit(-1); } } else if (maxbuf) { do { bufsizea2 = bufsizea; bufsize += BUF_STEPSIZE; setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&bufsize, opt_len); if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&bufsizea, &opt_len)) { perror("getsockopt"); exit(-1); } } while (bufsizea > bufsizea2); } if (getsockopt (sock, SOL_SOCKET, SO_RCVBUF, (void *) &bufsizea, &opt_len)) { perror("Couldn't get receive socket buffer size"); exit(-1); } printf("Getsockopt() reports %ld byte socket buffers\n", bufsizea); if (client) { /* * We're a client. Do active connect. */ struct hostent *hent; if ((hent = gethostbyname(host)) == NULL) { fprintf(stderr, "gethostbyname error\n"); exit(-1); } memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; memcpy(&name.sin_addr, hent->h_addr_list[0], 4); name.sin_port = htons(port); if (connect(sock, (struct sockaddr *) &name, sizeof(name)) != 0) { perror("connect"); exit(-1); } exit(read_until_close(sock, timeout)); } else { /* * We're a server. Listen, and loop indefinitely * accepting connections. */ struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = child_handler; if (sigaction(SIGCHLD, &sa, NULL)) { fprintf(stderr, "sigaction for SIGCHLD failed\n"); exit(-1); } c = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&c, sizeof (c)) != 0) { perror("setsockopt"); exit(-1); } #ifdef HAVE_SIN_LEN name.sin_len = 16; #endif name.sin_family = AF_INET; name.sin_addr.s_addr = 0; /* allow connection on any * interface */ name.sin_port = htons(port); if (bind(sock, (struct sockaddr *) &name, sizeof(name)) == -1) { perror("Bind failed"); exit(-1); } /* * listen for new connections */ do { result = listen(sock, 5); } while ((result == -1) && (errno == EINTR)); if (result == -1) { perror("Listen failed"); exit(-1); } if (daemon) daemonize(); /* Don't count on stdio from here on, use log() instead */ log(LOG_INFO, "Listening on TCP port: %d\n", port); while (1) { char *peerstr; newnamelen = sizeof(newname); do { newsock = accept(sock, (struct sockaddr *) &newname, &newnamelen); } while ((newsock == -1) && (errno == EINTR)); if (newsock == -1) { log(LOG_ERR, "Accept failed: %s\n", strerror(errno)); /* could be temporary, don't die */ continue; } peerstr = inet_ntoa(newname.sin_addr); // NOTE: Static buf #ifdef LIBWRAP { struct request_info req; request_init(&req, RQ_DAEMON, DAEMON, RQ_FILE, newsock, 0); fromhost(&req); if (!hosts_access(&req)) { log(LOG_INFO, "Connection refused from %s\n", peerstr); close(newsock); continue; } } #endif if (!child_avail) { log(LOG_ERR, "Too many clients, refusing %s\n", peerstr); close(newsock); continue; } pid = fork(); if (!pid) { /* * I am the child process */ int ret; /* don't hold onto the listening socket */ close(sock); log(LOG_INFO, "Connection from %s:%d\n", peerstr, ntohs(newname.sin_port)); ret = read_until_close(newsock, timeout); log(LOG_INFO, "Connection %s\n", (alarmed) ? "timeout" : "closed"); exit(ret); } else if (pid < 0) { log(LOG_ERR, "Fork failed"); /* could be temporary, don't die */ close(newsock); continue; } /* * Otherwise, I am the parent. * Close the accepted socket, down our available count and loop */ close(newsock); child_down(); } } return 0; }
/* wait for incoming connection requests */ void wait_for_connections(void){ struct sockaddr_in6 myname6; struct sockaddr_in6 src_sin; socklen_t socklen = sizeof(src_sin); struct sockaddr *remoteaddr = (struct sockaddr *)&src_sin; int rc; int sock, new_sd; pid_t pid; int flag=1; int max_fd = 0; int i = 0, j = 0; fd_set fdread; struct timeval timeout; int retval; #ifdef HAVE_LIBWRAP struct request_info req; #endif int rval; struct addrinfo addrinfo; struct addrinfo *res, *r; memset(&addrinfo, 0, sizeof(addrinfo)); addrinfo.ai_family=AF_UNSPEC; addrinfo.ai_socktype=SOCK_STREAM; addrinfo.ai_protocol=IPPROTO_TCP; if(!server_address || !strlen(server_address)) { server_address = NULL; addrinfo.ai_flags=AI_PASSIVE; } if (rval = getaddrinfo(server_address, server_port, &addrinfo, &res) != 0) { syslog(LOG_ERR,"Invalid server_address (%d: %s)",errno,strerror(errno)); exit(STATE_CRITICAL); } else { for (r=res; r; r = r->ai_next){ if (r->ai_family != AF_INET && r->ai_family != AF_INET6) continue; if (num_listen_socks >= MAX_LISTEN_SOCKS){ syslog(LOG_ERR,"Too many listen sockets. Enlarge MAX_LISTEN_SOCKS\n"); exit(STATE_UNKNOWN); } sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol); if (sock < 0) /* kernel may not support ipv6 */ continue; /* socket should be non-blocking */ fcntl(sock,F_SETFL,O_NONBLOCK); /* set the reuse address flag so we don't get errors when restarting */ flag=1; if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ syslog(LOG_ERR,"Could not set reuse address option on socket!\n"); exit(STATE_UNKNOWN); } #ifdef IPV6_V6ONLY /* Only communicate in IPv6 over AF_INET6 sockets. */ flag=1; if (r->ai_family == AF_INET6) if(setsockopt(sock,IPPROTO_IPV6,IPV6_V6ONLY,(char *)&flag,sizeof(flag))<0) { syslog(LOG_ERR,"Could not set IPV6_V6ONLY option on socket!\n"); exit(STATE_UNKNOWN); } #endif if(bind(sock, r->ai_addr, r->ai_addrlen) < 0) { syslog(LOG_ERR,"Network server bind failure (%d: %s)\n",errno,strerror(errno)); (void) close(sock); exit(STATE_CRITICAL); } listen_socks[num_listen_socks] = sock; num_listen_socks++; if (listen(sock, 5) < 0){ syslog(LOG_ERR,"Network server listen failure (%d: %s)\n",errno,strerror(errno)); exit(STATE_CRITICAL); } if(sock > max_fd) max_fd = sock; } freeaddrinfo(res); if(num_listen_socks == 0) { exit(STATE_CRITICAL); } } /* log warning about command arguments */ #ifdef ENABLE_COMMAND_ARGUMENTS if(allow_arguments==TRUE) syslog(LOG_NOTICE,"Warning: Daemon is configured to accept command arguments from clients!"); #endif syslog(LOG_INFO,"Listening for connections on port %s\n",server_port); if(allowed_hosts) syslog(LOG_INFO,"Allowing connections from: %s\n",allowed_hosts); /* listen for connection requests - fork() if we get one */ while(1){ /* wait for a connection request */ /* wait until there's something to do */ FD_ZERO(&fdread); for(i=0; i < num_listen_socks; i++) FD_SET(listen_socks[i],&fdread); timeout.tv_sec=0; timeout.tv_usec=500000; retval=select(max_fd+1,&fdread,NULL,NULL,&timeout); /* bail out if necessary */ if(sigrestart==TRUE || sigshutdown==TRUE) break; /* error */ if(retval<0) continue; /* accept a new connection request */ for (i = 0; i < num_listen_socks; i++){ if (!FD_ISSET(listen_socks[i], &fdread)) continue; new_sd=accept(listen_socks[i], remoteaddr, &socklen); /* some kind of error occurred... */ if(new_sd<0){ /* bail out if necessary */ if(sigrestart==TRUE || sigshutdown==TRUE) break; /* retry */ if(errno==EWOULDBLOCK || errno==EINTR) continue; /* socket is nonblocking and we don't have a connection yet */ if(errno==EAGAIN) continue; /* fix for HP-UX 11.0 - just retry */ if(errno==ENOBUFS) continue; } /* bail out if necessary */ if(sigrestart==TRUE || sigshutdown==TRUE) break; /* child process should handle the connection */ pid=fork(); if(pid==0){ /* fork again so we don't create zombies */ pid=fork(); if(pid==0){ /* hey, there was an error... */ if(new_sd<0){ /* log error to syslog facility */ syslog(LOG_ERR,"Network server accept failure (%d: %s)",errno,strerror(errno)); /* close sockets prioer to exiting */ for(j=0; j < num_listen_socks; j++) close(listen_socks[j]); return; } /* handle siOAgnals */ signal(SIGQUIT,child_sighandler); signal(SIGTERM,child_sighandler); signal(SIGHUP,child_sighandler); /* grandchild does not need to listen for connections, so close the sockets */ for(j=0; j < num_listen_socks; j++) close(listen_socks[j]); /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Connection from %s port %d",get_ip_str(remoteaddr, buf, BUFLEN),get_port(remoteaddr)); /* is this is a blessed machine? */ if(allowed_hosts){ if(!is_an_allowed_host(remoteaddr)){ /* log error to syslog facility */ syslog(LOG_ERR,"Host %s is not allowed to talk to us!",get_ip_str(remoteaddr, buf, BUFLEN)); /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Connection from %s closed.",get_ip_str(remoteaddr, buf, BUFLEN)); /* close socket prior to exiting */ close(new_sd); exit(STATE_OK); } else{ /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Host address is in allowed_hosts"); } } #ifdef HAVE_LIBWRAP /* Check whether or not connections are allowed from this host */ request_init(&req,RQ_DAEMON,"nrpe",RQ_FILE,new_sd,0); fromhost(&req); if(!hosts_access(&req)){ syslog(LOG_DEBUG,"Connection refused by TCP wrapper"); /* refuse the connection */ refuse(&req); close(new_sd); /* should not be reached */ syslog(LOG_ERR,"libwrap refuse() returns!"); exit(STATE_CRITICAL); } #endif /* handle the client connection */ handle_connection(new_sd); /* log info to syslog facility */ if(debug==TRUE) syslog(LOG_DEBUG,"Connection from %s closed.",get_ip_str(remoteaddr, buf, BUFLEN)); /* close socket prior to exiting */ close(new_sd); exit(STATE_OK); } /* first child returns immediately, grandchild is inherited by INIT process -> no zombies... */ else exit(STATE_OK); } /* parent ... */ else{ /* parent doesn't need the new connection */ close(new_sd); /* parent waits for first child to exit */ waitpid(pid,NULL,0); } } } /* close the sockets we're listening on */ for(j=0; j < num_listen_socks; j++) close(listen_socks[j]); return; }
void ssh_channel_dtcp_incoming_connection(SshStreamNotification op, SshStream stream, void *context) { SshLocalTcpForward fwd = (SshLocalTcpForward)context; char ip[20], port[20]; /* We should only receive new connection notifications. */ if (op != SSH_IP_NEW_CONNECTION) ssh_fatal("ssh_channel_dtcp_incoming_connection: op %d", (int)op); /* Get remote ip address and port. */ if (!ssh_tcp_get_remote_address(stream, ip, sizeof(ip))) strcpy(ip, "UNKNOWN"); if (!ssh_tcp_get_remote_port(stream, port, sizeof(port))) strcpy(port, "UNKNOWN"); #ifdef HAVE_LIBWRAP { struct request_info req; struct servent *serv; char fwdportname[32]; void *old_handler; old_handler = signal(SIGCHLD, SIG_DFL); /* try to find port's name in /etc/services */ serv = getservbyport(atoi(fwd->port), "tcp"); if (serv == NULL) { /* not found (or faulty getservbyport) - use the number as a name */ snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%s", fwd->port); } else { snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%.20s", serv->s_name); } /* fill req struct with port name and fd number */ request_init(&req, RQ_DAEMON, fwdportname, RQ_FILE, ssh_stream_fd_get_readfd(stream), NULL); fromhost(&req); if (!hosts_access(&req)) { ssh_conn_send_debug(fwd->common->conn, TRUE, "Fwd connection from %.500s to local port %s " "refused by tcp_wrappers.", eval_client(&req), fwdportname); ssh_log_event(fwd->common->config->log_facility, SSH_LOG_WARNING, "Fwd connection from %.500s to local port %s " "refused by tcp_wrappers.", eval_client(&req), fwdportname); ssh_stream_destroy(stream); signal(SIGCHLD, old_handler); return; } signal(SIGCHLD, old_handler); ssh_log_event(fwd->common->config->log_facility, SSH_LOG_INFORMATIONAL, "direct fwd connect from %.500s to local port %s", eval_client(&req), fwdportname); } #endif /* HAVE_LIBWRAP */ /* Send a request to open a channel and connect it to the given port. */ ssh_channel_dtcp_open_to_remote(fwd->common, stream, fwd->connect_to_host, fwd->connect_to_port, ip, port); }
int pptp_manager(int argc, char **argv) { int firstOpen = -1; int ctrl_pid; socklen_t addrsize; int hostSocket; fd_set connSet; int rc, sig_fd; rc = sigpipe_create(); if (rc < 0) { syslog(LOG_ERR, "MGR: unable to setup sigchld pipe!"); syslog_perror("sigpipe_create"); exit(-1); } sigpipe_assign(SIGCHLD); sigpipe_assign(SIGTERM); sig_fd = sigpipe_fd(); /* openlog() not required, done in pptpd.c */ syslog(LOG_INFO, "MGR: Manager process started"); if (!pptp_delegate) { syslog(LOG_INFO, "MGR: Maximum of %d connections available", pptp_connections); } /* Connect the host socket and activate it for listening */ if (createHostSocket(&hostSocket) < 0) { syslog(LOG_ERR, "MGR: Couldn't create host socket"); syslog_perror("createHostSocket"); exit(-1); } while (1) { int max_fd; FD_ZERO(&connSet); if (pptp_delegate) { FD_SET(hostSocket, &connSet); } else { firstOpen = slot_find_empty(); if (firstOpen == -1) { syslog(LOG_ERR, "MGR: No free connection slots or IPs - no more clients can connect!"); } else { FD_SET(hostSocket, &connSet); } } max_fd = hostSocket; FD_SET(sig_fd, &connSet); if (max_fd < sig_fd) max_fd = sig_fd; while (1) { if (select(max_fd + 1, &connSet, NULL, NULL, NULL) != -1) break; if (errno == EINTR) continue; syslog(LOG_ERR, "MGR: Error with manager select()!"); syslog_perror("select"); exit(-1); } if (FD_ISSET(sig_fd, &connSet)) { /* SIGCHLD */ int signum = sigpipe_read(); if (signum == SIGCHLD) sigchld_responder(signum); else if (signum == SIGTERM) { if (!keep_connections) sigterm_responder(); return signum; } } if (FD_ISSET(hostSocket, &connSet)) { /* A call came! */ int clientSocket; struct sockaddr_in client_addr; /* Accept call and launch PPTPCTRL */ addrsize = sizeof(client_addr); clientSocket = accept(hostSocket, (struct sockaddr *) &client_addr, &addrsize); #ifdef HAVE_LIBWRAP if (clientSocket != -1) { struct request_info r; request_init(&r, RQ_DAEMON, "pptpd", RQ_FILE, clientSocket, NULL); fromhost(&r); if (!hosts_access(&r)) { /* send a permission denied message? this is a tcp wrapper * type deny so probably best to just drop it immediately like * this, as tcp wrappers usually do. */ close(clientSocket); /* this would never be file descriptor 0, so use it as a error * value */ clientSocket = 0; } } #endif if (clientSocket == -1) { /* accept failed, but life goes on... */ syslog(LOG_ERR, "MGR: accept() failed"); syslog_perror("accept"); } else if (clientSocket != 0) { fd_set rfds; struct timeval tv; struct pptp_header ph; /* TODO: this select below prevents other connections from being processed during the wait for the first data packet from the client. */ /* * DOS protection: get a peek at the first packet * and do some checks on it before we continue. * A 10 second timeout on the first packet seems reasonable * to me, if anything looks sus, throw it away. */ FD_ZERO(&rfds); FD_SET(clientSocket, &rfds); tv.tv_sec = pptp_stimeout; tv.tv_usec = 0; if (select(clientSocket + 1, &rfds, NULL, NULL, &tv) <= 0) { syslog(LOG_ERR, "MGR: dropped slow initial connection"); close(clientSocket); continue; } if (recv(clientSocket, &ph, sizeof(ph), MSG_PEEK) != sizeof(ph)) { syslog(LOG_ERR, "MGR: dropped small initial connection"); close(clientSocket); continue; } ph.length = ntohs(ph.length); ph.pptp_type = ntohs(ph.pptp_type); ph.magic = ntohl(ph.magic); ph.ctrl_type = ntohs(ph.ctrl_type); if (ph.length <= 0 || ph.length > PPTP_MAX_CTRL_PCKT_SIZE) { syslog(LOG_WARNING, "MGR: initial packet length %d outside " "(0 - %d)", ph.length, PPTP_MAX_CTRL_PCKT_SIZE); goto dos_exit; } if (ph.magic != PPTP_MAGIC_COOKIE) { syslog(LOG_WARNING, "MGR: initial packet bad magic"); goto dos_exit; } if (ph.pptp_type != PPTP_CTRL_MESSAGE) { syslog(LOG_WARNING, "MGR: initial packet has bad type"); goto dos_exit; } if (ph.ctrl_type != START_CTRL_CONN_RQST) { syslog(LOG_WARNING, "MGR: initial packet has bad ctrl type " "0x%x", ph.ctrl_type); dos_exit: close(clientSocket); continue; } #ifndef HAVE_FORK switch (ctrl_pid = vfork()) { #else switch (ctrl_pid = fork()) { #endif case -1: /* error */ syslog(LOG_ERR, "MGR: fork() failed launching " PPTP_CTRL_BIN); close(clientSocket); break; case 0: /* child */ close(hostSocket); if (pptp_debug) syslog(LOG_DEBUG, "MGR: Launching " PPTP_CTRL_BIN " to handle client"); connectCall(clientSocket, !pptp_delegate ? firstOpen : 0); _exit(1); /* NORETURN */ default: /* parent */ close(clientSocket); unique_call_id += MAX_CALLS_PER_TCP_LINK; if (!pptp_delegate) slot_set_pid(firstOpen, ctrl_pid); break; } } } /* FD_ISSET(hostSocket, &connSet) */ } /* while (1) */ } /* pptp_manager() */ /* * Author: Kevin Thayer * * This creates a socket to listen on, sets the max # of pending connections and * various other options. * * Returns the fd of the host socket. * * The function return values are: * 0 for sucessful * -1 for bad socket creation * -2 for bad socket options * -3 for bad bind * -4 for bad listen */ static int createHostSocket(int *hostSocket) { int opt = 1; struct sockaddr_in address; #ifdef HAVE_GETSERVBYNAME struct servent *serv; #endif /* create the master socket and check it worked */ if ((*hostSocket = vrf_socket(vrf, AF_INET, SOCK_STREAM, 0)) <= 0) return -1; /* set master socket to allow daemon to be restarted with connections active */ if (setsockopt(*hostSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)) < 0) return -2; /* set up socket */ memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; if(bindaddr) address.sin_addr.s_addr = inet_addr(bindaddr); else address.sin_addr.s_addr = INADDR_ANY; #ifdef HAVE_GETSERVBYNAME if ((serv = getservbyname("pptp", "tcp")) != NULL) { address.sin_port = serv->s_port; } else #endif address.sin_port = htons(PPTP_PORT); /* bind the socket to the pptp port */ if (bind(*hostSocket, (struct sockaddr *) &address, sizeof(address)) < 0) return -3; /* minimal backlog to avoid DoS */ if (listen(*hostSocket, 3) < 0) return -4; return 0; }
MODRET wrap_handle_request(cmd_rec *cmd) { /* these variables are names expected to be set by the TCP wrapper code */ struct request_info request; char *user = NULL; config_rec *conf = NULL, *access_conf = NULL, *syslog_conf = NULL; hosts_allow_table = NULL; hosts_deny_table = NULL; /* hide passwords */ session.hide_password = TRUE; /* Sneaky...found in mod_auth.c's cmd_pass() function. Need to find the * login UID in order to resolve the possibly-login-dependent filename. */ user = (char *) get_param_ptr(cmd->server->conf, C_USER, FALSE); /* It's possible that a PASS command came before USER. This is a PRE_CMD * handler, so it won't be protected from this case; we'll need to do * it manually. */ if (!user) return DECLINED(cmd); /* Use mod_auth's _auth_resolve_user() [imported for use here] to get the * right configuration set, since the user may be logging in anonymously, * and the session struct hasn't yet been set for that yet (thus short- * circuiting the easiest way to get the right context...the macros. */ conf = wrap_resolve_user(cmd->pool, &user); /* Search first for user-specific access files. Multiple TCPUserAccessFiles * directives are allowed. */ if ((access_conf = find_config(conf ? conf->subset : CURRENT_CONF, CONF_PARAM, "TCPUserAccessFiles", FALSE)) != NULL) { int matched = FALSE; array_header *user_array = NULL; while (access_conf) { user_array = make_array(cmd->tmp_pool, 0, sizeof(char *)); *((char **) push_array(user_array)) = pstrdup(cmd->tmp_pool, user); /* Check the user expression -- don't forget the offset, to skip * the access file name strings in argv */ if (wrap_eval_expression(((char **) access_conf->argv) + 2, user_array)) { pr_log_debug(DEBUG4, MOD_WRAP_VERSION ": matched TCPUserAccessFiles expression"); matched = TRUE; break; } access_conf = find_config_next(access_conf, access_conf->next, CONF_PARAM, "TCPUserAccessFiles", FALSE); } if (!matched) access_conf = NULL; } /* Next, search for group-specific access files. Multiple * TCPGroupAccessFiles directives are allowed. */ if (!access_conf && (access_conf = find_config(conf ? conf->subset : CURRENT_CONF, CONF_PARAM, "TCPGroupAccessFiles", FALSE)) != NULL) { unsigned char matched = FALSE; /* NOTE: this gid_array is only necessary until Bug#1461 is fixed */ array_header *gid_array = make_array(cmd->pool, 0, sizeof(gid_t)); array_header *group_array = make_array(cmd->pool, 0, sizeof(char *)); while (access_conf) { if (pr_auth_getgroups(cmd->pool, user, &gid_array, &group_array) < 1) { pr_log_debug(DEBUG3, MOD_WRAP_VERSION ": no supplemental groups found for user '%s'", user); } else { /* Check the group expression -- don't forget the offset, to skip * the access file names strings in argv */ if (wrap_eval_expression(((char **) access_conf->argv) + 2, group_array)) { pr_log_debug(DEBUG4, MOD_WRAP_VERSION ": matched TCPGroupAccessFiles expression"); matched = TRUE; break; } } access_conf = find_config_next(access_conf, access_conf->next, CONF_PARAM, "TCPGroupAccessFiles", FALSE); } if (!matched) access_conf = NULL; } /* Finally for globally-applicable access files. Only one such directive * is allowed. */ if (!access_conf) { access_conf = find_config(conf ? conf->subset : CURRENT_CONF, CONF_PARAM, "TCPAccessFiles", FALSE); } if (access_conf) { hosts_allow_table = (char *) access_conf->argv[0]; hosts_deny_table = (char *) access_conf->argv[1]; } /* Now, check the retrieved filename, and see if it requires a login-time * file. */ if (hosts_allow_table != NULL && hosts_allow_table[0] == '~' && hosts_allow_table[1] == '/') { char *allow_real_table = NULL; allow_real_table = wrap_get_user_table(cmd, user, hosts_allow_table); if (!wrap_is_usable_file(allow_real_table)) { pr_log_pri(PR_LOG_WARNING, MOD_WRAP_VERSION ": configured TCPAllowFile %s is unusable", hosts_allow_table); hosts_allow_table = NULL; } else hosts_allow_table = allow_real_table; } if (hosts_deny_table != NULL && hosts_deny_table[0] == '~' && hosts_deny_table[1] == '/') { char *deny_real_table = NULL; deny_real_table = dir_realpath(cmd->pool, hosts_deny_table); if (!wrap_is_usable_file(deny_real_table)) { pr_log_pri(PR_LOG_WARNING, MOD_WRAP_VERSION ": configured TCPDenyFile %s is unusable", hosts_deny_table); hosts_deny_table = NULL; } else hosts_deny_table = deny_real_table; } /* Make sure that _both_ allow and deny TCPAccessFiles are present. * If not, log the missing file, and by default allow request to succeed. */ if (hosts_allow_table != NULL && hosts_deny_table != NULL) { /* Most common case...nothing more necessary */ } else if (hosts_allow_table == NULL && hosts_deny_table != NULL) { /* Log the missing file */ pr_log_pri(PR_LOG_INFO, MOD_WRAP_VERSION ": no usable allow access file -- " "allowing connection"); return DECLINED(cmd); } else if (hosts_allow_table != NULL && hosts_deny_table == NULL) { /* log the missing file */ pr_log_pri(PR_LOG_INFO, MOD_WRAP_VERSION ": no usable deny access file -- " "allowing connection"); return DECLINED(cmd); } else { /* Neither set -- assume the admin hasn't configured these directives * at all. */ return DECLINED(cmd); } /* Log the names of the allow/deny files being used. */ pr_log_pri(PR_LOG_DEBUG, MOD_WRAP_VERSION ": using access files: %s, %s", hosts_allow_table, hosts_deny_table); /* retrieve the user-defined syslog priorities, if any. Fall back to the * defaults as seen in tcpd.h if not defined. */ syslog_conf = find_config(main_server->conf, CONF_PARAM, "TCPAccessSyslogLevels", FALSE); if (syslog_conf) { allow_severity = (int) syslog_conf->argv[1]; deny_severity = (int) syslog_conf->argv[2]; } else { allow_severity = PR_LOG_INFO; deny_severity = PR_LOG_WARNING; } pr_log_debug(DEBUG4, MOD_WRAP_VERSION ": checking under service name '%s'", wrap_service_name); request_init(&request, RQ_DAEMON, wrap_service_name, RQ_FILE, session.c->rfd, 0); fromhost(&request); if (STR_EQ(eval_hostname(request.client), paranoid) || !hosts_access(&request)) { char *denymsg = NULL; /* log the denied connection */ wrap_log_request_denied(deny_severity, &request); /* check for AccessDenyMsg */ if ((denymsg = (char *) get_param_ptr(TOPLEVEL_CONF, "AccessDenyMsg", FALSE)) != NULL) denymsg = sreplace(cmd->tmp_pool, denymsg, "%u", user, NULL); if (denymsg) return ERROR_MSG(cmd, R_530, denymsg); else return ERROR_MSG(cmd, R_530, "Access denied."); } /* If request is allowable, return DECLINED (for engine to act as if this * handler was never called, else ERROR (for engine to abort processing and * deny request. */ wrap_log_request_allowed(allow_severity, &request); return DECLINED(cmd); }
void client_new(struct player_control *player_control, int fd, const struct sockaddr *sa, size_t sa_length, int uid) { static unsigned int next_client_num; struct client *client; char *remote; assert(player_control != NULL); assert(fd >= 0); #ifdef HAVE_LIBWRAP if (sa->sa_family != AF_UNIX) { char *hostaddr = sockaddr_to_string(sa, sa_length, NULL); const char *progname = g_get_prgname(); struct request_info req; request_init(&req, RQ_FILE, fd, RQ_DAEMON, progname, 0); fromhost(&req); if (!hosts_access(&req)) { /* tcp wrappers says no */ g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE, "libwrap refused connection (libwrap=%s) from %s", progname, hostaddr); g_free(hostaddr); close_socket(fd); return; } g_free(hostaddr); } #endif /* HAVE_WRAP */ if (client_list_is_full()) { g_warning("Max Connections Reached!"); close_socket(fd); return; } client = g_new0(struct client, 1); client->player_control = player_control; client->channel = g_io_channel_new_socket(fd); /* GLib is responsible for closing the file descriptor */ g_io_channel_set_close_on_unref(client->channel, true); /* NULL encoding means the stream is binary safe; the MPD protocol is UTF-8 only, but we are doing this call anyway to prevent GLib from messing around with the stream */ g_io_channel_set_encoding(client->channel, NULL, NULL); /* we prefer to do buffering */ g_io_channel_set_buffered(client->channel, false); client->source_id = g_io_add_watch(client->channel, G_IO_IN|G_IO_ERR|G_IO_HUP, client_in_event, client); client->input = fifo_buffer_new(4096); client->permission = getDefaultPermissions(); client->uid = uid; client->last_activity = g_timer_new(); client->cmd_list = NULL; client->cmd_list_OK = -1; client->cmd_list_size = 0; client->deferred_send = g_queue_new(); client->deferred_bytes = 0; client->num = next_client_num++; client->send_buf_used = 0; client->subscriptions = NULL; client->messages = NULL; client->num_messages = 0; (void)send(fd, GREETING, sizeof(GREETING) - 1, 0); client_list_add(client); remote = sockaddr_to_string(sa, sa_length, NULL); g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE, "[%u] opened from %s", client->num, remote); g_free(remote); }