#!/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.
#
"""Redirects all HTTP requests to the specified URL."""

import logging
import socket
import subprocess
import sys
import urllib2

import hash_mac_addr
import options

import tornado.httpclient
import tornado.ioloop
import tornado.web


optspec = """
http_bouncer [options...]
--
p,port=      TCP port to listen on [8888]
u,url=       URL to redirect ("bounce") users to. Include the format specifier %(mac)s to write the users' MAC address into the URL when bouncing. []
U,unix-path= Unix socket to use for authorization checking [/tmp/authorizer.sock]
"""

PKI_HOSTS = set(['pki.google.com', 'clients1.google.com'])


def mac_for_ip(remote_ip):
  arp_response = subprocess.check_output(['arp', remote_ip])
  return arp_response.split()[3]


class Redirector(tornado.web.RequestHandler):
  """Redirect users' HTTP connections to a captive portal landing page."""

  def initialize(self, substitute_mac):
    self.substitute_mac = substitute_mac
    self._http_client = tornado.httpclient.HTTPClient()

  def get(self):
    if self._is_crl_request():
      # proxy CRL/OCSP requests. Workaround for b/19825798.
      url = '%s://%s%s' % (self.request.protocol, self.request.host,
                           self.request.uri)
      logging.info('Forwarding request to %s', url)
      response = self._http_client.fetch(url)
      for (name, value) in response.headers.get_all():
        self.set_header(name, value)

      if response.body:
        self.set_header('Content-Length', len(response.body))
        self.write(response.body)
    else:
      if self.substitute_mac:
        mac = mac_for_ip(self.request.remote_ip)
        _, hashed_mac = hash_mac_addr.hash_mac_addr(mac)
        self.redirect(opt.url % {'mac': hashed_mac})

        if opt.unix_path:
          try:
            s = socket.socket(socket.AF_UNIX)
            s.connect(opt.unix_path)
            s.sendall('%s\n' % mac)
            s.close()
          except socket.error:
            logging.warning('Could not contact authorizer.')
      else:
        self.redirect(opt.url)

  def _is_crl_request(self):
    uri = self.request.uri
    return self.request.host in PKI_HOSTS and (uri.startswith('/ocsp/')
                                               or uri.endswith('.crl'))

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

  if not opt.port or not opt.url:
    o.fatal('port and url are required\n')

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

  try:
    formatted_url = opt.url % {'mac': '00:00:00:00:00:00'}
    urllib2.urlopen(formatted_url).getcode()
  except (TypeError, ValueError, urllib2.URLError):
    o.fatal('url must be a URL.')

  url_needs_mac = formatted_url != opt.url
  if url_needs_mac and not opt.unix_path:
    o.fatal('unix-path missing but URL requested MAC-based authorization')

  application = tornado.web.Application([
      (r'.*', Redirector, dict(substitute_mac=url_needs_mac)),
  ])

  try:
    application.listen(opt.port)
  except socket.gaierror:
    o.fatal('port must be a TCP port, and we must be able to bind it.')

  logging.info('Starting http_bouncer.')
  tornado.ioloop.IOLoop.instance().start()
