#!/usr/bin/python
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""authorizer: processes Terms of Service acceptance for users."""

import logging
import re
import subprocess
import sys
import time

import options
import tornado.escape
import tornado.httpclient
import tornado.ioloop
import tornado.netutil


optspec = """
authorizer [options...]
--
c,filter-chain= iptables chain to operate on [captive-portal-guests]
C,ca-certs=     path to CA certificates [/etc/ssl/certs/ca-certificates.crt]
d,dry-run       don't modify iptables
m,max-age=      oldest acceptance to consider as valid, in days [60]
n,nat-chain=    iptables NAT chain to operate on [captive-portal-guests-nat]
U,unix-path=    Unix socket to listen on [/tmp/authorizer.sock]
u,url=          URL to query for authentication [https://fiber-managed-wifi-tos.appspot.com/tos-accepted?id=%(mac)s]
"""

MAX_TRIES = 300

known_users = {}


def ip46tables(*args):
  if opt.dry_run:
    return 0

  x = subprocess.call(['iptables'] + list(args))
  y = subprocess.call(['ip6tables'] + list(args))
  return x | y


class Checker(object):
  """Manage checking and polling for Terms of Service acceptance."""

  def __init__(self, mac_addr, url):
    self.mac_addr = mac_addr
    self.url = url % {'mac': mac_addr}
    self.tries = 0
    self.callback = None

  def check(self):
    """Check if a remote service knows about a device with a supplied MAC."""
    logging.info('Checking TOS for %s', self.mac_addr)
    http_client = tornado.httpclient.HTTPClient()
    response = http_client.fetch(self.url, ca_certs=opt.ca_certs)
    response_obj = tornado.escape.json_decode(response.body)
    accepted_time = response_obj.get('accepted')
    self.tries += 1

    accepted = False
    if accepted_time:
      if accepted_time + (opt.max_age * 86400) > time.time():
        accepted = True
        if self.callback: self.callback.stop()
        logging.info('TOS accepted for %s', self.mac_addr)

        known_users[self.mac_addr] = response_obj
        result = ip46tables('-A', opt.filter_chain, '-m', 'mac',
                            '--mac-source', self.mac_addr, '-j', 'ACCEPT')
        result |= ip46tables('-t', 'nat', '-A', opt.nat_chain, '-m', 'mac',
                             '--mac-source', self.mac_addr, '-j', 'ACCEPT')
        if result:
          logging.error('Could not update firewall for device %s',
                        self.mac_addr)
      else:
        logging.info('TOS accepted too long ago for %s: %r', self.mac_addr,
                     accepted_time)

    elif self.callback and self.tries > MAX_TRIES:
      if not accepted:
        logging.info('TOS not accepted for %s before timeout.', self.mac_addr)
      self.callback.stop()

    return response, accepted

  def poll(self):
    self.callback = tornado.ioloop.PeriodicCallback(self.check, 1000)
    self.callback.start()


def accept(connection, unused_address):
  """Accept a MAC address and find out if it's authorized."""
  cf = connection.makefile()

  maybe_mac_addr = cf.readline().strip()
  if re.match('([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$', maybe_mac_addr):
    mac_addr = maybe_mac_addr.lower()
  else:
    logging.warning('can only check authorization for a MAC address.')
    cf.write('{}')
    return

  if mac_addr in known_users:
    logging.info('TOS accepted (cached) for %s', mac_addr)
    cached_response = known_users[mac_addr]
    cached_response['cached'] = True
    cf.write(tornado.escape.json_encode(cached_response))
    return

  checker = Checker(mac_addr, opt.url)
  response, accepted = checker.check()
  if not accepted:
    checker.poll()

  cf.write(response.body)


if __name__ == '__main__':
  o = options.Options(optspec)
  opt, flags, extra = o.parse(sys.argv[1:])

  if not opt.unix_path:
    o.fatal('unix-path is required\n')

  if not (opt.filter_chain and opt.nat_chain) and not opt.dry_run:
    o.fatal('(filter-chain and nat-chain) or dry-run is required\n')

  # work whether or not Tornado has configured the root logger already
  logging.basicConfig(level=logging.INFO)
  logging.getLogger().setLevel(logging.INFO)

  ip46tables('-F', opt.filter_chain)
  ip46tables('-t', 'nat', '-F', opt.nat_chain)

  sock = tornado.netutil.bind_unix_socket(opt.unix_path)
  ioloop = tornado.ioloop.IOLoop.instance()
  tornado.netutil.add_accept_handler(sock, accept, ioloop)

  logging.info('Started authorizer.')
  ioloop.start()

