2 # PLCAPI authentication parameters
4 # Mark Huang <mlhuang@cs.princeton.edu>
5 # Copyright (C) 2006 The Trustees of Princeton University
7 # $Id: Auth.py,v 1.2 2006/09/08 19:44:12 mlhuang Exp $
12 from PLC.Faults import *
13 from PLC.Parameter import Parameter, Mixed
14 from PLC.Persons import Persons
16 class Auth(Parameter, dict):
18 Base class for all API authentication methods.
21 def __init__(self, auth):
22 Parameter.__init__(self, auth, "API authentication structure", False)
27 PlanetLab version 3.x node authentication structure. Used by the
28 Boot Manager to make authenticated calls to the API based on a
29 unique node key or boot nonce value.
34 'AuthMethod': Parameter(str, "Authentication method to use, always 'hmac'", False),
35 'node_id': Parameter(str, "Node identifier", False),
36 'node_ip': Parameter(str, "Node primary IP address", False),
37 'value': Parameter(str, "HMAC of node key and method call", False)
40 def check(self, method, auth, *args):
41 # XXX Do HMAC checking
44 class AnonymousAuth(Auth):
46 PlanetLab version 3.x anonymous authentication structure.
51 'AuthMethod': Parameter(str, "Authentication method to use, always 'anonymous'", False),
54 def check(self, method, auth, *args):
55 # Sure, dude, whatever
58 class PasswordAuth(Auth):
60 PlanetLab version 3.x password authentication structure.
65 'AuthMethod': Parameter(str, "Authentication method to use, typically 'password'", False),
66 'Username': Parameter(str, "PlanetLab username, typically an e-mail address", False),
67 'AuthString': Parameter(str, "Authentication string, typically a password", False),
70 def check(self, method, auth, *args):
71 # Method.type_check() should have checked that all of the
72 # mandatory fields were present.
73 assert auth.has_key('Username')
75 # Get record (must be enabled)
76 persons = Persons(method.api, [auth['Username']], enabled = True)
78 raise PLCAuthenticationFailure, "No such account"
80 person = persons.values()[0]
82 if auth['Username'] == method.api.config.PLC_API_MAINTENANCE_USER:
83 # "Capability" authentication, whatever the hell that was
84 # supposed to mean. It really means, login as the special
85 # "maintenance user" using password authentication. Can
86 # only be used on particular machines (those in a list).
87 sources = method.api.config.PLC_API_MAINTENANCE_SOURCES.split()
88 if method.source is not None and method.source[0] not in sources:
89 raise PLCAuthenticationFailure, "Not allowed to login to maintenance account"
91 # Not sure why this is not stored in the DB
92 password = method.api.config.PLC_API_MAINTENANCE_PASSWORD
94 if auth['AuthString'] != password:
95 raise PLCAuthenticationFailure, "Maintenance account password verification failed"
97 # Compare encrypted plaintext against encrypted password stored in the DB
98 plaintext = auth['AuthString'].encode(method.api.encoding)
99 password = person['password']
101 # Protect against blank passwords in the DB
102 if password is None or password[:12] == "" or \
103 crypt.crypt(plaintext, password[:12]) != password:
104 raise PLCAuthenticationFailure, "Password verification failed"
106 if not set(person['roles']).intersection(method.roles):
107 raise PLCAuthenticationFailure, "Not allowed to call method"
109 method.caller = person