Exemple #1
0
    def process(self, *args, **kwargs):
        with make_db(self.db) as db:
            try:
                nodes = db.query(models.TrNode)
                for node in nodes:
                    r = db.query(
                        func.sum(
                            models.TrOnline.input_total).label("input_total"),
                        func.sum(models.TrOnline.output_total).label(
                            "output_total")).filter(
                                models.TrOnline.account_number ==
                                models.TrAccount.account_number,
                                models.TrAccount.customer_id ==
                                models.TrCustomer.customer_id,
                                models.TrCustomer.node_id == node.id).first()
                    if r and all([r.input_total, r.output_total]):
                        stat = models.TrFlowStat()
                        stat.node_id = node.id
                        stat.stat_time = int(time.time())
                        stat.input_total = r.input_total
                        stat.output_total = r.output_total
                        db.add(stat)
                db.commit()
                logger.info("flow stat task done")
            except Exception as err:
                db.rollback()
                logger.error('flow_stat_job err,%s' % (str(err)))

        return 120.0
    def acctounting(self):
        if not self.account:
            return logger.error(
                "[Acct] Received an accounting update request but user[%s] not exists"
                % self.request.account_number)

        ticket = Storage(**self.request)
        online = self.get_online(ticket.nas_addr, ticket.acct_session_id)
        if not online:
            sessiontime = ticket.acct_session_time
            updatetime = datetime.datetime.now()
            _starttime = updatetime - datetime.timedelta(seconds=sessiontime)
            online = Storage(
                account_number=self.account.account_number,
                nas_addr=ticket.nas_addr,
                acct_session_id=ticket.acct_session_id,
                acct_start_time=_starttime.strftime("%Y-%m-%d %H:%M:%S"),
                framed_ipaddr=ticket.framed_ipaddr,
                mac_addr=ticket.mac_addr,
                nas_port_id=ticket.nas_port_id,
                billing_times=ticket.acct_session_time,
                input_total=self.get_input_total(),
                output_total=self.get_output_total(),
                start_source=STATUS_TYPE_UPDATE)
            self.add_online(online)

        self.billing(online)
        logger.info('%s Accounting update request, update online' %
                    self.account.account_number)
Exemple #3
0
    def bill_botimes(self,online, product):
        #买断时长
        logger.info('%s > Buyout long time billing ' % self.account.account_number)
        time_length = self.get_user_time_length()
        sessiontime = self.request.acct_session_time
        billing_times = online.billing_times
        acct_times = sessiontime - billing_times
        user_time_length = time_length - acct_times
        if user_time_length < 0 :
            user_time_length = 0

        self.update_billing(Storage(
            account_number = online.account_number,
            nas_addr = online.nas_addr,
            acct_session_id = online.acct_session_id,
            acct_start_time = online.acct_start_time,
            acct_session_time = self.request.acct_session_time,
            input_total = self.get_input_total(),
            output_total = self.get_output_total(),
            acct_times = acct_times,
            acct_flows = 0,
            acct_fee = 0,
            actual_fee = 0,
            balance = 0,
            time_length = user_time_length,
            flow_length = 0,
            is_deduct = 1,
            create_time = datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S")
        ))
    
        if user_time_length == 0 :
            self.disconnect(online)
    def acctounting(self):
        if not self.account:
            return logger.error(
                "[Acct] Received an accounting update request but user[%s] not exists"% self.request.account_number)  

        ticket = Storage(**self.request)
        _datetime = datetime.datetime.now() 
        online = self.get_online(ticket.nas_addr,ticket.acct_session_id)    
        if not online:
            session_time = ticket.acct_session_time 
            stop_time = _datetime.strftime( "%Y-%m-%d %H:%M:%S")
            start_time = (_datetime - datetime.timedelta(seconds=int(session_time))).strftime( "%Y-%m-%d %H:%M:%S")
            ticket.acct_start_time = start_time
            ticket.acct_stop_time = stop_time
            ticket.start_source= STATUS_TYPE_STOP
            ticket.stop_source = STATUS_TYPE_STOP
            self.add_ticket(ticket)
        else:
            self.del_online(ticket.nas_addr,ticket.acct_session_id)
            ticket.acct_start_time = online.acct_start_time
            ticket.acct_stop_time= _datetime.strftime( "%Y-%m-%d %H:%M:%S")
            ticket.start_source = online.start_source
            ticket.stop_source = STATUS_TYPE_STOP
            self.add_ticket(ticket)

        self.billing(online)
        logger.info('%s Accounting stop request, remove online'% self.account.account_number)
Exemple #5
0
 def process(self, message):
     datagram, host, port = msgpack.unpackb(message[0])
     reply = self.processAuth(datagram, host, port)
     if not reply:
         return
     self.do_stat(reply.code)
     logger.info("[Radiusd] :: Send radius response: %s" % repr(reply))
     if self.config.system.debug:
         logger.debug(reply.format_str())
     self.pusher.push(msgpack.packb([reply.ReplyPacket(), host, port]))
Exemple #6
0
 def __init__(self, config, service='auth'):
     self.config = config
     self.service = service
     self.pusher = ZmqPushConnection(
         ZmqFactory(),
         ZmqEndpoint('bind', 'ipc:///tmp/radiusd-%s-message' % service))
     self.puller = ZmqPullConnection(
         ZmqFactory(),
         ZmqEndpoint('bind', 'ipc:///tmp/radiusd-%s-result' % service))
     self.puller.onPull = self.reply
     logger.info("init %s master pusher : %s " %
                 (self.service, self.pusher))
     logger.info("init %s master puller : %s " %
                 (self.service, self.puller))
Exemple #7
0
    def processAcct(self, datagram, host, port):
        try:
            bas = self.find_nas(host)
            if not bas:
                raise PacketError(
                    '[Radiusd] :: Dropping packet from unknown host %s' % host)

            secret, vendor_id = bas['bas_secret'], bas['vendor_id']
            req = self.createAcctPacket(packet=datagram,
                                        dict=self.dict,
                                        secret=six.b(str(secret)),
                                        vendor_id=vendor_id)

            self.do_stat(req.code, req.get_acct_status_type())

            logger.info("[Radiusd] :: Received radius request: %s" %
                        (repr(req)))
            if self.config.system.debug:
                logger.debug(req.format_str())

            if req.code != packet.AccountingRequest:
                raise PacketError(
                    'non-AccountingRequest packet on authentication socket')

            if not req.VerifyAcctRequest():
                raise PacketError('VerifyAcctRequest error')

            reply = req.CreateReply()
            self.pusher.push(msgpack.packb([reply.ReplyPacket(), host, port]))
            self.do_stat(reply.code)
            logger.info("[Radiusd] :: Send radius response: %s" % repr(reply))
            if self.config.system.debug:
                logger.debug(reply.format_str())

            status_type = req.get_acct_status_type()
            if status_type in self.acct_class:
                acct_func = self.acct_class[status_type](
                    self.db_engine, self.mcache, None,
                    req.get_ticket()).acctounting
                reactor.callLater(0.1, acct_func)
            else:
                logger.error('status_type <%s> not support' % status_type)
        except Exception as err:
            self.do_stat(0)
            errstr = 'RadiusError:Dropping invalid acct packet from {0} {1},{2}'.format(
                host, port, utils.safeunicode(err))
            logger.error(errstr)
            import traceback
            traceback.print_exc()
Exemple #8
0
    def process(self, *args, **kwargs):
        logger.info("start process expire_notify task")
        _enable = int(self.get_param_value("expire_notify_enable", 0))
        if not _enable:
            return 120.0
        _ndays = self.get_param_value("expire_notify_days")
        notify_tpl = self.get_param_value("expire_notify_tpl")
        notify_url = self.get_param_value("expire_notify_url")

        with make_db(self.db) as db:
            _now = datetime.datetime.now()
            _date = (datetime.datetime.now() +
                     datetime.timedelta(days=int(_ndays))).strftime("%Y-%m-%d")
            expire_query = db.query(
                models.TrAccount.account_number, models.TrAccount.expire_date,
                models.TrCustomer.email, models.TrCustomer.mobile).filter(
                    models.TrAccount.customer_id ==
                    models.TrCustomer.customer_id,
                    models.TrAccount.expire_date <= _date,
                    models.TrAccount.expire_date >= _now.strftime("%Y-%m-%d"),
                    models.TrAccount.status == 1)

            logger.info('expire_notify total: %s' % expire_query.count())
            for account, expire, email, mobile in expire_query:
                dispatch.pub('account_expire', account, async=False)
                ctx = notify_tpl.replace('#account#', account)
                ctx = ctx.replace('#expire#', expire)
                topic = ctx[:ctx.find('\n')]
                if email:
                    self.send_mail(email, topic,
                                   ctx).addCallbacks(logger.info, logger.error)

                url = notify_url.replace('{account}', account)
                url = url.replace('{expire}', expire)
                url = url.replace('{email}', email)
                url = url.replace('{mobile}', mobile)
                url = url.encode('utf-8')
                url = quote(url, ":?=/&")
                httpclient.get(url).addCallbacks(lambda r: logger.info(r.code),
                                                 logger.error)

        return self.get_notify_interval()
Exemple #9
0
 def __init__(self, config, dbengine):
     self.config = config
     self.dict = dictionary.Dictionary(
         os.path.join(os.path.dirname(toughradius.__file__),
                      'dictionarys/dictionary'))
     self.db_engine = dbengine or get_engine(config)
     self.mcache = mcache.Mcache()
     self.pusher = ZmqPushConnection(
         ZmqFactory(),
         ZmqEndpoint('connect', 'ipc:///tmp/radiusd-acct-result'))
     self.stat_pusher = ZmqPushConnection(
         ZmqFactory(), ZmqEndpoint('connect',
                                   'ipc:///tmp/radiusd-stat-task'))
     self.puller = ZmqPullConnection(
         ZmqFactory(),
         ZmqEndpoint('connect', 'ipc:///tmp/radiusd-acct-message'))
     self.puller.onPull = self.process
     logger.info("init acct worker pusher : %s " % (self.pusher))
     logger.info("init acct worker puller : %s " % (self.puller))
     logger.info("init auth stat pusher : %s " % (self.stat_pusher))
     self.acct_class = {
         STATUS_TYPE_START: RadiusAcctStart,
         STATUS_TYPE_STOP: RadiusAcctStop,
         STATUS_TYPE_UPDATE: RadiusAcctUpdate,
         STATUS_TYPE_ACCT_ON: RadiusAcctOnoff,
         STATUS_TYPE_ACCT_OFF: RadiusAcctOnoff
     }
Exemple #10
0
    def process(self, *args, **kwargs):
        with make_db(self.db) as db:
            try:
                nas_list = db.query(models.TrBas)
                for nas in nas_list:
                    if not nas.dns_name:
                        continue
                    results, _, _ = yield client.lookupAddress(nas.dns_name)
                    if not results:
                        logger.info("domain {0} resolver empty".format(
                            nas.dns_name))

                    if results[0].type == dns.A:
                        ipaddr = ".".join(
                            str(i) for i in struct.unpack(
                                "BBBB", results[0].payload.address))
                        if ipaddr:
                            nas.ip_addr = ipaddr
                            db.commit()
                            logger.info(
                                "domain {0} resolver {1}  success".format(
                                    nas.dns_name, ipaddr))
                    else:
                        logger.info("domain {0} no ip address,{1}".format(
                            nas.dns_name, repr(results)))

            except Exception as err:
                logger.error('ddns process error %s' %
                             utils.safeunicode(err.message))
        defer.returnValue(60)
Exemple #11
0
    def process(self, *args, **kwargs):
        with make_db(self.db) as db:
            try:
                nodes = db.query(models.TrNode)
                for node in nodes:
                    online_count = db.query(models.TrOnline.id).filter(
                        models.TrOnline.account_number ==
                        models.TrAccount.account_number,
                        models.TrAccount.customer_id ==
                        models.TrCustomer.customer_id,
                        models.TrCustomer.node_id == node.id).count()
                    stat = models.TrOnlineStat()
                    stat.node_id = node.id
                    stat.stat_time = int(time.time())
                    stat.total = online_count
                    db.add(stat)
                db.commit()
                logger.info("online stat task done")
            except Exception as err:
                db.rollback()
                logger.error('online_stat_job err,%s' % (str(err)))

        return 120.0
Exemple #12
0
 def bill_pptimes(self,online,product):
     # 预付费时长
     logger.info('%s > Prepaid long time billing ' % self.account.account_number)
     user_balance = self.get_user_balance()
     sessiontime = decimal.Decimal(self.request.acct_session_time)
     billing_times = decimal.Decimal(online.billing_times)
     acct_times = sessiontime - billing_times
     fee_price = decimal.Decimal(product['fee_price'])
     usedfee = acct_times/decimal.Decimal(3600) * fee_price
     usedfee = actual_fee = int(usedfee.to_integral_value())
     balance = user_balance - usedfee
     
     if balance < 0 :  
         balance = 0
         actual_fee = user_balance
         
     self.update_billing(Storage(
         account_number = online.account_number,
         nas_addr = online.nas_addr,
         acct_session_id = online.acct_session_id,
         acct_start_time = online.acct_start_time,
         acct_session_time = self.request.acct_session_time,
         input_total = self.get_input_total(),
         output_total = self.get_output_total(),
         acct_times = int(acct_times.to_integral_value()),
         acct_flows = 0,
         acct_fee = usedfee,
         actual_fee = actual_fee,
         balance = balance,
         time_length = 0,
         flow_length = 0,
         is_deduct = 1,
         create_time = datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S")
     ))
     
     if balance == 0 :
         self.disconnect(online)
Exemple #13
0
    def acctounting(self):
        if self.is_online(self.request.nas_addr, self.request.acct_session_id):
            return logger.error('online %s is exists' %
                                self.request.acct_session_id)

        if not self.account:
            return logger.error('user %s not exists' %
                                self.request.account_number)

        online = Storage(account_number=self.request.account_number,
                         nas_addr=self.request.nas_addr,
                         acct_session_id=self.request.acct_session_id,
                         acct_start_time=datetime.datetime.now().strftime(
                             "%Y-%m-%d %H:%M:%S"),
                         framed_ipaddr=self.request.framed_ipaddr,
                         mac_addr=self.request.mac_addr,
                         nas_port_id=self.request.nas_port_id,
                         billing_times=0,
                         input_total=0,
                         output_total=0,
                         start_source=STATUS_TYPE_START)
        self.add_online(online)
        logger.info('%s Accounting start request, add new online' %
                    online.account_number)
Exemple #14
0
 def __init__(self, config, dbengine):
     self.config = config
     self.dict = dictionary.Dictionary(
         os.path.join(os.path.dirname(toughradius.__file__),
                      'dictionarys/dictionary'))
     self.db_engine = dbengine or get_engine(config)
     self.aes = utils.AESCipher(key=self.config.system.secret)
     self.mcache = mcache.Mcache()
     self.pusher = ZmqPushConnection(
         ZmqFactory(),
         ZmqEndpoint('connect', 'ipc:///tmp/radiusd-auth-result'))
     self.stat_pusher = ZmqPushConnection(
         ZmqFactory(), ZmqEndpoint('connect',
                                   'ipc:///tmp/radiusd-stat-task'))
     self.puller = ZmqPullConnection(
         ZmqFactory(),
         ZmqEndpoint('connect', 'ipc:///tmp/radiusd-auth-message'))
     self.puller.onPull = self.process
     logger.info("init auth worker pusher : %s " % (self.pusher))
     logger.info("init auth worker puller : %s " % (self.puller))
     logger.info("init auth stat pusher : %s " % (self.stat_pusher))
Exemple #15
0
 def __init__(self,taskd, **kwargs):
     TaseBasic.__init__(self,taskd, **kwargs)
     self.statdata = statistics.MessageStat()
     self.puller = ZmqPullConnection(ZmqFactory(), ZmqEndpoint('bind', 'ipc:///tmp/radiusd-stat-task'))
     self.puller.onPull = self.update_stat
     logger.info("init Radius stat puller : %s " % ( self.puller))
 def acctounting(self):
     self.unlock_online(self.request.nas_addr, None)
     logger.info('bas accounting onoff success')
Exemple #17
0
    def processAuth(self, datagram, host, port):
        try:
            bas = self.find_nas(host)
            if not bas:
                raise PacketError(
                    '[Radiusd] :: Dropping packet from unknown host %s' % host)

            secret, vendor_id = bas['bas_secret'], bas['vendor_id']
            req = self.createAuthPacket(packet=datagram,
                                        dict=self.dict,
                                        secret=six.b(str(secret)),
                                        vendor_id=vendor_id)

            self.do_stat(req.code)

            logger.info("[Radiusd] :: Received radius request: %s" %
                        (repr(req)))
            if self.config.system.debug:
                logger.debug(req.format_str())

            if req.code != packet.AccessRequest:
                raise PacketError(
                    'non-AccessRequest packet on authentication socket')

            reply = req.CreateReply()
            reply.vendor_id = req.vendor_id

            aaa_request = dict(account_number=req.get_user_name(),
                               domain=req.get_domain(),
                               macaddr=req.client_mac,
                               nasaddr=req.get_nas_addr(),
                               vlanid1=req.vlanid1,
                               vlanid2=req.vlanid2)

            auth_resp = RadiusAuth(self.db_engine, self.mcache, self.aes,
                                   aaa_request).authorize()

            if auth_resp['code'] > 0:
                reply['Reply-Message'] = auth_resp['msg']
                reply.code = packet.AccessReject
                return reply

            if 'bypass' in auth_resp and int(auth_resp['bypass']) == 0:
                is_pwd_ok = True
            else:
                is_pwd_ok = req.is_valid_pwd(auth_resp.get('passwd'))

            if not is_pwd_ok:
                reply['Reply-Message'] = "password not match"
                reply.code = packet.AccessReject
                return reply
            else:
                if u"input_rate" in auth_resp and u"output_rate" in auth_resp:
                    reply = rate_process.process(
                        reply,
                        input_rate=auth_resp['input_rate'],
                        output_rate=auth_resp['output_rate'])

                attrs = auth_resp.get("attrs") or {}
                for attr_name in attrs:
                    try:
                        # todo: May have a type matching problem
                        reply.AddAttribute(utils.safestr(attr_name),
                                           attrs[attr_name])
                    except Exception as err:
                        errstr = "RadiusError:current radius cannot support attribute {0},{1}".format(
                            attr_name, utils.safestr(err.message))
                        logger.error(errstr)

                for attr, attr_val in req.resp_attrs.iteritems():
                    reply[attr] = attr_val

            reply['Reply-Message'] = 'success!'
            reply.code = packet.AccessAccept
            if not req.VerifyReply(reply):
                raise PacketError('VerifyReply error')
            return reply
        except Exception as err:
            self.do_stat(0)
            errstr = 'RadiusError:Dropping invalid auth packet from {0} {1},{2}'.format(
                host, port, utils.safeunicode(err))
            logger.error(errstr)
            import traceback
            traceback.print_exc()
Exemple #18
0
def run_worker(config, dbengine):
    logger.info('start radius worker: %s' % RADIUSAuthWorker(config, dbengine))
    logger.info('start radius worker: %s' % RADIUSAcctWorker(config, dbengine))
Exemple #19
0
 def add_handler(self, handle_cls, path, handle_params={}):
     logger.info("add handler [%s:%s]" % (path, repr(handle_cls)))
     self.handlers[path]= (path, handle_cls, handle_params)
Exemple #20
0
 def add_handler(self, handle_cls, path, handle_params={}):
     logger.info("add handler [%s:%s]" % (path, repr(handle_cls)))
     self.handlers[path] = (path, handle_cls, handle_params)