diff --git a/cas_server.admin.inc b/cas_server.admin.inc
new file mode 100644
index 0000000..5a3458c
--- /dev/null
+++ b/cas_server.admin.inc
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * CAS Server module settings UI.
+ */
+
+/**
+ * Provides settings pages.
+ */
+function cas_server_admin_settings() {
+  $form = array();
+  
+  $form['cas_server_service_whitelist_enable'] = array(
+    '#type' => 'radios',
+    '#title' => t('Service Whitelist'),
+    '#description' => t(
+      "When the service whitelist is enabled, CAS Server will only accept requests from services in the whitelist.
+      It's recommended that you leave this enabled."
+    ),
+    '#required' => TRUE,
+    '#options' => array(
+      0 => t('Disabled'),
+      1  => t('Enabled'),
+    ),
+    '#default_value' => variable_get('cas_server_service_whitelist_enable', 1),
+  );
+  
+  $form['whitelist'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Service Whitelist Settings'),
+    '#description' => t('Settings specific to the service whitelist mode you selected.'),
+    '#states' => array(
+      'visible' => array(
+        ':input[name="cas_server_service_whitelist_enable"]' => array('value' => '1'),
+      )
+    ),
+  );
+  
+  $format_variables = array(
+    '@format-url'        => '<' . t('URL') . '>',
+  );
+  $format_explanation_list_items = array(
+    t("<strong>@format-url</strong> is the service URL that should be accepted. E.g.:
+      '<code>http://site1.example.com</code>'.", $format_variables),
+  );
+  $example_list_items = array(
+    t('This would accept <em>all</em> service paths from a domain:
+      <pre><code>http://site1.example.com</code></pre>'),
+    t('This would only accept a single service path from a domain:
+      <pre><code>http://site1.example.com/some-path</code></pre>'),
+  );
+  $form['whitelist']['cas_server_service_whitelist'] = array(
+    '#type'          => 'textarea',
+    '#title'         => t('Whitelist'),
+    '#description'   => t("Define which services CAS Server will accept.<br />
+                           <br />
+                           Enter one service per line, in the format <strong>@format-url</strong>:<br />
+                           !format-explanation-list
+                           <br />
+                           Sample mappings:
+                           !example-list", $format_variables + array(
+                             '!format-explanation-list' => theme('item_list', array('items' => $format_explanation_list_items)),
+                             '!example-list' => theme('item_list', array('items' => $example_list_items)),
+                          )),
+    '#size'          => 35,
+    '#default_value' => variable_get('cas_server_service_whitelist', ''),
+  );
+  
+  return system_settings_form($form);
+}
diff --git a/cas_server.info b/cas_server.info
index 0ac73dd..736cf98 100644
--- a/cas_server.info
+++ b/cas_server.info
@@ -2,3 +2,4 @@ name = CAS Server
 package = Central Authentication Service
 core = 7.x
 description = "Provides protocol compliant CAS Server"
+configure = admin/config/people/cas_server
diff --git a/cas_server.module b/cas_server.module
index 7bb7713..9f40f4a 100644
--- a/cas_server.module
+++ b/cas_server.module
@@ -6,10 +6,39 @@
 define('CAS_LOGIN_COOKIE', 'cas_server_login');
 
 /**
+ * Implements hook_permission().
+ */
+function cas_server_permission() {
+  return array(
+    'administer cas server' => array(
+      'title' => t('Administer CAS Server'),
+      'description' => t('Configure CAS server settings.'),
+      'restrict access' => TRUE,
+    )
+  );
+}
+
+/**
  * Implementation of hook_menu
  */
 function cas_server_menu() {
   $items = array();
+  
+  $items['admin/config/people/cas_server'] = array(
+    'title' => 'CAS Server',
+    'description' => 'Configure central authentication services server',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('cas_server_admin_settings'),
+    'access arguments' => array('administer cas server'),
+    'type' => MENU_NORMAL_ITEM,
+    'file' => 'cas_server.admin.inc',
+  );
+  $items['admin/config/people/cas_server/settings'] = array(
+    'title' => 'Settings',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  
   $items['cas/login'] = array(
     'page callback' => 'cas_server_login',
     'title' => 'CAS Login',
@@ -85,9 +114,16 @@ function cas_server_login() {
   // Set login cookie so that we know we're in the process of logging in
   global $user;
   $output='';
+  
   if ($user->uid) {
     if ($_GET['service']) {
-      $_COOKIE[CAS_LOGIN_COOKIE] = $_REQUEST['service'];
+      // Check service against whitelist
+      if (!_cas_server_check_service_whitelist($_GET['service'])) {
+        $output=t('You do not have permission to log into CAS from this service.');
+      }
+      else {
+        $_COOKIE[CAS_LOGIN_COOKIE] = $_REQUEST['service'];
+      }
     }
     $output=t('You have successfully logged into CAS');
     cas_server_service_return();
@@ -99,7 +135,13 @@ function cas_server_login() {
     else {
       // Redirect to user login
       if ($_GET['service']) {
-        setcookie(CAS_LOGIN_COOKIE, $_REQUEST['service']);
+        // Check service against whitelist
+        if (!_cas_server_check_service_whitelist($_GET['service'])) {
+          $output=t('You do not have permission to log into CAS from this service.');
+        }
+        else {
+          setcookie(CAS_LOGIN_COOKIE, $_REQUEST['service']);
+        }
       }
       $output .= l(t('Login'), 'user', array('query' => array('destination' => 'cas/login')));
       drupal_goto('user', array('query' => array('destination' => 'cas/login')));
@@ -116,6 +158,14 @@ function cas_server_validate() {
   //Obtain the ticket from the url and validate it.
   $ticket = $_GET['ticket'];
   $service = $_GET['service'];
+  
+  // Check service against whitelist
+  if (!_cas_server_check_service_whitelist($service)) {
+    print "no\n";
+    print "\n";
+    return;
+  }
+  
   $user_name = _cas_server_validate($service, $ticket);
   if ($user_name) {
     print "yes\n";
@@ -133,6 +183,19 @@ function cas_server_validate() {
 function cas_server_service_validate() {
   $ticket = $_GET['ticket'];
   $service = $_GET['service'];
+  
+  // Check service against whitelist
+  if (!_cas_server_check_service_whitelist($service)) {
+    $cas_error='INVALID_REQUEST';
+    print "<cas:serviceReponse xmlns:cas='http://www.yale.edu/tp/cas'>\n" .
+          "  <cas:authenticationFailure code=\"$cas_error\">\n" .
+          "     Service $service not recognized.\n" .
+          "  </cas:authenticationFailure>" .
+          "</cas:serviceResponse>";
+    watchdog('cas', 'Service %service validation failed!', array('%service' => $service));
+    return;
+  }
+  
   $user_name = _cas_server_validate($service, $ticket);
   if (!$user_name ) $cas_error='INVALID_TICKET';
   if (!$ticket || !$service) $cas_error='INVALID_REQUEST';
@@ -157,6 +220,37 @@ function cas_server_service_validate() {
   }
 }
 
+function _cas_server_check_service_whitelist($service) {
+  if (variable_get('cas_server_service_whitelist_enable', 1) == 1) {
+    $service_parts = parse_url(trim($service));
+    
+    $mapping_raw = variable_get('cas_server_service_whitelist', '');
+    $lines = preg_split("/[\n\r]+/", $mapping_raw, -1, PREG_SPLIT_NO_EMPTY);
+    foreach ($lines as $line) {
+      if ($mapping_parts = parse_url(trim($line))) {
+        if (isset($mapping_parts['path']) && !empty($mapping_parts['path'])) {
+          if (
+            $mapping_parts['scheme'] == $service_parts['scheme'] &&
+            $mapping_parts['host'] == $service_parts['host'] &&
+            $mapping_parts['path'] == $service_parts['path']) {
+            return TRUE;
+          }
+        }
+        else {
+          if (
+            $mapping_parts['scheme'] == $service_parts['scheme'] &&
+            $mapping_parts['host'] == $service_parts['host']) {
+            return TRUE;
+          }
+        }
+      }
+    }
+    
+    return FALSE;
+  }
+  return TRUE;
+}
+
 /**
  * Test to see if a one time use ticket is valid
  *
@@ -202,6 +296,11 @@ function _cas_server_save_ticket($uid, $service) {
  * @TODO: Implement single sign out support
  */
 function cas_server_logout() {
+  // Check service against whitelist
+  if (!_cas_server_check_service_whitelist($_GET['service'])) {
+    return t('You do not have permission to log into CAS from this service.');
+  }
+  
   // Destroy the current session:
   session_destroy();
   module_invoke_all('user', 'logout', NULL, $user);
