trying out the hint from github issue
[plcapi.git] / PLC / Auth.py
index 8a6db57..3be444b 100644 (file)
@@ -21,6 +21,7 @@ from PLC.Nodes import Node, Nodes
 from PLC.Interfaces import Interface, Interfaces
 from PLC.Sessions import Session, Sessions
 from PLC.Peers import Peer, Peers
 from PLC.Interfaces import Interface, Interfaces
 from PLC.Sessions import Session, Sessions
 from PLC.Peers import Peer, Peers
+from PLC.Keys import Keys
 from PLC.Boot import notify_owners
 
 class Auth(Parameter):
 from PLC.Boot import notify_owners
 
 class Auth(Parameter):
@@ -71,25 +72,26 @@ class GPGAuth(Auth):
                     raise PLCAuthenticationFailure, "GPGAuth: Not allowed to call method, missing 'peer' role"
 
                 method.caller = peer = peers[0]
                     raise PLCAuthenticationFailure, "GPGAuth: Not allowed to call method, missing 'peer' role"
 
                 method.caller = peer = peers[0]
-                keys = [peer['key']]
+                gpg_keys = [ peer['key'] ]
             else:
                 persons = Persons(method.api, {'email': auth['name'], 'enabled': True, 'peer_id': None})
                 if not persons:
                     raise PLCAuthenticationFailure, "GPGAuth: No such user '%s'" % auth['name']
 
             else:
                 persons = Persons(method.api, {'email': auth['name'], 'enabled': True, 'peer_id': None})
                 if not persons:
                     raise PLCAuthenticationFailure, "GPGAuth: No such user '%s'" % auth['name']
 
+                method.caller = person = persons[0]
                 if not set(person['roles']).intersection(method.roles):
                     raise PLCAuthenticationFailure, "GPGAuth: Not allowed to call method, missing role"
 
                 if not set(person['roles']).intersection(method.roles):
                     raise PLCAuthenticationFailure, "GPGAuth: Not allowed to call method, missing role"
 
-                method.caller = person = persons[0]
                 keys = Keys(method.api, {'key_id': person['key_ids'], 'key_type': "gpg", 'peer_id': None})
                 keys = Keys(method.api, {'key_id': person['key_ids'], 'key_type': "gpg", 'peer_id': None})
+                gpg_keys = [ key['key'] for key in keys ]
 
 
-            if not keys:
-                raise PLCAuthenticationFailure, "GPGAuth: No GPG key on record for peer or user '%s'"
+            if not gpg_keys:
+                raise PLCAuthenticationFailure, "GPGAuth: No GPG key on record for peer or user '%s'"%auth['name']
 
 
-            for key in keys:
+            for gpg_key in gpg_keys:
                 try:
                     from PLC.GPG import gpg_verify
                 try:
                     from PLC.GPG import gpg_verify
-                    gpg_verify(args, key, auth['signature'], method.name)
+                    gpg_verify(args, gpg_key, auth['signature'], method.name)
                     return
                 except PLCAuthenticationFailure, fault:
                     pass
                     return
                 except PLCAuthenticationFailure, fault:
                     pass
@@ -132,20 +134,25 @@ class SessionAuth(Auth):
                 node = nodes[0]
 
                 if 'node' not in method.roles:
                 node = nodes[0]
 
                 if 'node' not in method.roles:
-                    raise PLCAuthenticationFailure, "SessionAuth: Not allowed to call method, missing 'node' role"
+                    # using PermissionDenied rather than AuthenticationFailure here because
+                    # if that fails we don't want to delete the session..
+                    raise PLCPermissionDenied, "SessionAuth: Not allowed to call method %s, missing 'node' role"%method.name
 
                 method.caller = node
 
             elif session['person_id'] is not None and session['expires'] > time.time():
                 persons = Persons(method.api, {'person_id': session['person_id'], 'enabled': True, 'peer_id': None})
                 if not persons:
 
                 method.caller = node
 
             elif session['person_id'] is not None and session['expires'] > time.time():
                 persons = Persons(method.api, {'person_id': session['person_id'], 'enabled': True, 'peer_id': None})
                 if not persons:
-                    raise PLCAuthenticationFailure, "SessionAuth: No such account"
+                    raise PLCAuthenticationFailure, "SessionAuth: No such enabled account"
                 person = persons[0]
 
                 if not set(person['roles']).intersection(method.roles):
                 person = persons[0]
 
                 if not set(person['roles']).intersection(method.roles):
-                    raise PLCPermissionDenied, "Not allowed to call method, missing role"
+                    method_message="method %s has roles [%s]"%(method.name,','.join(method.roles))
+                    person_message="caller %s has roles [%s]"%(person['email'],','.join(person['roles']))
+                    # not PLCAuthenticationFailure b/c that would end the session..
+                    raise PLCPermissionDenied, "SessionAuth: missing role, %s -- %s"%(method_message,person_message)
 
 
-                method.caller = persons[0]
+                method.caller = person
 
             else:
                 raise PLCAuthenticationFailure, "SessionAuth: Invalid session"
 
             else:
                 raise PLCAuthenticationFailure, "SessionAuth: Invalid session"
@@ -207,37 +214,11 @@ class BootAuth(Auth):
                 raise PLCAuthenticationFailure, "BootAuth: No such node"
             node = nodes[0]
 
                 raise PLCAuthenticationFailure, "BootAuth: No such node"
             node = nodes[0]
 
+            # Jan 2011 : removing support for old boot CDs
             if node['key']:
                 key = node['key']
             if node['key']:
                 key = node['key']
-            elif node['boot_nonce']:
-                # Allow very old nodes that do not have a node key in
-                # their configuration files to use their "boot nonce"
-                # instead. The boot nonce is a random value generated
-                # by the node itself and POSTed by the Boot CD when it
-                # requests the Boot Manager. This is obviously not
-                # very secure, so we only allow it to be used if the
-                # requestor IP is the same as the IP address we have
-                # on record for the node.
-                key = node['boot_nonce']
-
-                interface = None
-                if node['interface_ids']:
-                    interfaces = Interfaces(method.api, node['interface_ids'])
-                    for interface in interfaces:
-                        if interface['is_primary']:
-                            break
-
-                if not interface or not interface['is_primary']:
-                    raise PLCAuthenticationFailure, "BootAuth: No primary network interface on record"
-
-                if method.source is None:
-                    raise PLCAuthenticationFailure, "BootAuth: Cannot determine IP address of requestor"
-
-                if interface['ip'] != method.source[0]:
-                    raise PLCAuthenticationFailure, "BootAuth: Requestor IP %s does not match node IP %s" % \
-                          (method.source[0], interface['ip'])
             else:
             else:
-                raise PLCAuthenticationFailure, "BootAuth: No node key or boot nonce"
+                raise PLCAuthenticationFailure, "BootAuth: No node key"
 
             # Yes, this is the "canonicalization" method used.
             args = self.canonicalize(args)
 
             # Yes, this is the "canonicalization" method used.
             args = self.canonicalize(args)
@@ -324,7 +305,9 @@ class PasswordAuth(Auth):
                 raise PLCAuthenticationFailure, "PasswordAuth: Password verification failed"
 
         if not set(person['roles']).intersection(method.roles):
                 raise PLCAuthenticationFailure, "PasswordAuth: Password verification failed"
 
         if not set(person['roles']).intersection(method.roles):
-            raise PLCAuthenticationFailure, "PasswordAuth: Not allowed to call method, missing role"
+            method_message="method %s has roles [%s]"%(method.name,','.join(method.roles))
+            person_message="caller %s has roles [%s]"%(person['email'],','.join(person['roles']))
+            raise PLCAuthenticationFailure, "PasswordAuth: missing role, %s -- %s"%(method_message,person_message)
 
         method.caller = person
 
 
         method.caller = person