/* return true if access should be allowed to a service*/ BOOL check_access(int snum) { char *denyl,*allowl; BOOL ret = False; denyl = lp_hostsdeny(snum); if (denyl) denyl = strdup(denyl); allowl = lp_hostsallow(snum); if (allowl) allowl = strdup(allowl); if ((!denyl || *denyl==0) && (!allowl || *allowl==0)) ret = True; if (!ret) { if (allow_access(denyl,allowl,client_name(),client_addr())) { if (snum >= 0) DEBUG(2,("Allowed connection from %s (%s) to %s\n", client_name(),client_addr(), lp_servicename(snum))); ret = True; } else if (snum >= 0) DEBUG(0,("%s Denied connection from %s (%s) to %s\n", timestring(), client_name(),client_addr(), lp_servicename(snum))); } if (denyl) free(denyl); if (allowl) free(allowl); return(ret); }
/* return true if access should be allowed to a service for a socket */ BOOL check_access(int sock, char *allow_list, char *deny_list) { BOOL ret = False; BOOL only_ip = False; char *deny = NULL; char *allow = NULL; DEBUG(10,("check_access: allow = %s, deny = %s\n", allow_list ? allow_list : "NULL", deny_list ? deny_list : "NULL")); if (deny_list) deny = strdup(deny_list); if (allow_list) allow = strdup(allow_list); if ((!deny || *deny==0) && (!allow || *allow==0)) ret = True; if (!ret) { /* bypass gethostbyaddr() calls if the lists only contain IP addrs */ if (only_ipaddrs_in_list(allow) && only_ipaddrs_in_list(deny)) { only_ip = True; DEBUG (3, ("check_access: no hostnames in host allow/deny list.\n")); ret = allow_access(deny,allow, "", get_socket_addr(sock)); } else { DEBUG (3, ("check_access: hostnames in host allow/deny list.\n")); ret = allow_access(deny,allow, get_socket_name(sock), get_socket_addr(sock)); } if (ret) { DEBUG(2,("Allowed connection from %s (%s)\n", only_ip ? "" : get_socket_name(sock), get_socket_addr(sock))); } else { DEBUG(0,("Denied connection from %s (%s)\n", only_ip ? "" : get_socket_name(sock), get_socket_addr(sock))); } } SAFE_FREE(deny); SAFE_FREE(allow); return(ret); }
/* return true if access should be allowed to a service for a socket */ bool check_access(int sock, const char **allow_list, const char **deny_list) { bool ret = false; bool only_ip = false; if ((!deny_list || *deny_list==0) && (!allow_list || *allow_list==0)) ret = true; if (!ret) { char addr[INET6_ADDRSTRLEN]; /* Bypass name resolution calls if the lists * only contain IP addrs */ if (only_ipaddrs_in_list(allow_list) && only_ipaddrs_in_list(deny_list)) { only_ip = true; DEBUG (3, ("check_access: no hostnames " "in host allow/deny list.\n")); ret = allow_access(deny_list, allow_list, "", get_peer_addr(sock,addr,sizeof(addr))); } else { DEBUG (3, ("check_access: hostnames in " "host allow/deny list.\n")); ret = allow_access(deny_list, allow_list, get_peer_name(sock,true), get_peer_addr(sock,addr,sizeof(addr))); } if (ret) { DEBUG(2,("Allowed connection from %s (%s)\n", only_ip ? "" : get_peer_name(sock,true), get_peer_addr(sock,addr,sizeof(addr)))); } else { DEBUG(0,("Denied connection from %s (%s)\n", only_ip ? "" : get_peer_name(sock,true), get_peer_addr(sock,addr,sizeof(addr)))); } } return(ret); }
static BOOL get_md4pw(char *md4pw, char *mach_acct) { SAM_ACCOUNT *sampass = NULL; const uint8 *pass; BOOL ret; uint32 acct_ctrl; #if 0 /* * Currently this code is redundent as we already have a filter * by hostname list. What this code really needs to do is to * get a hosts allowed/hosts denied list from the SAM database * on a per user basis, and make the access decision there. * I will leave this code here for now as a reminder to implement * this at a later date. JRA. */ if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(), client_name(), client_addr())) { DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct)); return False; } #endif /* 0 */ if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass))) return False; /* JRA. This is ok as it is only used for generating the challenge. */ become_root(); ret=pdb_getsampwnam(sampass, mach_acct); unbecome_root(); if (ret==False) { DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct)); pdb_free_sam(&sampass); return False; } acct_ctrl = pdb_get_acct_ctrl(sampass); if (!(acct_ctrl & ACB_DISABLED) && ((acct_ctrl & ACB_DOMTRUST) || (acct_ctrl & ACB_WSTRUST) || (acct_ctrl & ACB_SVRTRUST)) && ((pass=pdb_get_nt_passwd(sampass)) != NULL)) { memcpy(md4pw, pass, 16); dump_data(5, md4pw, 16); pdb_free_sam(&sampass); return True; } DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct)); pdb_free_sam(&sampass); return False; }
static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address, const char *rhost, int snum, fstring dev) { char *raddr; raddr = tsocket_address_inet_addr_string(remote_address, talloc_tos()); if (raddr == NULL) { return NT_STATUS_NO_MEMORY; } if (!lp_snum_ok(snum) || !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum), rhost, raddr)) { return NT_STATUS_ACCESS_DENIED; } if (dev[0] == '?' || !dev[0]) { if (lp_printable(snum)) { fstrcpy(dev,"LPT1:"); } else if (strequal(lp_fstype(snum), "IPC")) { fstrcpy(dev, "IPC"); } else { fstrcpy(dev,"A:"); } } if (!strupper_m(dev)) { DEBUG(2,("strupper_m %s failed\n", dev)); return NT_STATUS_INVALID_PARAMETER; } if (lp_printable(snum)) { if (!strequal(dev, "LPT1:")) { return NT_STATUS_BAD_DEVICE_TYPE; } } else if (strequal(lp_fstype(snum), "IPC")) { if (!strequal(dev, "IPC")) { return NT_STATUS_BAD_DEVICE_TYPE; } } else if (!strequal(dev, "A:")) { return NT_STATUS_BAD_DEVICE_TYPE; } /* Behave as a printer if we are supposed to */ if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) { fstrcpy(dev, "LPT1:"); } return NT_STATUS_OK; }
/* * Simple forking HTTP proxy. It is an HTTP/1.0 proxy with knowledge of * HTTP/1.1. (The things lacking for HTTP/1.1 are the chunked transfer encoding * and the expect mechanism.) The proxy supports the CONNECT, GET, HEAD, and * POST methods. It supports Basic and Digest authentication of clients (use the * --proxy-auth option). * * HTTP/1.1 is defined in RFC 2616. Many comments refer to that document. * http://tools.ietf.org/html/rfc2616 * * HTTP authentication is discussed in RFC 2617. * http://tools.ietf.org/html/rfc2617 * * The CONNECT method is documented in an Internet draft and is specified as the * way to proxy HTTPS in RFC 2817, section 5. * http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 * http://tools.ietf.org/html/rfc2817#section-5 * * The CONNECT method is not limited to HTTP, but is potentially capable of * connecting to any TCP port on any host. The proxy connection is requested * with an HTTP request, but after that, the proxy does no interpretation of the * data passing through it. See section 6 of the above mentioned draft for the * security implications. */ int ncat_http_server(void) { int c, s; socklen_t sslen; union sockaddr_u conn; #ifndef WIN32 Signal(SIGCHLD, proxyreaper); #endif #if HAVE_HTTP_DIGEST http_digest_init_secret(); #endif #ifdef HAVE_OPENSSL if (o.ssl) setup_ssl_listen(); #endif s = do_listen(SOCK_STREAM, IPPROTO_TCP); for (;;) { sslen = sizeof(conn.storage); c = accept(s, &conn.sockaddr, &sslen); if (c == -1) { if (errno == EINTR) continue; die("accept"); } if (!allow_access(&conn)) { Close(c); continue; } fork_handler(s, c); } return 0; }
/* This is sufficiently different from the TCP code (wrt SSL, etc) that it * resides in its own simpler function */ static int ncat_listen_dgram(int proto) { struct { int fd; union sockaddr_u addr; } sockfd[NUM_LISTEN_ADDRS]; int i, fdn = -1; int fdmax, nbytes, n, fds_ready; char buf[DEFAULT_UDP_BUF_LEN] = { 0 }; char *tempbuf = NULL; fd_set read_fds; union sockaddr_u remotess; socklen_t sslen = sizeof(remotess.storage); struct timeval tv; struct timeval *tvp = NULL; unsigned int num_sockets; for (i = 0; i < NUM_LISTEN_ADDRS; i++) { sockfd[i].fd = -1; sockfd[i].addr.storage.ss_family = AF_UNSPEC; } FD_ZERO(&read_fds); /* Initialize remotess struct so recvfrom() doesn't hit the fan.. */ zmem(&remotess.storage, sizeof(remotess.storage)); remotess.storage.ss_family = o.af; #ifdef WIN32 set_pseudo_sigchld_handler(decrease_conn_count); #else /* Reap on SIGCHLD */ Signal(SIGCHLD, sigchld_handler); /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we send data to it before noticing. */ Signal(SIGPIPE, SIG_IGN); #endif /* Not sure if this problem exists on Windows, but fcntl and /dev/null don't */ #ifndef WIN32 /* Check whether stdin is closed. Because we treat this fd specially, we * can't risk it being reopened for an incoming connection, so we'll hold * it open instead. */ if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF) { logdebug("stdin is closed, attempting to reserve STDIN_FILENO\n"); i = open("/dev/null", O_RDONLY); if (i >= 0 && i != STDIN_FILENO) { /* Oh well, we tried */ logdebug("Couldn't reserve STDIN_FILENO\n"); close(i); } } #endif /* set for selecting udp listening sockets */ fd_set listen_fds; fd_list_t listen_fdlist; FD_ZERO(&listen_fds); init_fdlist(&listen_fdlist, num_listenaddrs); num_sockets = 0; for (i = 0; i < num_listenaddrs; i++) { /* create the UDP listen sockets */ sockfd[num_sockets].fd = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]); if (sockfd[num_sockets].fd == -1) { if (o.debug > 0) logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno())); continue; } FD_SET(sockfd[num_sockets].fd, &listen_fds); add_fd(&listen_fdlist, sockfd[num_sockets].fd); sockfd[num_sockets].addr = listenaddrs[i]; num_sockets++; } if (num_sockets == 0) { if (num_listenaddrs == 1) bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno())); else bye("Unable to open any listening sockets."); } if (o.idletimeout > 0) tvp = &tv; while (1) { int i, j, conn_count, socket_n; if (fdn != -1) { /*remove socket descriptor which is burnt */ FD_CLR(sockfd[fdn].fd, &listen_fds); rm_fd(&listen_fdlist, sockfd[fdn].fd); /* Rebuild the udp socket which got burnt */ sockfd[fdn].fd = do_listen(SOCK_DGRAM, proto, &sockfd[fdn].addr); if (sockfd[fdn].fd == -1) bye("do_listen: %s", socket_strerror(socket_errno())); FD_SET(sockfd[fdn].fd, &listen_fds); add_fd(&listen_fdlist, sockfd[fdn].fd); } fdn = -1; socket_n = -1; fd_set fds; FD_ZERO(&fds); while (1) { /* * We just select to get a list of sockets which we can talk to */ if (o.debug > 1) logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax); fds = listen_fds; if (o.idletimeout > 0) ms_to_timeval(tvp, o.idletimeout); fds_ready = fselect(listen_fdlist.fdmax + 1, &fds, NULL, NULL, tvp); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); if (fds_ready == 0) bye("Idle timeout expired (%d ms).", o.idletimeout); /* * Figure out which listening socket got a connection. This loop should * really call a function for each ready socket instead of breaking on * the first one. */ for (i = 0; i <= listen_fdlist.fdmax && fds_ready > 0; i++) { /* Loop through descriptors until there is something ready */ if (!FD_ISSET(i, &fds)) continue; /* Check each listening socket */ for (j = 0; j < num_sockets; j++) { if (i == sockfd[j].fd) { if (o.debug > 1) logdebug("Valid descriptor %d \n", i); fdn = j; socket_n = i; break; } } /* if we found a valid socket break */ if (fdn != -1) { fds_ready--; break; } } /* Make sure someone connected */ if (fdn == -1) continue; /* * We just peek so we can get the client connection details without * removing anything from the queue. Sigh. */ nbytes = recvfrom(socket_n, buf, sizeof(buf), MSG_PEEK, &remotess.sockaddr, &sslen); if (nbytes < 0) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } /* Check conditions that might cause us to deny the connection. */ conn_count = get_conn_count(); if (conn_count >= o.conn_limit) { if (o.verbose) loguser("New connection denied: connection limit reached (%d)\n", conn_count); } else if (!allow_access(&remotess)) { if (o.verbose) loguser("New connection denied: not allowed\n"); } else { /* Good to go. */ break; } /* Dump the current datagram */ nbytes = recv(socket_n, buf, sizeof(buf), 0); if (nbytes < 0) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } ncat_log_recv(buf, nbytes); } if (o.debug > 1) logdebug("Valid Connection from %d\n", socket_n); conn_inc++; /* * We're using connected udp. This has the down side of only * being able to handle one udp client at a time */ Connect(socket_n, &remotess.sockaddr, sslen); /* clean slate for buf */ zmem(buf, sizeof(buf)); /* are we executing a command? then do it */ if (o.cmdexec) { struct fdinfo info = { 0 }; info.fd = socket_n; if (o.keepopen) netrun(&info, o.cmdexec); else netexec(&info, o.cmdexec); continue; } FD_SET(socket_n, &read_fds); FD_SET(STDIN_FILENO, &read_fds); fdmax = socket_n; /* stdin -> socket and socket -> stdout */ while (1) { fd_set fds; fds = read_fds; if (o.debug > 1) logdebug("udp select'ing\n"); if (o.idletimeout > 0) ms_to_timeval(tvp, o.idletimeout); fds_ready = fselect(fdmax + 1, &fds, NULL, NULL, tvp); if (fds_ready == 0) bye("Idle timeout expired (%d ms).", o.idletimeout); if (FD_ISSET(STDIN_FILENO, &fds)) { nbytes = Read(STDIN_FILENO, buf, sizeof(buf)); if (nbytes <= 0) { if (nbytes < 0 && o.verbose) { logdebug("Error reading from stdin: %s\n", strerror(errno)); } else if (nbytes == 0 && o.debug) { logdebug("EOF on stdin\n"); } FD_CLR(STDIN_FILENO, &read_fds); if (nbytes < 0) return 1; continue; } if (o.crlf) fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state); if (!o.recvonly) { if (tempbuf != NULL) n = send(socket_n, tempbuf, nbytes, 0); else n = send(socket_n, buf, nbytes, 0); if (n < nbytes) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } ncat_log_send(buf, nbytes); } if (tempbuf != NULL) { free(tempbuf); tempbuf = NULL; } } if (FD_ISSET(socket_n, &fds)) { nbytes = recv(socket_n, buf, sizeof(buf), 0); if (nbytes < 0) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } ncat_log_recv(buf, nbytes); if (!o.sendonly) Write(STDOUT_FILENO, buf, nbytes); } zmem(buf, sizeof(buf)); } } return 0; }
/* Accept a connection on a listening socket. Allow or deny the connection. Fork a command if o.cmdexec is set. Otherwise, add the new socket to the watch set. */ static void handle_connection(int socket_accept) { union sockaddr_u remoteaddr; socklen_t ss_len; struct fdinfo s = { 0 }; int conn_count; zmem(&s, sizeof(s)); zmem(&remoteaddr, sizeof(remoteaddr.storage)); ss_len = sizeof(remoteaddr.storage); errno = 0; s.fd = accept(socket_accept, &remoteaddr.sockaddr, &ss_len); if (s.fd < 0) { if (o.debug) logdebug("Error in accept: %s\n", strerror(errno)); close(s.fd); return; } if (o.verbose) { #if HAVE_SYS_UN_H if (remoteaddr.sockaddr.sa_family == AF_UNIX) loguser("Connection from a client on Unix domain socket.\n"); else #endif if (o.chat) loguser("Connection from %s on file descriptor %d.\n", inet_socktop(&remoteaddr), s.fd); else loguser("Connection from %s.\n", inet_socktop(&remoteaddr)); } if (!o.keepopen && !o.broker) { int i; for (i = 0; i < num_listenaddrs; i++) { Close(listen_socket[i]); FD_CLR(listen_socket[i], &master_readfds); rm_fd(&client_fdlist, listen_socket[i]); } } if (o.verbose) { #if HAVE_SYS_UN_H if (remoteaddr.sockaddr.sa_family == AF_UNIX) loguser("Connection from %s.\n", remoteaddr.un.sun_path); else #endif loguser("Connection from %s:%hu.\n", inet_socktop(&remoteaddr), inet_port(&remoteaddr)); } /* Check conditions that might cause us to deny the connection. */ conn_count = get_conn_count(); if (conn_count >= o.conn_limit) { if (o.verbose) loguser("New connection denied: connection limit reached (%d)\n", conn_count); Close(s.fd); return; } if (!allow_access(&remoteaddr)) { if (o.verbose) loguser("New connection denied: not allowed\n"); Close(s.fd); return; } s.remoteaddr = remoteaddr; conn_inc++; unblock_socket(s.fd); #ifdef HAVE_OPENSSL if (o.ssl) { /* Add the socket to the necessary descriptor lists. */ FD_SET(s.fd, &sslpending_fds); FD_SET(s.fd, &master_readfds); FD_SET(s.fd, &master_writefds); /* Add it to our list of fds too for maintaining maxfd. */ if (add_fdinfo(&client_fdlist, &s) < 0) bye("add_fdinfo() failed."); } else #endif post_handle_connection(s); }
/* * Simple forking HTTP proxy. It is an HTTP/1.0 proxy with knowledge of * HTTP/1.1. (The things lacking for HTTP/1.1 are the chunked transfer encoding * and the expect mechanism.) The proxy supports the CONNECT, GET, HEAD, and * POST methods. It supports Basic and Digest authentication of clients (use the * --proxy-auth option). * * HTTP/1.1 is defined in RFC 2616. Many comments refer to that document. * http://tools.ietf.org/html/rfc2616 * * HTTP authentication is discussed in RFC 2617. * http://tools.ietf.org/html/rfc2617 * * The CONNECT method is documented in an Internet draft and is specified as the * way to proxy HTTPS in RFC 2817, section 5. * http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 * http://tools.ietf.org/html/rfc2817#section-5 * * The CONNECT method is not limited to HTTP, but is potentially capable of * connecting to any TCP port on any host. The proxy connection is requested * with an HTTP request, but after that, the proxy does no interpretation of the * data passing through it. See section 6 of the above mentioned draft for the * security implications. */ int ncat_http_server(void) { int c, i, j; int listen_socket[NUM_LISTEN_ADDRS]; socklen_t sslen; union sockaddr_u conn; struct timeval tv; struct timeval *tvp = NULL; #ifndef WIN32 Signal(SIGCHLD, proxyreaper); #endif #if HAVE_HTTP_DIGEST http_digest_init_secret(); #endif #ifdef HAVE_OPENSSL if (o.ssl) setup_ssl_listen(); #endif /* Clear the socket list */ for (i = 0; i < NUM_LISTEN_ADDRS; i++) listen_socket[i] = -1; /* set for selecting listening sockets */ fd_set listen_fds; fd_list_t listen_fdlist; FD_ZERO(&listen_fds); init_fdlist(&listen_fdlist, num_listenaddrs); /* Listen on each address, set up lists for select */ for (i = 0; i < num_listenaddrs; i++) { listen_socket[i] = do_listen(SOCK_STREAM, IPPROTO_TCP, &listenaddrs[i]); /* make us not block on accepts in wierd cases. See ncat_listen.c:209 */ unblock_socket(listen_socket[i]); /* setup select sets and max fd */ FD_SET(listen_socket[i], &listen_fds); add_fd(&listen_fdlist, listen_socket[i]); } if (o.idletimeout > 0) tvp = &tv; for (;;) { fd_set read_fds; sslen = sizeof(conn.storage); /* * We just select to get a list of sockets which we can talk to */ if (o.debug > 1) logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax); read_fds = listen_fds; if (o.idletimeout > 0) ms_to_timeval(tvp, o.idletimeout); int fds_ready = fselect(listen_fdlist.fdmax + 1, &read_fds, NULL, NULL, tvp); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); if (fds_ready == 0) bye("Idle timeout expired (%d ms).", o.idletimeout); for (i = 0; i <= listen_fdlist.fdmax && fds_ready > 0; i++) { /* Loop through descriptors until there is something ready */ if (!FD_ISSET(i, &read_fds)) continue; /* Check each listening socket */ for (j = 0; j < num_listenaddrs; j++) { if (i == listen_socket[j]) { fds_ready--; c = accept(i, &conn.sockaddr, &sslen); if (c == -1) { if (errno == EINTR) continue; die("accept"); } if (!allow_access(&conn)) { Close(c); continue; } if (o.debug > 1) logdebug("forking handler for %d\n", i); fork_handler(i, c); } } } } return 0; }
int main(int argc, const char *argv[]) { const char *config_file = get_dyn_CONFIGFILE(); int s; static int silent_mode = False; static int show_all_parameters = False; int ret = 0; poptContext pc; static char *parameter_name = NULL; static const char *section_name = NULL; const char *cname; const char *caddr; static int show_defaults; static int skip_logic_checks = 0; struct poptOption long_options[] = { POPT_AUTOHELP {"suppress-prompt", 's', POPT_ARG_VAL, &silent_mode, 1, "Suppress prompt for enter"}, {"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"}, {"skip-logic-checks", 'l', POPT_ARG_NONE, &skip_logic_checks, 1, "Skip the global checks"}, {"show-all-parameters", '\0', POPT_ARG_VAL, &show_all_parameters, True, "Show the parameters, type, possible values" }, {"parameter-name", '\0', POPT_ARG_STRING, ¶meter_name, 0, "Limit testparm to a named parameter" }, {"section-name", '\0', POPT_ARG_STRING, §ion_name, 0, "Limit testparm to a named section" }, POPT_COMMON_VERSION POPT_COMMON_DEBUGLEVEL POPT_COMMON_OPTION POPT_TABLEEND }; TALLOC_CTX *frame = talloc_stackframe(); load_case_tables(); /* * Set the default debug level to 2. * Allow it to be overridden by the command line, * not by smb.conf. */ lp_set_cmdline("log level", "2"); pc = poptGetContext(NULL, argc, argv, long_options, POPT_CONTEXT_KEEP_FIRST); poptSetOtherOptionHelp(pc, "[OPTION...] <config-file> [host-name] [host-ip]"); while(poptGetNextOpt(pc) != -1); if (show_all_parameters) { show_parameter_list(); exit(0); } setup_logging(poptGetArg(pc), DEBUG_STDERR); if (poptPeekArg(pc)) config_file = poptGetArg(pc); cname = poptGetArg(pc); caddr = poptGetArg(pc); poptFreeContext(pc); if ( cname && ! caddr ) { printf ( "ERROR: You must specify both a machine name and an IP address.\n" ); ret = 1; goto done; } fprintf(stderr,"Load smb config files from %s\n",config_file); if (!lp_load_with_registry_shares(config_file,False,True,False,True)) { fprintf(stderr,"Error loading services.\n"); ret = 1; goto done; } fprintf(stderr,"Loaded services file OK.\n"); if (skip_logic_checks == 0) { ret = do_global_checks(); } for (s=0;s<1000;s++) { if (VALID_SNUM(s)) if (strlen(lp_servicename(talloc_tos(), s)) > 12) { fprintf(stderr, "WARNING: You have some share names that are longer than 12 characters.\n" ); fprintf(stderr, "These may not be accessible to some older clients.\n" ); fprintf(stderr, "(Eg. Windows9x, WindowsMe, and smbclient prior to Samba 3.0.)\n" ); break; } } for (s=0;s<1000;s++) { if (VALID_SNUM(s) && (skip_logic_checks == 0)) { do_per_share_checks(s); } } if (!section_name && !parameter_name) { fprintf(stderr, "Server role: %s\n\n", server_role_str(lp_server_role())); } if (!cname) { if (!silent_mode) { fprintf(stderr,"Press enter to see a dump of your service definitions\n"); fflush(stdout); getc(stdin); } if (parameter_name || section_name) { bool isGlobal = False; s = GLOBAL_SECTION_SNUM; if (!section_name) { section_name = GLOBAL_NAME; isGlobal = True; } else if ((isGlobal=!strwicmp(section_name, GLOBAL_NAME)) == 0 && (s=lp_servicenumber(section_name)) == -1) { fprintf(stderr,"Unknown section %s\n", section_name); ret = 1; goto done; } if (parameter_name) { if (!dump_a_parameter( s, parameter_name, stdout, isGlobal)) { fprintf(stderr,"Parameter %s unknown for section %s\n", parameter_name, section_name); ret = 1; goto done; } } else { if (isGlobal == True) lp_dump(stdout, show_defaults, 0); else lp_dump_one(stdout, show_defaults, s); } goto done; } lp_dump(stdout, show_defaults, lp_numservices()); } if(cname && caddr){ /* this is totally ugly, a real `quick' hack */ for (s=0;s<1000;s++) { if (VALID_SNUM(s)) { if (allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), cname, caddr) && allow_access(lp_hosts_deny(s), lp_hosts_allow(s), cname, caddr)) { fprintf(stderr,"Allow connection from %s (%s) to %s\n", cname,caddr,lp_servicename(talloc_tos(), s)); } else { fprintf(stderr,"Deny connection from %s (%s) to %s\n", cname,caddr,lp_servicename(talloc_tos(), s)); } } } } done: gfree_loadparm(); TALLOC_FREE(frame); return ret; }
static int rsync_module(int fd, int i) { int argc=0; char *argv[MAX_ARGS]; char **argp; char line[MAXPATHLEN]; uid_t uid = (uid_t)-2; gid_t gid = (gid_t)-2; char *p; char *addr = client_addr(fd); char *host = client_name(fd); char *name = lp_name(i); int use_chroot = lp_use_chroot(i); int start_glob=0; int ret; char *request=NULL; extern int am_sender; extern int remote_version; extern int am_root; if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) { rprintf(FERROR,"rsync denied on module %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); return -1; } if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) { if (errno) { rprintf(FERROR,"failed to open lock file %s : %s\n", lp_lock_file(i), strerror(errno)); io_printf(fd,"@ERROR: failed to open lock file %s : %s\n", lp_lock_file(i), strerror(errno)); } else { rprintf(FERROR,"max connections (%d) reached\n", lp_max_connections(i)); io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections(i)); } return -1; } auth_user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD "); if (!auth_user) { rprintf(FERROR,"auth failed on module %s from %s (%s)\n", name, client_name(fd), client_addr(fd)); io_printf(fd,"@ERROR: auth failed on module %s\n",name); return -1; } module_id = i; if (lp_read_only(i)) read_only = 1; am_root = (getuid() == 0); if (am_root) { p = lp_uid(i); if (!name_to_uid(p, &uid)) { if (!isdigit(*p)) { rprintf(FERROR,"Invalid uid %s\n", p); io_printf(fd,"@ERROR: invalid uid\n"); return -1; } uid = atoi(p); } p = lp_gid(i); if (!name_to_gid(p, &gid)) { if (!isdigit(*p)) { rprintf(FERROR,"Invalid gid %s\n", p); io_printf(fd,"@ERROR: invalid gid\n"); return -1; } gid = atoi(p); } } p = lp_include_from(i); add_exclude_file(p, 1, 1); p = lp_include(i); add_include_line(p); p = lp_exclude_from(i); add_exclude_file(p, 1, 0); p = lp_exclude(i); add_exclude_line(p); log_open(); if (use_chroot) { if (chroot(lp_path(i))) { rprintf(FERROR,"chroot %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chroot failed\n"); return -1; } if (!push_dir("/", 0)) { rprintf(FERROR,"chdir %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chdir failed\n"); return -1; } } else { if (!push_dir(lp_path(i), 0)) { rprintf(FERROR,"chdir %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chdir failed\n"); return -1; } } if (am_root) { if (setgid(gid)) { rprintf(FERROR,"setgid %d failed\n", gid); io_printf(fd,"@ERROR: setgid failed\n"); return -1; } if (setuid(uid)) { rprintf(FERROR,"setuid %d failed\n", uid); io_printf(fd,"@ERROR: setuid failed\n"); return -1; } am_root = (getuid() == 0); } io_printf(fd,"@RSYNCD: OK\n"); argv[argc++] = "rsyncd"; while (1) { if (!read_line(fd, line, sizeof(line)-1)) { return -1; } if (!*line) break; p = line; argv[argc] = strdup(p); if (!argv[argc]) { return -1; } if (start_glob) { if (start_glob == 1) { request = strdup(p); start_glob++; } glob_expand(name, argv, &argc, MAX_ARGS, !use_chroot); } else { argc++; } if (strcmp(line,".") == 0) { start_glob = 1; } if (argc == MAX_ARGS) { return -1; } } if (!use_chroot) { /* * Note that this is applied to all parameters, whether or not * they are filenames, but no other legal parameters contain * the forms that need to be sanitized so it doesn't hurt; * it is not known at this point which parameters are files * and which aren't. */ for (i = 1; i < argc; i++) { sanitize_path(argv[i]); } } ret = parse_arguments(argc, argv, 0); if (request) { if (*auth_user) { rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n", am_sender?"on":"to", request, auth_user, host, addr); } else { rprintf(FINFO,"rsync %s %s from %s (%s)\n", am_sender?"on":"to", request, host, addr); } free(request); } #if !TRIDGE /* don't allow the logs to be flooded too fast */ if (verbose > 1) verbose = 1; #endif argc -= optind; argp = argv + optind; optind = 0; if (remote_version > 17 && am_sender) io_start_multiplex_out(fd); if (!ret) { option_error(); } if (lp_timeout(i)) { extern int io_timeout; io_timeout = lp_timeout(i); } start_server(fd, fd, argc, argp); return 0; }
static int do_share_checks(struct loadparm_context *lp_ctx, const char *cname, const char *caddr, bool silent_mode, bool show_defaults, const char *section_name, const char *parameter_name) { int ret = 0; int s; for (s=0;s<lp_numservices(lp_ctx);s++) { struct loadparm_service *service = lp_servicebynum(lp_ctx, s); if (service != NULL) if (strlen(lp_servicename(lp_servicebynum(lp_ctx, s))) > 12) { fprintf(stderr, "WARNING: You have some share names that are longer than 12 characters.\n" ); fprintf(stderr, "These may not be accessible to some older clients.\n" ); fprintf(stderr, "(Eg. Windows9x, WindowsMe, and not listed in smbclient in Samba 3.0.)\n" ); break; } } for (s=0;s<lp_numservices(lp_ctx);s++) { struct loadparm_service *service = lp_servicebynum(lp_ctx, s); if (service != NULL) { const char **deny_list = lp_hostsdeny(service, lp_default_service(lp_ctx)); const char **allow_list = lp_hostsallow(service, lp_default_service(lp_ctx)); int i; if(deny_list) { for (i=0; deny_list[i]; i++) { char *hasstar = strchr_m(deny_list[i], '*'); char *hasquery = strchr_m(deny_list[i], '?'); if(hasstar || hasquery) { fprintf(stderr,"Invalid character %c in hosts deny list (%s) for service %s.\n", hasstar ? *hasstar : *hasquery, deny_list[i], lp_servicename(service) ); } } } if(allow_list) { for (i=0; allow_list[i]; i++) { char *hasstar = strchr_m(allow_list[i], '*'); char *hasquery = strchr_m(allow_list[i], '?'); if(hasstar || hasquery) { fprintf(stderr,"Invalid character %c in hosts allow list (%s) for service %s.\n", hasstar ? *hasstar : *hasquery, allow_list[i], lp_servicename(service) ); } } } } } if (!cname) { if (!silent_mode) { fprintf(stderr,"Press enter to see a dump of your service definitions\n"); fflush(stdout); getc(stdin); } if (section_name != NULL || parameter_name != NULL) { struct loadparm_service *service = NULL; if (!section_name) { section_name = GLOBAL_NAME; service = NULL; } else if ((!strwicmp(section_name, GLOBAL_NAME)) == 0 && (service=lp_service(lp_ctx, section_name)) == NULL) { fprintf(stderr,"Unknown section %s\n", section_name); return(1); } if (!parameter_name) { lp_dump_one(stdout, show_defaults, service, lp_default_service(lp_ctx)); } else { ret = !lp_dump_a_parameter(lp_ctx, service, parameter_name, stdout); } } else { lp_dump(lp_ctx, stdout, show_defaults, lp_numservices(lp_ctx)); } return(ret); } if(cname && caddr){ /* this is totally ugly, a real `quick' hack */ for (s=0;s<lp_numservices(lp_ctx);s++) { struct loadparm_service *service = lp_servicebynum(lp_ctx, s); if (service != NULL) { if (allow_access(NULL, lp_hostsdeny(NULL, lp_default_service(lp_ctx)), lp_hostsallow(NULL, lp_default_service(lp_ctx)), cname, caddr) && allow_access(NULL, lp_hostsdeny(service, lp_default_service(lp_ctx)), lp_hostsallow(service, lp_default_service(lp_ctx)), cname, caddr)) { fprintf(stderr,"Allow connection from %s (%s) to %s\n", cname,caddr,lp_servicename(service)); } else { fprintf(stderr,"Deny connection from %s (%s) to %s\n", cname,caddr,lp_servicename(service)); } } } } return ret; }
/* This is sufficiently different from the TCP code (wrt SSL, etc) that it * resides in its own simpler function */ static int ncat_listen_dgram(int proto) { int sockfd[NUM_LISTEN_ADDRS]; int i, fdn = -1; int fdmax, nbytes, fds_ready; char buf[DEFAULT_UDP_BUF_LEN] = {0}; char *tempbuf = NULL; fd_set read_fds; union sockaddr_u remotess; socklen_t sslen = sizeof(remotess.storage); for (i = 0; i < NUM_LISTEN_ADDRS; i++) { sockfd[i] = -1; } FD_ZERO(&read_fds); /* Initialize remotess struct so recvfrom() doesn't hit the fan.. */ zmem(&remotess.storage, sizeof(remotess.storage)); remotess.storage.ss_family = o.af; #ifdef WIN32 set_pseudo_sigchld_handler(decrease_conn_count); #else /* Reap on SIGCHLD */ Signal(SIGCHLD, sigchld_handler); /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we send data to it before noticing. */ Signal(SIGPIPE, SIG_IGN); #endif /* set for selecting udp listening sockets */ fd_set listen_fds; fd_list_t listen_fdlist; FD_ZERO(&listen_fds); init_fdlist(&listen_fdlist, num_listenaddrs); for (i = 0; i < num_listenaddrs; i++) { /* create the UDP listen sockets */ sockfd[i] = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]); FD_SET(sockfd[i],&listen_fds); add_fd(&listen_fdlist, sockfd[i]); } while (1) { int i, j, conn_count, socket_n; if (fdn != -1) { /*remove socket descriptor which is burnt */ FD_CLR(sockfd[fdn], &listen_fds); rm_fd(&listen_fdlist, sockfd[fdn]); /* Rebuild the udp socket which got burnt */ sockfd[fdn] = do_listen(SOCK_DGRAM, proto, &listenaddrs[fdn]); FD_SET(sockfd[fdn],&listen_fds); add_fd(&listen_fdlist, sockfd[fdn]); } fdn = -1; socket_n = -1; fd_set fds; FD_ZERO(&fds); while (1) { /* * We just select to get a list of sockets which we can talk to */ if (o.debug > 1) logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax); fds = listen_fds; fds_ready = fselect(listen_fdlist.fdmax + 1, &fds, NULL, NULL, NULL); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); /* * Figure out which listening socket got a connection. This loop should * really call a function for each ready socket instead of breaking on * the first one. */ for (i = 0; i <= listen_fdlist.fdmax && fds_ready >0; i++) { /* Loop through descriptors until there is something ready */ if (!FD_ISSET(i, &fds)) continue; /* Check each listening socket */ for (j = 0; j < num_listenaddrs; j++) { if (i == sockfd[j]) { if (o.debug >1) logdebug("Valid descriptor %d \n", i); fdn = j; socket_n = i; break; } } /* if we found a valid socket break */ if (fdn != -1) { fds_ready--; break; } } /* Make sure someone connected */ if (fdn == -1) continue; /* * We just peek so we can get the client connection details without * removing anything from the queue. Sigh. */ nbytes = Recvfrom(socket_n, buf, sizeof(buf), MSG_PEEK, &remotess.sockaddr, &sslen); /* Check conditions that might cause us to deny the connection. */ conn_count = get_conn_count(); if (conn_count >= o.conn_limit) { if (o.verbose) loguser("New connection denied: connection limit reached (%d)\n", conn_count); } else if (!allow_access(&remotess)) { if (o.verbose) loguser("New connection denied: not allowed\n"); } else { /* Good to go. */ break; } /* Dump the current datagram */ Recv(socket_n, buf, sizeof(buf), 0); } if (o.debug > 1) logdebug("Valid Connection from %d\n", socket_n); conn_inc++; /* * We're using connected udp. This has the down side of only * being able to handle one udp client at a time */ Connect(socket_n, &remotess.sockaddr, sslen); /* clean slate for buf */ zmem(buf, sizeof(buf)); /* are we executing a command? then do it */ if (o.cmdexec) { struct fdinfo info = { 0 }; info.fd = socket_n; if (o.keepopen) netrun(&info, o.cmdexec); else netexec(&info, o.cmdexec); continue; } FD_SET(socket_n, &read_fds); FD_SET(STDIN_FILENO, &read_fds); fdmax = socket_n; /* stdin -> socket and socket -> stdout */ while (1) { fd_set fds; fds = read_fds; if (o.debug > 1) logdebug("udp select'ing\n"); fds_ready = fselect(fdmax + 1, &fds, NULL, NULL, NULL); if (FD_ISSET(STDIN_FILENO, &fds)) { nbytes = Read(STDIN_FILENO, buf, sizeof(buf)); if (nbytes < 0) { loguser("%s.\n", strerror(errno)); return 1; } else if (nbytes == 0) { return 0; } if (o.crlf) fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state); if (!o.recvonly) { if (tempbuf != NULL) send(socket_n, tempbuf, nbytes, 0); else send(socket_n, buf, nbytes, 0); } if (tempbuf != NULL) { free(tempbuf); tempbuf = NULL; } } if (FD_ISSET(socket_n, &fds)) { nbytes = recv(socket_n, buf, sizeof(buf), 0); if (nbytes < 0) { loguser("%s.\n", socket_strerror(socket_errno())); close(socket_n); return 1; } if (!o.sendonly) Write(STDOUT_FILENO, buf, nbytes); } zmem(buf, sizeof(buf)); } } return 0; }