예제 #1
0
    def sokect_handler(self, socket, address):
        if self.debug and logger.is_debug():
            logger.get_logger().debug('%s: accept connection', address)

        # send welcome
        socket.sendall(Messager.data_for_welcome())
        conn_inbox = Queue()
        answer_thread = gevent.spawn(self.answer_fiber, socket, address, conn_inbox)
        while self._running:
            try:
                message = Messager.receive_msg(socket)
                if not message:
                    if self.debug and logger.is_debug():
                        logger.get_logger().debug('%s: connection has been closed by client.', address)
                    break;
                if isinstance(message, Answer):
                    logger.get_logger().error('%s: unexpected message received: %s', address, message)
                    continue
                elif isinstance(message, Query):
                    if self.debug and logger.is_debug():
                        logger.get_logger().debug('%s: message received: %s', address, message)
                    message.inbox = conn_inbox
                    self._query_queue.put(message)
            except gevent.socket.error as ex:
                logger.get_logger().error('%s: socket error: %s', address, repr(ex))
                break
            except:
                logger.get_logger().error('%s: exception: %s', address, traceback.format_exc())
                break

        if self.debug and logger.is_debug():
            logger.get_logger().debug('%s: close connection', address)
        socket.close()
        # stop answer thread
        conn_inbox.put(StopIteration)
예제 #2
0
    def answer_fiber(self, socket, address, inbox):
        for answer in inbox:
            if not isinstance(answer, Answer):
                logger.get_logger().error('invalid answer %s', answer)
                continue

            if self.debug and logger.is_debug():
                logger.get_logger().debug('%s: reply answer: %s', address, answer)
            socket.sendall(answer.get_data())

        if self.debug and logger.is_debug():
            logger.get_logger().debug('%s: answer fiber stop', address)
예제 #3
0
 def get_passwd(self):
     try:
         return self.PwDecrypt(self.get(2)[0])
     except:
         if is_debug():
             debug('Exception while trying to get password')
         return None
예제 #4
0
    def receive_next_msg(self):
        if self.protocol == 'tcp':
            message = Messager.receive_msg(self._socket)

        elif self.protocol == 'udp':
            pkt, address = self.unitive_recvfrom(65535)
            message = Messager.message_from_data(pkt)

        if self.debug and logger.is_debug():
            if isinstance(message, Query):
                logger.get_logger().debug('SQ:%d method=%s', message.qid, message.method)
            elif isinstance(message, Answer):
                logger.get_logger().debug('SA:%d status=%d', message.qid, message.status)

        if not message:
            raise Exception('Recieved Unknown packet')

        if isinstance(message, Answer):
            qid = message.qid
            if self.pending.get(qid):
                del self.pending[qid]
            status = message.status
            if status:
                raise ProxyError(qid, status, message.data)
        return message;
예제 #5
0
    def send_accept(self, req, radiusnas, time_available, speed_ul, speed_dl,
                    data_limit):
        reply = req.CreateReply()
        reply.source = req.source
        reply.code = packet.AccessAccept

        reply.set_session_timeout(time_available)
        reply.set_idle_timeout(time_available)
        reply.set_intrim_update()
        if speed_dl:
            reply.set_special_int(radiusnas.vendor_id, "speed_dl",
                                  int(speed_dl))
        if speed_ul:
            reply.set_special_int(radiusnas.vendor_id, "speed_ul",
                                  int(speed_ul))
        #setting data limits is a bit tricky, some routers accept single value for total data.
        #some accept different for dl/ul
        reply.set_special_int(radiusnas.vendor_id, "data_limit",
                              int(data_limit))
        reply.set_special_int(radiusnas.vendor_id, "dl_data_limit",
                              int(data_limit))
        reply.set_special_int(radiusnas.vendor_id, "ul_data_limit",
                              int(data_limit))
        req.sock.sendto(reply.ReplyPacket(), reply.source)

        if is_debug():
            debug("[Auth] send an authentication accept,user[%s]"\
                %(req.get_username()))
예제 #6
0
 def get_username(self):
     try:
         return tools.DecodeString(self.get(1)[0])
     except:
         if is_debug():
             exception('Exception while trying to get username')
         return None
예제 #7
0
 def get_nasid(self):
     try:
         return self.get(32)[0]
     except:
         if is_debug():
             exception('Exception while trying to get nas id')
         return None
예제 #8
0
 def get_acctstatustype(self):
     try:
         return tools.DecodeInteger(self.get(40)[0])
     except:
         if is_debug():
             exception(
                 'Exception while trying to get nas accounting status')
         return None
예제 #9
0
 def __init__(self, setting):
     self.setting = setting
     self.debug = setting.get('debug', False)
     self._running = True
     self._adapters = {}
     self._proxies = {}
     if self.debug and logger.is_debug():
         logger.get_logger().debug("application setting %s", setting)
예제 #10
0
 def get_accnt_sessionid(self):
     try:
         return self.get(44)[0]
     except:
         if is_debug():
             exception(
                 'Exception while trying to get accounting session id')
         return None
예제 #11
0
    def connect(self):
        if self.protocol == 'tcp':
            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        elif self.protocol == 'udp':
            self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        self._socket.connect((self.host, self.port))
        if self.debug and logger.is_debug():
            ip, port = self._socket.getsockname()
            logger.get_logger().debug('address = %s:%d' % (ip, port))

        if self.welcome:
            type = Messager.receive_msg_type(self._socket)
            if type != MESSAGE_TYPE_WELCOME:
                raise Exception('Imcomplete message')

            if self.debug and logger.is_debug():
                logger.get_logger().debug('S.WELCOME')
예제 #12
0
    def send_quest(self, qid, method, params, twoway=True):
        if qid:
            self.pending[qid] = time.time()

        if self.debug and logger.is_debug():
            logger.get_logger().debug('CQ:%d service=%s method=%s', qid, self.service, method)

        self.unitive_send(Messager.data_for_query(qid, self.service, method, params))
        return qid
예제 #13
0
    def process(self, req):
        attr_keys = list(req.keys())
        if is_debug():
            log_ctx.base_info(ip=req.source[0], msgtype='ACCOUNTING PKT')
            #for attr in attr_keys:
            debug_info = '\t\t'.join("%s: %s" % (attr, req[attr])
                                     for attr in attr_keys)
            debug("Accounting packet from :%s [%s]" %
                  (req.source[0], debug_info))

        username = req.get_username()
        if not username:
            debug('ERROR no username provided')
            return self.send_response(req)

        radiususer = db.get_radiususer_from_name(username)
        if not radiususer:
            debug('ERROR radius user not found in DB')
            return self.send_response(req)
        if not radiususer.active:
            debug('ERROR radius user is not active')
            return self.send_response(req)

        radiusnas_id = radiususer.nas_id
        radiusnas = db.get_nas_from_id(radiusnas_id)

        if not radiusnas:
            debug('ERROR no radiusnas')
            return self.send_response(req)

        log_ctx.add_nas_info(nasid=radiusnas_id, siteid=radiusnas.siteid)

        req.secret = radiusnas.secret

        reply = req.CreateReply()
        reply.source = req.source

        acct_status_type = req.get_acctstatustype()

        if acct_status_type == STATUS_TYPE_START:
            log_ctx.update_packet_type('Accounting Start')
            return self.start_accounting(req, radiusnas)
        elif acct_status_type == STATUS_TYPE_STOP:
            log_ctx.update_packet_type('Accounting Stop')
            return self.stop_accounting(req, radiusnas)
        elif acct_status_type == STATUS_TYPE_UPDATE:
            log_ctx.update_packet_type('Accounting Status')
            return self.update_accounting(req, radiusnas)
        elif acct_status_type == STATUS_TYPE_NAS_ON or \
             acct_status_type == STATUS_TYPE_NAS_OFF  :
            log_ctx.update_packet_type('Accounting NAS On/Off')
            return self.nasonoff_accounting(req, radiusnas, acct_status_type)
        else:
            return self.send_response(req)
예제 #14
0
    def stop_accounting(self, req, radiusnas):
        username = req.get_username()

        if not username:
            if is_debug():
                debug('Got empty username')
            return self.send_response(req)

        sessionid = req.get_accnt_sessionid()
        if not sessionid:
            if is_debug():
                debug('Got empty sessionid')
            return self.send_response(req)

        radiususer = db.get_radiususer(radiusnas.id, username)
        if not radiususer:
            if is_debug():
                debug('Got unknown username :%s' % username)
            return self.send_response(req)

        radiussession = db.get_radiussession(radiusnas, radiususer, sessionid)

        if not radiussession:
            if is_debug():
                debug('No session found ')
            return self.send_response(req)

        data_used = req.get_totaldatausage()
        time_used = round(req.get_acctsessiontime() / 60, 0)
        db.update_radiussession(radiussession.id,
                                data_used=data_used,
                                time_used=time_used,
                                disassoc=True)
        send_accounting_stop_signal(username)
        if is_debug():
            debug(
                '[Acct] User[%s] Session-ID[%s] Used[%s Mb] in [%s mins] STOP'
                % (radiususer.radiususer, radiussession.accnt_sessionid,
                   data_used, time_used))
        return self.send_response(req)
예제 #15
0
 def _handle_wildcard_servant(self, query):
     if self.debug and logger.is_debug():
         logger.get_logger().debug('handle_wildcard_servant: %s', query)
     try:
         result = self._wildcard_servant(query.service, query.method, query.params)
         if query.qid:
             query.inbox.put(Answer(query.qid, 0, result))
     except proxy.ProxyError as ex:
         if query.qid:
             query.inbox.put(Answer(ex.qid, ex.status, ex.params))
     except:
         if query.qid:
             query.inbox.put(Answer(query.qid, 1, self._make_exception_params(query)))
예제 #16
0
    def activate(self):
        for i in range(self._servant_worker_num):
            gevent.spawn(self.servant_worker)

        self._pool = Pool(self._accept_pool_num)
        endpoint = self._endpoint
        try:
            service, proto, host, port = proxy.parse_endpoint(endpoint)
            if proto != 'tcp':
                raise proxy.ProxyError(1, 'only tcp server supported now')
            server = StreamServer((host, int(port)), self.sokect_handler, spawn=self._pool)
            if self.debug and logger.is_debug():
                logger.get_logger().debug('adapter start %s', endpoint)
            self._servers.append(server)
            server.start()
        except:
            logger.get_logger().error('start adapter fail %s', endpoint, exc_info = 1)
예제 #17
0
    def _handle_normal_servant(self, query):
        called_method = query.method
        if self.debug and logger.is_debug():
            logger.get_logger().debug('handle_normal_servant: %s', query)
        servant = self._servants.get(query.service)
        if not servant:
            #build exception at params
            exdict = {}
            exdict['exception'] = 'ServantNotFound'
            exdict['code'] = 1
            exdict['message'] = "servant %s not found in adapter %s" % (query.service, self._endpoint)
            exdict['raiser'] = self._endpoint
            if query.qid:
                query.inbox.put(Answer(query.qid, 1, exdict))
            else:
                logger.get_logger().warning("%s.%s %s", query.service, called_method, exdict)
            return

        if called_method[0] == '\0':
            callback = servant._special_callback(query)
        else:
            callback = servant.find_method(called_method)

        if not callback:
            self._method_not_found(called_method, query)
            return

        try:
            time_start = time.time()
            servant.before_method_call(called_method, time_start)
            result = callback(Params(query.params))
            servant.after_method_call(called_method, time_start, (time.time() - time_start) * 1000)
            if query.qid:
                result = dict(result)
                query.inbox.put(Answer(query.qid, 0, result))
        except proxy.ProxyError as ex:
            if query.qid:
                query.inbox.put(Answer(query.qid, ex.status, ex.params))
            else:
                logger.get_logger().warning("%s.%s %d %s", query.service, called_method, ex.status, ex.params)
        except:
            logger.get_logger().error("query %d handle fail", query.qid, exc_info = 1)
            if query.qid:
                query.inbox.put(Answer(query.qid, 1, self._make_exception_params(query)))
예제 #18
0
    def start_accounting(self, req, radiusnas):
        username = req.get_username()

        if not username:
            if is_debug():
                debug('Got empty username')
            return self.send_response(req)

        sessionid = req.get_accnt_sessionid()
        if not sessionid:
            if is_debug():
                debug('Got empty sessionid')
            return self.send_response(req)

        radiususer = db.get_radiususer(radiusnas.id, username)
        if not radiususer:
            if is_debug():
                debug('Got unknown username :%s' % username)
            return self.send_response(req)

        framed_ip_address = req.get_framed_ip()
        if not framed_ip_address:
            if is_debug():
                debug('ERROR no Framed-IP provided')
            return self.send_response(req)

        send_accounting_start_signal(username)

        radiussession = db.create_radius_session(radiusnas, radiususer,
                                                 sessionid, framed_ip_address)
        if not radiussession:
            if is_debug():
                debug(
                    'Something went wrong while accounting session creation ')
            return self.send_response(req)

        if is_debug():
            debug('[Acct] User[%s],Nas[%s] billing starting' %
                  (radiususer.radiususer, radiusnas.id))

        return self.send_response(req)
예제 #19
0
 def send_answer(self, qid, status, data):
     if self.debug and logger.is_debug():
         logger.get_logger().debug('CA:%d %d %s', qid, status, data)
     self.unitive_send(Messager.data_for_answer(qid, status, data))
예제 #20
0
    def process(self, req):
        attr_keys = list(req.keys())
        if is_debug():
            # for attr in attr_keys:
            log_ctx.base_info(ip=req.source[0], msgtype='AUTH PKT')
            debug_info = '\t\t'.join("%s: %s" % (attr, req[attr])
                                     for attr in attr_keys)
            debug("Received [%s]" % (debug_info))

        username = req.get_username()
        if not username:
            debug('ERROR no username provided')
            return self.send_reject(req, 'ERROR no username provided')

        radiususer = db.get_radiususer_from_name(username)
        if not radiususer:
            debug('ERROR radius user not found in DB')
            return self.send_reject(
                req,
                'ERROR no radiususer found with given username or radiususer not active'
            )

        if not radiususer.active:
            debug('ERROR radius user is inactive')
            return self.send_reject(
                req,
                'ERROR no radiususer found with given username or radiususer not active'
            )

        radiusnas_id = radiususer.nas_id
        radiusnas = db.get_nas_from_id(radiusnas_id)

        if not radiusnas:
            return self.send_reject(req, 'ERROR unknown NAS ID')
        log_ctx.add_nas_info(nasid=radiusnas_id, siteid=radiusnas.siteid)

        #set secret
        req.secret = radiusnas.secret

        if not req.is_valid_pwd(radiususer.radiuspass):
            if is_debug():
                debug('Got unknown password ')
            return self.send_reject(req, 'ERROR Incorrect password')

        session_expiry = arrow.get(radiususer.stoptime)
        time_available = session_expiry.timestamp - arrow.utcnow().timestamp
        if not time_available > 0:
            if is_debug():
                debug('Guestsession:%s expired at :%s ' %
                      (radiususer.stoptime, session_expiry.humanize()))
            return self.send_reject(req, 'ERROR expired user credentials')

        rcvd_mac = req.get_macaddr()
        if not rcvd_mac:
            return self.send_reject(req,
                                    'ERROR no Calling-Station-Id provided')

        if not rcvd_mac.lower() == radiususer.mac.lower():
            if is_debug():
                debug('Expected MAC :%s got ;%s ' % (radiususer.mac, rcvd_mac))
            return self.send_reject(
                req, 'ERROR Invalid credentials for this device')

        return self.send_accept(
            req,
            radiusnas,
            time_available=time_available,
            speed_ul=int(radiususer.speed_ul),  #convert to bps
            speed_dl=int(radiususer.speed_dl),
            data_limit=radiususer.data_limit)  #convert to bytes