#!/usr/bin/python # Debug ##import os ##print "Content-type: text/html\n" ##import sys ##sys.stderr = sys.stdout # Copyright 2011 Jon Rifkin # # 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. #----------------------------------------------------------------------- # Usage #----------------------------------------------------------------------- # # Purpose # Authenticate users against a CAS server from your python cgi scripts. # # Using in your script # # import pycas # status, id, cookie = pycas.login(CAS_SERVER,THIS_SCRIPT) # # Required Parameters # # - CAS_SERVER : the url of your CAS server # (for example, https://login.yoursite.edu). # - THIS_SCRIPT: the url of the calling python cgi script. # # Returned Values # # - status: return code, 0 for success. # - id : the user name returned by cas. # - cookie: when non-blank, send this cookie to the client's # browser so it can authenticate for the rest of the # session. # # Optional Parmaters: # - lifetime: lifetime of the cookie in seconds, enforced by pycas. # Default is 0, meaning unlimited lifetime. # - path: Authentication cookie applies for all urls under 'path'. # Defaults to "/" (all urls). # - protocol: CAS protocol version. Default is 2. Can be set to 1. # - secure: Default is 1, which authenticates for https connections only. # - opt: set to 'renew' or 'gateway' for these CAS options. # # Examples: # status, id, cookie = pycas.login(CAS_SERVER,THIS_SCRIPT,protocol=1,secure=0) # status, id, cookie = pycas.login(CAS_SERVER,THIS_SCRIPT,path="/cgi-bin/accts") # # Status Codes are listed below. # #----------------------------------------------------------------------- # Constants #----------------------------------------------------------------------- # # Secret used to produce hash. This can be any string. Hackers # who know this string can forge this script's authentication cookie. SECRET = "7f16162998eb7efafb1498f75190a937" # Name field for pycas cookie PYCAS_NAME = "pycas" # CAS Staus Codes: returned to calling program by login() function. CAS_OK = 0 # CAS authentication successful. CAS_COOKIE_EXPIRED = 1 # PYCAS cookie exceeded its lifetime. CAS_COOKIE_INVALID = 2 # PYCAS cookie is invalid (probably corrupted). CAS_TICKET_INVALID = 3 # CAS server ticket invalid. CAS_GATEWAY = 4 # CAS server returned without ticket while in gateway mode. # Status codes returned internally by function get_cookie_status(). COOKIE_AUTH = 0 # PYCAS cookie is valid. COOKIE_NONE = 1 # No PYCAS cookie found. COOKIE_GATEWAY = 2 # PYCAS gateway cookie found. COOKIE_INVALID = 3 # Invalid PYCAS cookie found. # Status codes returned internally by function get_ticket_status(). TICKET_OK = 0 # Valid CAS server ticket found. TICKET_NONE = 1 # No CAS server ticket found. TICKET_INVALID = 2 # Invalid CAS server ticket found. CAS_MSG = ( "CAS authentication successful.", "PYCAS cookie exceeded its lifetime.", "PYCAS cookie is invalid (probably corrupted).", "CAS server ticket invalid.", "CAS server returned without ticket while in gateway mode.", ) ###Optional log file for debugging ###LOG_FILE="/tmp/cas.log" #----------------------------------------------------------------------- # Imports #----------------------------------------------------------------------- import os import cgi from hashlib import md5 import time import urllib import urlparse #----------------------------------------------------------------------- # Functions #----------------------------------------------------------------------- # For debugging. def writelog(msg): f = open(LOG_FILE,"a") timestr = time.strftime("%Y-%m-%d %H:%M:%S "); f.write(timestr + msg + "\n"); f.close() # Used for parsing xml. Search str for first occurance of # ..... and return text (striped of leading and # trailing whitespace) between tags. Return "" if tag not # found. def parse_tag(str,tag): tag1_pos1 = str.find("<" + tag) # No tag found, return empty string. if tag1_pos1==-1: return "" tag1_pos2 = str.find(">",tag1_pos1) if tag1_pos2==-1: return "" tag2_pos1 = str.find("this link. """ % (cas_url) raise SystemExit # Send log out message def logout(cas_host, service_url="", destination_url="", secure=1): cas_url = cas_host + "/cas/logout" domain, path = urlparse.urlparse(service_url)[1:3] cookie = make_pycas_cookie("", domain, path, secure, expires="Thu, 01 Jan 1970 00:00:00 GMT") if destination_url != "": cas_url += "&url=%s" % destination_url print "Location: %s" % cas_url print "Content-type: text/html" print cookie print "" print "If your browser does not redirect you, then please follow this link." % (cas_url) print cookie raise SystemExit # Retrieve id from pycas cookie and test data for validity # (to prevent mailicious users from falsely authenticating). # Return status and id (id will be empty string if unknown). def decode_cookie(cookie_vals,lifetime=None): # Test for now cookies if cookie_vals==None: return COOKIE_NONE, "" # Test each cookie value cookie_attrs = [] for cookie_val in cookie_vals: # Remove trailing ; if cookie_val and cookie_val[-1]==";": cookie_val = cookie_val[0:-1] # Test for pycas gateway cookie if cookie_val=="gateway": cookie_attrs.append(COOKIE_GATEWAY) # Test for valid pycas authentication cookie. else: # Separate cookie parts oldhash = cookie_val[0:8] timestr, id = split2(cookie_val[8:],":") # Verify hash newhash=makehash(timestr + ":" + id) if oldhash==makehash(timestr + ":" + id): # Check lifetime if lifetime: if str(int(time.time()+int(lifetime))) castest.py

pycas.py


""" # Print browser parameters from pycas.login if cgi.FieldStorage().has_key("ticket"): ticket = cgi.FieldStorage()["ticket"].value else: ticket = "" in_cookie = os.getenv("HTTP_COOKIE") print """

Parameters sent from browser
Ticket %s
Cookie %s

""" % (ticket,in_cookie) # Print output from pycas.login print """

Parameters returned from pycas.login()
status %s - %s
id %s
cookie %s

""" % (status,CAS_MSG[status],id,cookie)