def log(self, handler): """Log a handled request.""" logger.log("%s [%s/%s]: %s" % \ (self.requesthandler.client_address[0], re.search("[^.]+$", str(self.__class__)).group(0), re.search("[^.]+$", str(handler.__class__)).group(0), self.selector))
def log(self, handler): """Log a handled request.""" logger.log("%s [%s/%s]: %s" % \ (self.requesthandler.client_address[0], type(self).__name__, type(handler).__name__, self.selector))
def initpgrp(config): if 'setpgrp' in os.__dict__: os.setpgrp() pgrp = os.getpgrp() logger.log("Process group is %d" % pgrp) return pgrp else: logger.log("setpgrp() unavailable; not initializing process group") return None
def initpgrp(config): if "setpgrp" in os.__dict__: os.setpgrp() pgrp = os.getpgrp() logger.log("Process group is %d" % pgrp) return pgrp else: logger.log("setpgrp() unavailable; not initializing process group") return None
def init_security(config: ConfigParser) -> None: uid = None gid = None if config.has_option("pygopherd", "setuid"): import pwd uid = pwd.getpwnam(config.get("pygopherd", "setuid"))[2] if config.has_option("pygopherd", "setgid"): import grp gid = grp.getgrnam(config.get("pygopherd", "setgid"))[2] if config.getboolean("pygopherd", "usechroot"): chroot_user = config.get("pygopherd", "root") os.chroot(chroot_user) logger.log(f"Chrooted to {chroot_user}") config.set("pygopherd", "root", "/") if uid is not None or gid is not None: os.setgroups(()) logger.log("Supplemental group list cleared.") if gid is not None: os.setregid(gid, gid) logger.log(f"Switched to group {gid}") if uid is not None: os.setreuid(uid, uid) logger.log(f"Switched to uid {uid}")
def initsecurity(config): idsetuid = None idsetgid = None if config.has_option("pygopherd", "setuid"): import pwd idsetuid = pwd.getpwnam(config.get("pygopherd", "setuid"))[2] if config.has_option("pygopherd", "setgid"): import grp idsetgid = grp.getgrnam(config.get("pygopherd", "setgid"))[2] if config.getboolean("pygopherd", "usechroot"): os.chroot(config.get("pygopherd", "root")) logger.log("Chrooted to " + config.get("pygopherd", "root")) config.set("pygopherd", "root", "/") if idsetuid != None or idsetgid != None: os.setgroups(()) logger.log("Supplemental group list cleared.") if idsetgid != None: os.setregid(idsetgid, idsetgid) logger.log("Switched to group %d" % idsetgid) if idsetuid != None: os.setreuid(idsetuid, idsetuid) logger.log("Switched to uid %d" % idsetuid)
def initsecurity(config): idsetuid = None idsetgid = None if config.has_option("pygopherd", "setuid"): import pwd idsetuid = pwd.getpwnam(config.get("pygopherd", "setuid"))[2] if config.has_option("pygopherd", "setgid"): import grp idsetgid = grp.getgrnam(config.get("pygopherd", "setgid"))[2] if config.getboolean("pygopherd", "usechroot"): os.chroot(config.get("pygopherd", "root")) logger.log("Chrooted to " + config.get("pygopherd", "root")) config.set("pygopherd", "root", "/") if idsetuid != None or idsetgid != None: os.setgroups( () ) logger.log("Supplemental group list cleared.") if idsetgid != None: os.setregid(idsetgid, idsetgid) logger.log("Switched to group %d" % idsetgid) if idsetuid != None: os.setreuid(idsetuid, idsetuid) logger.log("Switched to uid %d" % idsetuid)
def getserverobject(config): # Pick up the server type from the config. servertype = eval("socketserver." + config.get("pygopherd", "servertype")) class MyServer(servertype): allow_reuse_address = 1 def server_bind(self): """Override server_bind to store server name.""" servertype.server_bind(self) # Set a timeout. if config.has_option('pygopherd', 'timeout'): mytimeout = struct.pack( "ll", int(config.get('pygopherd', 'timeout')), 0) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, mytimeout) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO, mytimeout) #self.socket.settimeout(int(config.get('pygopherd', 'timeout'))) host, port = self.socket.getsockname() if config.has_option("pygopherd", "servername"): self.server_name = config.get("pygopherd", "servername") else: self.server_name = socket.getfqdn(host) if config.has_option("pygopherd", "advertisedport"): self.server_port = config.getint("pygopherd", "advertisedport") else: self.server_port = port # Instantiate a server. Has to be done before the security so we can # get a privileged port if necessary. interface = '' if config.has_option('pygopherd', 'interface'): servername = config.get('pygopherd', 'interface') interface = config.get('pygopherd', 'interface') try: s = MyServer((interface, config.getint('pygopherd', 'port')), GopherRequestHandler) except: GopherExceptions.log(sys.exc_info()[1], None, None) logger.log("Application startup NOT successful!") raise s.config = config return s
def initeverything(conffile): config = initconffile(conffile) initlogger(config, conffile) initexceptions(config) initmimetypes(config) s = getserverobject(config) initconditionaldetach(config) initpidfile(config) pgrp = initpgrp(config) initsighandlers(config, pgrp) initsecurity(config) os.chdir(config.get("pygopherd", "root")) logger.log("Running. Root is '%s'" % config.get("pygopherd", "root")) return s
def log(exception, protocol = None, handler = None): """Logs an exception. It will try to generate a nice-looking string based on the arguments passed in.""" protostr = 'None' handlerstr = 'None' ipaddr = 'unknown-address' exceptionclass = type(exception).__name__ if protocol: protostr = type(protocol).__name__ ipaddr = protocol.requesthandler.client_address[0] if handler: handlerstr = type(handler).__name__ logger.log("%s [%s/%s] EXCEPTION %s: %s" % \ (ipaddr, protostr, handlerstr, exceptionclass, str(exception)))
def log(exception, protocol = None, handler = None): """Logs an exception. It will try to generate a nice-looking string based on the arguments passed in.""" protostr = 'None' handlerstr = 'None' ipaddr = 'unknown-address' exceptionclass = re.search("[^.]+$", str(exception.__class__)).group(0) if protocol: protostr = re.search("[^.]+$", str(protocol.__class__)).group(0) ipaddr = protocol.requesthandler.client_address[0] if handler: handlerstr = re.search("[^.]+$", str(handler.__class__)).group(0) logger.log("%s [%s/%s] EXCEPTION %s: %s" % \ (ipaddr, protostr, handlerstr, exceptionclass, str(exception)))
def getserverobject(config): # Pick up the server type from the config. servertype = eval("SocketServer." + config.get("pygopherd", "servertype")) class MyServer(servertype): allow_reuse_address = 1 def server_bind(self): """Override server_bind to store server name.""" servertype.server_bind(self) # Set a timeout. if config.has_option("pygopherd", "timeout"): mytimeout = struct.pack("ll", long(config.get("pygopherd", "timeout")), 0) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, mytimeout) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO, mytimeout) # self.socket.settimeout(int(config.get('pygopherd', 'timeout'))) host, port = self.socket.getsockname() if config.has_option("pygopherd", "servername"): self.server_name = config.get("pygopherd", "servername") else: self.server_name = socket.getfqdn(host) if config.has_option("pygopherd", "advertisedport"): self.server_port = config.getint("pygopherd", "advertisedport") else: self.server_port = port # Instantiate a server. Has to be done before the security so we can # get a privileged port if necessary. interface = "" if config.has_option("pygopherd", "interface"): servername = config.get("pygopherd", "interface") interface = config.get("pygopherd", "interface") try: s = MyServer((interface, config.getint("pygopherd", "port")), GopherRequestHandler) except: GopherExceptions.log(sys.exc_info()[1], None, None) logger.log("Application startup NOT successful!") raise s.config = config return s
def initialize(filename: str) -> pygopherd.server.BaseServer: config = init_config(filename) init_logger(config, filename) init_exceptions(config) init_mimetypes(config) context = init_ssl_context(config) server = get_server(config, context=context) init_conditional_detach(config) init_pidfile(config) init_process_group(config) init_signal_handlers() init_security(config) root = config.get("pygopherd", "root") logger.log(f"Running. Root is '{root}'") return server
def initmimetypes(config): mimetypesfiles = config.get("pygopherd", "mimetypes").split(":") mimetypesfiles = filter(lambda x: os.path.isfile(x) and os.access(x, os.R_OK), mimetypesfiles) if not mimetypesfiles: errmsg = "Could not find any mimetypes files; check mimetypes option in config." logger.log(errmsg) raise Exception, errmsg configencoding = eval(config.get("pygopherd", "encoding")) mimetypes.encodings_map.clear() for key, value in configencoding: mimetypes.encodings_map[key] = value mimetypes.init(mimetypesfiles) logger.log("mimetypes initialized with files: " + str(mimetypesfiles)) # Set up the inverse mapping file. pygopherd.fileext.init()
def log( exception: Exception, protocol: typing.Optional[BaseGopherProtocol] = None, handler: typing.Optional[BaseHandler] = None, ): """Logs an exception. It will try to generate a nice-looking string based on the arguments passed in.""" protostr = "None" handlerstr = "None" ipaddr = "unknown-address" exceptionclass = type(exception).__name__ if protocol: protostr = type(protocol).__name__ ipaddr = protocol.requesthandler.client_address[0] if handler: handlerstr = type(handler).__name__ logger.log("%s [%s/%s] EXCEPTION %s: %s" % (ipaddr, protostr, handlerstr, exceptionclass, str(exception)))
def init_mimetypes(config: ConfigParser) -> None: files = config.get("pygopherd", "mimetypes").split(":") files = [x for x in files if os.path.isfile(x) and os.access(x, os.R_OK)] if not files: errmsg = "Could not find any mimetypes files; check mimetypes option in config." logger.log(errmsg) raise Exception(errmsg) encoding = eval(config.get("pygopherd", "encoding")) mimetypes.encodings_map.clear() for key, value in encoding: mimetypes.encodings_map[key] = value mimetypes.init(files) logger.log(f"mimetypes initialized with files: {files}") # Set up the inverse mapping file. pygopherd.fileext.init()
def initmimetypes(config): mimetypesfiles = config.get("pygopherd", "mimetypes").split(":") mimetypesfiles = filter( lambda x: os.path.isfile(x) and os.access(x, os.R_OK), mimetypesfiles) if not mimetypesfiles: errmsg = "Could not find any mimetypes files; check mimetypes option in config." logger.log(errmsg) raise Exception(errmsg) configencoding = eval(config.get("pygopherd", "encoding")) mimetypes.encodings_map.clear() for key, value in configencoding: mimetypes.encodings_map[key] = value mimetypes.init(mimetypesfiles) logger.log("mimetypes initialized with files: " + str(mimetypesfiles)) # Set up the inverse mapping file. pygopherd.fileext.init()
def termhandler(signum, frame): if os.getpid() == pid: # Master killed; kill children. logger.log("SIGTERM (%d) received in master; doing orderly shutdown" % signum) logger.log("Terminating all of process group with SIGHUP") # Ignore this signal so that our own process won't get it again. signal.signal(signal.SIGHUP, signal.SIG_IGN) os.kill(0, signal.SIGHUP) logger.log("Master application process now exiting. Goodbye.") sys.exit(6) else: # Shouldn't need this -- just in case. logger.log("SIGTERM (%d) received in child; terminating this process" % signum) os._exit(7) # So we don't raise SystemExit
def termhandler(signum, frame): if os.getpid() == pid: # Master killed; kill children. logger.log("SIGTERM (%d) received in master; doing orderly shutdown" \ % signum) logger.log("Terminating all of process group %d with SIGHUP" % \ (pgrp)) # Ignore this signal so that our own process won't get it again. signal.signal(signal.SIGHUP, signal.SIG_IGN) os.kill(0, signal.SIGHUP) logger.log("Master application process now exiting. Goodbye.") sys.exit(6) else: # Shouldn't need this -- just in case. logger.log("SIGTERM (%d) received in child; terminating this process" \ % signum) os._exit(7) # So we don't raise SystemExit
def get_server( config: ConfigParser, context: typing.Optional[ssl.SSLContext] = None ) -> pygopherd.server.BaseServer: # Pick up the server type from the config. server_class: typing.Type[pygopherd.server.BaseServer] server_type = config.get("pygopherd", "servertype") if server_type == "ForkingTCPServer": server_class = pygopherd.server.ForkingTCPServer elif server_type == "ThreadingTCPServer": server_class = pygopherd.server.ThreadingTCPServer else: raise RuntimeError(f"Invalid servertype option: {server_type}") # Instantiate a server. Has to be done before the security so we can # get a privileged port if necessary. interface = "" if config.has_option("pygopherd", "interface"): interface = config.get("pygopherd", "interface") port = config.getint("pygopherd", "port") address = (interface, port) try: server = server_class(config, address, GopherRequestHandler, context=context) except Exception as e: GopherExceptions.log(e, None, None) logger.log("Application startup NOT successful!") raise return server
def init_process_group(config: ConfigParser) -> None: try: os.setpgrp() process_group = os.getpgrp() except OSError as e: logger.log(f"setpgrp() failed with {e}") except AttributeError: logger.log("setpgrp() unavailable; not initializing process group") else: logger.log(f"Process group is {process_group}")
def initconditionaldetach(config): if config.getboolean("pygopherd", "detach"): pid = os.fork() if pid: logger.log("Parent process detaching; child is %d" % pid) sys.exit(0)
def initlogger(config, conffile): logger.init(config) logger.log("Pygopherd starting, using configuration file %s" % conffile)
def init_logger(config: ConfigParser, filename: str) -> None: logger.init(config) logger.log(f"Pygopherd starting, using configuration file {filename}")
def huphandler(signum, frame): logger.log("SIGHUP (%d) received; terminating process" % signum) os._exit(5) # So we don't raise SystemExit
def init_conditional_detach(config: ConfigParser) -> None: if config.getboolean("pygopherd", "detach"): pid = os.fork() if pid: logger.log("Parent process detaching; child is %d" % pid) sys.exit(0)