예제 #1
0
파일: server.py 프로젝트: B-Rich/smart
	def _receive( self, socket ):
		"""Signal callback: Handles incoming data. Processes SSL events
		and parses the incoming data. If a vaild UMCP was found it is
		passed to _handle.

		:param fd socket: file descriptor or socket object that reported incoming data
		"""
		state = self.__states[ socket ]
		data = ''

		try:
			data = socket.recv( RECV_BUFFER_SIZE )
		except SSL.WantReadError:
			# this error can be ignored (SSL need to do something)
			return True
		except ( SSL.SysCallError, SSL.Error ), error:
			statistics.connections.inactive()
			if self.__states[ socket ].username in statistics.users:
				statistics.users.remove( self.__states[ socket ].username )
			CRYPT.warn( 'SSL error: %s. Probably the socket was closed by the client.' % str( error ) )
			if self.__states[ socket ].processor is not None:
				self.__states[ socket ].processor.shutdown()
			notifier.socket_remove( socket )
			del self.__states[ socket ]
			socket.close()
			return False
예제 #2
0
파일: server.py 프로젝트: B-Rich/smart
	def _do_send( self, socket ):
		state = self.__states[ socket ]
		id, first = state.resend_queue.pop( 0 )
		try:
			ret = socket.send( first )
			if ret < len( first ):
				state.resend_queue.insert( 0, ( id, first[ ret : ] ) )
			else:
				if id != -1:
					del state.requests[ id ]
		except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
			CRYPT.info( 'UMCP: SSL error during re-send' )
			state.resend_queue.insert( 0, ( id, first ) )
			return True
		except ( SSL.SysCallError, SSL.Error ), error:
			statistics.connections.inactive()
			if self.__states[ socket ].username in statistics.users:
				statistics.users.remove( self.__states[ socket ].username )
			CRYPT.warn( 'SSL error: %s. Probably the socket was closed by the client.' % str( error ) )
			if self.__states[ socket ].processor is not None:
				self.__states[ socket ].processor.shutdown()
			notifier.socket_remove( socket )
			del self.__states[ socket ]
			socket.close()
			return False
예제 #3
0
	def close( self ):
		"""
		Close the IO to the child.
		"""
		notifier.socket_remove( self.fp )
		self.fp.close()
		self.signal_emit( 'closed', self.name )
예제 #4
0
파일: server.py 프로젝트: B-Rich/smart
	def exit( self ):
		'''Closes all open connections.'''
		# remove all sockets
		for sock, state in self.__states.items():
			CORE.info( 'Shutting down connection %s' % sock )
			if state.processor is not None:
				state.processor.shutdown()
			notifier.socket_remove( sock )
			statistics.connections.inactive()
		# delete states
		for state in self.__states.values():
			del state
		self.__states = {}
    def _cleanup(self, socket):
        state = self.__states.pop(socket, None)
        if state is None:
            return

        state.session.close_session()

        notifier.socket_remove(socket)
        try:
            socket.close()
        except Exception:
            pass

        state.session.signal_disconnect('success', self._response)
    def exit(self):
        '''Shuts down all open connections.'''
        CORE.warn('Shutting down all open connections')
        if self.__ssl and not self.__unix:
            notifier.socket_remove(self.connection)
            self.connection.close()
        else:
            notifier.socket_remove(self.__realsocket)
            self.__realsocket.close()
        if self.__unix:
            os.unlink(self.__unix)

        if self.__magic:
            self.__bucket.exit()
    def _cleanup(self, socket):
        if socket not in self.__states:
            return

        self.__states[socket].session.shutdown()

        notifier.socket_remove(socket)
        self.__states[socket].session.__del__()
        del self.__states[socket]

        try:
            socket.close()
        except:
            pass
예제 #8
0
파일: server.py 프로젝트: B-Rich/smart
	def exit( self ):
		'''Shuts down all open connections.'''
		CORE.warn( 'Shutting down all open connections' )
		if self.__ssl and not self.__unix:
			notifier.socket_remove( self.connection )
			self.connection.close()
		else:
			notifier.socket_remove( self.__realsocket )
			self.__realsocket.close()
		if self.__unix:
			os.unlink( self.__unix )

		if self.__magic:
			self.__bucket.exit()
    def _recv(self, sock):
        try:
            recv = ''
            while True:
                recv += sock.recv(RECV_BUFFER_SIZE)
                if self.__ssl and not self.__unix:
                    if not sock.pending():
                        break
                else:
                    break
        except socket.error as exc:
            CORE.warn('Client: _recv: error on socket: %s' % (exc, ))
            recv = None
        except SSL.SysCallError:
            # lost connection or any other unfixable error
            recv = None
        except SSL.Error:
            error = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
            # lost connection: UMC daemon died probably
            if error == errno.EPIPE:
                recv = None
            else:
                return True

        if not recv:
            self.signal_emit('closed')
            try:
                sock.close()
            except:
                pass
            notifier.socket_remove(sock)
            return False

        if self.__buffer:
            recv = self.__buffer + recv
            self.__buffer = ''
        try:
            while recv:
                response = Response()
                recv = response.parse(recv)
                self._handle(response)
        except IncompleteMessageError:
            self.__buffer = recv
            # waiting for the rest
        except ParseError as exc:
            CORE.warn('Client: _recv: error parsing message: %s' % (exc, ))
            self.signal_emit('error', exc)

        return True
예제 #10
0
    def _init_socket(self):
        if self.__unix:
            self.__realsocket = socket.socket(socket.AF_UNIX,
                                              socket.SOCK_STREAM)
        else:
            self.__realsocket = socket.socket(socket.AF_INET,
                                              socket.SOCK_STREAM)
        self.__realsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        fcntl.fcntl(self.__realsocket.fileno(), fcntl.F_SETFD, 1)

        if self.__ssl and not self.__unix:
            self.__socket = SSL.Connection(self.__crypto_context,
                                           self.__realsocket)
        else:
            if self.__socket:
                notifier.socket_remove(self.__socket)
                self.__socket.close()
            self.__socket = None
예제 #11
0
	def _response( self, msg, state ):
		''' Send UMCP response to client. If the status code is 250 the
		module process is asking for exit. This method forfills the
		request.'''
		# FIXME: error handling is missing!!
		if not msg.id in state.requests and msg.id != -1:
			CORE.info( 'The given response is invalid or not known (%s)' % msg.id )
			return

		try:
			statistics.requests.inactive()
			data = str( msg )
			# there is not data from another request in the send queue
			if not state.resend_queue:
				ret = state.socket.send( data )
			else:
				ret = 0
			# not all data could be send; retry later
			if ret < len( data ):
				if not state.resend_queue:
					notifier.socket_add( state.socket, self._do_send, notifier.IO_WRITE )
				state.resend_queue.append( ( msg.id, data[ ret : ] ) )
		except ( SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError ):
			CRYPT.info( 'UMCP: SSL error need to re-send chunk' )
			notifier.socket_add( state.socket, self._do_send, notifier.IO_WRITE )
			state.resend_queue.append( data )
		except ( SSL.SysCallError, SSL.Error, socket.error ), error:
			statistics.connections.inactive()
			# clean up if not already done
			if state.socket in self.__states:
				if state.username in statistics.users:
					statistics.users.remove( state.username )
					CRYPT.warn( 'SSL error: %s. Probably the socket was closed by the client.' % str( error ) )
					if state.processor is not None:
						state.processor.shutdown()
					notifier.socket_remove( state.socket )
					del self.__states[ state.socket ]
					try:
						state.socket.close()
					except:
						pass
			return
예제 #12
0
    def exit(self):
        '''Shuts down all open connections.'''
        CORE.warn('Shutting down all open connections')

        if self.__bucket:
            self.__bucket.exit()

        if self.__ssl and not self.__unix:
            notifier.socket_remove(self.connection)
            self.connection.close()
        elif self.__realsocket:
            notifier.socket_remove(self.__realsocket)
            self.__realsocket.close()
            self.__realsocket = None
        if self.__unix:
            if os.path.exists(self.__unix):
                os.unlink(self.__unix)
            self.__unix = None

        self.__bucket = None
    def exit(self):
        '''Shuts down all open connections.'''
        CORE.warn('Shutting down all open connections')

        if self.__bucket:
            self.__bucket.exit()

        if self._child_number is not None:
            self._children.pop(self._child_number, None)

        if self.__ssl and self.__port:
            notifier.socket_remove(self.connection)
            self.connection.close()
        elif not self.__ssl and self.__port and self.__realtcpsocket:
            notifier.socket_remove(self.__realtcpsocket)
            self.__realtcpsocket.close()
            self.__realtcpsocket = None
        if self.__unix:
            if self.__realunixsocket is not None:
                notifier.socket_remove(self.__realunixsocket)
                self.__realunixsocket.close()
                self.__realunixsocket = None
            if self._child_number is None and os.path.exists(self.__unix):
                os.unlink(self.__unix)
            self.__unix = None

        self.__bucket = None
예제 #14
0
	def _receive_data( self, sock ):
		debug( LOGDEBUG, 'GOT NEW DATA' )

		if not self._connectionstates.has_key( sock ):
			debug( LOGERROR, 'unknown socket' )
			return True

		state = self._connectionstates[ sock ]
		data = ''

		try:
			data = sock.recv( 16384 )
		except SSL.WantReadError:
			# this error can be ignored (SSL need to do something)
			debug(LOGDEBUG, 'SSL.WantReadError')
			return True
		except ( SSL.SysCallError, SSL.Error ), error:
			debug( LOGINFO, 'SSL error: %s. Probably the socket was closed by the client.' % str( error ) )
			notifier.socket_remove( sock )
			del self._connectionstates[ sock ]
			sock.close()
			return False
예제 #15
0
    def _receive_data(self, sock):
        debug(LOGDEBUG, "GOT NEW DATA")

        if not self._connectionstates.has_key(sock):
            debug(LOGERROR, "unknown socket")
            return True

        state = self._connectionstates[sock]
        data = ""

        try:
            data = sock.recv(16384)
        except SSL.WantReadError:
            # this error can be ignored (SSL need to do something)
            debug(LOGDEBUG, "SSL.WantReadError")
            return True
        except (SSL.SysCallError, SSL.Error), error:
            debug(LOGINFO, "SSL error: %s. Probably the socket was closed by the client." % str(error))
            notifier.socket_remove(sock)
            del self._connectionstates[sock]
            sock.close()
            return False
예제 #16
0
def _stdin( fd ):
	print 'read: ' + os.read( fd, 512 )
	notifier.socket_remove( 0 )
	return False
예제 #17
0
            recv = sock.recv(16384)
        except SSL.SysCallError, e:
            # lost connection or any other unfixable error
            recv = None
        except SSL.Error:
            error = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
            if error == errno.EPIPE:
                # lost connection: server died probably
                debug(LOGDEBUG, 'EPIPE')
                recv = None
            else:
                return True

        if not recv:
            sock.close()
            notifier.socket_remove(sock)
            notifier.socket_remove(sock, condition=notifier.IO_WRITE)
            self._socket = None
            notifier.timer_add(1000, notifier.Callback(self.reconnect))
            return False

        self._inbuffer += recv

        debug(
            LOGDEBUG, 'BUFFER: len=%d    got %d bytes' %
            (len(self._inbuffer), len(recv)))

        # repeat while enough data is present
        while len(self._inbuffer) > 4:
            # get length of pickle object
            plen = struct.unpack('!I', self._inbuffer[0:4])[0]
예제 #18
0
def _stdin(fd):
    notifier.socket_remove(0)
    return False
예제 #19
0
class MagicBucket( object ):
	'''Manages a connection (session) to the UMC server. Therefore it
	ensures that without successful authentication no other command is
	accepted. After the user has authenticated the commands are passed
	on to the Processor.'''
	def __init__( self ):
		self.__states = {}

	def __del__( self ):
		self.exit()

	def new( self, client, socket ):
		"""Is called by the Server object to annouce a new incoming
		connection.

		:param str client: IP address + port
		:param fd socket: a file descriptor or socket object
		"""
		CORE.info( 'Established connection: %s' % client )
		state = State( client, socket )
		state.signal_connect( 'authenticated', self._authenticated )
		self.__states[ socket ] = state
		notifier.socket_add( socket , self._receive )
		statistics.connections.new()

	def exit( self ):
		'''Closes all open connections.'''
		# remove all sockets
		for sock, state in self.__states.items():
			CORE.info( 'Shutting down connection %s' % sock )
			if state.processor is not None:
				state.processor.shutdown()
			notifier.socket_remove( sock )
			statistics.connections.inactive()
		# delete states
		for state in self.__states.values():
			del state
		self.__states = {}

	def _authenticated( self, success, state ):
		"""Signal callback: Invoked when a authentication has been
		tried. This function generates the UMCP response.

		:param bool success: True if the authentication was successful
		:param State state: the state object for the connection (see also :class:`~univention.management.console.protocol.session.State`)
		"""
		if success:
			statistics.users.add( state.username )
			state.authResponse.status = SUCCESS
		else:
			state.authResponse.status = BAD_REQUEST_AUTH_FAILED
		state.authenticated = success
		self._response( state.authResponse, state )
		state.authResponse = None

	def _receive( self, socket ):
		"""Signal callback: Handles incoming data. Processes SSL events
		and parses the incoming data. If a vaild UMCP was found it is
		passed to _handle.

		:param fd socket: file descriptor or socket object that reported incoming data
		"""
		state = self.__states[ socket ]
		data = ''

		try:
			data = socket.recv( RECV_BUFFER_SIZE )
		except SSL.WantReadError:
			# this error can be ignored (SSL need to do something)
			return True
		except ( SSL.SysCallError, SSL.Error ), error:
			statistics.connections.inactive()
			if self.__states[ socket ].username in statistics.users:
				statistics.users.remove( self.__states[ socket ].username )
			CRYPT.warn( 'SSL error: %s. Probably the socket was closed by the client.' % str( error ) )
			if self.__states[ socket ].processor is not None:
				self.__states[ socket ].processor.shutdown()
			notifier.socket_remove( socket )
			del self.__states[ socket ]
			socket.close()
			return False

		if not len( data ):
			notifier.socket_remove( socket )
			del self.__states[ socket ]
			socket.close()
			return False

		state.buffer += data

		msg = None
		try:
			while state.buffer:
				msg = Message()
				state.buffer = msg.parse( state.buffer )
				self._handle( state, msg )
		except IncompleteMessageError, e:
			CORE.info( 'MagicBucket: incomplete message: %s' % str( e ) )
예제 #20
0
def _stdin( fd ):
	notifier.socket_remove( 0 )
	return False
예제 #21
0
			recv = sock.recv( 16384 )
		except SSL.SysCallError, e:
			# lost connection or any other unfixable error
			recv = None
		except SSL.Error:
			error = sock.getsockopt( socket.SOL_SOCKET, socket.SO_ERROR )
			if error == errno.EPIPE:
				# lost connection: server died probably
				debug( LOGDEBUG, 'EPIPE' )
				recv = None
			else:
				return True

		if not recv:
			sock.close()
			notifier.socket_remove( sock )
			notifier.socket_remove( sock, condition = notifier.IO_WRITE )
			self._socket = None
			notifier.timer_add( 1000, notifier.Callback( self.reconnect ) )
			return False

		self._inbuffer += recv

		debug( LOGDEBUG, 'BUFFER: len=%d    got %d bytes' % (len(self._inbuffer), len(recv)))

		# repeat while enough data is present
		while len(self._inbuffer) > 4:
			# get length of pickle object
			plen = struct.unpack('!I', self._inbuffer[0:4])[0]
			if plen+4 <= len(self._inbuffer):
				# unpickle data
예제 #22
0
class LogCollectorServer( object ):
	def __init__( self, port = 7450 ):
		self._port = port
		self._connectionstates = {}
		self._ack_queue = []

		self._targetdir = '/root/log/'
		if baseconfig.has_key('logcollector/targetdir'):
			self._targetdir = baseconfig[ 'logcollector/targetdir' ]
		else:
			debug( LOGERROR, 'WARNING: baseconfig variable "logcollector/targetdir" is not set' )
			debug( LOGERROR, 'WARNING: using "logcollector/targetdir=%s" as default' % self._targetdir )

		self._logrot_keepcnt = 99
		if baseconfig.has_key('logcollector/logrotation/keepcount'):
			try:
				self._logrot_keepcnt = int(baseconfig[ 'logcollector/logrotation/keepcount' ])
			except:
				debug( LOGERROR, 'WARNING: baseconfig variable "logcollector/logrotation/keepcount" contains invalid value' )
				sys.exit(1)
		else:
			debug( LOGERROR, 'WARNING: baseconfig variable "logcollector/logrotation/keepcount" is not set' )
			debug( LOGERROR, 'WARNING: using "logcollector/logrotation/keepcount=%s" as default' % self._logrot_keepcnt )

		self._logrot_maxsize = ''
		if baseconfig.has_key('logcollector/logrotation/maxsize'):
			try:
				self._logrot_maxsize = baseconfig[ 'logcollector/logrotation/maxsize' ]
			except:
				pass
		if not self._logrot_maxsize:
			self._logrot_maxsize = '10M'
			debug( LOGERROR, 'WARNING: baseconfig variable "logcollector/logrotation/maxsize" is not set' )
			debug( LOGERROR, 'WARNING: using "logcollector/logrotation/maxsize=%s" as default' % self._logrot_maxsize )


		multi = ''
		if self._logrot_maxsize[-1].upper() in 'KMG':
			multi = self._logrot_maxsize[-1].upper()
			self._logrot_maxsize = self._logrot_maxsize[:-1]

		try:
			val = int(self._logrot_maxsize[:-1])
		except:
			val = 10
			multi = 'M'
		if multi == 'K':
			val *= 1024
		elif multi == 'M':
			val *= 1024 * 1024
		elif multi == 'G':
			val *= 1024 * 1024 * 1024
		self._logrot_maxsize = val

		self._realsocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
		self._realsocket.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
		self._realsocket.setblocking( 0 )
		fcntl.fcntl(self._realsocket.fileno(), fcntl.F_SETFD, 1)

		self.crypto_context = SSL.Context( SSL.SSLv23_METHOD )
		self.crypto_context.set_cipher_list('DEFAULT')
		self.crypto_context.set_options( SSL.OP_NO_SSLv2 )
		self.crypto_context.set_verify( SSL.VERIFY_PEER, self._verify_cert_cb )
		dir = '/etc/univention/ssl/%s' % baseconfig[ 'hostname' ]
		self.crypto_context.use_privatekey_file( os.path.join( dir, 'private.key' ) )
		self.crypto_context.use_certificate_file( os.path.join( dir, 'cert.pem' ) )
		self.crypto_context.load_verify_locations( os.path.join( dir, '/etc/univention/ssl/ucsCA', 'CAcert.pem' ) )

		self.connection = SSL.Connection( self.crypto_context , self._realsocket )
		self.connection.setblocking(0)
		self.connection.bind( ( '', self._port ) )
		debug( LOGDEBUG, 'Server listening to SSL connects' )
		self.connection.listen( 20 )

		notifier.socket_add( self.connection, self._incoming_connection )


	def _verify_cert_cb( self, conn, cert, errnum, depth, ok ):
		debug( LOGDEBUG, 'Got certificate: %s' % cert.get_subject() )
		debug( LOGDEBUG, 'Got certificate issuer: %s' % cert.get_issuer() )
		debug( LOGDEBUG, 'errnum=%d  depth=%d  ok=%d' % (errnum, depth, ok) )
		return ok


	def _incoming_connection( self, socket ):
		socket, addr = socket.accept()
		socket.setblocking( 0 )
		if addr:
			client = '%s:%d' % ( addr[ 0 ], addr[ 1 ] )
		else:
			client = ''

		debug( LOGERROR, 'incoming connection: %s' % client )

		# create new state
		state = { 'clientaddr': client,
				  'nextId': 1,
				  'inbuffer': '',
				  'outbuffer': '',
				  'targetdir': '',
				  'filelist': {} }
		self._connectionstates[ socket ] = state
		notifier.socket_add( socket , self._receive_data )

		return True


	def _receive_data( self, sock ):
		debug( LOGDEBUG, 'GOT NEW DATA' )

		if not self._connectionstates.has_key( sock ):
			debug( LOGERROR, 'unknown socket' )
			return True

		state = self._connectionstates[ sock ]
		data = ''

		try:
			data = sock.recv( 16384 )
		except SSL.WantReadError:
			# this error can be ignored (SSL need to do something)
			debug(LOGDEBUG, 'SSL.WantReadError')
			return True
		except ( SSL.SysCallError, SSL.Error ), error:
			debug( LOGINFO, 'SSL error: %s. Probably the socket was closed by the client.' % str( error ) )
			notifier.socket_remove( sock )
			del self._connectionstates[ sock ]
			sock.close()
			return False

		if not len( data ):
			notifier.socket_remove( sock )
			del self._connectionstates[ sock ]
			sock.close()
			return False

		state[ 'inbuffer' ] += data

		debug( LOGDEBUG, 'BUFFER: len=%d    got %d bytes' % (len(state['inbuffer']), len(data)))

		# repeat while enough data is present
		while len(state['inbuffer']) > 4:
			# get length of pickle object
			plen = struct.unpack('!I', state['inbuffer'][0:4])[0]
			if plen+4 <= len(state['inbuffer']):
				# unpickle data
				packet = cPickle.loads( state['inbuffer'][4:4+plen] )
				# remove data from buffer
				state['inbuffer'] = state['inbuffer'][4+plen:]

				# handle packet
				if type(packet) == type({}):
					if packet.has_key('action'):
						if packet['action'] == 'SETUP':
							self._handle_packet_setup( sock, state, packet )
						elif packet['action'] == 'DATA':
							self._handle_packet_data( sock, state, packet )
			else:
				# not enough data
				break

		# send ACKs
		if self._ack_queue:
			packet = { 'id': 0,
					   'action': 'ACK',
					   'data': self._ack_queue }
			self._send_pickled( sock, packet )
			self._ack_queue = []

		return True
예제 #23
0
def _stdin(fd):
    print 'read: ' + os.read(fd, 512)
    notifier.socket_remove(0)
    return False
예제 #24
0
파일: client.py 프로젝트: B-Rich/smart
			recv = None
		except SSL.Error:
			error = sock.getsockopt( socket.SOL_SOCKET, socket.SO_ERROR )
			# lost connection: UMC daemon died probably
			if error == errno.EPIPE:
				recv = None
			else:
				return True

		if not recv:
			self.signal_emit( 'closed' )
			try:
				sock.close()
			except:
				pass
			notifier.socket_remove( sock )
			return False

		if self.__buffer:
			recv = self.__buffer + recv
			self.__buffer = ''
		try:
			while recv:
				response = Response()
				recv = response.parse( recv )
				self._handle( response )
		except IncompleteMessageError:
			self.__buffer = recv
			# waiting for the rest
		except ( ParseError, UnknownCommandError ), e:
			self.signal_emit( 'error', e )