Merge remote-tracking branch 'upstream/master'
This commit is contained in:
4
TODO
4
TODO
@@ -1,3 +1,3 @@
|
||||
1. Write documentations.
|
||||
2. Write unittests for signature related utility methods.
|
||||
1. Write documentation.
|
||||
2. Write unit tests for signature related utility methods.
|
||||
3. Complete saml2 message class.
|
||||
|
||||
@@ -28,7 +28,7 @@ instance, the friendly name is used as the key.
|
||||
Setup
|
||||
-----
|
||||
|
||||
I you look in the example/sp directory of the distribution you will see
|
||||
If you look in the example/sp directory of the distribution you will see
|
||||
the necessary files:
|
||||
|
||||
application.py
|
||||
@@ -64,7 +64,7 @@ it line by line::
|
||||
|
||||
"service": ["sp"],
|
||||
|
||||
Tells the software what type of services the software are suppost to
|
||||
Tells the software what type of services the software is supposed to
|
||||
supply. It is used to check for the
|
||||
completeness of the configuration and also when constructing metadata from
|
||||
the configuration. More about that later. Allowed values are: "sp"
|
||||
@@ -119,13 +119,13 @@ building metadata. ::
|
||||
#telephone_number
|
||||
}]
|
||||
|
||||
Another piece of information that only is matters if you build and distribute
|
||||
Another piece of information that only matters if you build and distribute
|
||||
metadata.
|
||||
|
||||
So, now to that part. In order to allow the IdP to talk to you you may have
|
||||
to provide the one running the IdP with a metadata file.
|
||||
If you have a SP configuration file similar to the one I've walked you
|
||||
through here, but with your information. You can make the metadata file
|
||||
through here, but with your information, you can make the metadata file
|
||||
by running the make_metadata script you can find in the tools directory.
|
||||
|
||||
Change directory to where you have the configuration file and do ::
|
||||
@@ -138,7 +138,7 @@ Repoze configuration
|
||||
--------------------
|
||||
|
||||
I'm not going through the INI file format here. You should read
|
||||
`Middleware Responsibilities <http://static.repoze.org/whodocs/narr.html>`_
|
||||
`Middleware Responsibilities <http://docs.repoze.org/who/2.0/middleware.html>`_
|
||||
to get a good introduction to the concept.
|
||||
|
||||
The configuration of the pysaml2 part in the applications middleware are
|
||||
@@ -178,16 +178,16 @@ Which means that the plugin is used in all phases.
|
||||
The application
|
||||
---------------
|
||||
|
||||
Is as said before extremly simple. The only thing that is connected to
|
||||
the PySaml2 configuration are at the bottom, namely where the server are.
|
||||
The app is, as said before, extremely simple. The only thing that is connected to
|
||||
the PySaml2 configuration is at the bottom, namely where the server is.
|
||||
You have to ascertain that this coincides with what is specified in the
|
||||
PySaml2 configuration. Apart from that there really are no thing in
|
||||
PySaml2 configuration. Apart from that there really is nothing in
|
||||
application.py that demands that you use PySaml2 as middleware. If you
|
||||
switched to using the LDAP or CAS plugins nothing would change in the
|
||||
application. In the application configuration yes! But not in the application.
|
||||
And that is really how it should be done.
|
||||
|
||||
There is one assumption and that is that the middleware plugin that gathers
|
||||
information about the user places the extra information in as value on the
|
||||
There is one assumption, and that is that the middleware plugin that gathers
|
||||
information about the user places the extra information in as a value on the
|
||||
"user" property in the dictionary found under the key "repoze.who.identity"
|
||||
in the environment.
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
Configuration of pySAML2 entities
|
||||
=================================
|
||||
|
||||
Whether you plan to run a pySAML2 Service Provider, Identity provider or an
|
||||
Whether you plan to run a pySAML2 Service Provider, Identity Provider or an
|
||||
attribute authority you have to configure it. The format of the configuration
|
||||
file is the same disregarding which type of service you plan to run.
|
||||
What differs is some of the directives.
|
||||
Below you will find a list of all the used directives in alphabetic order.
|
||||
file is the same regardless of which type of service you plan to run.
|
||||
What differs are some of the directives.
|
||||
Below you will find a list of all the used directives in alphabetical order.
|
||||
The configuration is written as a python module which contains a named
|
||||
dictionary ("CONFIG") that contains the configuration directives.
|
||||
|
||||
The basic structure of the configuration file is therefor like this::
|
||||
The basic structure of the configuration file is therefore like this::
|
||||
|
||||
from saml2 import BINDING_HTTP_REDIRECT
|
||||
|
||||
@@ -90,9 +90,9 @@ The attribute map module contains a MAP dictionary with three items. The
|
||||
The *to* and *fro* sub-dictionaries then contain the mapping between the names.
|
||||
|
||||
As you see the format is again a python dictionary where the key is the
|
||||
name to convert from and the value is the name to convert to.
|
||||
name to convert from, and the value is the name to convert to.
|
||||
|
||||
Since *to* in most cases are the inverse of the *fro* file, the
|
||||
Since *to* in most cases is the inverse of the *fro* file, the
|
||||
software allowes you to only specify one of them and it will
|
||||
automatically create the other.
|
||||
|
||||
@@ -111,7 +111,7 @@ contact_person
|
||||
|
||||
This is only used by *make_metadata.py* when it constructs the metadata for
|
||||
the service described by the configuration file.
|
||||
This is where you described who can be contacted if questions arises
|
||||
This is where you describe who can be contacted if questions arise
|
||||
about the service or if support is needed. The possible types are according to
|
||||
the standard **technical**, **support**, **administrative**, **billing**
|
||||
and **other**.::
|
||||
@@ -148,7 +148,7 @@ Format::
|
||||
|
||||
The globally unique identifier of the entity.
|
||||
|
||||
.. note:: There is a recommendation that the entityid should point to a real
|
||||
.. note:: It is recommended that the entityid should point to a real
|
||||
webpage where the metadata for the entity can be found.
|
||||
|
||||
key_file
|
||||
@@ -160,13 +160,13 @@ Format::
|
||||
|
||||
*key_file* is the name of a PEM formatted file that contains the private key
|
||||
of the service. This is presently used both to encrypt/sign assertions and as
|
||||
client key in a HTTPS session.
|
||||
the client key in an HTTPS session.
|
||||
|
||||
metadata
|
||||
^^^^^^^^
|
||||
|
||||
Contains a list of places where metadata can be found. This can be either
|
||||
a file accessible on the server the service runs on or somewhere on the net.::
|
||||
a file accessible on the server the service runs on, or somewhere on the net.::
|
||||
|
||||
"metadata" : {
|
||||
"local": [
|
||||
@@ -180,8 +180,8 @@ a file accessible on the server the service runs on or somewhere on the net.::
|
||||
},
|
||||
|
||||
The above configuration means that the service should read two local
|
||||
metadata files and on top of that load one from the net. To verify the
|
||||
authenticity of the file downloaded from the net the local copy of the
|
||||
metadata files, and on top of that load one from the net. To verify the
|
||||
authenticity of the file downloaded from the net, the local copy of the
|
||||
public key should be used.
|
||||
This public key must be acquired by some out-of-band method.
|
||||
|
||||
@@ -205,7 +205,7 @@ Where you describe the organization responsible for the service.::
|
||||
service
|
||||
^^^^^^^
|
||||
|
||||
Which services the server will provide, those are combinations of "idp","sp"
|
||||
Which services the server will provide; those are combinations of "idp", "sp"
|
||||
and "aa".
|
||||
So if a server is a Service Provider (SP) then the configuration
|
||||
could look something like this::
|
||||
@@ -228,13 +228,13 @@ could look something like this::
|
||||
|
||||
There are two options common to all services: 'name' and 'endpoints'.
|
||||
The remaining options are specific to one or the other of the service types.
|
||||
Which one is specified along side the name of the option
|
||||
Which one is specified along side the name of the option.
|
||||
|
||||
timeslack
|
||||
^^^^^^^^^
|
||||
|
||||
If your computer and another computer that you are communicating with are not
|
||||
in synch regarding the computer clock. Then you here can state how big a
|
||||
in synch regarding the computer clock, then here you can state how big a
|
||||
difference you are prepared to accept.
|
||||
|
||||
.. note:: This will indiscriminately effect all time comparisons.
|
||||
@@ -275,7 +275,7 @@ policy
|
||||
|
||||
If the server is an IdP and/or an AA then there might be reasons to do things
|
||||
differently depending on who is asking; this is where that is specified.
|
||||
The keys are 'default' and SP entity identifiers, default is used whenever
|
||||
The keys are 'default' and SP entity identifiers. Default is used whenever
|
||||
there is no entry for a specific SP. The reasoning is also that if there is
|
||||
no default and only SP entity identifiers as keys, then the server will only
|
||||
except connections from the specified SPs.
|
||||
@@ -301,12 +301,12 @@ An example might be::
|
||||
}
|
||||
|
||||
*lifetime*
|
||||
is the maximum amount of time before the information should be
|
||||
This is the maximum amount of time before the information should be
|
||||
regarded as stale. In an Assertion this is represented in the NotOnOrAfter
|
||||
attribute.
|
||||
*attribute_restrictions*
|
||||
By default there is no restrictions as to which attributes should be
|
||||
return. Instead all the attributes and values that is gathered by the
|
||||
return. Instead all the attributes and values that are gathered by the
|
||||
database backends will be returned if nothing else is stated.
|
||||
In the example above the SP with the entity identifier
|
||||
"urn:mace:umu.se:saml:roland:sp"
|
||||
@@ -332,7 +332,7 @@ regular expressions.::
|
||||
}
|
||||
}
|
||||
|
||||
Here only mail addresses that ends with ".umu.se" will be returned.
|
||||
Here only mail addresses that end with ".umu.se" will be returned.
|
||||
|
||||
sp
|
||||
^^
|
||||
@@ -345,7 +345,7 @@ authn_requests_signed
|
||||
Indicates if the Authentication Requests sent by this SP should be signed
|
||||
by default. This can be overriden by application code for a specific call.
|
||||
|
||||
This set the AuthnRequestsSigned attribute of the SPSSODescriptor node.
|
||||
This sets the AuthnRequestsSigned attribute of the SPSSODescriptor node
|
||||
of the metadata so the IdP will know this SP preference.
|
||||
|
||||
Valid values are "true" or "false". Default value is "false".
|
||||
@@ -362,9 +362,9 @@ Example::
|
||||
idp
|
||||
"""
|
||||
|
||||
Defines the set of IdPs that this SP is allowed to use. If not all the IdPs in
|
||||
the metadata is allowed, then the value is expected to be a list with entity
|
||||
identifiers for the allowed IdPs.
|
||||
Defines the set of IdPs that this SP is allowed to use; if unset, all listed
|
||||
IdPs may be used. If set, then the value is expected to be a list with entity
|
||||
identifiers for the allowed IdPs.
|
||||
A typical configuration, when the allowed set of IdPs are limited, would look
|
||||
something like this::
|
||||
|
||||
@@ -376,8 +376,6 @@ something like this::
|
||||
|
||||
In this case the SP has only one IdP it can use.
|
||||
|
||||
If all IdPs present in the metadata loaded this directive must be left out.
|
||||
|
||||
optional_attributes
|
||||
"""""""""""""""""""
|
||||
|
||||
@@ -415,7 +413,7 @@ want_assertions_signed
|
||||
""""""""""""""""""""""
|
||||
|
||||
Indicates if this SP wants the IdP to send the assertions signed. This
|
||||
set the WantAssertionsSigned attribute of the SPSSODescriptor node.
|
||||
sets the WantAssertionsSigned attribute of the SPSSODescriptor node
|
||||
of the metadata so the IdP will know this SP preference.
|
||||
|
||||
Valid values are "true" or "false". Default value is "true".
|
||||
@@ -440,7 +438,7 @@ endpoints
|
||||
"""""""""
|
||||
|
||||
Where the endpoints for the services provided are.
|
||||
This directive has as value a dictionary with one of the following keys:
|
||||
This directive has as value a dictionary with one or more of the following keys:
|
||||
|
||||
* artifact_resolution_service (aa, idp and sp)
|
||||
* assertion_consumer_service (sp)
|
||||
@@ -474,7 +472,7 @@ Indicates if this entity will sign the Logout Requests originated from it.
|
||||
|
||||
This can be overriden by application code for a specific call.
|
||||
|
||||
Valid values are "true" or "false". Default value is "false"
|
||||
Valid values are "true" or "false". Default value is "false".
|
||||
|
||||
Example::
|
||||
|
||||
@@ -491,7 +489,7 @@ The name of a database where the map between a local identifier and
|
||||
a distributed identifier is kept. By default this is a shelve database.
|
||||
So if you just specify name, then a shelve database with that name
|
||||
is created. On the other hand if you specify a tuple then the first
|
||||
element in the tuple specifise which type of database you want to use
|
||||
element in the tuple specifies which type of database you want to use
|
||||
and the second element is the address of the database.
|
||||
|
||||
Example::
|
||||
@@ -519,7 +517,7 @@ Gives information about common identifiers for virtual_organizations::
|
||||
},
|
||||
|
||||
Keys in this dictionary are the identifiers for the virtual organizations.
|
||||
The arguments per organization is 'nameid_format' and 'common_identifier'.
|
||||
The arguments per organization are 'nameid_format' and 'common_identifier'.
|
||||
Useful if all the IdPs and AAs that are involved in a virtual organization
|
||||
have common attribute values for users that are part of the VO.
|
||||
|
||||
@@ -562,8 +560,8 @@ We start with a simple but fairly complete Service provider configuration::
|
||||
}
|
||||
|
||||
This is the typical setup for a SP.
|
||||
A metadata file to load is *always* needed, but it can of course be
|
||||
containing anything from 1 up to many entity descriptions.
|
||||
A metadata file to load is *always* needed, but it can of course
|
||||
contain anything from 1 up to many entity descriptions.
|
||||
|
||||
------
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@ If you have not done it yet, read the :ref:`install`
|
||||
Well, now you have it installed and you want to do something.
|
||||
|
||||
And I'm sorry to tell you this; but there isn't really a lot you can do with
|
||||
this code on it's own.
|
||||
this code on its own.
|
||||
|
||||
Sure you can send a AuthenticationRequest to an IdentityProvider or a
|
||||
AttributeQuery to an AttributeAuthority but in order to get what they
|
||||
AttributeQuery to an AttributeAuthority, but in order to get what they
|
||||
return you have to sit behind a Web server. Well that is not really true since
|
||||
the AttributeQuery would be over SOAP and you would get the result over the
|
||||
connection you have to the AttributeAuthority.
|
||||
@@ -29,7 +29,7 @@ But it can be used in a non-WSGI environment too.
|
||||
|
||||
So you will find descriptions of both cases here.
|
||||
|
||||
The configuration is the same disregarding whether you are using PySAML2 in a
|
||||
The configuration is the same regardless of whether you are using PySAML2 in a
|
||||
WSGI or non-WSGI environment.
|
||||
|
||||
.. toctree::
|
||||
|
||||
@@ -13,7 +13,7 @@ pysaml2
|
||||
|
||||
PySAML2 is a pure python implementation of SAML2. It contains all necessary pieces for building a SAML2 service
|
||||
provider or an identity provider. The distribution contains examples of both. Originally written to work in a WSGI
|
||||
environment there are extensions that allow you to use it with other frameworks.
|
||||
environment, there are extensions that allow you to use it with other frameworks.
|
||||
|
||||
Contents:
|
||||
|
||||
@@ -39,4 +39,4 @@ Indices and tables
|
||||
|
||||
<a href="https://github.com/rohe/pysaml2" class="github" target="_blank">
|
||||
<img style="position: absolute; top: 0; right: 0; border: 0;" src="_static/ViewmeonGitHub.png" alt="View me on GitHub" class="github"/>
|
||||
</a>
|
||||
</a>
|
||||
|
||||
@@ -53,5 +53,5 @@ The tests are based on the pypy test environment, so::
|
||||
py.test
|
||||
|
||||
is what you should use. If you don't have py.test, get it it's part of pypy!
|
||||
It's really good !
|
||||
It's really good!
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
rm -f ./code/*
|
||||
sphinx-apidoc -F -o ../doc/code ../src
|
||||
make clean
|
||||
make html
|
||||
make html
|
||||
|
||||
@@ -1,30 +1,40 @@
|
||||
This is a very simple setup just to check that all your gear are in order.
|
||||
|
||||
The setup consists of one IdP and one SP.
|
||||
The IdP authenticates users by using a htpasswd plugin and gets the identity information
|
||||
from the ini-plugin.
|
||||
The setup consists of one IdP and one SP, in idp2/ and sp-wsgi/ respectively.
|
||||
|
||||
All this is in the idp/who.ini configuration file, the file used for authentication
|
||||
is idp/passwd and the ini file is idp/idp_user.ini.
|
||||
To run the setup do:
|
||||
|
||||
The passwords in passwd in clear text:
|
||||
./all.sh start
|
||||
|
||||
roland:friend
|
||||
ozzie:two
|
||||
derek:three
|
||||
ryan:four
|
||||
ischiro:five
|
||||
and then use your favourite webbrowser to look at "http://localhost:8087/"
|
||||
|
||||
To shut it down do:
|
||||
|
||||
./all.sh stop
|
||||
|
||||
The IdP authenticates users using a dictionary built in to idp2/idp.py;
|
||||
look for the dictionary called PASSWD inside that file.
|
||||
|
||||
Other metadata about the accounts (names, email addresses, etc) are
|
||||
stored in idp2/idp_user.py. (Note, not all accounts have all such data
|
||||
defined.)
|
||||
|
||||
The username:password pairs in PASSWD:
|
||||
|
||||
haho0032:qwerty
|
||||
roland:dianakra
|
||||
babs:howes
|
||||
upper:crust
|
||||
|
||||
The SP doesn't do anything but show you the information that the IdP sent.
|
||||
|
||||
Note, the listeners are all configured to bind to localhost (127.0.0.1) only.
|
||||
If you want to be able to connect to them externally, grep "HOST = '127.0.0.1'"
|
||||
example/*/*.py and replace 127.0.0.1 with 0.0.0.0 or a specific IP.
|
||||
|
||||
To make it easy, for me :-), both the IdP and the SP uses the same keys.
|
||||
To generate new keys, run create_key.sh and follow its instructions.
|
||||
|
||||
To run the setup do
|
||||
There are alternate IdP and SP configs in idp2_repoze/ and sp-repoze/ that
|
||||
are still in flux; do not use them unless you know what you are doing.
|
||||
|
||||
./all.sh start
|
||||
|
||||
and then use your favourit webbrowser to look at "http://localhost:8087/whoami"
|
||||
|
||||
./all stop
|
||||
|
||||
will of course stop your IdP and SP.
|
||||
@@ -2,19 +2,19 @@
|
||||
|
||||
startme() {
|
||||
cd sp-wsgi
|
||||
if [ ! -f conf.py ] ; then
|
||||
cp conf.py.example conf.py
|
||||
if [ ! -f sp_conf.py ] ; then
|
||||
cp sp_conf.py.example sp_conf.py
|
||||
fi
|
||||
../../tools/make_metadata.py conf > sp.xml
|
||||
../../tools/make_metadata.py sp_conf > sp.xml
|
||||
|
||||
cd ../idp2
|
||||
if [ ! -f idp_conf.py ] ; then
|
||||
cp idp_conf.py.example conf.py
|
||||
cp idp_conf.py.example idp_conf.py
|
||||
fi
|
||||
../../tools/make_metadata.py idp_conf > idp.xml
|
||||
|
||||
cd ../sp-wsgi
|
||||
./sp.py conf &
|
||||
./sp.py sp_conf &
|
||||
|
||||
cd ../idp2
|
||||
./idp.py idp_conf &
|
||||
@@ -34,4 +34,4 @@ case "$1" in
|
||||
*) echo "usage: $0 start|stop|restart" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
openssl genrsa -des3 -out server.key 1024
|
||||
#!/bin/bash
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Generating a new test key and certificate. To change the defaults offered
|
||||
by openssl, edit your openssl.cnf, such as /etc/ssl/openssl.cnf
|
||||
|
||||
EOF
|
||||
|
||||
openssl genrsa -out server.key 1024
|
||||
chmod 600 server.key
|
||||
openssl req -new -key server.key -out server.csr
|
||||
cp server.key server.key.org
|
||||
openssl rsa -in server.key.org -out server.key
|
||||
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
|
||||
|
||||
cat <<EOH
|
||||
|
||||
Now to enable these new keys, do:
|
||||
|
||||
cp server.key idp2/pki/mykey.pem
|
||||
cp server.crt idp2/pki/mycert.pem
|
||||
|
||||
cp server.key sp-wsgi/pki/mykey.pem
|
||||
cp server.crt sp-wsgi/pki/mycert.pem
|
||||
|
||||
EOH
|
||||
|
||||
@@ -871,7 +871,7 @@ def application(environ, start_response):
|
||||
captures in the WSGI environment as `myapp.url_args` so that
|
||||
the functions from above can access the url placeholders.
|
||||
|
||||
If nothing matches call the `not_found` function.
|
||||
If nothing matches, call the `not_found` function.
|
||||
|
||||
:param environ: The HTTP application environment
|
||||
:param start_response: The application to run when the handling of the
|
||||
@@ -976,10 +976,11 @@ if __name__ == '__main__':
|
||||
module_directory=_rot + 'modules',
|
||||
input_encoding='utf-8', output_encoding='utf-8')
|
||||
|
||||
HOST = '127.0.0.1'
|
||||
PORT = 8088
|
||||
|
||||
SRV = make_server('', PORT, application)
|
||||
print "IdP listening on port: %s" % PORT
|
||||
SRV = make_server(HOST, PORT, application)
|
||||
print "IdP listening on %s:%s" % (HOST, PORT)
|
||||
SRV.serve_forever()
|
||||
else:
|
||||
_rot = args.mako_root
|
||||
|
||||
@@ -116,7 +116,7 @@ CONFIG = {
|
||||
"email_address": "support@example.com"
|
||||
},
|
||||
],
|
||||
# This database holds the map between a subjects local identifier and
|
||||
# This database holds the map between a subject's local identifier and
|
||||
# the identifier returned to a SP
|
||||
"xmlsec_binary": xmlsec_path,
|
||||
#"attribute_map_dir": "../attributemaps",
|
||||
@@ -141,4 +141,4 @@ PWD_VERIFY = "%s/verify_pwd" % BASE
|
||||
AUTHORIZATION = {
|
||||
"CAS" : {"ACR": "CAS", "WEIGHT": 1, "URL": CAS_VERIFY},
|
||||
"UserPassword" : {"ACR": "PASSWORD", "WEIGHT": 2, "URL": PWD_VERIFY}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,10 +869,10 @@ def application(environ, start_response):
|
||||
"""
|
||||
The main WSGI application. Dispatch the current request to
|
||||
the functions from above and store the regular expression
|
||||
captures in the WSGI environment as `myapp.url_args` so that
|
||||
captures in the WSGI environment as `myapp.url_args` so that
|
||||
the functions from above can access the url placeholders.
|
||||
|
||||
If nothing matches call the `not_found` function.
|
||||
If nothing matches, call the `not_found` function.
|
||||
|
||||
:param environ: The HTTP application environment
|
||||
:param start_response: The application to run when the handling of the
|
||||
@@ -977,10 +977,11 @@ if __name__ == '__main__':
|
||||
module_directory=_rot + 'modules',
|
||||
input_encoding='utf-8', output_encoding='utf-8')
|
||||
|
||||
HOST = '127.0.0.1'
|
||||
PORT = 8088
|
||||
|
||||
SRV = make_server('', PORT, application)
|
||||
print "IdP listening on port: %s" % PORT
|
||||
SRV = make_server(HOST, PORT, application)
|
||||
print "IdP listening on %s:%s" % (HOST, PORT)
|
||||
SRV.serve_forever()
|
||||
else:
|
||||
_rot = args.mako_root
|
||||
|
||||
@@ -116,7 +116,7 @@ CONFIG = {
|
||||
"email_address": "support@example.com"
|
||||
},
|
||||
],
|
||||
# This database holds the map between a subjects local identifier and
|
||||
# This database holds the map between a subject's local identifier and
|
||||
# the identifier returned to a SP
|
||||
"xmlsec_binary": xmlsec_path,
|
||||
#"attribute_map_dir": "../attributemaps",
|
||||
@@ -141,4 +141,4 @@ PWD_VERIFY = "%s/verify_pwd" % BASE
|
||||
AUTHORIZATION = {
|
||||
"CAS" : {"ACR": "CAS", "WEIGHT": 1, "URL": CAS_VERIFY},
|
||||
"UserPassword" : {"ACR": "PASSWORD", "WEIGHT": 2, "URL": PWD_VERIFY}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ def whoami(environ, start_response, user):
|
||||
if not nameid:
|
||||
return not_authn(environ, start_response)
|
||||
if ava:
|
||||
response = ["<h2>Your identity are supposed to be</h2>"]
|
||||
response = ["<h2>Your identity is supposed to be</h2>"]
|
||||
response.extend(dict_to_table(ava))
|
||||
else:
|
||||
response = [
|
||||
@@ -222,10 +222,10 @@ def application(environ, start_response):
|
||||
"""
|
||||
The main WSGI application. Dispatch the current request to
|
||||
the functions from above and store the regular expression
|
||||
captures in the WSGI environment as `myapp.url_args` so that
|
||||
captures in the WSGI environment as `myapp.url_args` so that
|
||||
the functions from above can access the url placeholders.
|
||||
|
||||
If nothing matches call the `not_found` function.
|
||||
If nothing matches, call the `not_found` function.
|
||||
|
||||
:param environ: The HTTP application environment
|
||||
:param start_response: The application to run when the handling of the
|
||||
@@ -268,6 +268,7 @@ app_with_auth = make_middleware_with_config(application, {"here": "."},
|
||||
log_file="repoze_who.log")
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
HOST = '127.0.0.1'
|
||||
PORT = 8087
|
||||
|
||||
# allow uwsgi or gunicorn mount
|
||||
@@ -291,6 +292,6 @@ if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
|
||||
from wsgiref.simple_server import make_server
|
||||
srv = make_server('', PORT, app_with_auth)
|
||||
print "SP listening on port: %s" % PORT
|
||||
srv.serve_forever()
|
||||
srv = make_server(HOST, PORT, app_with_auth)
|
||||
print "SP listening on %s:%s" % (HOST, PORT)
|
||||
srv.serve_forever()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from saml2.assertion import Policy
|
||||
|
||||
HOST = '127.0.0.1'
|
||||
PORT = 8087
|
||||
HTTPS = False
|
||||
|
||||
@@ -11,6 +12,6 @@ POLICY = Policy(
|
||||
)
|
||||
|
||||
# HTTPS cert information
|
||||
SERVER_CERT = "pki/ssl.crt"
|
||||
SERVER_KEY = "pki/ssl.pem"
|
||||
CERT_CHAIN = ""
|
||||
SERVER_CERT = "pki/mycert.pem"
|
||||
SERVER_KEY = "pki/mykey.pem"
|
||||
CERT_CHAIN = ""
|
||||
|
||||
@@ -93,7 +93,7 @@ def dict_to_table(ava, lev=0, width=1):
|
||||
def handle_static(environ, start_response, path):
|
||||
"""
|
||||
Creates a response for a static file. There might be a longer path
|
||||
then just /static/... if so strip the path leading up to static.
|
||||
then just /static/... - if so strip the path leading up to static.
|
||||
|
||||
:param environ: wsgi enviroment
|
||||
:param start_response: wsgi start response
|
||||
@@ -534,7 +534,7 @@ class SSO(object):
|
||||
self.cache.relay_state[_rstate] = came_from
|
||||
ht_args = _cli.apply_binding(_binding, "%s" % req, destination,
|
||||
relay_state=_rstate)
|
||||
_sid = req.id
|
||||
_sid = req_id
|
||||
logger.debug("ht_args: %s" % ht_args)
|
||||
except Exception, exc:
|
||||
logger.exception(exc)
|
||||
@@ -645,7 +645,7 @@ def application(environ, start_response):
|
||||
The main WSGI application. Dispatch the current request to
|
||||
the functions from above.
|
||||
|
||||
If nothing matches call the `not_found` function.
|
||||
If nothing matches, call the `not_found` function.
|
||||
|
||||
:param environ: The HTTP application environment
|
||||
:param start_response: The application to run when the handling of the
|
||||
@@ -683,13 +683,14 @@ def application(environ, start_response):
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
HOST = service_conf.HOST
|
||||
PORT = service_conf.PORT
|
||||
# ------- HTTPS -------
|
||||
# These should point to relevant files
|
||||
SERVER_CERT = service_conf.SERVER_CERT
|
||||
SERVER_KEY = service_conf.SERVER_KEY
|
||||
# This is of course the certificate chain for the CA that signed
|
||||
# you cert and all the way up to the top
|
||||
# your cert and all the way up to the top
|
||||
CERT_CHAIN = service_conf.CERT_CHAIN
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -727,13 +728,13 @@ if __name__ == '__main__':
|
||||
|
||||
add_urls()
|
||||
|
||||
SRV = wsgiserver.CherryPyWSGIServer(('0.0.0.0', PORT), application)
|
||||
SRV = wsgiserver.CherryPyWSGIServer((HOST, PORT), application)
|
||||
|
||||
if service_conf.HTTPS:
|
||||
SRV.ssl_adapter = ssl_pyopenssl.pyOpenSSLAdapter(SERVER_CERT,
|
||||
SERVER_KEY, CERT_CHAIN)
|
||||
logger.info("Server starting")
|
||||
print "SP listening on port: %s" % PORT
|
||||
print "SP listening on %s:%s" % (HOST, PORT)
|
||||
try:
|
||||
SRV.start()
|
||||
except KeyboardInterrupt:
|
||||
|
||||
3
setup.py
3
setup.py
@@ -46,7 +46,8 @@ install_requires = [
|
||||
'pycrypto', # 'Crypto'
|
||||
'pytz',
|
||||
'pyOpenSSL',
|
||||
'python-dateutil'
|
||||
'python-dateutil',
|
||||
'argparse'
|
||||
]
|
||||
|
||||
tests_require = [
|
||||
|
||||
@@ -78,7 +78,8 @@ def _match(attr, ava):
|
||||
return None
|
||||
|
||||
|
||||
def filter_on_attributes(ava, required=None, optional=None, acs=None):
|
||||
def filter_on_attributes(ava, required=None, optional=None, acs=None,
|
||||
fail_on_unfulfilled_requirements=True):
|
||||
""" Filter
|
||||
|
||||
:param ava: An attribute value assertion as a dictionary
|
||||
@@ -86,6 +87,8 @@ def filter_on_attributes(ava, required=None, optional=None, acs=None):
|
||||
required
|
||||
:param optional: list of RequestedAttribute instances defined to be
|
||||
optional
|
||||
:param fail_on_unfulfilled_requirements: If required attributes
|
||||
are missing fail or fail not depending on this parameter.
|
||||
:return: The modified attribute value assertion
|
||||
"""
|
||||
res = {}
|
||||
@@ -116,7 +119,7 @@ def filter_on_attributes(ava, required=None, optional=None, acs=None):
|
||||
values = []
|
||||
res[_fn] = _filter_values(ava[_fn], values, True)
|
||||
continue
|
||||
else:
|
||||
elif fail_on_unfulfilled_requirements:
|
||||
desc = "Required attribute missing: '%s' (%s)" % (attr["name"],
|
||||
_name)
|
||||
raise MissingValue(desc)
|
||||
@@ -434,6 +437,16 @@ class Policy(object):
|
||||
|
||||
return self.get("attribute_restrictions", sp_entity_id)
|
||||
|
||||
def get_fail_on_missing_requested(self, sp_entity_id):
|
||||
""" Return the whether the IdP should should fail if the SPs
|
||||
requested attributes could not be found.
|
||||
|
||||
:param sp_entity_id: The SP entity ID
|
||||
:return: The restrictions
|
||||
"""
|
||||
|
||||
return self.get("fail_on_missing_requested", sp_entity_id, True)
|
||||
|
||||
def entity_category_attributes(self, ec):
|
||||
if not self._restrictions:
|
||||
return None
|
||||
@@ -492,7 +505,9 @@ class Policy(object):
|
||||
|
||||
if required or optional:
|
||||
logger.debug("required: %s, optional: %s" % (required, optional))
|
||||
ava = filter_on_attributes(ava, required, optional, self.acs)
|
||||
ava = filter_on_attributes(
|
||||
ava, required, optional, self.acs,
|
||||
self.get_fail_on_missing_requested(sp_entity_id))
|
||||
|
||||
return ava
|
||||
|
||||
@@ -543,6 +558,103 @@ class EntityCategories(object):
|
||||
pass
|
||||
|
||||
|
||||
def _authn_context_class_ref(authn_class, authn_auth=None):
|
||||
"""
|
||||
Construct the authn context with a authn context class reference
|
||||
:param authn_class: The authn context class reference
|
||||
:param authn_auth: Authenticating Authority
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
cntx_class = factory(saml.AuthnContextClassRef, text=authn_class)
|
||||
if authn_auth:
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_class_ref=cntx_class,
|
||||
authenticating_authority=factory(
|
||||
saml.AuthenticatingAuthority, text=authn_auth))
|
||||
else:
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_class_ref=cntx_class)
|
||||
|
||||
|
||||
def _authn_context_decl(decl, authn_auth=None):
|
||||
"""
|
||||
Construct the authn context with a authn context declaration
|
||||
:param decl: The authn context declaration
|
||||
:param authn_auth: Authenticating Authority
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_decl=decl,
|
||||
authenticating_authority=factory(
|
||||
saml.AuthenticatingAuthority, text=authn_auth))
|
||||
|
||||
|
||||
def _authn_context_decl_ref(decl_ref, authn_auth=None):
|
||||
"""
|
||||
Construct the authn context with a authn context declaration reference
|
||||
:param decl_ref: The authn context declaration reference
|
||||
:param authn_auth: Authenticating Authority
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_decl_ref=decl_ref,
|
||||
authenticating_authority=factory(
|
||||
saml.AuthenticatingAuthority, text=authn_auth))
|
||||
|
||||
|
||||
def authn_statement(authn_class=None, authn_auth=None,
|
||||
authn_decl=None, authn_decl_ref=None, authn_instant="",
|
||||
subject_locality=""):
|
||||
"""
|
||||
Construct the AuthnStatement
|
||||
:param authn_class: Authentication Context Class reference
|
||||
:param authn_auth: Authenticating Authority
|
||||
:param authn_decl: Authentication Context Declaration
|
||||
:param authn_decl_ref: Authentication Context Declaration reference
|
||||
:param authn_instant: When the Authentication was performed.
|
||||
Assumed to be seconds since the Epoch.
|
||||
:param subject_locality: Specifies the DNS domain name and IP address
|
||||
for the system from which the assertion subject was apparently
|
||||
authenticated.
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
if authn_instant:
|
||||
_instant = instant(time_stamp=authn_instant)
|
||||
else:
|
||||
_instant = instant()
|
||||
|
||||
if authn_class:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid(),
|
||||
authn_context=_authn_context_class_ref(
|
||||
authn_class, authn_auth))
|
||||
elif authn_decl:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid(),
|
||||
authn_context=_authn_context_decl(authn_decl, authn_auth))
|
||||
elif authn_decl_ref:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid(),
|
||||
authn_context=_authn_context_decl_ref(authn_decl_ref,
|
||||
authn_auth))
|
||||
else:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid())
|
||||
|
||||
if subject_locality:
|
||||
res.subject_locality = saml.SubjectLocality(text=subject_locality)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
class Assertion(dict):
|
||||
""" Handles assertions about subjects """
|
||||
|
||||
@@ -550,101 +662,6 @@ class Assertion(dict):
|
||||
dict.__init__(self, dic)
|
||||
self.acs = []
|
||||
|
||||
@staticmethod
|
||||
def _authn_context_decl(decl, authn_auth=None):
|
||||
"""
|
||||
Construct the authn context with a authn context declaration
|
||||
:param decl: The authn context declaration
|
||||
:param authn_auth: Authenticating Authority
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_decl=decl,
|
||||
authenticating_authority=factory(
|
||||
saml.AuthenticatingAuthority, text=authn_auth))
|
||||
|
||||
def _authn_context_decl_ref(self, decl_ref, authn_auth=None):
|
||||
"""
|
||||
Construct the authn context with a authn context declaration reference
|
||||
:param decl_ref: The authn context declaration reference
|
||||
:param authn_auth: Authenticating Authority
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_decl_ref=decl_ref,
|
||||
authenticating_authority=factory(
|
||||
saml.AuthenticatingAuthority, text=authn_auth))
|
||||
|
||||
@staticmethod
|
||||
def _authn_context_class_ref(authn_class, authn_auth=None):
|
||||
"""
|
||||
Construct the authn context with a authn context class reference
|
||||
:param authn_class: The authn context class reference
|
||||
:param authn_auth: Authenticating Authority
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
cntx_class = factory(saml.AuthnContextClassRef, text=authn_class)
|
||||
if authn_auth:
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_class_ref=cntx_class,
|
||||
authenticating_authority=factory(
|
||||
saml.AuthenticatingAuthority, text=authn_auth))
|
||||
else:
|
||||
return factory(saml.AuthnContext,
|
||||
authn_context_class_ref=cntx_class)
|
||||
|
||||
def _authn_statement(self, authn_class=None, authn_auth=None,
|
||||
authn_decl=None, authn_decl_ref=None, authn_instant="",
|
||||
subject_locality=""):
|
||||
"""
|
||||
Construct the AuthnStatement
|
||||
:param authn_class: Authentication Context Class reference
|
||||
:param authn_auth: Authenticating Authority
|
||||
:param authn_decl: Authentication Context Declaration
|
||||
:param authn_decl_ref: Authentication Context Declaration reference
|
||||
:param authn_instant: When the Authentication was performed.
|
||||
Assumed to be seconds since the Epoch.
|
||||
:param subject_locality: Specifies the DNS domain name and IP address
|
||||
for the system from which the assertion subject was apparently
|
||||
authenticated.
|
||||
:return: An AuthnContext instance
|
||||
"""
|
||||
if authn_instant:
|
||||
_instant = instant(time_stamp=authn_instant)
|
||||
else:
|
||||
_instant = instant()
|
||||
|
||||
if authn_class:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid(),
|
||||
authn_context=self._authn_context_class_ref(
|
||||
authn_class, authn_auth))
|
||||
elif authn_decl:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid(),
|
||||
authn_context=self._authn_context_decl(authn_decl, authn_auth))
|
||||
elif authn_decl_ref:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid(),
|
||||
authn_context=self._authn_context_decl_ref(authn_decl_ref,
|
||||
authn_auth))
|
||||
else:
|
||||
res = factory(
|
||||
saml.AuthnStatement,
|
||||
authn_instant=_instant,
|
||||
session_index=sid())
|
||||
|
||||
if subject_locality:
|
||||
res.subject_locality = saml.SubjectLocality(text=subject_locality)
|
||||
|
||||
return res
|
||||
|
||||
def construct(self, sp_entity_id, in_response_to, consumer_url,
|
||||
name_id, attrconvs, policy, issuer, authn_class=None,
|
||||
authn_auth=None, authn_decl=None, encrypt=None,
|
||||
@@ -695,10 +712,10 @@ class Assertion(dict):
|
||||
conds = policy.conditions(sp_entity_id)
|
||||
|
||||
if authn_auth or authn_class or authn_decl or authn_decl_ref:
|
||||
_authn_statement = self._authn_statement(authn_class, authn_auth,
|
||||
authn_decl, authn_decl_ref,
|
||||
authn_instant,
|
||||
subject_locality)
|
||||
_authn_statement = authn_statement(authn_class, authn_auth,
|
||||
authn_decl, authn_decl_ref,
|
||||
authn_instant,
|
||||
subject_locality)
|
||||
else:
|
||||
_authn_statement = None
|
||||
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
# See http://technet.microsoft.com/en-us/library/cc733065(v=ws.10).aspx
|
||||
# and http://technet.microsoft.com/en-us/library/ee913589(v=ws.10).aspx
|
||||
# for information regarding the default claim types supported by
|
||||
# Microsoft ADFS v1.x.
|
||||
CLAIMS = 'http://schemas.xmlsoap.org/claims/'
|
||||
|
||||
|
||||
MAP = {
|
||||
"identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified",
|
||||
"fro": {
|
||||
'http://schemas.xmlsoap.org/claims/commonname': 'commonName',
|
||||
'http://schemas.xmlsoap.org/claims/emailaddress': 'emailAddress',
|
||||
'http://schemas.xmlsoap.org/claims/group': 'group',
|
||||
'http://schemas.xmlsoap.org/claims/upn': 'upn',
|
||||
},
|
||||
"to": {
|
||||
'commonName': 'http://schemas.xmlsoap.org/claims/commonname',
|
||||
'emailAddress': 'http://schemas.xmlsoap.org/claims/emailaddress',
|
||||
'group': 'http://schemas.xmlsoap.org/claims/group',
|
||||
'upn': 'http://schemas.xmlsoap.org/claims/upn',
|
||||
'fro': {
|
||||
CLAIMS+'commonname': 'commonName',
|
||||
CLAIMS+'emailaddress': 'emailAddress',
|
||||
CLAIMS+'group': 'group',
|
||||
CLAIMS+'upn': 'upn',
|
||||
},
|
||||
'to': {
|
||||
'commonName': CLAIMS+'commonname',
|
||||
'emailAddress': CLAIMS+'emailaddress',
|
||||
'group': CLAIMS+'group',
|
||||
'upn': CLAIMS+'upn',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
# See http://technet.microsoft.com/en-us/library/ee913589(v=ws.10).aspx
|
||||
# for information regarding the default claim types supported by
|
||||
# Microsoft ADFS v2.0.
|
||||
CLAIMS = 'http://schemas.xmlsoap.org/claims/'
|
||||
COM_WS_CLAIMS = 'http://schemas.xmlsoap.com/ws/2005/05/identity/claims/'
|
||||
MS_CLAIMS = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/'
|
||||
ORG_WS_CLAIMS = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/'
|
||||
|
||||
|
||||
MAP = {
|
||||
"identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified",
|
||||
"fro": {
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'emailAddress',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname': 'givenName',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'name',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn': 'upn',
|
||||
'http://schemas.xmlsoap.org/claims/commonname': 'commonName',
|
||||
'http://schemas.xmlsoap.org/claims/group': 'group',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/role': 'role',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname': 'surname',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier': 'privatePersonalId',
|
||||
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier': 'nameId',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod': 'authenticationMethod',
|
||||
'http://schemas.xmlsoap.com/ws/2005/05/identity/claims/denyonlysid': 'denyOnlySid',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid': 'denyOnlyPrimarySid',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid': 'denyOnlyPrimaryGroupSid',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid': 'groupSid',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid': 'primaryGroupSid',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid': 'primarySid',
|
||||
'http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname': 'windowsAccountName',
|
||||
},
|
||||
"to": {
|
||||
'emailAddress': 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
|
||||
'givenName': 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname',
|
||||
'name': 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name',
|
||||
'upn': 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn',
|
||||
'commonName': 'http://schemas.xmlsoap.org/claims/commonname',
|
||||
'group': 'http://schemas.xmlsoap.org/claims/group',
|
||||
'role': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role',
|
||||
'surname': 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname',
|
||||
'privatePersonalId': 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier',
|
||||
'nameId': 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier',
|
||||
'authenticationMethod': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod',
|
||||
'denyOnlySid': 'http://schemas.xmlsoap.com/ws/2005/05/identity/claims/denyonlysid',
|
||||
'denyOnlyPrimarySid': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid',
|
||||
'denyOnlyPrimaryGroupSid': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid',
|
||||
'groupSid': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid',
|
||||
'primaryGroupSid': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid',
|
||||
'primarySid': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid',
|
||||
'windowsAccountName': 'http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname',
|
||||
'fro': {
|
||||
CLAIMS+'commonname': 'commonName',
|
||||
CLAIMS+'group': 'group',
|
||||
COM_WS_CLAIMS+'denyonlysid': 'denyOnlySid',
|
||||
MS_CLAIMS+'authenticationmethod': 'authenticationMethod',
|
||||
MS_CLAIMS+'denyonlyprimarygroupsid': 'denyOnlyPrimaryGroupSid',
|
||||
MS_CLAIMS+'denyonlyprimarysid': 'denyOnlyPrimarySid',
|
||||
MS_CLAIMS+'groupsid': 'groupSid',
|
||||
MS_CLAIMS+'primarygroupsid': 'primaryGroupSid',
|
||||
MS_CLAIMS+'primarysid': 'primarySid',
|
||||
MS_CLAIMS+'role': 'role',
|
||||
MS_CLAIMS+'windowsaccountname': 'windowsAccountName',
|
||||
ORG_WS_CLAIMS+'emailaddress': 'emailAddress',
|
||||
ORG_WS_CLAIMS+'givenname': 'givenName',
|
||||
ORG_WS_CLAIMS+'name': 'name',
|
||||
ORG_WS_CLAIMS+'nameidentifier': 'nameId',
|
||||
ORG_WS_CLAIMS+'privatepersonalidentifier': 'privatePersonalId',
|
||||
ORG_WS_CLAIMS+'surname': 'surname',
|
||||
ORG_WS_CLAIMS+'upn': 'upn',
|
||||
},
|
||||
'to': {
|
||||
'authenticationMethod': MS_CLAIMS+'authenticationmethod',
|
||||
'commonName': CLAIMS+'commonname',
|
||||
'denyOnlyPrimaryGroupSid': MS_CLAIMS+'denyonlyprimarygroupsid',
|
||||
'denyOnlyPrimarySid': MS_CLAIMS+'denyonlyprimarysid',
|
||||
'denyOnlySid': COM_WS_CLAIMS+'denyonlysid',
|
||||
'emailAddress': ORG_WS_CLAIMS+'emailaddress',
|
||||
'givenName': ORG_WS_CLAIMS+'givenname',
|
||||
'group': CLAIMS+'group',
|
||||
'groupSid': MS_CLAIMS+'groupsid',
|
||||
'name': ORG_WS_CLAIMS+'name',
|
||||
'nameId': ORG_WS_CLAIMS+'nameidentifier',
|
||||
'primaryGroupSid': MS_CLAIMS+'primarygroupsid',
|
||||
'primarySid': MS_CLAIMS+'primarysid',
|
||||
'privatePersonalId': ORG_WS_CLAIMS+'privatepersonalidentifier',
|
||||
'role': MS_CLAIMS+'role',
|
||||
'surname': ORG_WS_CLAIMS+'surname',
|
||||
'upn': ORG_WS_CLAIMS+'upn',
|
||||
'windowsAccountName': MS_CLAIMS+'windowsaccountname',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,326 +1,328 @@
|
||||
DEF = 'urn:mace:dir:attribute-def:'
|
||||
|
||||
|
||||
MAP = {
|
||||
"identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:basic",
|
||||
"fro": {
|
||||
'urn:mace:dir:attribute-def:aRecord': 'aRecord',
|
||||
'urn:mace:dir:attribute-def:aliasedEntryName': 'aliasedEntryName',
|
||||
'urn:mace:dir:attribute-def:aliasedObjectName': 'aliasedObjectName',
|
||||
'urn:mace:dir:attribute-def:associatedDomain': 'associatedDomain',
|
||||
'urn:mace:dir:attribute-def:associatedName': 'associatedName',
|
||||
'urn:mace:dir:attribute-def:audio': 'audio',
|
||||
'urn:mace:dir:attribute-def:authorityRevocationList': 'authorityRevocationList',
|
||||
'urn:mace:dir:attribute-def:buildingName': 'buildingName',
|
||||
'urn:mace:dir:attribute-def:businessCategory': 'businessCategory',
|
||||
'urn:mace:dir:attribute-def:c': 'c',
|
||||
'urn:mace:dir:attribute-def:cACertificate': 'cACertificate',
|
||||
'urn:mace:dir:attribute-def:cNAMERecord': 'cNAMERecord',
|
||||
'urn:mace:dir:attribute-def:carLicense': 'carLicense',
|
||||
'urn:mace:dir:attribute-def:certificateRevocationList': 'certificateRevocationList',
|
||||
'urn:mace:dir:attribute-def:cn': 'cn',
|
||||
'urn:mace:dir:attribute-def:co': 'co',
|
||||
'urn:mace:dir:attribute-def:commonName': 'commonName',
|
||||
'urn:mace:dir:attribute-def:countryName': 'countryName',
|
||||
'urn:mace:dir:attribute-def:crossCertificatePair': 'crossCertificatePair',
|
||||
'urn:mace:dir:attribute-def:dITRedirect': 'dITRedirect',
|
||||
'urn:mace:dir:attribute-def:dSAQuality': 'dSAQuality',
|
||||
'urn:mace:dir:attribute-def:dc': 'dc',
|
||||
'urn:mace:dir:attribute-def:deltaRevocationList': 'deltaRevocationList',
|
||||
'urn:mace:dir:attribute-def:departmentNumber': 'departmentNumber',
|
||||
'urn:mace:dir:attribute-def:description': 'description',
|
||||
'urn:mace:dir:attribute-def:destinationIndicator': 'destinationIndicator',
|
||||
'urn:mace:dir:attribute-def:displayName': 'displayName',
|
||||
'urn:mace:dir:attribute-def:distinguishedName': 'distinguishedName',
|
||||
'urn:mace:dir:attribute-def:dmdName': 'dmdName',
|
||||
'urn:mace:dir:attribute-def:dnQualifier': 'dnQualifier',
|
||||
'urn:mace:dir:attribute-def:documentAuthor': 'documentAuthor',
|
||||
'urn:mace:dir:attribute-def:documentIdentifier': 'documentIdentifier',
|
||||
'urn:mace:dir:attribute-def:documentLocation': 'documentLocation',
|
||||
'urn:mace:dir:attribute-def:documentPublisher': 'documentPublisher',
|
||||
'urn:mace:dir:attribute-def:documentTitle': 'documentTitle',
|
||||
'urn:mace:dir:attribute-def:documentVersion': 'documentVersion',
|
||||
'urn:mace:dir:attribute-def:domainComponent': 'domainComponent',
|
||||
'urn:mace:dir:attribute-def:drink': 'drink',
|
||||
'urn:mace:dir:attribute-def:eduOrgHomePageURI': 'eduOrgHomePageURI',
|
||||
'urn:mace:dir:attribute-def:eduOrgIdentityAuthNPolicyURI': 'eduOrgIdentityAuthNPolicyURI',
|
||||
'urn:mace:dir:attribute-def:eduOrgLegalName': 'eduOrgLegalName',
|
||||
'urn:mace:dir:attribute-def:eduOrgSuperiorURI': 'eduOrgSuperiorURI',
|
||||
'urn:mace:dir:attribute-def:eduOrgWhitePagesURI': 'eduOrgWhitePagesURI',
|
||||
'urn:mace:dir:attribute-def:eduPersonAffiliation': 'eduPersonAffiliation',
|
||||
'urn:mace:dir:attribute-def:eduPersonEntitlement': 'eduPersonEntitlement',
|
||||
'urn:mace:dir:attribute-def:eduPersonNickname': 'eduPersonNickname',
|
||||
'urn:mace:dir:attribute-def:eduPersonOrgDN': 'eduPersonOrgDN',
|
||||
'urn:mace:dir:attribute-def:eduPersonOrgUnitDN': 'eduPersonOrgUnitDN',
|
||||
'urn:mace:dir:attribute-def:eduPersonPrimaryAffiliation': 'eduPersonPrimaryAffiliation',
|
||||
'urn:mace:dir:attribute-def:eduPersonPrimaryOrgUnitDN': 'eduPersonPrimaryOrgUnitDN',
|
||||
'urn:mace:dir:attribute-def:eduPersonPrincipalName': 'eduPersonPrincipalName',
|
||||
'urn:mace:dir:attribute-def:eduPersonScopedAffiliation': 'eduPersonScopedAffiliation',
|
||||
'urn:mace:dir:attribute-def:eduPersonTargetedID': 'eduPersonTargetedID',
|
||||
'urn:mace:dir:attribute-def:email': 'email',
|
||||
'urn:mace:dir:attribute-def:emailAddress': 'emailAddress',
|
||||
'urn:mace:dir:attribute-def:employeeNumber': 'employeeNumber',
|
||||
'urn:mace:dir:attribute-def:employeeType': 'employeeType',
|
||||
'urn:mace:dir:attribute-def:enhancedSearchGuide': 'enhancedSearchGuide',
|
||||
'urn:mace:dir:attribute-def:facsimileTelephoneNumber': 'facsimileTelephoneNumber',
|
||||
'urn:mace:dir:attribute-def:favouriteDrink': 'favouriteDrink',
|
||||
'urn:mace:dir:attribute-def:fax': 'fax',
|
||||
'urn:mace:dir:attribute-def:federationFeideSchemaVersion': 'federationFeideSchemaVersion',
|
||||
'urn:mace:dir:attribute-def:friendlyCountryName': 'friendlyCountryName',
|
||||
'urn:mace:dir:attribute-def:generationQualifier': 'generationQualifier',
|
||||
'urn:mace:dir:attribute-def:givenName': 'givenName',
|
||||
'urn:mace:dir:attribute-def:gn': 'gn',
|
||||
'urn:mace:dir:attribute-def:homePhone': 'homePhone',
|
||||
'urn:mace:dir:attribute-def:homePostalAddress': 'homePostalAddress',
|
||||
'urn:mace:dir:attribute-def:homeTelephoneNumber': 'homeTelephoneNumber',
|
||||
'urn:mace:dir:attribute-def:host': 'host',
|
||||
'urn:mace:dir:attribute-def:houseIdentifier': 'houseIdentifier',
|
||||
'urn:mace:dir:attribute-def:info': 'info',
|
||||
'urn:mace:dir:attribute-def:initials': 'initials',
|
||||
'urn:mace:dir:attribute-def:internationaliSDNNumber': 'internationaliSDNNumber',
|
||||
'urn:mace:dir:attribute-def:janetMailbox': 'janetMailbox',
|
||||
'urn:mace:dir:attribute-def:jpegPhoto': 'jpegPhoto',
|
||||
'urn:mace:dir:attribute-def:knowledgeInformation': 'knowledgeInformation',
|
||||
'urn:mace:dir:attribute-def:l': 'l',
|
||||
'urn:mace:dir:attribute-def:labeledURI': 'labeledURI',
|
||||
'urn:mace:dir:attribute-def:localityName': 'localityName',
|
||||
'urn:mace:dir:attribute-def:mDRecord': 'mDRecord',
|
||||
'urn:mace:dir:attribute-def:mXRecord': 'mXRecord',
|
||||
'urn:mace:dir:attribute-def:mail': 'mail',
|
||||
'urn:mace:dir:attribute-def:mailPreferenceOption': 'mailPreferenceOption',
|
||||
'urn:mace:dir:attribute-def:manager': 'manager',
|
||||
'urn:mace:dir:attribute-def:member': 'member',
|
||||
'urn:mace:dir:attribute-def:mobile': 'mobile',
|
||||
'urn:mace:dir:attribute-def:mobileTelephoneNumber': 'mobileTelephoneNumber',
|
||||
'urn:mace:dir:attribute-def:nSRecord': 'nSRecord',
|
||||
'urn:mace:dir:attribute-def:name': 'name',
|
||||
'urn:mace:dir:attribute-def:norEduOrgAcronym': 'norEduOrgAcronym',
|
||||
'urn:mace:dir:attribute-def:norEduOrgNIN': 'norEduOrgNIN',
|
||||
'urn:mace:dir:attribute-def:norEduOrgSchemaVersion': 'norEduOrgSchemaVersion',
|
||||
'urn:mace:dir:attribute-def:norEduOrgUniqueIdentifier': 'norEduOrgUniqueIdentifier',
|
||||
'urn:mace:dir:attribute-def:norEduOrgUniqueNumber': 'norEduOrgUniqueNumber',
|
||||
'urn:mace:dir:attribute-def:norEduOrgUnitUniqueIdentifier': 'norEduOrgUnitUniqueIdentifier',
|
||||
'urn:mace:dir:attribute-def:norEduOrgUnitUniqueNumber': 'norEduOrgUnitUniqueNumber',
|
||||
'urn:mace:dir:attribute-def:norEduPersonBirthDate': 'norEduPersonBirthDate',
|
||||
'urn:mace:dir:attribute-def:norEduPersonLIN': 'norEduPersonLIN',
|
||||
'urn:mace:dir:attribute-def:norEduPersonNIN': 'norEduPersonNIN',
|
||||
'urn:mace:dir:attribute-def:o': 'o',
|
||||
'urn:mace:dir:attribute-def:objectClass': 'objectClass',
|
||||
'urn:mace:dir:attribute-def:organizationName': 'organizationName',
|
||||
'urn:mace:dir:attribute-def:organizationalStatus': 'organizationalStatus',
|
||||
'urn:mace:dir:attribute-def:organizationalUnitName': 'organizationalUnitName',
|
||||
'urn:mace:dir:attribute-def:otherMailbox': 'otherMailbox',
|
||||
'urn:mace:dir:attribute-def:ou': 'ou',
|
||||
'urn:mace:dir:attribute-def:owner': 'owner',
|
||||
'urn:mace:dir:attribute-def:pager': 'pager',
|
||||
'urn:mace:dir:attribute-def:pagerTelephoneNumber': 'pagerTelephoneNumber',
|
||||
'urn:mace:dir:attribute-def:personalSignature': 'personalSignature',
|
||||
'urn:mace:dir:attribute-def:personalTitle': 'personalTitle',
|
||||
'urn:mace:dir:attribute-def:photo': 'photo',
|
||||
'urn:mace:dir:attribute-def:physicalDeliveryOfficeName': 'physicalDeliveryOfficeName',
|
||||
'urn:mace:dir:attribute-def:pkcs9email': 'pkcs9email',
|
||||
'urn:mace:dir:attribute-def:postOfficeBox': 'postOfficeBox',
|
||||
'urn:mace:dir:attribute-def:postalAddress': 'postalAddress',
|
||||
'urn:mace:dir:attribute-def:postalCode': 'postalCode',
|
||||
'urn:mace:dir:attribute-def:preferredDeliveryMethod': 'preferredDeliveryMethod',
|
||||
'urn:mace:dir:attribute-def:preferredLanguage': 'preferredLanguage',
|
||||
'urn:mace:dir:attribute-def:presentationAddress': 'presentationAddress',
|
||||
'urn:mace:dir:attribute-def:protocolInformation': 'protocolInformation',
|
||||
'urn:mace:dir:attribute-def:pseudonym': 'pseudonym',
|
||||
'urn:mace:dir:attribute-def:registeredAddress': 'registeredAddress',
|
||||
'urn:mace:dir:attribute-def:rfc822Mailbox': 'rfc822Mailbox',
|
||||
'urn:mace:dir:attribute-def:roleOccupant': 'roleOccupant',
|
||||
'urn:mace:dir:attribute-def:roomNumber': 'roomNumber',
|
||||
'urn:mace:dir:attribute-def:sOARecord': 'sOARecord',
|
||||
'urn:mace:dir:attribute-def:searchGuide': 'searchGuide',
|
||||
'urn:mace:dir:attribute-def:secretary': 'secretary',
|
||||
'urn:mace:dir:attribute-def:seeAlso': 'seeAlso',
|
||||
'urn:mace:dir:attribute-def:serialNumber': 'serialNumber',
|
||||
'urn:mace:dir:attribute-def:singleLevelQuality': 'singleLevelQuality',
|
||||
'urn:mace:dir:attribute-def:sn': 'sn',
|
||||
'urn:mace:dir:attribute-def:st': 'st',
|
||||
'urn:mace:dir:attribute-def:stateOrProvinceName': 'stateOrProvinceName',
|
||||
'urn:mace:dir:attribute-def:street': 'street',
|
||||
'urn:mace:dir:attribute-def:streetAddress': 'streetAddress',
|
||||
'urn:mace:dir:attribute-def:subtreeMaximumQuality': 'subtreeMaximumQuality',
|
||||
'urn:mace:dir:attribute-def:subtreeMinimumQuality': 'subtreeMinimumQuality',
|
||||
'urn:mace:dir:attribute-def:supportedAlgorithms': 'supportedAlgorithms',
|
||||
'urn:mace:dir:attribute-def:supportedApplicationContext': 'supportedApplicationContext',
|
||||
'urn:mace:dir:attribute-def:surname': 'surname',
|
||||
'urn:mace:dir:attribute-def:telephoneNumber': 'telephoneNumber',
|
||||
'urn:mace:dir:attribute-def:teletexTerminalIdentifier': 'teletexTerminalIdentifier',
|
||||
'urn:mace:dir:attribute-def:telexNumber': 'telexNumber',
|
||||
'urn:mace:dir:attribute-def:textEncodedORAddress': 'textEncodedORAddress',
|
||||
'urn:mace:dir:attribute-def:title': 'title',
|
||||
'urn:mace:dir:attribute-def:uid': 'uid',
|
||||
'urn:mace:dir:attribute-def:uniqueIdentifier': 'uniqueIdentifier',
|
||||
'urn:mace:dir:attribute-def:uniqueMember': 'uniqueMember',
|
||||
'urn:mace:dir:attribute-def:userCertificate': 'userCertificate',
|
||||
'urn:mace:dir:attribute-def:userClass': 'userClass',
|
||||
'urn:mace:dir:attribute-def:userPKCS12': 'userPKCS12',
|
||||
'urn:mace:dir:attribute-def:userPassword': 'userPassword',
|
||||
'urn:mace:dir:attribute-def:userSMIMECertificate': 'userSMIMECertificate',
|
||||
'urn:mace:dir:attribute-def:userid': 'userid',
|
||||
'urn:mace:dir:attribute-def:x121Address': 'x121Address',
|
||||
'urn:mace:dir:attribute-def:x500UniqueIdentifier': 'x500UniqueIdentifier',
|
||||
},
|
||||
"to": {
|
||||
'aRecord': 'urn:mace:dir:attribute-def:aRecord',
|
||||
'aliasedEntryName': 'urn:mace:dir:attribute-def:aliasedEntryName',
|
||||
'aliasedObjectName': 'urn:mace:dir:attribute-def:aliasedObjectName',
|
||||
'associatedDomain': 'urn:mace:dir:attribute-def:associatedDomain',
|
||||
'associatedName': 'urn:mace:dir:attribute-def:associatedName',
|
||||
'audio': 'urn:mace:dir:attribute-def:audio',
|
||||
'authorityRevocationList': 'urn:mace:dir:attribute-def:authorityRevocationList',
|
||||
'buildingName': 'urn:mace:dir:attribute-def:buildingName',
|
||||
'businessCategory': 'urn:mace:dir:attribute-def:businessCategory',
|
||||
'c': 'urn:mace:dir:attribute-def:c',
|
||||
'cACertificate': 'urn:mace:dir:attribute-def:cACertificate',
|
||||
'cNAMERecord': 'urn:mace:dir:attribute-def:cNAMERecord',
|
||||
'carLicense': 'urn:mace:dir:attribute-def:carLicense',
|
||||
'certificateRevocationList': 'urn:mace:dir:attribute-def:certificateRevocationList',
|
||||
'cn': 'urn:mace:dir:attribute-def:cn',
|
||||
'co': 'urn:mace:dir:attribute-def:co',
|
||||
'commonName': 'urn:mace:dir:attribute-def:commonName',
|
||||
'countryName': 'urn:mace:dir:attribute-def:countryName',
|
||||
'crossCertificatePair': 'urn:mace:dir:attribute-def:crossCertificatePair',
|
||||
'dITRedirect': 'urn:mace:dir:attribute-def:dITRedirect',
|
||||
'dSAQuality': 'urn:mace:dir:attribute-def:dSAQuality',
|
||||
'dc': 'urn:mace:dir:attribute-def:dc',
|
||||
'deltaRevocationList': 'urn:mace:dir:attribute-def:deltaRevocationList',
|
||||
'departmentNumber': 'urn:mace:dir:attribute-def:departmentNumber',
|
||||
'description': 'urn:mace:dir:attribute-def:description',
|
||||
'destinationIndicator': 'urn:mace:dir:attribute-def:destinationIndicator',
|
||||
'displayName': 'urn:mace:dir:attribute-def:displayName',
|
||||
'distinguishedName': 'urn:mace:dir:attribute-def:distinguishedName',
|
||||
'dmdName': 'urn:mace:dir:attribute-def:dmdName',
|
||||
'dnQualifier': 'urn:mace:dir:attribute-def:dnQualifier',
|
||||
'documentAuthor': 'urn:mace:dir:attribute-def:documentAuthor',
|
||||
'documentIdentifier': 'urn:mace:dir:attribute-def:documentIdentifier',
|
||||
'documentLocation': 'urn:mace:dir:attribute-def:documentLocation',
|
||||
'documentPublisher': 'urn:mace:dir:attribute-def:documentPublisher',
|
||||
'documentTitle': 'urn:mace:dir:attribute-def:documentTitle',
|
||||
'documentVersion': 'urn:mace:dir:attribute-def:documentVersion',
|
||||
'domainComponent': 'urn:mace:dir:attribute-def:domainComponent',
|
||||
'drink': 'urn:mace:dir:attribute-def:drink',
|
||||
'eduOrgHomePageURI': 'urn:mace:dir:attribute-def:eduOrgHomePageURI',
|
||||
'eduOrgIdentityAuthNPolicyURI': 'urn:mace:dir:attribute-def:eduOrgIdentityAuthNPolicyURI',
|
||||
'eduOrgLegalName': 'urn:mace:dir:attribute-def:eduOrgLegalName',
|
||||
'eduOrgSuperiorURI': 'urn:mace:dir:attribute-def:eduOrgSuperiorURI',
|
||||
'eduOrgWhitePagesURI': 'urn:mace:dir:attribute-def:eduOrgWhitePagesURI',
|
||||
'eduPersonAffiliation': 'urn:mace:dir:attribute-def:eduPersonAffiliation',
|
||||
'eduPersonEntitlement': 'urn:mace:dir:attribute-def:eduPersonEntitlement',
|
||||
'eduPersonNickname': 'urn:mace:dir:attribute-def:eduPersonNickname',
|
||||
'eduPersonOrgDN': 'urn:mace:dir:attribute-def:eduPersonOrgDN',
|
||||
'eduPersonOrgUnitDN': 'urn:mace:dir:attribute-def:eduPersonOrgUnitDN',
|
||||
'eduPersonPrimaryAffiliation': 'urn:mace:dir:attribute-def:eduPersonPrimaryAffiliation',
|
||||
'eduPersonPrimaryOrgUnitDN': 'urn:mace:dir:attribute-def:eduPersonPrimaryOrgUnitDN',
|
||||
'eduPersonPrincipalName': 'urn:mace:dir:attribute-def:eduPersonPrincipalName',
|
||||
'eduPersonScopedAffiliation': 'urn:mace:dir:attribute-def:eduPersonScopedAffiliation',
|
||||
'eduPersonTargetedID': 'urn:mace:dir:attribute-def:eduPersonTargetedID',
|
||||
'email': 'urn:mace:dir:attribute-def:email',
|
||||
'emailAddress': 'urn:mace:dir:attribute-def:emailAddress',
|
||||
'employeeNumber': 'urn:mace:dir:attribute-def:employeeNumber',
|
||||
'employeeType': 'urn:mace:dir:attribute-def:employeeType',
|
||||
'enhancedSearchGuide': 'urn:mace:dir:attribute-def:enhancedSearchGuide',
|
||||
'facsimileTelephoneNumber': 'urn:mace:dir:attribute-def:facsimileTelephoneNumber',
|
||||
'favouriteDrink': 'urn:mace:dir:attribute-def:favouriteDrink',
|
||||
'fax': 'urn:mace:dir:attribute-def:fax',
|
||||
'federationFeideSchemaVersion': 'urn:mace:dir:attribute-def:federationFeideSchemaVersion',
|
||||
'friendlyCountryName': 'urn:mace:dir:attribute-def:friendlyCountryName',
|
||||
'generationQualifier': 'urn:mace:dir:attribute-def:generationQualifier',
|
||||
'givenName': 'urn:mace:dir:attribute-def:givenName',
|
||||
'gn': 'urn:mace:dir:attribute-def:gn',
|
||||
'homePhone': 'urn:mace:dir:attribute-def:homePhone',
|
||||
'homePostalAddress': 'urn:mace:dir:attribute-def:homePostalAddress',
|
||||
'homeTelephoneNumber': 'urn:mace:dir:attribute-def:homeTelephoneNumber',
|
||||
'host': 'urn:mace:dir:attribute-def:host',
|
||||
'houseIdentifier': 'urn:mace:dir:attribute-def:houseIdentifier',
|
||||
'info': 'urn:mace:dir:attribute-def:info',
|
||||
'initials': 'urn:mace:dir:attribute-def:initials',
|
||||
'internationaliSDNNumber': 'urn:mace:dir:attribute-def:internationaliSDNNumber',
|
||||
'janetMailbox': 'urn:mace:dir:attribute-def:janetMailbox',
|
||||
'jpegPhoto': 'urn:mace:dir:attribute-def:jpegPhoto',
|
||||
'knowledgeInformation': 'urn:mace:dir:attribute-def:knowledgeInformation',
|
||||
'l': 'urn:mace:dir:attribute-def:l',
|
||||
'labeledURI': 'urn:mace:dir:attribute-def:labeledURI',
|
||||
'localityName': 'urn:mace:dir:attribute-def:localityName',
|
||||
'mDRecord': 'urn:mace:dir:attribute-def:mDRecord',
|
||||
'mXRecord': 'urn:mace:dir:attribute-def:mXRecord',
|
||||
'mail': 'urn:mace:dir:attribute-def:mail',
|
||||
'mailPreferenceOption': 'urn:mace:dir:attribute-def:mailPreferenceOption',
|
||||
'manager': 'urn:mace:dir:attribute-def:manager',
|
||||
'member': 'urn:mace:dir:attribute-def:member',
|
||||
'mobile': 'urn:mace:dir:attribute-def:mobile',
|
||||
'mobileTelephoneNumber': 'urn:mace:dir:attribute-def:mobileTelephoneNumber',
|
||||
'nSRecord': 'urn:mace:dir:attribute-def:nSRecord',
|
||||
'name': 'urn:mace:dir:attribute-def:name',
|
||||
'norEduOrgAcronym': 'urn:mace:dir:attribute-def:norEduOrgAcronym',
|
||||
'norEduOrgNIN': 'urn:mace:dir:attribute-def:norEduOrgNIN',
|
||||
'norEduOrgSchemaVersion': 'urn:mace:dir:attribute-def:norEduOrgSchemaVersion',
|
||||
'norEduOrgUniqueIdentifier': 'urn:mace:dir:attribute-def:norEduOrgUniqueIdentifier',
|
||||
'norEduOrgUniqueNumber': 'urn:mace:dir:attribute-def:norEduOrgUniqueNumber',
|
||||
'norEduOrgUnitUniqueIdentifier': 'urn:mace:dir:attribute-def:norEduOrgUnitUniqueIdentifier',
|
||||
'norEduOrgUnitUniqueNumber': 'urn:mace:dir:attribute-def:norEduOrgUnitUniqueNumber',
|
||||
'norEduPersonBirthDate': 'urn:mace:dir:attribute-def:norEduPersonBirthDate',
|
||||
'norEduPersonLIN': 'urn:mace:dir:attribute-def:norEduPersonLIN',
|
||||
'norEduPersonNIN': 'urn:mace:dir:attribute-def:norEduPersonNIN',
|
||||
'o': 'urn:mace:dir:attribute-def:o',
|
||||
'objectClass': 'urn:mace:dir:attribute-def:objectClass',
|
||||
'organizationName': 'urn:mace:dir:attribute-def:organizationName',
|
||||
'organizationalStatus': 'urn:mace:dir:attribute-def:organizationalStatus',
|
||||
'organizationalUnitName': 'urn:mace:dir:attribute-def:organizationalUnitName',
|
||||
'otherMailbox': 'urn:mace:dir:attribute-def:otherMailbox',
|
||||
'ou': 'urn:mace:dir:attribute-def:ou',
|
||||
'owner': 'urn:mace:dir:attribute-def:owner',
|
||||
'pager': 'urn:mace:dir:attribute-def:pager',
|
||||
'pagerTelephoneNumber': 'urn:mace:dir:attribute-def:pagerTelephoneNumber',
|
||||
'personalSignature': 'urn:mace:dir:attribute-def:personalSignature',
|
||||
'personalTitle': 'urn:mace:dir:attribute-def:personalTitle',
|
||||
'photo': 'urn:mace:dir:attribute-def:photo',
|
||||
'physicalDeliveryOfficeName': 'urn:mace:dir:attribute-def:physicalDeliveryOfficeName',
|
||||
'pkcs9email': 'urn:mace:dir:attribute-def:pkcs9email',
|
||||
'postOfficeBox': 'urn:mace:dir:attribute-def:postOfficeBox',
|
||||
'postalAddress': 'urn:mace:dir:attribute-def:postalAddress',
|
||||
'postalCode': 'urn:mace:dir:attribute-def:postalCode',
|
||||
'preferredDeliveryMethod': 'urn:mace:dir:attribute-def:preferredDeliveryMethod',
|
||||
'preferredLanguage': 'urn:mace:dir:attribute-def:preferredLanguage',
|
||||
'presentationAddress': 'urn:mace:dir:attribute-def:presentationAddress',
|
||||
'protocolInformation': 'urn:mace:dir:attribute-def:protocolInformation',
|
||||
'pseudonym': 'urn:mace:dir:attribute-def:pseudonym',
|
||||
'registeredAddress': 'urn:mace:dir:attribute-def:registeredAddress',
|
||||
'rfc822Mailbox': 'urn:mace:dir:attribute-def:rfc822Mailbox',
|
||||
'roleOccupant': 'urn:mace:dir:attribute-def:roleOccupant',
|
||||
'roomNumber': 'urn:mace:dir:attribute-def:roomNumber',
|
||||
'sOARecord': 'urn:mace:dir:attribute-def:sOARecord',
|
||||
'searchGuide': 'urn:mace:dir:attribute-def:searchGuide',
|
||||
'secretary': 'urn:mace:dir:attribute-def:secretary',
|
||||
'seeAlso': 'urn:mace:dir:attribute-def:seeAlso',
|
||||
'serialNumber': 'urn:mace:dir:attribute-def:serialNumber',
|
||||
'singleLevelQuality': 'urn:mace:dir:attribute-def:singleLevelQuality',
|
||||
'sn': 'urn:mace:dir:attribute-def:sn',
|
||||
'st': 'urn:mace:dir:attribute-def:st',
|
||||
'stateOrProvinceName': 'urn:mace:dir:attribute-def:stateOrProvinceName',
|
||||
'street': 'urn:mace:dir:attribute-def:street',
|
||||
'streetAddress': 'urn:mace:dir:attribute-def:streetAddress',
|
||||
'subtreeMaximumQuality': 'urn:mace:dir:attribute-def:subtreeMaximumQuality',
|
||||
'subtreeMinimumQuality': 'urn:mace:dir:attribute-def:subtreeMinimumQuality',
|
||||
'supportedAlgorithms': 'urn:mace:dir:attribute-def:supportedAlgorithms',
|
||||
'supportedApplicationContext': 'urn:mace:dir:attribute-def:supportedApplicationContext',
|
||||
'surname': 'urn:mace:dir:attribute-def:surname',
|
||||
'telephoneNumber': 'urn:mace:dir:attribute-def:telephoneNumber',
|
||||
'teletexTerminalIdentifier': 'urn:mace:dir:attribute-def:teletexTerminalIdentifier',
|
||||
'telexNumber': 'urn:mace:dir:attribute-def:telexNumber',
|
||||
'textEncodedORAddress': 'urn:mace:dir:attribute-def:textEncodedORAddress',
|
||||
'title': 'urn:mace:dir:attribute-def:title',
|
||||
'uid': 'urn:mace:dir:attribute-def:uid',
|
||||
'uniqueIdentifier': 'urn:mace:dir:attribute-def:uniqueIdentifier',
|
||||
'uniqueMember': 'urn:mace:dir:attribute-def:uniqueMember',
|
||||
'userCertificate': 'urn:mace:dir:attribute-def:userCertificate',
|
||||
'userClass': 'urn:mace:dir:attribute-def:userClass',
|
||||
'userPKCS12': 'urn:mace:dir:attribute-def:userPKCS12',
|
||||
'userPassword': 'urn:mace:dir:attribute-def:userPassword',
|
||||
'userSMIMECertificate': 'urn:mace:dir:attribute-def:userSMIMECertificate',
|
||||
'userid': 'urn:mace:dir:attribute-def:userid',
|
||||
'x121Address': 'urn:mace:dir:attribute-def:x121Address',
|
||||
'x500UniqueIdentifier': 'urn:mace:dir:attribute-def:x500UniqueIdentifier',
|
||||
'fro': {
|
||||
DEF+'aRecord': 'aRecord',
|
||||
DEF+'aliasedEntryName': 'aliasedEntryName',
|
||||
DEF+'aliasedObjectName': 'aliasedObjectName',
|
||||
DEF+'associatedDomain': 'associatedDomain',
|
||||
DEF+'associatedName': 'associatedName',
|
||||
DEF+'audio': 'audio',
|
||||
DEF+'authorityRevocationList': 'authorityRevocationList',
|
||||
DEF+'buildingName': 'buildingName',
|
||||
DEF+'businessCategory': 'businessCategory',
|
||||
DEF+'c': 'c',
|
||||
DEF+'cACertificate': 'cACertificate',
|
||||
DEF+'cNAMERecord': 'cNAMERecord',
|
||||
DEF+'carLicense': 'carLicense',
|
||||
DEF+'certificateRevocationList': 'certificateRevocationList',
|
||||
DEF+'cn': 'cn',
|
||||
DEF+'co': 'co',
|
||||
DEF+'commonName': 'commonName',
|
||||
DEF+'countryName': 'countryName',
|
||||
DEF+'crossCertificatePair': 'crossCertificatePair',
|
||||
DEF+'dITRedirect': 'dITRedirect',
|
||||
DEF+'dSAQuality': 'dSAQuality',
|
||||
DEF+'dc': 'dc',
|
||||
DEF+'deltaRevocationList': 'deltaRevocationList',
|
||||
DEF+'departmentNumber': 'departmentNumber',
|
||||
DEF+'description': 'description',
|
||||
DEF+'destinationIndicator': 'destinationIndicator',
|
||||
DEF+'displayName': 'displayName',
|
||||
DEF+'distinguishedName': 'distinguishedName',
|
||||
DEF+'dmdName': 'dmdName',
|
||||
DEF+'dnQualifier': 'dnQualifier',
|
||||
DEF+'documentAuthor': 'documentAuthor',
|
||||
DEF+'documentIdentifier': 'documentIdentifier',
|
||||
DEF+'documentLocation': 'documentLocation',
|
||||
DEF+'documentPublisher': 'documentPublisher',
|
||||
DEF+'documentTitle': 'documentTitle',
|
||||
DEF+'documentVersion': 'documentVersion',
|
||||
DEF+'domainComponent': 'domainComponent',
|
||||
DEF+'drink': 'drink',
|
||||
DEF+'eduOrgHomePageURI': 'eduOrgHomePageURI',
|
||||
DEF+'eduOrgIdentityAuthNPolicyURI': 'eduOrgIdentityAuthNPolicyURI',
|
||||
DEF+'eduOrgLegalName': 'eduOrgLegalName',
|
||||
DEF+'eduOrgSuperiorURI': 'eduOrgSuperiorURI',
|
||||
DEF+'eduOrgWhitePagesURI': 'eduOrgWhitePagesURI',
|
||||
DEF+'eduPersonAffiliation': 'eduPersonAffiliation',
|
||||
DEF+'eduPersonEntitlement': 'eduPersonEntitlement',
|
||||
DEF+'eduPersonNickname': 'eduPersonNickname',
|
||||
DEF+'eduPersonOrgDN': 'eduPersonOrgDN',
|
||||
DEF+'eduPersonOrgUnitDN': 'eduPersonOrgUnitDN',
|
||||
DEF+'eduPersonPrimaryAffiliation': 'eduPersonPrimaryAffiliation',
|
||||
DEF+'eduPersonPrimaryOrgUnitDN': 'eduPersonPrimaryOrgUnitDN',
|
||||
DEF+'eduPersonPrincipalName': 'eduPersonPrincipalName',
|
||||
DEF+'eduPersonScopedAffiliation': 'eduPersonScopedAffiliation',
|
||||
DEF+'eduPersonTargetedID': 'eduPersonTargetedID',
|
||||
DEF+'email': 'email',
|
||||
DEF+'emailAddress': 'emailAddress',
|
||||
DEF+'employeeNumber': 'employeeNumber',
|
||||
DEF+'employeeType': 'employeeType',
|
||||
DEF+'enhancedSearchGuide': 'enhancedSearchGuide',
|
||||
DEF+'facsimileTelephoneNumber': 'facsimileTelephoneNumber',
|
||||
DEF+'favouriteDrink': 'favouriteDrink',
|
||||
DEF+'fax': 'fax',
|
||||
DEF+'federationFeideSchemaVersion': 'federationFeideSchemaVersion',
|
||||
DEF+'friendlyCountryName': 'friendlyCountryName',
|
||||
DEF+'generationQualifier': 'generationQualifier',
|
||||
DEF+'givenName': 'givenName',
|
||||
DEF+'gn': 'gn',
|
||||
DEF+'homePhone': 'homePhone',
|
||||
DEF+'homePostalAddress': 'homePostalAddress',
|
||||
DEF+'homeTelephoneNumber': 'homeTelephoneNumber',
|
||||
DEF+'host': 'host',
|
||||
DEF+'houseIdentifier': 'houseIdentifier',
|
||||
DEF+'info': 'info',
|
||||
DEF+'initials': 'initials',
|
||||
DEF+'internationaliSDNNumber': 'internationaliSDNNumber',
|
||||
DEF+'janetMailbox': 'janetMailbox',
|
||||
DEF+'jpegPhoto': 'jpegPhoto',
|
||||
DEF+'knowledgeInformation': 'knowledgeInformation',
|
||||
DEF+'l': 'l',
|
||||
DEF+'labeledURI': 'labeledURI',
|
||||
DEF+'localityName': 'localityName',
|
||||
DEF+'mDRecord': 'mDRecord',
|
||||
DEF+'mXRecord': 'mXRecord',
|
||||
DEF+'mail': 'mail',
|
||||
DEF+'mailPreferenceOption': 'mailPreferenceOption',
|
||||
DEF+'manager': 'manager',
|
||||
DEF+'member': 'member',
|
||||
DEF+'mobile': 'mobile',
|
||||
DEF+'mobileTelephoneNumber': 'mobileTelephoneNumber',
|
||||
DEF+'nSRecord': 'nSRecord',
|
||||
DEF+'name': 'name',
|
||||
DEF+'norEduOrgAcronym': 'norEduOrgAcronym',
|
||||
DEF+'norEduOrgNIN': 'norEduOrgNIN',
|
||||
DEF+'norEduOrgSchemaVersion': 'norEduOrgSchemaVersion',
|
||||
DEF+'norEduOrgUniqueIdentifier': 'norEduOrgUniqueIdentifier',
|
||||
DEF+'norEduOrgUniqueNumber': 'norEduOrgUniqueNumber',
|
||||
DEF+'norEduOrgUnitUniqueIdentifier': 'norEduOrgUnitUniqueIdentifier',
|
||||
DEF+'norEduOrgUnitUniqueNumber': 'norEduOrgUnitUniqueNumber',
|
||||
DEF+'norEduPersonBirthDate': 'norEduPersonBirthDate',
|
||||
DEF+'norEduPersonLIN': 'norEduPersonLIN',
|
||||
DEF+'norEduPersonNIN': 'norEduPersonNIN',
|
||||
DEF+'o': 'o',
|
||||
DEF+'objectClass': 'objectClass',
|
||||
DEF+'organizationName': 'organizationName',
|
||||
DEF+'organizationalStatus': 'organizationalStatus',
|
||||
DEF+'organizationalUnitName': 'organizationalUnitName',
|
||||
DEF+'otherMailbox': 'otherMailbox',
|
||||
DEF+'ou': 'ou',
|
||||
DEF+'owner': 'owner',
|
||||
DEF+'pager': 'pager',
|
||||
DEF+'pagerTelephoneNumber': 'pagerTelephoneNumber',
|
||||
DEF+'personalSignature': 'personalSignature',
|
||||
DEF+'personalTitle': 'personalTitle',
|
||||
DEF+'photo': 'photo',
|
||||
DEF+'physicalDeliveryOfficeName': 'physicalDeliveryOfficeName',
|
||||
DEF+'pkcs9email': 'pkcs9email',
|
||||
DEF+'postOfficeBox': 'postOfficeBox',
|
||||
DEF+'postalAddress': 'postalAddress',
|
||||
DEF+'postalCode': 'postalCode',
|
||||
DEF+'preferredDeliveryMethod': 'preferredDeliveryMethod',
|
||||
DEF+'preferredLanguage': 'preferredLanguage',
|
||||
DEF+'presentationAddress': 'presentationAddress',
|
||||
DEF+'protocolInformation': 'protocolInformation',
|
||||
DEF+'pseudonym': 'pseudonym',
|
||||
DEF+'registeredAddress': 'registeredAddress',
|
||||
DEF+'rfc822Mailbox': 'rfc822Mailbox',
|
||||
DEF+'roleOccupant': 'roleOccupant',
|
||||
DEF+'roomNumber': 'roomNumber',
|
||||
DEF+'sOARecord': 'sOARecord',
|
||||
DEF+'searchGuide': 'searchGuide',
|
||||
DEF+'secretary': 'secretary',
|
||||
DEF+'seeAlso': 'seeAlso',
|
||||
DEF+'serialNumber': 'serialNumber',
|
||||
DEF+'singleLevelQuality': 'singleLevelQuality',
|
||||
DEF+'sn': 'sn',
|
||||
DEF+'st': 'st',
|
||||
DEF+'stateOrProvinceName': 'stateOrProvinceName',
|
||||
DEF+'street': 'street',
|
||||
DEF+'streetAddress': 'streetAddress',
|
||||
DEF+'subtreeMaximumQuality': 'subtreeMaximumQuality',
|
||||
DEF+'subtreeMinimumQuality': 'subtreeMinimumQuality',
|
||||
DEF+'supportedAlgorithms': 'supportedAlgorithms',
|
||||
DEF+'supportedApplicationContext': 'supportedApplicationContext',
|
||||
DEF+'surname': 'surname',
|
||||
DEF+'telephoneNumber': 'telephoneNumber',
|
||||
DEF+'teletexTerminalIdentifier': 'teletexTerminalIdentifier',
|
||||
DEF+'telexNumber': 'telexNumber',
|
||||
DEF+'textEncodedORAddress': 'textEncodedORAddress',
|
||||
DEF+'title': 'title',
|
||||
DEF+'uid': 'uid',
|
||||
DEF+'uniqueIdentifier': 'uniqueIdentifier',
|
||||
DEF+'uniqueMember': 'uniqueMember',
|
||||
DEF+'userCertificate': 'userCertificate',
|
||||
DEF+'userClass': 'userClass',
|
||||
DEF+'userPKCS12': 'userPKCS12',
|
||||
DEF+'userPassword': 'userPassword',
|
||||
DEF+'userSMIMECertificate': 'userSMIMECertificate',
|
||||
DEF+'userid': 'userid',
|
||||
DEF+'x121Address': 'x121Address',
|
||||
DEF+'x500UniqueIdentifier': 'x500UniqueIdentifier',
|
||||
},
|
||||
'to': {
|
||||
'aRecord': DEF+'aRecord',
|
||||
'aliasedEntryName': DEF+'aliasedEntryName',
|
||||
'aliasedObjectName': DEF+'aliasedObjectName',
|
||||
'associatedDomain': DEF+'associatedDomain',
|
||||
'associatedName': DEF+'associatedName',
|
||||
'audio': DEF+'audio',
|
||||
'authorityRevocationList': DEF+'authorityRevocationList',
|
||||
'buildingName': DEF+'buildingName',
|
||||
'businessCategory': DEF+'businessCategory',
|
||||
'c': DEF+'c',
|
||||
'cACertificate': DEF+'cACertificate',
|
||||
'cNAMERecord': DEF+'cNAMERecord',
|
||||
'carLicense': DEF+'carLicense',
|
||||
'certificateRevocationList': DEF+'certificateRevocationList',
|
||||
'cn': DEF+'cn',
|
||||
'co': DEF+'co',
|
||||
'commonName': DEF+'commonName',
|
||||
'countryName': DEF+'countryName',
|
||||
'crossCertificatePair': DEF+'crossCertificatePair',
|
||||
'dITRedirect': DEF+'dITRedirect',
|
||||
'dSAQuality': DEF+'dSAQuality',
|
||||
'dc': DEF+'dc',
|
||||
'deltaRevocationList': DEF+'deltaRevocationList',
|
||||
'departmentNumber': DEF+'departmentNumber',
|
||||
'description': DEF+'description',
|
||||
'destinationIndicator': DEF+'destinationIndicator',
|
||||
'displayName': DEF+'displayName',
|
||||
'distinguishedName': DEF+'distinguishedName',
|
||||
'dmdName': DEF+'dmdName',
|
||||
'dnQualifier': DEF+'dnQualifier',
|
||||
'documentAuthor': DEF+'documentAuthor',
|
||||
'documentIdentifier': DEF+'documentIdentifier',
|
||||
'documentLocation': DEF+'documentLocation',
|
||||
'documentPublisher': DEF+'documentPublisher',
|
||||
'documentTitle': DEF+'documentTitle',
|
||||
'documentVersion': DEF+'documentVersion',
|
||||
'domainComponent': DEF+'domainComponent',
|
||||
'drink': DEF+'drink',
|
||||
'eduOrgHomePageURI': DEF+'eduOrgHomePageURI',
|
||||
'eduOrgIdentityAuthNPolicyURI': DEF+'eduOrgIdentityAuthNPolicyURI',
|
||||
'eduOrgLegalName': DEF+'eduOrgLegalName',
|
||||
'eduOrgSuperiorURI': DEF+'eduOrgSuperiorURI',
|
||||
'eduOrgWhitePagesURI': DEF+'eduOrgWhitePagesURI',
|
||||
'eduPersonAffiliation': DEF+'eduPersonAffiliation',
|
||||
'eduPersonEntitlement': DEF+'eduPersonEntitlement',
|
||||
'eduPersonNickname': DEF+'eduPersonNickname',
|
||||
'eduPersonOrgDN': DEF+'eduPersonOrgDN',
|
||||
'eduPersonOrgUnitDN': DEF+'eduPersonOrgUnitDN',
|
||||
'eduPersonPrimaryAffiliation': DEF+'eduPersonPrimaryAffiliation',
|
||||
'eduPersonPrimaryOrgUnitDN': DEF+'eduPersonPrimaryOrgUnitDN',
|
||||
'eduPersonPrincipalName': DEF+'eduPersonPrincipalName',
|
||||
'eduPersonScopedAffiliation': DEF+'eduPersonScopedAffiliation',
|
||||
'eduPersonTargetedID': DEF+'eduPersonTargetedID',
|
||||
'email': DEF+'email',
|
||||
'emailAddress': DEF+'emailAddress',
|
||||
'employeeNumber': DEF+'employeeNumber',
|
||||
'employeeType': DEF+'employeeType',
|
||||
'enhancedSearchGuide': DEF+'enhancedSearchGuide',
|
||||
'facsimileTelephoneNumber': DEF+'facsimileTelephoneNumber',
|
||||
'favouriteDrink': DEF+'favouriteDrink',
|
||||
'fax': DEF+'fax',
|
||||
'federationFeideSchemaVersion': DEF+'federationFeideSchemaVersion',
|
||||
'friendlyCountryName': DEF+'friendlyCountryName',
|
||||
'generationQualifier': DEF+'generationQualifier',
|
||||
'givenName': DEF+'givenName',
|
||||
'gn': DEF+'gn',
|
||||
'homePhone': DEF+'homePhone',
|
||||
'homePostalAddress': DEF+'homePostalAddress',
|
||||
'homeTelephoneNumber': DEF+'homeTelephoneNumber',
|
||||
'host': DEF+'host',
|
||||
'houseIdentifier': DEF+'houseIdentifier',
|
||||
'info': DEF+'info',
|
||||
'initials': DEF+'initials',
|
||||
'internationaliSDNNumber': DEF+'internationaliSDNNumber',
|
||||
'janetMailbox': DEF+'janetMailbox',
|
||||
'jpegPhoto': DEF+'jpegPhoto',
|
||||
'knowledgeInformation': DEF+'knowledgeInformation',
|
||||
'l': DEF+'l',
|
||||
'labeledURI': DEF+'labeledURI',
|
||||
'localityName': DEF+'localityName',
|
||||
'mDRecord': DEF+'mDRecord',
|
||||
'mXRecord': DEF+'mXRecord',
|
||||
'mail': DEF+'mail',
|
||||
'mailPreferenceOption': DEF+'mailPreferenceOption',
|
||||
'manager': DEF+'manager',
|
||||
'member': DEF+'member',
|
||||
'mobile': DEF+'mobile',
|
||||
'mobileTelephoneNumber': DEF+'mobileTelephoneNumber',
|
||||
'nSRecord': DEF+'nSRecord',
|
||||
'name': DEF+'name',
|
||||
'norEduOrgAcronym': DEF+'norEduOrgAcronym',
|
||||
'norEduOrgNIN': DEF+'norEduOrgNIN',
|
||||
'norEduOrgSchemaVersion': DEF+'norEduOrgSchemaVersion',
|
||||
'norEduOrgUniqueIdentifier': DEF+'norEduOrgUniqueIdentifier',
|
||||
'norEduOrgUniqueNumber': DEF+'norEduOrgUniqueNumber',
|
||||
'norEduOrgUnitUniqueIdentifier': DEF+'norEduOrgUnitUniqueIdentifier',
|
||||
'norEduOrgUnitUniqueNumber': DEF+'norEduOrgUnitUniqueNumber',
|
||||
'norEduPersonBirthDate': DEF+'norEduPersonBirthDate',
|
||||
'norEduPersonLIN': DEF+'norEduPersonLIN',
|
||||
'norEduPersonNIN': DEF+'norEduPersonNIN',
|
||||
'o': DEF+'o',
|
||||
'objectClass': DEF+'objectClass',
|
||||
'organizationName': DEF+'organizationName',
|
||||
'organizationalStatus': DEF+'organizationalStatus',
|
||||
'organizationalUnitName': DEF+'organizationalUnitName',
|
||||
'otherMailbox': DEF+'otherMailbox',
|
||||
'ou': DEF+'ou',
|
||||
'owner': DEF+'owner',
|
||||
'pager': DEF+'pager',
|
||||
'pagerTelephoneNumber': DEF+'pagerTelephoneNumber',
|
||||
'personalSignature': DEF+'personalSignature',
|
||||
'personalTitle': DEF+'personalTitle',
|
||||
'photo': DEF+'photo',
|
||||
'physicalDeliveryOfficeName': DEF+'physicalDeliveryOfficeName',
|
||||
'pkcs9email': DEF+'pkcs9email',
|
||||
'postOfficeBox': DEF+'postOfficeBox',
|
||||
'postalAddress': DEF+'postalAddress',
|
||||
'postalCode': DEF+'postalCode',
|
||||
'preferredDeliveryMethod': DEF+'preferredDeliveryMethod',
|
||||
'preferredLanguage': DEF+'preferredLanguage',
|
||||
'presentationAddress': DEF+'presentationAddress',
|
||||
'protocolInformation': DEF+'protocolInformation',
|
||||
'pseudonym': DEF+'pseudonym',
|
||||
'registeredAddress': DEF+'registeredAddress',
|
||||
'rfc822Mailbox': DEF+'rfc822Mailbox',
|
||||
'roleOccupant': DEF+'roleOccupant',
|
||||
'roomNumber': DEF+'roomNumber',
|
||||
'sOARecord': DEF+'sOARecord',
|
||||
'searchGuide': DEF+'searchGuide',
|
||||
'secretary': DEF+'secretary',
|
||||
'seeAlso': DEF+'seeAlso',
|
||||
'serialNumber': DEF+'serialNumber',
|
||||
'singleLevelQuality': DEF+'singleLevelQuality',
|
||||
'sn': DEF+'sn',
|
||||
'st': DEF+'st',
|
||||
'stateOrProvinceName': DEF+'stateOrProvinceName',
|
||||
'street': DEF+'street',
|
||||
'streetAddress': DEF+'streetAddress',
|
||||
'subtreeMaximumQuality': DEF+'subtreeMaximumQuality',
|
||||
'subtreeMinimumQuality': DEF+'subtreeMinimumQuality',
|
||||
'supportedAlgorithms': DEF+'supportedAlgorithms',
|
||||
'supportedApplicationContext': DEF+'supportedApplicationContext',
|
||||
'surname': DEF+'surname',
|
||||
'telephoneNumber': DEF+'telephoneNumber',
|
||||
'teletexTerminalIdentifier': DEF+'teletexTerminalIdentifier',
|
||||
'telexNumber': DEF+'telexNumber',
|
||||
'textEncodedORAddress': DEF+'textEncodedORAddress',
|
||||
'title': DEF+'title',
|
||||
'uid': DEF+'uid',
|
||||
'uniqueIdentifier': DEF+'uniqueIdentifier',
|
||||
'uniqueMember': DEF+'uniqueMember',
|
||||
'userCertificate': DEF+'userCertificate',
|
||||
'userClass': DEF+'userClass',
|
||||
'userPKCS12': DEF+'userPKCS12',
|
||||
'userPassword': DEF+'userPassword',
|
||||
'userSMIMECertificate': DEF+'userSMIMECertificate',
|
||||
'userid': DEF+'userid',
|
||||
'x121Address': DEF+'x121Address',
|
||||
'x500UniqueIdentifier': DEF+'x500UniqueIdentifier',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +1,52 @@
|
||||
__author__ = 'rolandh'
|
||||
|
||||
EDUPERSON_OID = "urn:oid:1.3.6.1.4.1.5923.1.1.1."
|
||||
X500ATTR_OID = "urn:oid:2.5.4."
|
||||
NOREDUPERSON_OID = "urn:oid:1.3.6.1.4.1.2428.90.1."
|
||||
NETSCAPE_LDAP = "urn:oid:2.16.840.1.113730.3.1."
|
||||
EDUCOURSE_OID = 'urn:oid:1.3.6.1.4.1.5923.1.6.1.'
|
||||
EDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.'
|
||||
NETSCAPE_LDAP = 'urn:oid:2.16.840.1.113730.3.1.'
|
||||
NOREDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.2428.90.1.'
|
||||
PKCS_9 = 'urn:oid:1.2.840.113549.1.9.1.'
|
||||
SCHAC = 'urn:oid:1.3.6.1.4.1.25178.1.2.'
|
||||
SIS = 'urn:oid:1.2.752.194.10.2.'
|
||||
UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.'
|
||||
PKCS_9 = "urn:oid:1.2.840.113549.1.9.1."
|
||||
UMICH = "urn:oid:1.3.6.1.4.1.250.1.57."
|
||||
SCHAC = "urn:oid:1.3.6.1.4.1.25178.1.2."
|
||||
UMICH = 'urn:oid:1.3.6.1.4.1.250.1.57.'
|
||||
X500ATTR_OID = 'urn:oid:2.5.4.'
|
||||
|
||||
#urn:oid:1.3.6.1.4.1.1466.115.121.1.26
|
||||
|
||||
MAP = {
|
||||
"identifier": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
|
||||
"fro": {
|
||||
'identifier': 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
|
||||
'fro': {
|
||||
EDUCOURSE_OID+'1': 'eduCourseOffering',
|
||||
EDUCOURSE_OID+'2': 'eduCourseMember',
|
||||
EDUPERSON_OID+'1': 'eduPersonAffiliation',
|
||||
EDUPERSON_OID+'2': 'eduPersonNickname',
|
||||
EDUPERSON_OID+'9': 'eduPersonScopedAffiliation',
|
||||
EDUPERSON_OID+'11': 'eduPersonAssurance',
|
||||
EDUPERSON_OID+'10': 'eduPersonTargetedID',
|
||||
EDUPERSON_OID+'3': 'eduPersonOrgDN',
|
||||
EDUPERSON_OID+'4': 'eduPersonOrgUnitDN',
|
||||
EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation',
|
||||
EDUPERSON_OID+'6': 'eduPersonPrincipalName',
|
||||
EDUPERSON_OID+'7': 'eduPersonEntitlement',
|
||||
EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN',
|
||||
EDUPERSON_OID+'9': 'eduPersonScopedAffiliation',
|
||||
EDUPERSON_OID+'10': 'eduPersonTargetedID',
|
||||
EDUPERSON_OID+'11': 'eduPersonAssurance',
|
||||
NETSCAPE_LDAP+'1': 'carLicense',
|
||||
NETSCAPE_LDAP+'2': 'departmentNumber',
|
||||
NETSCAPE_LDAP+'3': 'employeeNumber',
|
||||
NETSCAPE_LDAP+'4': 'employeeType',
|
||||
NETSCAPE_LDAP+'39': 'preferredLanguage',
|
||||
NETSCAPE_LDAP+'40': 'userSMIMECertificate',
|
||||
NETSCAPE_LDAP+'216': 'userPKCS12',
|
||||
NETSCAPE_LDAP+'241': 'displayName',
|
||||
NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber',
|
||||
NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber',
|
||||
NOREDUPERSON_OID+'3': 'norEduPersonBirthDate',
|
||||
NOREDUPERSON_OID+'4': 'norEduPersonLIN',
|
||||
NOREDUPERSON_OID+'5': 'norEduPersonNIN',
|
||||
NOREDUPERSON_OID+'6': 'norEduOrgAcronym',
|
||||
NOREDUPERSON_OID+'7': 'norEduOrgUniqueIdentifier',
|
||||
NOREDUPERSON_OID+'4': 'norEduPersonLIN',
|
||||
EDUPERSON_OID+'1': 'eduPersonAffiliation',
|
||||
NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber',
|
||||
NETSCAPE_LDAP+'40': 'userSMIMECertificate',
|
||||
NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber',
|
||||
NETSCAPE_LDAP+'241': 'displayName',
|
||||
UCL_DIR_PILOT+'37': 'associatedDomain',
|
||||
EDUPERSON_OID+'6': 'eduPersonPrincipalName',
|
||||
NOREDUPERSON_OID+'8': 'norEduOrgUnitUniqueIdentifier',
|
||||
NOREDUPERSON_OID+'9': 'federationFeideSchemaVersion',
|
||||
X500ATTR_OID+'53': 'deltaRevocationList',
|
||||
X500ATTR_OID+'52': 'supportedAlgorithms',
|
||||
X500ATTR_OID+'51': 'houseIdentifier',
|
||||
X500ATTR_OID+'50': 'uniqueMember',
|
||||
X500ATTR_OID+'19': 'physicalDeliveryOfficeName',
|
||||
X500ATTR_OID+'18': 'postOfficeBox',
|
||||
X500ATTR_OID+'17': 'postalCode',
|
||||
X500ATTR_OID+'16': 'postalAddress',
|
||||
X500ATTR_OID+'15': 'businessCategory',
|
||||
X500ATTR_OID+'14': 'searchGuide',
|
||||
EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation',
|
||||
X500ATTR_OID+'12': 'title',
|
||||
X500ATTR_OID+'11': 'ou',
|
||||
X500ATTR_OID+'10': 'o',
|
||||
X500ATTR_OID+'37': 'cACertificate',
|
||||
X500ATTR_OID+'36': 'userCertificate',
|
||||
X500ATTR_OID+'31': 'member',
|
||||
X500ATTR_OID+'30': 'supportedApplicationContext',
|
||||
X500ATTR_OID+'33': 'roleOccupant',
|
||||
X500ATTR_OID+'32': 'owner',
|
||||
NETSCAPE_LDAP+'1': 'carLicense',
|
||||
NOREDUPERSON_OID+'10': 'norEduPersonLegalName',
|
||||
NOREDUPERSON_OID+'11': 'norEduOrgSchemaVersion',
|
||||
NOREDUPERSON_OID+'12': 'norEduOrgNIN',
|
||||
PKCS_9+'1': 'email',
|
||||
NETSCAPE_LDAP+'3': 'employeeNumber',
|
||||
NETSCAPE_LDAP+'2': 'departmentNumber',
|
||||
X500ATTR_OID+'39': 'certificateRevocationList',
|
||||
X500ATTR_OID+'38': 'authorityRevocationList',
|
||||
NETSCAPE_LDAP+'216': 'userPKCS12',
|
||||
EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN',
|
||||
X500ATTR_OID+'9': 'street',
|
||||
X500ATTR_OID+'8': 'st',
|
||||
NETSCAPE_LDAP+'39': 'preferredLanguage',
|
||||
EDUPERSON_OID+'7': 'eduPersonEntitlement',
|
||||
X500ATTR_OID+'2': 'knowledgeInformation',
|
||||
X500ATTR_OID+'7': 'l',
|
||||
X500ATTR_OID+'6': 'c',
|
||||
X500ATTR_OID+'5': 'serialNumber',
|
||||
X500ATTR_OID+'4': 'sn',
|
||||
X500ATTR_OID+'3': 'cn',
|
||||
UCL_DIR_PILOT+'60': 'jpegPhoto',
|
||||
X500ATTR_OID+'65': 'pseudonym',
|
||||
NOREDUPERSON_OID+'5': 'norEduPersonNIN',
|
||||
UCL_DIR_PILOT+'3': 'mail',
|
||||
UCL_DIR_PILOT+'25': 'dc',
|
||||
X500ATTR_OID+'40': 'crossCertificatePair',
|
||||
X500ATTR_OID+'42': 'givenName',
|
||||
X500ATTR_OID+'43': 'initials',
|
||||
X500ATTR_OID+'44': 'generationQualifier',
|
||||
X500ATTR_OID+'45': 'x500UniqueIdentifier',
|
||||
X500ATTR_OID+'46': 'dnQualifier',
|
||||
X500ATTR_OID+'47': 'enhancedSearchGuide',
|
||||
X500ATTR_OID+'48': 'protocolInformation',
|
||||
X500ATTR_OID+'54': 'dmdName',
|
||||
NETSCAPE_LDAP+'4': 'employeeType',
|
||||
X500ATTR_OID+'22': 'teletexTerminalIdentifier',
|
||||
X500ATTR_OID+'23': 'facsimileTelephoneNumber',
|
||||
X500ATTR_OID+'20': 'telephoneNumber',
|
||||
X500ATTR_OID+'21': 'telexNumber',
|
||||
X500ATTR_OID+'26': 'registeredAddress',
|
||||
X500ATTR_OID+'27': 'destinationIndicator',
|
||||
X500ATTR_OID+'24': 'x121Address',
|
||||
X500ATTR_OID+'25': 'internationaliSDNNumber',
|
||||
X500ATTR_OID+'28': 'preferredDeliveryMethod',
|
||||
X500ATTR_OID+'29': 'presentationAddress',
|
||||
EDUPERSON_OID+'3': 'eduPersonOrgDN',
|
||||
NOREDUPERSON_OID+'3': 'norEduPersonBirthDate',
|
||||
UMICH+'57': 'labeledURI',
|
||||
UCL_DIR_PILOT+'1': 'uid',
|
||||
UCL_DIR_PILOT+'43': 'co',
|
||||
SCHAC+'1': 'schacMotherTongue',
|
||||
SCHAC+'2': 'schacGender',
|
||||
SCHAC+'3': 'schacDateOfBirth',
|
||||
@@ -119,132 +67,177 @@ MAP = {
|
||||
SCHAC+'19': 'schacUserStatus',
|
||||
SCHAC+'20': 'schacProjectMembership',
|
||||
SCHAC+'21': 'schacProjectSpecificRole',
|
||||
},
|
||||
"to": {
|
||||
'cn': X500ATTR_OID+'3',
|
||||
'commonName': X500ATTR_OID+'3',
|
||||
'roleOccupant': X500ATTR_OID+'33',
|
||||
'gn': X500ATTR_OID+'42',
|
||||
'norEduPersonNIN': NOREDUPERSON_OID+'5',
|
||||
'title': X500ATTR_OID+'12',
|
||||
'facsimileTelephoneNumber': X500ATTR_OID+'23',
|
||||
'mail': UCL_DIR_PILOT+'3',
|
||||
'postOfficeBox': X500ATTR_OID+'18',
|
||||
'fax': X500ATTR_OID+'23',
|
||||
'telephoneNumber': X500ATTR_OID+'20',
|
||||
'norEduPersonBirthDate': NOREDUPERSON_OID+'3',
|
||||
'rfc822Mailbox': UCL_DIR_PILOT+'3',
|
||||
'dc': UCL_DIR_PILOT+'25',
|
||||
'countryName': X500ATTR_OID+'6',
|
||||
'emailAddress': PKCS_9+'1',
|
||||
'employeeNumber': NETSCAPE_LDAP+'3',
|
||||
'organizationName': X500ATTR_OID+'10',
|
||||
'eduPersonAssurance': EDUPERSON_OID+'11',
|
||||
'norEduOrgAcronym': NOREDUPERSON_OID+'6',
|
||||
'registeredAddress': X500ATTR_OID+'26',
|
||||
'physicalDeliveryOfficeName': X500ATTR_OID+'19',
|
||||
SIS+'1': 'sisLegalGuardianFor',
|
||||
SIS+'2': 'sisSchoolGrade',
|
||||
UCL_DIR_PILOT+'1': 'uid',
|
||||
UCL_DIR_PILOT+'3': 'mail',
|
||||
UCL_DIR_PILOT+'25': 'dc',
|
||||
UCL_DIR_PILOT+'37': 'associatedDomain',
|
||||
UCL_DIR_PILOT+'43': 'co',
|
||||
UCL_DIR_PILOT+'60': 'jpegPhoto',
|
||||
UMICH+'57': 'labeledURI',
|
||||
X500ATTR_OID+'2': 'knowledgeInformation',
|
||||
X500ATTR_OID+'3': 'cn',
|
||||
X500ATTR_OID+'4': 'sn',
|
||||
X500ATTR_OID+'5': 'serialNumber',
|
||||
X500ATTR_OID+'6': 'c',
|
||||
X500ATTR_OID+'7': 'l',
|
||||
X500ATTR_OID+'8': 'st',
|
||||
X500ATTR_OID+'9': 'street',
|
||||
X500ATTR_OID+'10': 'o',
|
||||
X500ATTR_OID+'11': 'ou',
|
||||
X500ATTR_OID+'12': 'title',
|
||||
X500ATTR_OID+'14': 'searchGuide',
|
||||
X500ATTR_OID+'15': 'businessCategory',
|
||||
X500ATTR_OID+'16': 'postalAddress',
|
||||
X500ATTR_OID+'17': 'postalCode',
|
||||
X500ATTR_OID+'18': 'postOfficeBox',
|
||||
X500ATTR_OID+'19': 'physicalDeliveryOfficeName',
|
||||
X500ATTR_OID+'20': 'telephoneNumber',
|
||||
X500ATTR_OID+'21': 'telexNumber',
|
||||
X500ATTR_OID+'22': 'teletexTerminalIdentifier',
|
||||
X500ATTR_OID+'23': 'facsimileTelephoneNumber',
|
||||
X500ATTR_OID+'24': 'x121Address',
|
||||
X500ATTR_OID+'25': 'internationaliSDNNumber',
|
||||
X500ATTR_OID+'26': 'registeredAddress',
|
||||
X500ATTR_OID+'27': 'destinationIndicator',
|
||||
X500ATTR_OID+'28': 'preferredDeliveryMethod',
|
||||
X500ATTR_OID+'29': 'presentationAddress',
|
||||
X500ATTR_OID+'30': 'supportedApplicationContext',
|
||||
X500ATTR_OID+'31': 'member',
|
||||
X500ATTR_OID+'32': 'owner',
|
||||
X500ATTR_OID+'33': 'roleOccupant',
|
||||
X500ATTR_OID+'36': 'userCertificate',
|
||||
X500ATTR_OID+'37': 'cACertificate',
|
||||
X500ATTR_OID+'38': 'authorityRevocationList',
|
||||
X500ATTR_OID+'39': 'certificateRevocationList',
|
||||
X500ATTR_OID+'40': 'crossCertificatePair',
|
||||
X500ATTR_OID+'42': 'givenName',
|
||||
X500ATTR_OID+'43': 'initials',
|
||||
X500ATTR_OID+'44': 'generationQualifier',
|
||||
X500ATTR_OID+'45': 'x500UniqueIdentifier',
|
||||
X500ATTR_OID+'46': 'dnQualifier',
|
||||
X500ATTR_OID+'47': 'enhancedSearchGuide',
|
||||
X500ATTR_OID+'48': 'protocolInformation',
|
||||
X500ATTR_OID+'50': 'uniqueMember',
|
||||
X500ATTR_OID+'51': 'houseIdentifier',
|
||||
X500ATTR_OID+'52': 'supportedAlgorithms',
|
||||
X500ATTR_OID+'53': 'deltaRevocationList',
|
||||
X500ATTR_OID+'54': 'dmdName',
|
||||
X500ATTR_OID+'65': 'pseudonym',
|
||||
},
|
||||
'to': {
|
||||
'associatedDomain': UCL_DIR_PILOT+'37',
|
||||
'l': X500ATTR_OID+'7',
|
||||
'stateOrProvinceName': X500ATTR_OID+'8',
|
||||
'federationFeideSchemaVersion': NOREDUPERSON_OID+'9',
|
||||
'pkcs9email': PKCS_9+'1',
|
||||
'givenName': X500ATTR_OID+'42',
|
||||
'givenname': X500ATTR_OID+'42',
|
||||
'x500UniqueIdentifier': X500ATTR_OID+'45',
|
||||
'eduPersonNickname': EDUPERSON_OID+'2',
|
||||
'houseIdentifier': X500ATTR_OID+'51',
|
||||
'street': X500ATTR_OID+'9',
|
||||
'supportedAlgorithms': X500ATTR_OID+'52',
|
||||
'preferredLanguage': NETSCAPE_LDAP+'39',
|
||||
'postalAddress': X500ATTR_OID+'16',
|
||||
'email': PKCS_9+'1',
|
||||
'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8',
|
||||
'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8',
|
||||
'c': X500ATTR_OID+'6',
|
||||
'teletexTerminalIdentifier': X500ATTR_OID+'22',
|
||||
'o': X500ATTR_OID+'10',
|
||||
'cACertificate': X500ATTR_OID+'37',
|
||||
'telexNumber': X500ATTR_OID+'21',
|
||||
'ou': X500ATTR_OID+'11',
|
||||
'initials': X500ATTR_OID+'43',
|
||||
'eduPersonOrgUnitDN': EDUPERSON_OID+'4',
|
||||
'deltaRevocationList': X500ATTR_OID+'53',
|
||||
'norEduPersonLIN': NOREDUPERSON_OID+'4',
|
||||
'supportedApplicationContext': X500ATTR_OID+'30',
|
||||
'eduPersonEntitlement': EDUPERSON_OID+'7',
|
||||
'generationQualifier': X500ATTR_OID+'44',
|
||||
'eduPersonAffiliation': EDUPERSON_OID+'1',
|
||||
'edupersonaffiliation': EDUPERSON_OID+'1',
|
||||
'eduPersonPrincipalName': EDUPERSON_OID+'6',
|
||||
'edupersonprincipalname': EDUPERSON_OID+'6',
|
||||
'eppn': EDUPERSON_OID+'6',
|
||||
'localityName': X500ATTR_OID+'7',
|
||||
'owner': X500ATTR_OID+'32',
|
||||
'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2',
|
||||
'searchGuide': X500ATTR_OID+'14',
|
||||
'certificateRevocationList': X500ATTR_OID+'39',
|
||||
'organizationalUnitName': X500ATTR_OID+'11',
|
||||
'userCertificate': X500ATTR_OID+'36',
|
||||
'preferredDeliveryMethod': X500ATTR_OID+'28',
|
||||
'internationaliSDNNumber': X500ATTR_OID+'25',
|
||||
'uniqueMember': X500ATTR_OID+'50',
|
||||
'departmentNumber': NETSCAPE_LDAP+'2',
|
||||
'enhancedSearchGuide': X500ATTR_OID+'47',
|
||||
'userPKCS12': NETSCAPE_LDAP+'216',
|
||||
'eduPersonTargetedID': EDUPERSON_OID+'10',
|
||||
'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1',
|
||||
'x121Address': X500ATTR_OID+'24',
|
||||
'destinationIndicator': X500ATTR_OID+'27',
|
||||
'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5',
|
||||
'surname': X500ATTR_OID+'4',
|
||||
'jpegPhoto': UCL_DIR_PILOT+'60',
|
||||
'eduPersonScopedAffiliation': EDUPERSON_OID+'9',
|
||||
'edupersonscopedaffiliation': EDUPERSON_OID+'9',
|
||||
'protocolInformation': X500ATTR_OID+'48',
|
||||
'knowledgeInformation': X500ATTR_OID+'2',
|
||||
'employeeType': NETSCAPE_LDAP+'4',
|
||||
'userSMIMECertificate': NETSCAPE_LDAP+'40',
|
||||
'member': X500ATTR_OID+'31',
|
||||
'streetAddress': X500ATTR_OID+'9',
|
||||
'dmdName': X500ATTR_OID+'54',
|
||||
'postalCode': X500ATTR_OID+'17',
|
||||
'pseudonym': X500ATTR_OID+'65',
|
||||
'dnQualifier': X500ATTR_OID+'46',
|
||||
'crossCertificatePair': X500ATTR_OID+'40',
|
||||
'eduPersonOrgDN': EDUPERSON_OID+'3',
|
||||
'authorityRevocationList': X500ATTR_OID+'38',
|
||||
'displayName': NETSCAPE_LDAP+'241',
|
||||
'businessCategory': X500ATTR_OID+'15',
|
||||
'serialNumber': X500ATTR_OID+'5',
|
||||
'norEduOrgUniqueIdentifier': NOREDUPERSON_OID+'7',
|
||||
'st': X500ATTR_OID+'8',
|
||||
'c': X500ATTR_OID+'6',
|
||||
'cACertificate': X500ATTR_OID+'37',
|
||||
'carLicense': NETSCAPE_LDAP+'1',
|
||||
'presentationAddress': X500ATTR_OID+'29',
|
||||
'sn': X500ATTR_OID+'4',
|
||||
'domainComponent': UCL_DIR_PILOT+'25',
|
||||
'labeledURI': UMICH+'57',
|
||||
'uid': UCL_DIR_PILOT+'1',
|
||||
'certificateRevocationList': X500ATTR_OID+'39',
|
||||
'cn': X500ATTR_OID+'3',
|
||||
'co': UCL_DIR_PILOT+'43',
|
||||
'friendlyCountryName': UCL_DIR_PILOT+'43',
|
||||
'schacMotherTongue':SCHAC+'1',
|
||||
'crossCertificatePair': X500ATTR_OID+'40',
|
||||
'dc': UCL_DIR_PILOT+'25',
|
||||
'deltaRevocationList': X500ATTR_OID+'53',
|
||||
'departmentNumber': NETSCAPE_LDAP+'2',
|
||||
'destinationIndicator': X500ATTR_OID+'27',
|
||||
'displayName': NETSCAPE_LDAP+'241',
|
||||
'dmdName': X500ATTR_OID+'54',
|
||||
'dnQualifier': X500ATTR_OID+'46',
|
||||
'eduCourseMember': EDUCOURSE_OID+'2',
|
||||
'eduCourseOffering': EDUCOURSE_OID+'1',
|
||||
'eduPersonAffiliation': EDUPERSON_OID+'1',
|
||||
'eduPersonAssurance': EDUPERSON_OID+'11',
|
||||
'eduPersonEntitlement': EDUPERSON_OID+'7',
|
||||
'eduPersonNickname': EDUPERSON_OID+'2',
|
||||
'eduPersonOrgDN': EDUPERSON_OID+'3',
|
||||
'eduPersonOrgUnitDN': EDUPERSON_OID+'4',
|
||||
'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5',
|
||||
'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8',
|
||||
'eduPersonPrincipalName': EDUPERSON_OID+'6',
|
||||
'eduPersonScopedAffiliation': EDUPERSON_OID+'9',
|
||||
'eduPersonTargetedID': EDUPERSON_OID+'10',
|
||||
'email': PKCS_9+'1',
|
||||
'employeeNumber': NETSCAPE_LDAP+'3',
|
||||
'employeeType': NETSCAPE_LDAP+'4',
|
||||
'enhancedSearchGuide': X500ATTR_OID+'47',
|
||||
'facsimileTelephoneNumber': X500ATTR_OID+'23',
|
||||
'federationFeideSchemaVersion': NOREDUPERSON_OID+'9',
|
||||
'generationQualifier': X500ATTR_OID+'44',
|
||||
'givenName': X500ATTR_OID+'42',
|
||||
'houseIdentifier': X500ATTR_OID+'51',
|
||||
'initials': X500ATTR_OID+'43',
|
||||
'internationaliSDNNumber': X500ATTR_OID+'25',
|
||||
'jpegPhoto': UCL_DIR_PILOT+'60',
|
||||
'knowledgeInformation': X500ATTR_OID+'2',
|
||||
'l': X500ATTR_OID+'7',
|
||||
'labeledURI': UMICH+'57',
|
||||
'mail': UCL_DIR_PILOT+'3',
|
||||
'member': X500ATTR_OID+'31',
|
||||
'norEduOrgAcronym': NOREDUPERSON_OID+'6',
|
||||
'norEduOrgNIN': NOREDUPERSON_OID+'12',
|
||||
'norEduOrgSchemaVersion': NOREDUPERSON_OID+'11',
|
||||
'norEduOrgUniqueIdentifier': NOREDUPERSON_OID+'7',
|
||||
'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1',
|
||||
'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8',
|
||||
'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2',
|
||||
'norEduPersonBirthDate': NOREDUPERSON_OID+'3',
|
||||
'norEduPersonLIN': NOREDUPERSON_OID+'4',
|
||||
'norEduPersonLegalName': NOREDUPERSON_OID+'10',
|
||||
'norEduPersonNIN': NOREDUPERSON_OID+'5',
|
||||
'o': X500ATTR_OID+'10',
|
||||
'ou': X500ATTR_OID+'11',
|
||||
'owner': X500ATTR_OID+'32',
|
||||
'physicalDeliveryOfficeName': X500ATTR_OID+'19',
|
||||
'postOfficeBox': X500ATTR_OID+'18',
|
||||
'postalAddress': X500ATTR_OID+'16',
|
||||
'postalCode': X500ATTR_OID+'17',
|
||||
'preferredDeliveryMethod': X500ATTR_OID+'28',
|
||||
'preferredLanguage': NETSCAPE_LDAP+'39',
|
||||
'presentationAddress': X500ATTR_OID+'29',
|
||||
'protocolInformation': X500ATTR_OID+'48',
|
||||
'pseudonym': X500ATTR_OID+'65',
|
||||
'registeredAddress': X500ATTR_OID+'26',
|
||||
'roleOccupant': X500ATTR_OID+'33',
|
||||
'schacCountryOfCitizenship': SCHAC+'5',
|
||||
'schacCountryOfResidence': SCHAC+'11',
|
||||
'schacDateOfBirth': SCHAC+'3',
|
||||
'schacExpiryDate': SCHAC+'17',
|
||||
'schacGender': SCHAC+'2',
|
||||
'schacDateOfBirth':SCHAC+'3',
|
||||
'schacPlaceOfBirth': SCHAC+'4',
|
||||
'schacCountryOfCitizenship':SCHAC+'5',
|
||||
'schacSn1': SCHAC+'6',
|
||||
'schacSn2': SCHAC+'7',
|
||||
'schacPersonalTitle':SCHAC+'8',
|
||||
'schacHomeOrganization': SCHAC+'9',
|
||||
'schacHomeOrganizationType': SCHAC+'10',
|
||||
'schacCountryOfResidence': SCHAC+'11',
|
||||
'schacUserPresenceID': SCHAC+'12',
|
||||
'schacMotherTongue': SCHAC+'1',
|
||||
'schacPersonalPosition': SCHAC+'13',
|
||||
'schacPersonalTitle': SCHAC+'8',
|
||||
'schacPersonalUniqueCode': SCHAC+'14',
|
||||
'schacPersonalUniqueID': SCHAC+'15',
|
||||
'schacExpiryDate': SCHAC+'17',
|
||||
'schacUserPrivateAttribute': SCHAC+'18',
|
||||
'schacUserStatus': SCHAC+'19',
|
||||
'schacPlaceOfBirth': SCHAC+'4',
|
||||
'schacProjectMembership': SCHAC+'20',
|
||||
'schacProjectSpecificRole': SCHAC+'21',
|
||||
}
|
||||
}
|
||||
'schacSn1': SCHAC+'6',
|
||||
'schacSn2': SCHAC+'7',
|
||||
'schacUserPresenceID': SCHAC+'12',
|
||||
'schacUserPrivateAttribute': SCHAC+'18',
|
||||
'schacUserStatus': SCHAC+'19',
|
||||
'searchGuide': X500ATTR_OID+'14',
|
||||
'serialNumber': X500ATTR_OID+'5',
|
||||
'sisLegalGuardianFor': SIS+'1',
|
||||
'sisSchoolGrade': SIS+'2',
|
||||
'sn': X500ATTR_OID+'4',
|
||||
'st': X500ATTR_OID+'8',
|
||||
'street': X500ATTR_OID+'9',
|
||||
'supportedAlgorithms': X500ATTR_OID+'52',
|
||||
'supportedApplicationContext': X500ATTR_OID+'30',
|
||||
'telephoneNumber': X500ATTR_OID+'20',
|
||||
'teletexTerminalIdentifier': X500ATTR_OID+'22',
|
||||
'telexNumber': X500ATTR_OID+'21',
|
||||
'title': X500ATTR_OID+'12',
|
||||
'uid': UCL_DIR_PILOT+'1',
|
||||
'uniqueMember': X500ATTR_OID+'50',
|
||||
'userCertificate': X500ATTR_OID+'36',
|
||||
'userPKCS12': NETSCAPE_LDAP+'216',
|
||||
'userSMIMECertificate': NETSCAPE_LDAP+'40',
|
||||
'x121Address': X500ATTR_OID+'24',
|
||||
'x500UniqueIdentifier': X500ATTR_OID+'45',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,82 @@
|
||||
EDUPERSON_OID = "urn:oid:1.3.6.1.4.1.5923.1.1.1."
|
||||
X500ATTR = "urn:oid:2.5.4."
|
||||
NOREDUPERSON_OID = "urn:oid:1.3.6.1.4.1.2428.90.1."
|
||||
NETSCAPE_LDAP = "urn:oid:2.16.840.1.113730.3.1."
|
||||
UCL_DIR_PILOT = "urn:oid:0.9.2342.19200300.100.1."
|
||||
PKCS_9 = "urn:oid:1.2.840.113549.1.9."
|
||||
UMICH = "urn:oid:1.3.6.1.4.1.250.1.57."
|
||||
EDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.'
|
||||
NETSCAPE_LDAP = 'urn:oid:2.16.840.1.113730.3.1.'
|
||||
NOREDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.2428.90.1.'
|
||||
PKCS_9 = 'urn:oid:1.2.840.113549.1.9.'
|
||||
UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.'
|
||||
UMICH = 'urn:oid:1.3.6.1.4.1.250.1.57.'
|
||||
X500ATTR = 'urn:oid:2.5.4.'
|
||||
|
||||
|
||||
MAP = {
|
||||
"identifier": "urn:mace:shibboleth:1.0:attributeNamespace:uri",
|
||||
"fro": {
|
||||
'fro': {
|
||||
EDUPERSON_OID+'1': 'eduPersonAffiliation',
|
||||
EDUPERSON_OID+'2': 'eduPersonNickname',
|
||||
EDUPERSON_OID+'9': 'eduPersonScopedAffiliation',
|
||||
EDUPERSON_OID+'11': 'eduPersonAssurance',
|
||||
EDUPERSON_OID+'10': 'eduPersonTargetedID',
|
||||
EDUPERSON_OID+'3': 'eduPersonOrgDN',
|
||||
EDUPERSON_OID+'4': 'eduPersonOrgUnitDN',
|
||||
EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation',
|
||||
EDUPERSON_OID+'6': 'eduPersonPrincipalName',
|
||||
EDUPERSON_OID+'7': 'eduPersonEntitlement',
|
||||
EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN',
|
||||
EDUPERSON_OID+'9': 'eduPersonScopedAffiliation',
|
||||
EDUPERSON_OID+'10': 'eduPersonTargetedID',
|
||||
EDUPERSON_OID+'11': 'eduPersonAssurance',
|
||||
NETSCAPE_LDAP+'1': 'carLicense',
|
||||
NETSCAPE_LDAP+'2': 'departmentNumber',
|
||||
NETSCAPE_LDAP+'3': 'employeeNumber',
|
||||
NETSCAPE_LDAP+'4': 'employeeType',
|
||||
NETSCAPE_LDAP+'39': 'preferredLanguage',
|
||||
NETSCAPE_LDAP+'40': 'userSMIMECertificate',
|
||||
NETSCAPE_LDAP+'216': 'userPKCS12',
|
||||
NETSCAPE_LDAP+'241': 'displayName',
|
||||
NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber',
|
||||
NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber',
|
||||
NOREDUPERSON_OID+'3': 'norEduPersonBirthDate',
|
||||
NOREDUPERSON_OID+'4': 'norEduPersonLIN',
|
||||
NOREDUPERSON_OID+'5': 'norEduPersonNIN',
|
||||
NOREDUPERSON_OID+'6': 'norEduOrgAcronym',
|
||||
NOREDUPERSON_OID+'7': 'norEduOrgUniqueIdentifier',
|
||||
NOREDUPERSON_OID+'4': 'norEduPersonLIN',
|
||||
EDUPERSON_OID+'1': 'eduPersonAffiliation',
|
||||
NOREDUPERSON_OID+'2': 'norEduOrgUnitUniqueNumber',
|
||||
NETSCAPE_LDAP+'40': 'userSMIMECertificate',
|
||||
NOREDUPERSON_OID+'1': 'norEduOrgUniqueNumber',
|
||||
NETSCAPE_LDAP+'241': 'displayName',
|
||||
UCL_DIR_PILOT+'37': 'associatedDomain',
|
||||
EDUPERSON_OID+'6': 'eduPersonPrincipalName',
|
||||
NOREDUPERSON_OID+'8': 'norEduOrgUnitUniqueIdentifier',
|
||||
NOREDUPERSON_OID+'9': 'federationFeideSchemaVersion',
|
||||
X500ATTR+'53': 'deltaRevocationList',
|
||||
X500ATTR+'52': 'supportedAlgorithms',
|
||||
X500ATTR+'51': 'houseIdentifier',
|
||||
X500ATTR+'50': 'uniqueMember',
|
||||
X500ATTR+'19': 'physicalDeliveryOfficeName',
|
||||
X500ATTR+'18': 'postOfficeBox',
|
||||
X500ATTR+'17': 'postalCode',
|
||||
X500ATTR+'16': 'postalAddress',
|
||||
X500ATTR+'15': 'businessCategory',
|
||||
X500ATTR+'14': 'searchGuide',
|
||||
EDUPERSON_OID+'5': 'eduPersonPrimaryAffiliation',
|
||||
X500ATTR+'12': 'title',
|
||||
X500ATTR+'11': 'ou',
|
||||
X500ATTR+'10': 'o',
|
||||
X500ATTR+'37': 'cACertificate',
|
||||
X500ATTR+'36': 'userCertificate',
|
||||
X500ATTR+'31': 'member',
|
||||
X500ATTR+'30': 'supportedApplicationContext',
|
||||
X500ATTR+'33': 'roleOccupant',
|
||||
X500ATTR+'32': 'owner',
|
||||
NETSCAPE_LDAP+'1': 'carLicense',
|
||||
PKCS_9+'1': 'email',
|
||||
NETSCAPE_LDAP+'3': 'employeeNumber',
|
||||
NETSCAPE_LDAP+'2': 'departmentNumber',
|
||||
X500ATTR+'39': 'certificateRevocationList',
|
||||
X500ATTR+'38': 'authorityRevocationList',
|
||||
NETSCAPE_LDAP+'216': 'userPKCS12',
|
||||
EDUPERSON_OID+'8': 'eduPersonPrimaryOrgUnitDN',
|
||||
X500ATTR+'9': 'street',
|
||||
X500ATTR+'8': 'st',
|
||||
NETSCAPE_LDAP+'39': 'preferredLanguage',
|
||||
EDUPERSON_OID+'7': 'eduPersonEntitlement',
|
||||
X500ATTR+'2': 'knowledgeInformation',
|
||||
X500ATTR+'7': 'l',
|
||||
X500ATTR+'6': 'c',
|
||||
X500ATTR+'5': 'serialNumber',
|
||||
X500ATTR+'4': 'sn',
|
||||
UCL_DIR_PILOT+'60': 'jpegPhoto',
|
||||
X500ATTR+'65': 'pseudonym',
|
||||
NOREDUPERSON_OID+'5': 'norEduPersonNIN',
|
||||
UCL_DIR_PILOT+'3': 'mail',
|
||||
UCL_DIR_PILOT+'25': 'dc',
|
||||
UCL_DIR_PILOT+'37': 'associatedDomain',
|
||||
UCL_DIR_PILOT+'60': 'jpegPhoto',
|
||||
X500ATTR+'2': 'knowledgeInformation',
|
||||
X500ATTR+'4': 'sn',
|
||||
X500ATTR+'5': 'serialNumber',
|
||||
X500ATTR+'6': 'c',
|
||||
X500ATTR+'7': 'l',
|
||||
X500ATTR+'8': 'st',
|
||||
X500ATTR+'9': 'street',
|
||||
X500ATTR+'10': 'o',
|
||||
X500ATTR+'11': 'ou',
|
||||
X500ATTR+'12': 'title',
|
||||
X500ATTR+'14': 'searchGuide',
|
||||
X500ATTR+'15': 'businessCategory',
|
||||
X500ATTR+'16': 'postalAddress',
|
||||
X500ATTR+'17': 'postalCode',
|
||||
X500ATTR+'18': 'postOfficeBox',
|
||||
X500ATTR+'19': 'physicalDeliveryOfficeName',
|
||||
X500ATTR+'20': 'telephoneNumber',
|
||||
X500ATTR+'21': 'telexNumber',
|
||||
X500ATTR+'22': 'teletexTerminalIdentifier',
|
||||
X500ATTR+'23': 'facsimileTelephoneNumber',
|
||||
X500ATTR+'24': 'x121Address',
|
||||
X500ATTR+'25': 'internationaliSDNNumber',
|
||||
X500ATTR+'26': 'registeredAddress',
|
||||
X500ATTR+'27': 'destinationIndicator',
|
||||
X500ATTR+'28': 'preferredDeliveryMethod',
|
||||
X500ATTR+'29': 'presentationAddress',
|
||||
X500ATTR+'30': 'supportedApplicationContext',
|
||||
X500ATTR+'31': 'member',
|
||||
X500ATTR+'32': 'owner',
|
||||
X500ATTR+'33': 'roleOccupant',
|
||||
X500ATTR+'36': 'userCertificate',
|
||||
X500ATTR+'37': 'cACertificate',
|
||||
X500ATTR+'38': 'authorityRevocationList',
|
||||
X500ATTR+'39': 'certificateRevocationList',
|
||||
X500ATTR+'40': 'crossCertificatePair',
|
||||
X500ATTR+'42': 'givenName',
|
||||
X500ATTR+'43': 'initials',
|
||||
@@ -76,115 +85,107 @@ MAP = {
|
||||
X500ATTR+'46': 'dnQualifier',
|
||||
X500ATTR+'47': 'enhancedSearchGuide',
|
||||
X500ATTR+'48': 'protocolInformation',
|
||||
X500ATTR+'50': 'uniqueMember',
|
||||
X500ATTR+'51': 'houseIdentifier',
|
||||
X500ATTR+'52': 'supportedAlgorithms',
|
||||
X500ATTR+'53': 'deltaRevocationList',
|
||||
X500ATTR+'54': 'dmdName',
|
||||
NETSCAPE_LDAP+'4': 'employeeType',
|
||||
X500ATTR+'22': 'teletexTerminalIdentifier',
|
||||
X500ATTR+'23': 'facsimileTelephoneNumber',
|
||||
X500ATTR+'20': 'telephoneNumber',
|
||||
X500ATTR+'21': 'telexNumber',
|
||||
X500ATTR+'26': 'registeredAddress',
|
||||
X500ATTR+'27': 'destinationIndicator',
|
||||
X500ATTR+'24': 'x121Address',
|
||||
X500ATTR+'25': 'internationaliSDNNumber',
|
||||
X500ATTR+'28': 'preferredDeliveryMethod',
|
||||
X500ATTR+'29': 'presentationAddress',
|
||||
EDUPERSON_OID+'3': 'eduPersonOrgDN',
|
||||
NOREDUPERSON_OID+'3': 'norEduPersonBirthDate',
|
||||
X500ATTR+'65': 'pseudonym',
|
||||
},
|
||||
"to":{
|
||||
'roleOccupant': X500ATTR+'33',
|
||||
'gn': X500ATTR+'42',
|
||||
'norEduPersonNIN': NOREDUPERSON_OID+'5',
|
||||
'title': X500ATTR+'12',
|
||||
'facsimileTelephoneNumber': X500ATTR+'23',
|
||||
'mail': UCL_DIR_PILOT+'3',
|
||||
'postOfficeBox': X500ATTR+'18',
|
||||
'fax': X500ATTR+'23',
|
||||
'telephoneNumber': X500ATTR+'20',
|
||||
'norEduPersonBirthDate': NOREDUPERSON_OID+'3',
|
||||
'rfc822Mailbox': UCL_DIR_PILOT+'3',
|
||||
'dc': UCL_DIR_PILOT+'25',
|
||||
'to': {
|
||||
'associatedDomain': UCL_DIR_PILOT+'37',
|
||||
'authorityRevocationList': X500ATTR+'38',
|
||||
'businessCategory': X500ATTR+'15',
|
||||
'c': X500ATTR+'6',
|
||||
'cACertificate': X500ATTR+'37',
|
||||
'carLicense': NETSCAPE_LDAP+'1',
|
||||
'certificateRevocationList': X500ATTR+'39',
|
||||
'countryName': X500ATTR+'6',
|
||||
'crossCertificatePair': X500ATTR+'40',
|
||||
'dc': UCL_DIR_PILOT+'25',
|
||||
'deltaRevocationList': X500ATTR+'53',
|
||||
'departmentNumber': NETSCAPE_LDAP+'2',
|
||||
'destinationIndicator': X500ATTR+'27',
|
||||
'displayName': NETSCAPE_LDAP+'241',
|
||||
'dmdName': X500ATTR+'54',
|
||||
'dnQualifier': X500ATTR+'46',
|
||||
'domainComponent': UCL_DIR_PILOT+'25',
|
||||
'eduPersonAffiliation': EDUPERSON_OID+'1',
|
||||
'eduPersonAssurance': EDUPERSON_OID+'11',
|
||||
'eduPersonEntitlement': EDUPERSON_OID+'7',
|
||||
'eduPersonNickname': EDUPERSON_OID+'2',
|
||||
'eduPersonOrgDN': EDUPERSON_OID+'3',
|
||||
'eduPersonOrgUnitDN': EDUPERSON_OID+'4',
|
||||
'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5',
|
||||
'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8',
|
||||
'eduPersonPrincipalName': EDUPERSON_OID+'6',
|
||||
'eduPersonScopedAffiliation': EDUPERSON_OID+'9',
|
||||
'eduPersonTargetedID': EDUPERSON_OID+'10',
|
||||
'email': PKCS_9+'1',
|
||||
'emailAddress': PKCS_9+'1',
|
||||
'employeeNumber': NETSCAPE_LDAP+'3',
|
||||
'organizationName': X500ATTR+'10',
|
||||
'eduPersonAssurance': EDUPERSON_OID+'11',
|
||||
'norEduOrgAcronym': NOREDUPERSON_OID+'6',
|
||||
'registeredAddress': X500ATTR+'26',
|
||||
'physicalDeliveryOfficeName': X500ATTR+'19',
|
||||
'associatedDomain': UCL_DIR_PILOT+'37',
|
||||
'l': X500ATTR+'7',
|
||||
'stateOrProvinceName': X500ATTR+'8',
|
||||
'federationFeideSchemaVersion': NOREDUPERSON_OID+'9',
|
||||
'pkcs9email': PKCS_9+'1',
|
||||
'givenName': X500ATTR+'42',
|
||||
'x500UniqueIdentifier': X500ATTR+'45',
|
||||
'eduPersonNickname': EDUPERSON_OID+'2',
|
||||
'houseIdentifier': X500ATTR+'51',
|
||||
'street': X500ATTR+'9',
|
||||
'supportedAlgorithms': X500ATTR+'52',
|
||||
'preferredLanguage': NETSCAPE_LDAP+'39',
|
||||
'postalAddress': X500ATTR+'16',
|
||||
'email': PKCS_9+'1',
|
||||
'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8',
|
||||
'eduPersonPrimaryOrgUnitDN': EDUPERSON_OID+'8',
|
||||
'c': X500ATTR+'6',
|
||||
'teletexTerminalIdentifier': X500ATTR+'22',
|
||||
'o': X500ATTR+'10',
|
||||
'cACertificate': X500ATTR+'37',
|
||||
'telexNumber': X500ATTR+'21',
|
||||
'ou': X500ATTR+'11',
|
||||
'initials': X500ATTR+'43',
|
||||
'eduPersonOrgUnitDN': EDUPERSON_OID+'4',
|
||||
'deltaRevocationList': X500ATTR+'53',
|
||||
'norEduPersonLIN': NOREDUPERSON_OID+'4',
|
||||
'supportedApplicationContext': X500ATTR+'30',
|
||||
'eduPersonEntitlement': EDUPERSON_OID+'7',
|
||||
'generationQualifier': X500ATTR+'44',
|
||||
'eduPersonAffiliation': EDUPERSON_OID+'1',
|
||||
'eduPersonPrincipalName': EDUPERSON_OID+'6',
|
||||
'localityName': X500ATTR+'7',
|
||||
'owner': X500ATTR+'32',
|
||||
'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2',
|
||||
'searchGuide': X500ATTR+'14',
|
||||
'certificateRevocationList': X500ATTR+'39',
|
||||
'organizationalUnitName': X500ATTR+'11',
|
||||
'userCertificate': X500ATTR+'36',
|
||||
'preferredDeliveryMethod': X500ATTR+'28',
|
||||
'internationaliSDNNumber': X500ATTR+'25',
|
||||
'uniqueMember': X500ATTR+'50',
|
||||
'departmentNumber': NETSCAPE_LDAP+'2',
|
||||
'enhancedSearchGuide': X500ATTR+'47',
|
||||
'userPKCS12': NETSCAPE_LDAP+'216',
|
||||
'eduPersonTargetedID': EDUPERSON_OID+'10',
|
||||
'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1',
|
||||
'x121Address': X500ATTR+'24',
|
||||
'destinationIndicator': X500ATTR+'27',
|
||||
'eduPersonPrimaryAffiliation': EDUPERSON_OID+'5',
|
||||
'surname': X500ATTR+'4',
|
||||
'jpegPhoto': UCL_DIR_PILOT+'60',
|
||||
'eduPersonScopedAffiliation': EDUPERSON_OID+'9',
|
||||
'protocolInformation': X500ATTR+'48',
|
||||
'knowledgeInformation': X500ATTR+'2',
|
||||
'employeeType': NETSCAPE_LDAP+'4',
|
||||
'userSMIMECertificate': NETSCAPE_LDAP+'40',
|
||||
'enhancedSearchGuide': X500ATTR+'47',
|
||||
'facsimileTelephoneNumber': X500ATTR+'23',
|
||||
'fax': X500ATTR+'23',
|
||||
'federationFeideSchemaVersion': NOREDUPERSON_OID+'9',
|
||||
'generationQualifier': X500ATTR+'44',
|
||||
'givenName': X500ATTR+'42',
|
||||
'gn': X500ATTR+'42',
|
||||
'houseIdentifier': X500ATTR+'51',
|
||||
'initials': X500ATTR+'43',
|
||||
'internationaliSDNNumber': X500ATTR+'25',
|
||||
'jpegPhoto': UCL_DIR_PILOT+'60',
|
||||
'knowledgeInformation': X500ATTR+'2',
|
||||
'l': X500ATTR+'7',
|
||||
'localityName': X500ATTR+'7',
|
||||
'mail': UCL_DIR_PILOT+'3',
|
||||
'member': X500ATTR+'31',
|
||||
'streetAddress': X500ATTR+'9',
|
||||
'dmdName': X500ATTR+'54',
|
||||
'postalCode': X500ATTR+'17',
|
||||
'pseudonym': X500ATTR+'65',
|
||||
'dnQualifier': X500ATTR+'46',
|
||||
'crossCertificatePair': X500ATTR+'40',
|
||||
'eduPersonOrgDN': EDUPERSON_OID+'3',
|
||||
'authorityRevocationList': X500ATTR+'38',
|
||||
'displayName': NETSCAPE_LDAP+'241',
|
||||
'businessCategory': X500ATTR+'15',
|
||||
'serialNumber': X500ATTR+'5',
|
||||
'norEduOrgAcronym': NOREDUPERSON_OID+'6',
|
||||
'norEduOrgUniqueIdentifier': NOREDUPERSON_OID+'7',
|
||||
'st': X500ATTR+'8',
|
||||
'carLicense': NETSCAPE_LDAP+'1',
|
||||
'norEduOrgUniqueNumber': NOREDUPERSON_OID+'1',
|
||||
'norEduOrgUnitUniqueIdentifier': NOREDUPERSON_OID+'8',
|
||||
'norEduOrgUnitUniqueNumber': NOREDUPERSON_OID+'2',
|
||||
'norEduPersonBirthDate': NOREDUPERSON_OID+'3',
|
||||
'norEduPersonLIN': NOREDUPERSON_OID+'4',
|
||||
'norEduPersonNIN': NOREDUPERSON_OID+'5',
|
||||
'o': X500ATTR+'10',
|
||||
'organizationName': X500ATTR+'10',
|
||||
'organizationalUnitName': X500ATTR+'11',
|
||||
'ou': X500ATTR+'11',
|
||||
'owner': X500ATTR+'32',
|
||||
'physicalDeliveryOfficeName': X500ATTR+'19',
|
||||
'pkcs9email': PKCS_9+'1',
|
||||
'postOfficeBox': X500ATTR+'18',
|
||||
'postalAddress': X500ATTR+'16',
|
||||
'postalCode': X500ATTR+'17',
|
||||
'preferredDeliveryMethod': X500ATTR+'28',
|
||||
'preferredLanguage': NETSCAPE_LDAP+'39',
|
||||
'presentationAddress': X500ATTR+'29',
|
||||
'protocolInformation': X500ATTR+'48',
|
||||
'pseudonym': X500ATTR+'65',
|
||||
'registeredAddress': X500ATTR+'26',
|
||||
'rfc822Mailbox': UCL_DIR_PILOT+'3',
|
||||
'roleOccupant': X500ATTR+'33',
|
||||
'searchGuide': X500ATTR+'14',
|
||||
'serialNumber': X500ATTR+'5',
|
||||
'sn': X500ATTR+'4',
|
||||
'domainComponent': UCL_DIR_PILOT+'25',
|
||||
'st': X500ATTR+'8',
|
||||
'stateOrProvinceName': X500ATTR+'8',
|
||||
'street': X500ATTR+'9',
|
||||
'streetAddress': X500ATTR+'9',
|
||||
'supportedAlgorithms': X500ATTR+'52',
|
||||
'supportedApplicationContext': X500ATTR+'30',
|
||||
'surname': X500ATTR+'4',
|
||||
'telephoneNumber': X500ATTR+'20',
|
||||
'teletexTerminalIdentifier': X500ATTR+'22',
|
||||
'telexNumber': X500ATTR+'21',
|
||||
'title': X500ATTR+'12',
|
||||
'uniqueMember': X500ATTR+'50',
|
||||
'userCertificate': X500ATTR+'36',
|
||||
'userPKCS12': NETSCAPE_LDAP+'216',
|
||||
'userSMIMECertificate': NETSCAPE_LDAP+'40',
|
||||
'x121Address': X500ATTR+'24',
|
||||
'x500UniqueIdentifier': X500ATTR+'45',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +269,8 @@ class Config(object):
|
||||
acs = ac_factory()
|
||||
|
||||
if not acs:
|
||||
raise ConfigurationError("No attribute converters, something is wrong!!")
|
||||
raise ConfigurationError(
|
||||
"No attribute converters, something is wrong!!")
|
||||
|
||||
_acs = self.getattr("attribute_converters", typ)
|
||||
if _acs:
|
||||
|
||||
@@ -8,13 +8,15 @@ from saml2.soap import parse_soap_enveloped_saml_artifact_resolve
|
||||
from saml2.soap import class_instances_from_soap_enveloped_saml_thingies
|
||||
from saml2.soap import open_soap_envelope
|
||||
|
||||
from saml2 import samlp, SamlBase, SAMLError
|
||||
from saml2 import samlp
|
||||
from saml2 import SamlBase
|
||||
from saml2 import SAMLError
|
||||
from saml2 import saml
|
||||
from saml2 import response
|
||||
from saml2 import response as saml_response
|
||||
from saml2 import BINDING_URI
|
||||
from saml2 import BINDING_HTTP_ARTIFACT
|
||||
from saml2 import BINDING_PAOS
|
||||
from saml2 import request
|
||||
from saml2 import request as saml_request
|
||||
from saml2 import soap
|
||||
from saml2 import element_to_extension_element
|
||||
from saml2 import extension_elements_to_elements
|
||||
@@ -296,7 +298,16 @@ class Entity(HTTPBase):
|
||||
|
||||
return info
|
||||
|
||||
def unravel(self, txt, binding, msgtype="response"):
|
||||
@staticmethod
|
||||
def unravel(txt, binding, msgtype="response"):
|
||||
"""
|
||||
Will unpack the received text. Depending on the context the original
|
||||
response may have been transformed before transmission.
|
||||
:param txt:
|
||||
:param binding:
|
||||
:param msgtype:
|
||||
:return:
|
||||
"""
|
||||
#logger.debug("unravel '%s'" % txt)
|
||||
if binding not in [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST,
|
||||
BINDING_SOAP, BINDING_URI, BINDING_HTTP_ARTIFACT,
|
||||
@@ -309,7 +320,8 @@ class Entity(HTTPBase):
|
||||
elif binding == BINDING_HTTP_POST:
|
||||
xmlstr = base64.b64decode(txt)
|
||||
elif binding == BINDING_SOAP:
|
||||
func = getattr(soap, "parse_soap_enveloped_saml_%s" % msgtype)
|
||||
func = getattr(soap,
|
||||
"parse_soap_enveloped_saml_%s" % msgtype)
|
||||
xmlstr = func(txt)
|
||||
elif binding == BINDING_HTTP_ARTIFACT:
|
||||
xmlstr = base64.b64decode(txt)
|
||||
@@ -320,7 +332,8 @@ class Entity(HTTPBase):
|
||||
|
||||
return xmlstr
|
||||
|
||||
def parse_soap_message(self, text):
|
||||
@staticmethod
|
||||
def parse_soap_message(text):
|
||||
"""
|
||||
|
||||
:param text: The SOAP message
|
||||
@@ -330,7 +343,8 @@ class Entity(HTTPBase):
|
||||
ecp,
|
||||
samlp])
|
||||
|
||||
def unpack_soap_message(self, text):
|
||||
@staticmethod
|
||||
def unpack_soap_message(text):
|
||||
"""
|
||||
Picks out the parts of the SOAP message, body and headers apart
|
||||
:param text: The SOAP message
|
||||
@@ -438,7 +452,8 @@ class Entity(HTTPBase):
|
||||
msg.extension_elements = extensions
|
||||
|
||||
def _response(self, in_response_to, consumer_url=None, status=None,
|
||||
issuer=None, sign=False, to_sign=None, encrypt_assertion=False, encrypt_cert=None, **kwargs):
|
||||
issuer=None, sign=False, to_sign=None,
|
||||
encrypt_assertion=False, encrypt_cert=None, **kwargs):
|
||||
""" Create a Response.
|
||||
|
||||
:param in_response_to: The session identifier of the request
|
||||
@@ -471,10 +486,13 @@ class Entity(HTTPBase):
|
||||
if encrypt_assertion:
|
||||
sign_class = [(class_name(response), response.id)]
|
||||
if sign:
|
||||
response.signature = pre_signature_part(response.id, self.sec.my_cert, 1)
|
||||
response.signature = pre_signature_part(response.id,
|
||||
self.sec.my_cert, 1)
|
||||
cbxs = CryptoBackendXmlSec1(self.config.xmlsec_binary)
|
||||
_, cert_file = make_temp("%s" % encrypt_cert, decode=False)
|
||||
response = cbxs.encrypt_assertion(response, cert_file, pre_encryption_part())#template(response.assertion.id))
|
||||
response = cbxs.encrypt_assertion(response, cert_file,
|
||||
pre_encryption_part())
|
||||
# template(response.assertion.id))
|
||||
if sign:
|
||||
return signed_instance_factory(response, self.sec, sign_class)
|
||||
else:
|
||||
@@ -520,13 +538,14 @@ class Entity(HTTPBase):
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
def srv2typ(self, service):
|
||||
@staticmethod
|
||||
def srv2typ(service):
|
||||
for typ in ["aa", "pdp", "aq"]:
|
||||
if service in ENDPOINTS[typ]:
|
||||
if typ == "aa":
|
||||
return "attribute_authority"
|
||||
elif typ == "aq":
|
||||
return "authn_authority"
|
||||
return "authn_authority"
|
||||
else:
|
||||
return typ
|
||||
|
||||
@@ -570,12 +589,14 @@ class Entity(HTTPBase):
|
||||
origdoc = xmlstr
|
||||
xmlstr = self.unravel(xmlstr, binding, request_cls.msgtype)
|
||||
must = self.config.getattr("want_authn_requests_signed", "idp")
|
||||
only_valid_cert = self.config.getattr("want_authn_requests_only_with_valid_cert", "idp")
|
||||
only_valid_cert = self.config.getattr(
|
||||
"want_authn_requests_only_with_valid_cert", "idp")
|
||||
if only_valid_cert is None:
|
||||
only_valid_cert = False
|
||||
if only_valid_cert:
|
||||
must = True
|
||||
_request = _request.loads(xmlstr, binding, origdoc=origdoc, must=must, only_valid_cert=only_valid_cert)
|
||||
_request = _request.loads(xmlstr, binding, origdoc=origdoc, must=must,
|
||||
only_valid_cert=only_valid_cert)
|
||||
|
||||
_log_debug("Loaded request")
|
||||
|
||||
@@ -674,14 +695,14 @@ class Entity(HTTPBase):
|
||||
|
||||
return response
|
||||
|
||||
def create_artifact_resolve(self, artifact, destination, sid, consent=None,
|
||||
extensions=None, sign=False):
|
||||
def create_artifact_resolve(self, artifact, destination, sessid,
|
||||
consent=None, extensions=None, sign=False):
|
||||
"""
|
||||
Create a ArtifactResolve request
|
||||
|
||||
:param artifact:
|
||||
:param destination:
|
||||
:param sid: session id
|
||||
:param sessid: session id
|
||||
:param consent:
|
||||
:param extensions:
|
||||
:param sign:
|
||||
@@ -690,7 +711,7 @@ class Entity(HTTPBase):
|
||||
|
||||
artifact = Artifact(text=artifact)
|
||||
|
||||
return self._message(ArtifactResolve, destination, sid,
|
||||
return self._message(ArtifactResolve, destination, sessid,
|
||||
consent, extensions, sign, artifact=artifact)
|
||||
|
||||
def create_artifact_response(self, request, artifact, bindings=None,
|
||||
@@ -763,7 +784,7 @@ class Entity(HTTPBase):
|
||||
was not.
|
||||
"""
|
||||
|
||||
return self._parse_request(xmlstr, request.ManageNameIDRequest,
|
||||
return self._parse_request(xmlstr, saml_request.ManageNameIDRequest,
|
||||
"manage_name_id_service", binding)
|
||||
|
||||
def create_manage_name_id_response(self, request, bindings=None,
|
||||
@@ -781,17 +802,21 @@ class Entity(HTTPBase):
|
||||
|
||||
def parse_manage_name_id_request_response(self, string,
|
||||
binding=BINDING_SOAP):
|
||||
return self._parse_response(string, response.ManageNameIDResponse,
|
||||
"manage_name_id_service", binding)
|
||||
return self._parse_response(string, saml_response.ManageNameIDResponse,
|
||||
"manage_name_id_service", binding,
|
||||
asynchop=False)
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
def _parse_response(self, xmlstr, response_cls, service, binding, outstanding_certs=None, **kwargs):
|
||||
def _parse_response(self, xmlstr, response_cls, service, binding,
|
||||
outstanding_certs=None, **kwargs):
|
||||
""" Deal with a Response
|
||||
|
||||
:param xmlstr: The response as a xml string
|
||||
:param response_cls: What type of response it is
|
||||
:param binding: What type of binding this message came through.
|
||||
:param outstanding_certs: Certificates that belongs to me that the
|
||||
IdP may have used to encrypt a response/assertion/..
|
||||
:param kwargs: Extra key word arguments
|
||||
:return: None if the reply doesn't contain a valid SAML Response,
|
||||
otherwise the response.
|
||||
@@ -800,20 +825,20 @@ class Entity(HTTPBase):
|
||||
response = None
|
||||
|
||||
if self.config.accepted_time_diff:
|
||||
kwargs["timeslack"] = self.config.accepted_time_diff
|
||||
timeslack = self.config.accepted_time_diff
|
||||
|
||||
if "asynchop" not in kwargs:
|
||||
if binding in [BINDING_SOAP, BINDING_PAOS]:
|
||||
kwargs["asynchop"] = False
|
||||
asynchop = False
|
||||
else:
|
||||
kwargs["asynchop"] = True
|
||||
asynchop = True
|
||||
|
||||
if xmlstr:
|
||||
if "return_addrs" not in kwargs:
|
||||
if binding in [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]:
|
||||
try:
|
||||
# expected return address
|
||||
kwargs["return_addrs"] = self.config.endpoint(
|
||||
return_addrs = self.config.endpoint(
|
||||
service, binding=binding)
|
||||
except Exception:
|
||||
logger.info("Not supposed to handle this!")
|
||||
@@ -827,12 +852,6 @@ class Entity(HTTPBase):
|
||||
|
||||
xmlstr = self.unravel(xmlstr, binding, response_cls.msgtype)
|
||||
origxml = xmlstr
|
||||
if outstanding_certs is not None:
|
||||
_response = samlp.any_response_from_string(xmlstr)
|
||||
if len(_response.encrypted_assertion) > 0:
|
||||
_, cert_file = make_temp("%s" % outstanding_certs[_response.in_response_to]["key"], decode=False)
|
||||
cbxs = CryptoBackendXmlSec1(self.config.xmlsec_binary)
|
||||
xmlstr = cbxs.decrypt(xmlstr, cert_file)
|
||||
if not xmlstr: # Not a valid reponse
|
||||
return None
|
||||
|
||||
@@ -851,16 +870,14 @@ class Entity(HTTPBase):
|
||||
|
||||
logger.debug("XMLSTR: %s" % xmlstr)
|
||||
|
||||
if hasattr(response.response, 'encrypted_assertion'):
|
||||
for encrypted_assertion in response.response.encrypted_assertion:
|
||||
if encrypted_assertion.extension_elements is not None:
|
||||
assertion_list = extension_elements_to_elements(encrypted_assertion.extension_elements, [saml])
|
||||
for assertion in assertion_list:
|
||||
_assertion = saml.assertion_from_string(str(assertion))
|
||||
response.response.assertion.append(_assertion)
|
||||
|
||||
if response:
|
||||
response = response.verify()
|
||||
if outstanding_certs:
|
||||
_, key_file = make_temp(
|
||||
"%s" % outstanding_certs[
|
||||
response.in_response_to]["key"], decode=False)
|
||||
else:
|
||||
key_file = ""
|
||||
response = response.verify(key_file)
|
||||
|
||||
if not response:
|
||||
return None
|
||||
@@ -887,7 +904,7 @@ class Entity(HTTPBase):
|
||||
was not.
|
||||
"""
|
||||
|
||||
return self._parse_request(xmlstr, request.LogoutRequest,
|
||||
return self._parse_request(xmlstr, saml_request.LogoutRequest,
|
||||
"single_logout_service", binding)
|
||||
|
||||
def use_artifact(self, message, endpoint_index=0):
|
||||
@@ -964,7 +981,7 @@ class Entity(HTTPBase):
|
||||
kwargs = {"entity_id": self.config.entityid,
|
||||
"attribute_converters": self.config.attribute_converters}
|
||||
|
||||
resp = self._parse_response(xmlstr, response.ArtifactResponse,
|
||||
resp = self._parse_response(xmlstr, saml_response.ArtifactResponse,
|
||||
"artifact_resolve", BINDING_SOAP,
|
||||
**kwargs)
|
||||
# should just be one
|
||||
|
||||
@@ -775,37 +775,58 @@ class MetadataStore(object):
|
||||
return [m["text"] for m in ad["affiliate_member"]]
|
||||
|
||||
def entity_categories(self, entity_id):
|
||||
ent = self.__getitem__(entity_id)
|
||||
res = []
|
||||
try:
|
||||
ext = ent["extensions"]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
for elem in ext["extension_elements"]:
|
||||
if elem["__class__"] == ENTITYATTRIBUTES:
|
||||
for attr in elem["attribute"]:
|
||||
if attr["name"] == ENTITY_CATEGORY:
|
||||
res.extend([v["text"] for v in
|
||||
attr["attribute_value"]])
|
||||
"""
|
||||
Get a list of entity categories for an entity id.
|
||||
|
||||
return res
|
||||
:param entity_id: Entity id
|
||||
:return: Entity categories
|
||||
|
||||
:type entity_id: string
|
||||
:rtype: [string]
|
||||
"""
|
||||
attributes = self.entity_attributes(entity_id)
|
||||
return attributes.get(ENTITY_CATEGORY, [])
|
||||
|
||||
def supported_entity_categories(self, entity_id):
|
||||
ent = self.__getitem__(entity_id)
|
||||
res = []
|
||||
try:
|
||||
ext = ent["extensions"]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
for elem in ext["extension_elements"]:
|
||||
if elem["__class__"] == ENTITYATTRIBUTES:
|
||||
for attr in elem["attribute"]:
|
||||
if attr["name"] == ENTITY_CATEGORY_SUPPORT:
|
||||
res.extend([v["text"] for v in
|
||||
attr["attribute_value"]])
|
||||
"""
|
||||
Get a list of entity category support for an entity id.
|
||||
|
||||
:param entity_id: Entity id
|
||||
:return: Entity category support
|
||||
|
||||
:type entity_id: string
|
||||
:rtype: [string]
|
||||
"""
|
||||
attributes = self.entity_attributes(entity_id)
|
||||
return attributes.get(ENTITY_CATEGORY_SUPPORT, [])
|
||||
|
||||
def entity_attributes(self, entity_id):
|
||||
"""
|
||||
Get all entity attributes for an entry in the metadata.
|
||||
|
||||
Example return data:
|
||||
|
||||
{'http://macedir.org/entity-category': ['something', 'something2'],
|
||||
'http://example.org/saml-foo': ['bar']}
|
||||
|
||||
:param entity_id: Entity id
|
||||
:return: dict with keys and value-lists from metadata
|
||||
|
||||
:type entity_id: string
|
||||
:rtype: dict
|
||||
"""
|
||||
res = {}
|
||||
try:
|
||||
ext = self.__getitem__(entity_id)["extensions"]
|
||||
except KeyError:
|
||||
return res
|
||||
for elem in ext["extension_elements"]:
|
||||
if elem["__class__"] == ENTITYATTRIBUTES:
|
||||
for attr in elem["attribute"]:
|
||||
if attr["name"] not in res:
|
||||
res[attr["name"]] = []
|
||||
res[attr["name"]] += [v["text"] for v in attr[
|
||||
"attribute_value"]]
|
||||
return res
|
||||
|
||||
def bindings(self, entity_id, typ, service):
|
||||
|
||||
@@ -42,8 +42,8 @@ import xmldsig as ds
|
||||
import xmlenc as xenc
|
||||
|
||||
from saml2 import samlp
|
||||
from saml2 import class_name
|
||||
from saml2 import saml
|
||||
from saml2 import extension_element_to_element
|
||||
from saml2 import extension_elements_to_elements
|
||||
from saml2 import SAMLError
|
||||
from saml2 import time_util
|
||||
@@ -387,7 +387,7 @@ class StatusResponse(object):
|
||||
|
||||
if self.asynchop:
|
||||
if self.response.destination and \
|
||||
self.response.destination not in self.return_addrs:
|
||||
self.response.destination not in self.return_addrs:
|
||||
logger.error("%s not in %s" % (self.response.destination,
|
||||
self.return_addrs))
|
||||
return None
|
||||
@@ -399,7 +399,7 @@ class StatusResponse(object):
|
||||
def loads(self, xmldata, decode=True, origxml=None):
|
||||
return self._loads(xmldata, decode, origxml)
|
||||
|
||||
def verify(self):
|
||||
def verify(self, key_file=""):
|
||||
try:
|
||||
return self._verify()
|
||||
except AssertionError:
|
||||
@@ -473,6 +473,7 @@ class AuthnResponse(StatusResponse):
|
||||
self.came_from = ""
|
||||
self.ava = None
|
||||
self.assertion = None
|
||||
self.assertions = []
|
||||
self.session_not_on_or_after = 0
|
||||
self.allow_unsolicited = allow_unsolicited
|
||||
self.require_signature = want_assertions_signed
|
||||
@@ -739,8 +740,13 @@ class AuthnResponse(StatusResponse):
|
||||
return self.name_id
|
||||
|
||||
def _assertion(self, assertion):
|
||||
self.assertion = assertion
|
||||
"""
|
||||
Check the assertion
|
||||
:param assertion:
|
||||
:return: True/False depending on if the assertion is sane or not
|
||||
"""
|
||||
|
||||
self.assertion = assertion
|
||||
logger.debug("assertion context: %s" % (self.context,))
|
||||
logger.debug("assertion keys: %s" % (assertion.keyswv()))
|
||||
logger.debug("outstanding_queries: %s" % (self.outstanding_queries,))
|
||||
@@ -773,54 +779,61 @@ class AuthnResponse(StatusResponse):
|
||||
logger.exception("get subject")
|
||||
raise
|
||||
|
||||
def _encrypted_assertion(self, xmlstr):
|
||||
if xmlstr.encrypted_data:
|
||||
assertion_str = self.sec.decrypt(xmlstr.encrypted_data.to_string())
|
||||
if not assertion_str:
|
||||
raise DecryptionFailed()
|
||||
assertion = saml.assertion_from_string(assertion_str)
|
||||
else:
|
||||
decrypt_xml = self.sec.decrypt(xmlstr)
|
||||
def decrypt_assertions(self, encrypted_assertions, key_file=""):
|
||||
res = []
|
||||
for encrypted_assertion in encrypted_assertions:
|
||||
if encrypted_assertion.extension_elements:
|
||||
assertions = extension_elements_to_elements(
|
||||
encrypted_assertion.extension_elements, [saml, samlp])
|
||||
for assertion in assertions:
|
||||
if assertion.signature:
|
||||
if not self.sec.verify_signature(
|
||||
"%s" % assertion, key_file,
|
||||
node_name=class_name(assertion)):
|
||||
logger.error(
|
||||
"Failed to verify signature on '%s'" % assertion)
|
||||
raise SignatureError()
|
||||
res.append(assertion)
|
||||
return res
|
||||
|
||||
logger.debug("Decryption successfull")
|
||||
|
||||
self.response = samlp.response_from_string(decrypt_xml)
|
||||
logger.debug("Parsed decrypted assertion successfull")
|
||||
|
||||
enc = self.response.encrypted_assertion[0].extension_elements[0]
|
||||
assertion = extension_element_to_element(
|
||||
enc, saml.ELEMENT_FROM_STRING, namespace=saml.NAMESPACE)
|
||||
|
||||
logger.debug("Decrypted Assertion: %s" % assertion)
|
||||
return self._assertion(assertion)
|
||||
|
||||
def parse_assertion(self):
|
||||
def parse_assertion(self, key_file=""):
|
||||
if self.context == "AuthnQuery":
|
||||
# can contain one or more assertions
|
||||
pass
|
||||
else: # This is a saml2int limitation
|
||||
try:
|
||||
assert len(self.response.assertion) == 1 or \
|
||||
len(self.response.encrypted_assertion) == 1
|
||||
len(self.response.encrypted_assertion) == 1
|
||||
except AssertionError:
|
||||
raise Exception("No assertion part")
|
||||
|
||||
if self.response.encrypted_assertion:
|
||||
logger.debug("***Encrypted assertion/-s***")
|
||||
decr_text = self.sec.decrypt(self.xmlstr)
|
||||
resp = samlp.response_from_string(decr_text)
|
||||
res = self.decrypt_assertions(resp.encrypted_assertion, key_file)
|
||||
if self.response.assertion:
|
||||
self.response.assertion.extend(res)
|
||||
else:
|
||||
self.response.assertion = res
|
||||
self.response.encrypted_assertion = []
|
||||
|
||||
if self.response.assertion:
|
||||
logger.debug("***Unencrypted response***")
|
||||
logger.debug("***Unencrypted assertion***")
|
||||
for assertion in self.response.assertion:
|
||||
if not self._assertion(assertion):
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
logger.debug("***Encrypted response***")
|
||||
for assertion in self.response.encrypted_assertion:
|
||||
if not self._encrypted_assertion(assertion):
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
self.assertions.append(assertion)
|
||||
self.assertion = self.assertions[0]
|
||||
|
||||
def verify(self):
|
||||
return True
|
||||
|
||||
def verify(self, key_file=""):
|
||||
""" Verify that the assertion is syntactically correct and
|
||||
the signature is correct if present."""
|
||||
the signature is correct if present.
|
||||
:param key_file: If not the default key file should be used this is it.
|
||||
"""
|
||||
|
||||
try:
|
||||
self._verify()
|
||||
@@ -830,7 +843,7 @@ class AuthnResponse(StatusResponse):
|
||||
if not isinstance(self.response, samlp.Response):
|
||||
return self
|
||||
|
||||
if self.parse_assertion():
|
||||
if self.parse_assertion(key_file):
|
||||
return self
|
||||
else:
|
||||
logger.error("Could not parse the assertion")
|
||||
@@ -1056,7 +1069,7 @@ class AssertionIDResponse(object):
|
||||
|
||||
return self._postamble()
|
||||
|
||||
def verify(self):
|
||||
def verify(self, key_file=""):
|
||||
try:
|
||||
valid_instance(self.response)
|
||||
except NotValid, exc:
|
||||
|
||||
@@ -246,6 +246,8 @@ class AttributeValueBase(SamlBase):
|
||||
# clear type
|
||||
#self.clear_type()
|
||||
self.set_text(tree.text)
|
||||
if XSI_NIL in self.extension_attributes:
|
||||
del self.extension_attributes[XSI_NIL]
|
||||
try:
|
||||
typ = self.extension_attributes[XSI_TYPE]
|
||||
_verify_value_type(typ, getattr(self, "text"))
|
||||
|
||||
@@ -35,12 +35,13 @@ from Crypto.PublicKey import RSA
|
||||
from saml2.cert import OpenSSLWrapper
|
||||
from saml2.extension import pefim
|
||||
from saml2.saml import EncryptedAssertion
|
||||
from saml2.samlp import Response, response_from_string
|
||||
from saml2.samlp import Response
|
||||
|
||||
import xmldsig as ds
|
||||
import xmlenc as enc
|
||||
|
||||
from saml2 import samlp, SAMLError, extension_elements_to_elements
|
||||
from saml2 import samlp
|
||||
from saml2 import SAMLError
|
||||
from saml2 import extension_elements_to_elements
|
||||
from saml2 import class_name
|
||||
from saml2 import saml
|
||||
from saml2 import ExtensionElement
|
||||
@@ -74,7 +75,8 @@ RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
|
||||
RSA_1_5 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
|
||||
TRIPLE_DES_CBC = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
|
||||
XMLTAG = "<?xml version='1.0'?>"
|
||||
PREFIX = "<?xml version='1.0' encoding='UTF-8'?>"
|
||||
PREFIX1 = "<?xml version='1.0' encoding='UTF-8'?>"
|
||||
PREFIX2 = '<?xml version="1.0" encoding="UTF-8"?>'
|
||||
|
||||
|
||||
class SigverError(SAMLError):
|
||||
@@ -125,8 +127,12 @@ def rm_xmltag(statement):
|
||||
statement = statement[len(XMLTAG):]
|
||||
if statement[0] == '\n':
|
||||
statement = statement[1:]
|
||||
elif statement.startswith(PREFIX):
|
||||
statement = statement[len(PREFIX):]
|
||||
elif statement.startswith(PREFIX1):
|
||||
statement = statement[len(PREFIX1):]
|
||||
if statement[0] == '\n':
|
||||
statement = statement[1:]
|
||||
elif statement.startswith(PREFIX2):
|
||||
statement = statement[len(PREFIX2):]
|
||||
if statement[0] == '\n':
|
||||
statement = statement[1:]
|
||||
|
||||
@@ -693,7 +699,7 @@ class CryptoBackend():
|
||||
def encrypt(self, text, recv_key, template, key_type):
|
||||
raise NotImplementedError()
|
||||
|
||||
def encrypt_assertion(self, statement, recv_key, key_type):
|
||||
def encrypt_assertion(self, statement, recv_key, key_type, xpath=""):
|
||||
raise NotImplementedError()
|
||||
|
||||
def decrypt(self, enctext, key_file):
|
||||
@@ -733,12 +739,25 @@ class CryptoBackendXmlSec1(CryptoBackend):
|
||||
except IndexError:
|
||||
return ""
|
||||
|
||||
def encrypt(self, text, recv_key, template, key_type):
|
||||
def encrypt(self, text, recv_key, template, session_key_type, xpath=""):
|
||||
"""
|
||||
|
||||
:param text: The text to be compiled
|
||||
:param recv_key: Filename of a file where the key resides
|
||||
:param template: Filename of a file with the pre-encryption part
|
||||
:param session_key_type: Type and size of a new session key
|
||||
"des-192" generates a new 192 bits DES key for DES3 encryption
|
||||
:param xpath: What should be encrypted
|
||||
:return:
|
||||
"""
|
||||
logger.debug("Encryption input len: %d" % len(text))
|
||||
_, fil = make_temp("%s" % text, decode=False)
|
||||
|
||||
com_list = [self.xmlsec, "--encrypt", "--pubkey-cert-pem", recv_key,
|
||||
"--session-key", key_type, "--xml-data", fil]
|
||||
"--session-key", session_key_type, "--xml-data", fil]
|
||||
|
||||
if xpath:
|
||||
com_list.extend(['--node-xpath', xpath])
|
||||
|
||||
(_stdout, _stderr, output) = self._run_xmlsec(com_list, [template],
|
||||
exception=DecryptError,
|
||||
@@ -767,7 +786,8 @@ class CryptoBackendXmlSec1(CryptoBackend):
|
||||
"--session-key", key_type, "--xml-data", fil,
|
||||
"--node-xpath", ASSERT_XPATH]
|
||||
|
||||
(_stdout, _stderr, output) = self._run_xmlsec(com_list, [tmpl], exception=EncryptError, validate_output=False)
|
||||
(_stdout, _stderr, output) = self._run_xmlsec(
|
||||
com_list, [tmpl], exception=EncryptError, validate_output=False)
|
||||
|
||||
os.unlink(fil)
|
||||
if not output:
|
||||
@@ -1206,7 +1226,7 @@ class SecurityContext(object):
|
||||
|
||||
:param text: Text to encrypt
|
||||
:param recv_key: A file containing the receivers public key
|
||||
:param template: A file containing the XML document template
|
||||
:param template: A file containing the XMLSEC template
|
||||
:param key_type: The type of session key to use
|
||||
:result: An encrypted XML text
|
||||
"""
|
||||
@@ -1262,8 +1282,7 @@ class SecurityContext(object):
|
||||
return self.crypto.validate_signature(signedtext, cert_file=cert_file,
|
||||
cert_type=cert_type,
|
||||
node_name=node_name,
|
||||
node_id=node_id, id_attr=id_attr,
|
||||
)
|
||||
node_id=node_id, id_attr=id_attr)
|
||||
|
||||
def _check_signature(self, decoded_xml, item, node_name=NODE_NAME,
|
||||
origdoc=None, id_attr="", must=False,
|
||||
@@ -1735,7 +1754,10 @@ def pre_encrypt_assertion(response):
|
||||
assertion = response.assertion
|
||||
response.assertion = None
|
||||
response.encrypted_assertion = EncryptedAssertion()
|
||||
response.encrypted_assertion.add_extension_element(assertion)
|
||||
if isinstance(assertion, list):
|
||||
response.encrypted_assertion.add_extension_elements(assertion)
|
||||
else:
|
||||
response.encrypted_assertion.add_extension_element(assertion)
|
||||
# txt = "%s" % response
|
||||
# _ass = "%s" % assertion
|
||||
# _ass = rm_xmltag(_ass)
|
||||
|
||||
@@ -81,8 +81,9 @@ def parse_duration(duration):
|
||||
assert duration[index] == "P"
|
||||
index += 1
|
||||
|
||||
dic = dict([(typ, 0) for (code, typ) in D_FORMAT])
|
||||
|
||||
dic = dict([(typ, 0) for (code, typ) in D_FORMAT if typ])
|
||||
dlen = len(duration)
|
||||
|
||||
for code, typ in D_FORMAT:
|
||||
#print duration[index:], code
|
||||
if duration[index] == '-':
|
||||
@@ -94,25 +95,36 @@ def parse_duration(duration):
|
||||
raise Exception("Not allowed to end with 'T'")
|
||||
else:
|
||||
raise Exception("Missing T")
|
||||
elif duration[index] == "T":
|
||||
continue
|
||||
else:
|
||||
try:
|
||||
mod = duration[index:].index(code)
|
||||
_val = duration[index:index + mod]
|
||||
try:
|
||||
dic[typ] = int(duration[index:index + mod])
|
||||
dic[typ] = int(_val)
|
||||
except ValueError:
|
||||
if code == "S":
|
||||
# smallest value used may also have a decimal fraction
|
||||
if mod + index + 1 == dlen:
|
||||
try:
|
||||
dic[typ] = float(duration[index:index + mod])
|
||||
dic[typ] = float(_val)
|
||||
except ValueError:
|
||||
raise Exception("Not a float")
|
||||
if "," in _val:
|
||||
_val = _val.replace(",", ".")
|
||||
try:
|
||||
dic[typ] = float(_val)
|
||||
except ValueError:
|
||||
raise Exception("Not a float")
|
||||
else:
|
||||
raise Exception("Not a float")
|
||||
else:
|
||||
raise Exception(
|
||||
"Fractions not allow on anything byt seconds")
|
||||
raise ValueError(
|
||||
"Fraction not allowed on other than smallest value")
|
||||
index = mod + index + 1
|
||||
except ValueError:
|
||||
dic[typ] = 0
|
||||
|
||||
if index == len(duration):
|
||||
if index == dlen:
|
||||
break
|
||||
|
||||
return sign, dic
|
||||
|
||||
@@ -224,4 +224,4 @@ def test_xmlsec_cryptobackend():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_xmlsec_cryptobackend()
|
||||
test_xmlsec_cryptobackend()
|
||||
|
||||
@@ -323,4 +323,4 @@ MAP = {
|
||||
'x121Address': 'urn:mace:dir:attribute-def:x121Address',
|
||||
'x500UniqueIdentifier': 'urn:mace:dir:attribute-def:x500UniqueIdentifier',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,4 +196,4 @@ MAP = {
|
||||
'labeledURI': UMICH+'57',
|
||||
'uid': UCL_DIR_PILOT+'1'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,4 +187,4 @@ MAP = {
|
||||
'sn': X500ATTR+'4',
|
||||
'domainComponent': UCL_DIR_PILOT+'25',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,4 @@
|
||||
<ns0:Body>
|
||||
<ns3:AuthnRequest/>
|
||||
</ns0:Body>
|
||||
</ns0:Envelope>
|
||||
</ns0:Envelope>
|
||||
|
||||
@@ -12,4 +12,4 @@ w9NTEImw8CmUzzzmMd7TBM2epwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAJpIWdXn
|
||||
FL/j9Cm/Pdn6Yoxkf1mWy8L8WSwF8j9xfkvp53/GMd9IFkgkBbZo+F9CDH2la6H3
|
||||
vseA3ZJrXrxSn5RBhI5XJ85DGfdcMYJy3K42Y6mAUghVv1n+rf39w/cyuSRIW0IY
|
||||
XE3ANufnryezpDUffXpzdUltuTCpu2qfKEj2
|
||||
-----END CERTIFICATE-----
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
<ns0:CipherData>
|
||||
<ns0:CipherValue/>
|
||||
</ns0:CipherData>
|
||||
</ns0:EncryptedData>
|
||||
</ns0:EncryptedData>
|
||||
|
||||
@@ -187,4 +187,4 @@ class FakeIDP(Server):
|
||||
else: # Just POST
|
||||
response = "%s" % _resp
|
||||
|
||||
return DummyResponse(200, response)
|
||||
return DummyResponse(200, response)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
curl -G -O http://md.incommon.org/InCommon/InCommon-metadata.xml
|
||||
curl -G -O http://metadata.aai.switch.ch/metadata.aaitest.xml
|
||||
curl -G -O http://metadata.aai.switch.ch/metadata.aaitest.xml
|
||||
|
||||
@@ -15,4 +15,4 @@ EgYDVQQDEwtrYWxtYXIyLm9yZ4IJALIv7VqXanQYMAwGA1UdEwQFMAMBAf8wDQYJ
|
||||
KoZIhvcNAQEFBQADgYEALx5V6xKtPr7urC/QOWiHxUChQO+SJsbnlwIquwaEGgUf
|
||||
0WrGidPu04zdv+VpKtR+/KZbIDuSWx0/AkbexiE9ZUzJ2GvdVSxr/uON9CtQIQTp
|
||||
5WjZD0KaieaoIMy/w5shc+trjkV550g/MWFFqAjproXwHRrEQoAxWL0smtR1R/I=
|
||||
-----END CERTIFICATE-----
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -71,4 +71,4 @@
|
||||
</ns1:AttributeStatement>
|
||||
</ns1:Assertion>
|
||||
</ns1:EncryptedAssertion>
|
||||
</ns0:Response>
|
||||
</ns0:Response>
|
||||
|
||||
@@ -17,4 +17,4 @@ vvjpFAcbu/ILfzsXk19zKInCXmFWW5UNl2iq9GRCKltMyWZ/8m74cZpm1X3x4u33
|
||||
u+VTbtj/ZeTzqsriFfXo2q8EsdEK+27tvluNbdUgEayz8YIFrLI9LJRlWH6X6BWh
|
||||
PbIrR0sd263vE/1fgWbeB66CRXys0oQ92k9arc+gkVB2hZ8o4BK82LkwO30Ueo+l
|
||||
oHJ24vcX55P2LXmP+x+hIjMXICkqly0QE7kUVUVBisQ=
|
||||
-----END CERTIFICATE-----
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -2,8 +2,8 @@ from pathutils import full_path
|
||||
from pathutils import xmlsec_path
|
||||
|
||||
CONFIG = {
|
||||
"entityid" : "urn:mace:example.com:saml:roland:sp",
|
||||
"name" : "urn:mace:example.com:saml:roland:sp",
|
||||
"entityid": "urn:mace:example.com:saml:roland:sp",
|
||||
"name": "urn:mace:example.com:saml:roland:sp",
|
||||
"description": "My own SP",
|
||||
"service": {
|
||||
"sp": {
|
||||
@@ -25,14 +25,14 @@ CONFIG = {
|
||||
"local": [full_path("idp.xml"), full_path("vo_metadata.xml")],
|
||||
},
|
||||
"virtual_organization": {
|
||||
"urn:mace:example.com:it:tek":{
|
||||
"urn:mace:example.com:it:tek": {
|
||||
"nameid_format": "urn:oid:1.3.6.1.4.1.1466.115.121.1.15-NameID",
|
||||
"common_identifier": "umuselin",
|
||||
}
|
||||
},
|
||||
"subject_data": "subject_data.db",
|
||||
"accepted_time_diff": 60,
|
||||
"attribute_map_dir" : full_path("attributemaps"),
|
||||
"attribute_map_dir": full_path("attributemaps"),
|
||||
"valid_for": 6,
|
||||
"organization": {
|
||||
"name": ("AB Exempel", "se"),
|
||||
@@ -40,12 +40,13 @@ CONFIG = {
|
||||
"url": "http://www.example.org",
|
||||
},
|
||||
"contact_person": [{
|
||||
"given_name": "Roland",
|
||||
"sur_name": "Hedberg",
|
||||
"telephone_number": "+46 70 100 0000",
|
||||
"email_address": ["tech@eample.com", "tech@example.org"],
|
||||
"contact_type": "technical"
|
||||
},
|
||||
"given_name": "Roland",
|
||||
"sur_name": "Hedberg",
|
||||
"telephone_number": "+46 70 100 0000",
|
||||
"email_address": ["tech@eample.com",
|
||||
"tech@example.org"],
|
||||
"contact_type": "technical"
|
||||
},
|
||||
],
|
||||
"logger": {
|
||||
"rotating": {
|
||||
|
||||
@@ -101,4 +101,4 @@
|
||||
</saml:Attribute>
|
||||
</saml:AttributeStatement>
|
||||
</saml:Assertion>
|
||||
</samlp:Response>
|
||||
</samlp:Response>
|
||||
|
||||
@@ -118659,4 +118659,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
@@ -206,4 +206,4 @@ def test_6():
|
||||
assert tr.algorithm == "http://www.w3.org/TR/1999/REC-xpath-19991116"
|
||||
assert len(tr.x_path) == 1
|
||||
assert tr.x_path[0].text.strip() == """self::xenc:EncryptedData[@Id="example1"]"""
|
||||
|
||||
|
||||
|
||||
@@ -7,38 +7,43 @@ from saml2.time_util import f_quotient, modulo, parse_duration, add_duration
|
||||
from saml2.time_util import str_to_time, instant, valid, in_a_while
|
||||
from saml2.time_util import before, after, not_before, not_on_or_after
|
||||
|
||||
|
||||
def test_f_quotient():
|
||||
assert f_quotient(-1,3) == -1
|
||||
assert f_quotient(0,3) == 0
|
||||
assert f_quotient(1,3) == 0
|
||||
assert f_quotient(2,3) == 0
|
||||
assert f_quotient(3,3) == 1
|
||||
assert f_quotient(3.123,3) == 1
|
||||
assert f_quotient(-1, 3) == -1
|
||||
assert f_quotient(0, 3) == 0
|
||||
assert f_quotient(1, 3) == 0
|
||||
assert f_quotient(2, 3) == 0
|
||||
assert f_quotient(3, 3) == 1
|
||||
assert f_quotient(3.123, 3) == 1
|
||||
|
||||
|
||||
def test_modulo():
|
||||
assert modulo(-1,3) == 2
|
||||
assert modulo(0,3) == 0
|
||||
assert modulo(1,3) == 1
|
||||
assert modulo(2,3) == 2
|
||||
assert modulo(3,3) == 0
|
||||
assert modulo(-1, 3) == 2
|
||||
assert modulo(0, 3) == 0
|
||||
assert modulo(1, 3) == 1
|
||||
assert modulo(2, 3) == 2
|
||||
assert modulo(3, 3) == 0
|
||||
x = 3.123
|
||||
assert modulo(3.123,3) == x - 3
|
||||
assert modulo(3.123, 3) == x - 3
|
||||
|
||||
|
||||
def test_f_quotient_2():
|
||||
assert f_quotient(0, 1, 13) == -1
|
||||
for i in range(1,13):
|
||||
for i in range(1, 13):
|
||||
assert f_quotient(i, 1, 13) == 0
|
||||
assert f_quotient(13, 1, 13) == 1
|
||||
assert f_quotient(13.123, 1, 13) == 1
|
||||
|
||||
|
||||
def test_modulo_2():
|
||||
assert modulo(0, 1, 13) == 12
|
||||
for i in range(1,13):
|
||||
for i in range(1, 13):
|
||||
assert modulo(i, 1, 13) == i
|
||||
assert modulo(13, 1, 13) == 1
|
||||
#x = 0.123
|
||||
#assert modulo(13+x, 1, 13) == 1+x
|
||||
|
||||
|
||||
def test_parse_duration():
|
||||
(sign, d) = parse_duration("P1Y3M5DT7H10M3.3S")
|
||||
assert sign == "+"
|
||||
@@ -48,7 +53,46 @@ def test_parse_duration():
|
||||
assert d['tm_mday'] == 5
|
||||
assert d['tm_year'] == 1
|
||||
assert d['tm_min'] == 10
|
||||
|
||||
|
||||
|
||||
def test_parse_duration2():
|
||||
(sign, d) = parse_duration("PT30M")
|
||||
assert sign == "+"
|
||||
assert d['tm_sec'] == 0
|
||||
assert d['tm_mon'] == 0
|
||||
assert d['tm_hour'] == 0
|
||||
assert d['tm_mday'] == 0
|
||||
assert d['tm_year'] == 0
|
||||
assert d['tm_min'] == 30
|
||||
|
||||
|
||||
PATTERNS = {
|
||||
"P3Y6M4DT12H30M5S": {'tm_sec': 5, 'tm_hour': 12, 'tm_mday': 4,
|
||||
'tm_year': 3, 'tm_mon': 6, 'tm_min': 30},
|
||||
"P23DT23H": {'tm_sec': 0, 'tm_hour': 23, 'tm_mday': 23, 'tm_year': 0,
|
||||
'tm_mon': 0, 'tm_min': 0},
|
||||
"P4Y": {'tm_sec': 0, 'tm_hour': 0, 'tm_mday': 0, 'tm_year': 4,
|
||||
'tm_mon': 0, 'tm_min': 0},
|
||||
"P1M": {'tm_sec': 0, 'tm_hour': 0, 'tm_mday': 0, 'tm_year': 0,
|
||||
'tm_mon': 1, 'tm_min': 0},
|
||||
"PT1M": {'tm_sec': 0, 'tm_hour': 0, 'tm_mday': 0, 'tm_year': 0,
|
||||
'tm_mon': 0, 'tm_min': 1},
|
||||
"P0.5Y": {'tm_sec': 0, 'tm_hour': 0, 'tm_mday': 0, 'tm_year': 0.5,
|
||||
'tm_mon': 0, 'tm_min': 0},
|
||||
"P0,5Y": {'tm_sec': 0, 'tm_hour': 0, 'tm_mday': 0, 'tm_year': 0.5,
|
||||
'tm_mon': 0, 'tm_min': 0},
|
||||
"PT36H": {'tm_sec': 0, 'tm_hour': 36, 'tm_mday': 0, 'tm_year': 0,
|
||||
'tm_mon': 0, 'tm_min': 0},
|
||||
"P1DT12H": {'tm_sec': 0, 'tm_hour': 12, 'tm_mday': 1, 'tm_year': 0,
|
||||
'tm_mon': 0, 'tm_min': 0}
|
||||
}
|
||||
|
||||
|
||||
def test_parse_duration_n():
|
||||
for dur, _val in PATTERNS.items():
|
||||
(sign, d) = parse_duration(dur)
|
||||
assert d == _val
|
||||
|
||||
def test_add_duration_1():
|
||||
#2000-01-12T12:13:14Z P1Y3M5DT7H10M3S 2001-04-17T19:23:17Z
|
||||
t = add_duration(str_to_time("2000-01-12T12:13:14Z"), "P1Y3M5DT7H10M3S")
|
||||
@@ -58,17 +102,19 @@ def test_add_duration_1():
|
||||
assert t.tm_hour == 19
|
||||
assert t.tm_min == 23
|
||||
assert t.tm_sec == 17
|
||||
|
||||
|
||||
|
||||
def test_add_duration_2():
|
||||
#2000-01-12 PT33H 2000-01-13
|
||||
t = add_duration(str_to_time("2000-01-12T00:00:00Z"),"PT33H")
|
||||
t = add_duration(str_to_time("2000-01-12T00:00:00Z"), "PT33H")
|
||||
assert t.tm_year == 2000
|
||||
assert t.tm_mon == 1
|
||||
assert t.tm_mday == 14
|
||||
assert t.tm_hour == 9
|
||||
assert t.tm_min == 0
|
||||
assert t.tm_sec == 0
|
||||
|
||||
|
||||
|
||||
def test_str_to_time():
|
||||
t = calendar.timegm(str_to_time("2000-01-12T00:00:00Z"))
|
||||
#TODO: Find all instances of time.mktime(.....)
|
||||
@@ -78,22 +124,25 @@ def test_str_to_time():
|
||||
# do this as an external method in the
|
||||
assert t == 947635200
|
||||
|
||||
|
||||
def test_instant():
|
||||
inst = str_to_time(instant())
|
||||
now = time.gmtime()
|
||||
|
||||
assert now >= inst
|
||||
|
||||
|
||||
|
||||
def test_valid():
|
||||
assert valid("2000-01-12T00:00:00Z") == False
|
||||
current_year = datetime.datetime.today().year
|
||||
assert valid("%d-01-12T00:00:00Z" % (current_year + 1)) == True
|
||||
this_instance = instant()
|
||||
time.sleep(1)
|
||||
assert valid(this_instance) == False # unless on a very fast machine :-)
|
||||
assert valid(this_instance) == False # unless on a very fast machine :-)
|
||||
soon = in_a_while(seconds=10)
|
||||
assert valid(soon) == True
|
||||
|
||||
|
||||
|
||||
def test_timeout():
|
||||
soon = in_a_while(seconds=1)
|
||||
time.sleep(2)
|
||||
@@ -122,3 +171,7 @@ def test_not_on_or_after():
|
||||
current_year = datetime.datetime.today().year
|
||||
assert not_on_or_after("%d-01-01T00:00:00Z" % (current_year + 1)) == True
|
||||
assert not_on_or_after("%d-01-01T00:00:00Z" % (current_year - 1)) == False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_parse_duration_n()
|
||||
|
||||
@@ -151,7 +151,7 @@ def test_audience():
|
||||
assert aud_restr.audience.text == "urn:foo:bar"
|
||||
|
||||
def test_conditions():
|
||||
conditions = utils.factory( saml.Conditions,
|
||||
conditions = utils.factory(saml.Conditions,
|
||||
not_before="2009-10-30T07:58:10.852Z",
|
||||
not_on_or_after="2009-10-30T08:03:10.852Z",
|
||||
audience_restriction=[utils.factory(saml.AudienceRestriction,
|
||||
|
||||
@@ -18,9 +18,11 @@ from saml2.validate import valid_anytype
|
||||
|
||||
from py.test import raises
|
||||
|
||||
def _eq(l1,l2):
|
||||
|
||||
def _eq(l1, l2):
|
||||
return set(l1) == set(l2)
|
||||
|
||||
|
||||
def test_duration():
|
||||
assert valid_duration("P1Y2M3DT10H30M")
|
||||
assert valid_duration("P1Y2M3DT10H30M1.567S")
|
||||
@@ -31,41 +33,45 @@ def test_duration():
|
||||
assert valid_duration("P0Y1347M")
|
||||
assert valid_duration("P0Y1347M0D")
|
||||
assert valid_duration("-P1347M")
|
||||
assert valid_duration("P1Y2MT2.5H")
|
||||
|
||||
raises(NotValid, 'valid_duration("P-1347M")')
|
||||
raises(NotValid, ' valid_duration("P1Y2MT")')
|
||||
raises(NotValid, ' valid_duration("P1Y2MT2xH")')
|
||||
|
||||
raises( NotValid, 'valid_duration("P-1347M")')
|
||||
raises( NotValid, ' valid_duration("P1Y2MT")')
|
||||
raises( NotValid, ' valid_duration("P1Y2MT2.5H")')
|
||||
raises( NotValid, ' valid_duration("P1Y2MT2xH")')
|
||||
|
||||
|
||||
def test_unsigned_short():
|
||||
assert valid_unsigned_short("1234")
|
||||
|
||||
raises( NotValid, ' valid_unsigned_short("-1234")')
|
||||
raises( NotValid, ' valid_unsigned_short("1234567890")')
|
||||
|
||||
raises(NotValid, ' valid_unsigned_short("-1234")')
|
||||
raises(NotValid, ' valid_unsigned_short("1234567890")')
|
||||
|
||||
|
||||
def test_valid_non_negative_integer():
|
||||
assert valid_non_negative_integer("1234567890")
|
||||
|
||||
raises( NotValid, 'valid_non_negative_integer("-123")')
|
||||
raises( NotValid, 'valid_non_negative_integer("123.56")')
|
||||
|
||||
raises(NotValid, 'valid_non_negative_integer("-123")')
|
||||
raises(NotValid, 'valid_non_negative_integer("123.56")')
|
||||
assert valid_non_negative_integer("12345678901234567890")
|
||||
|
||||
|
||||
def test_valid_string():
|
||||
assert valid_string(u'example')
|
||||
|
||||
raises( NotValid, 'valid_string("02656c6c6f".decode("hex"))')
|
||||
|
||||
|
||||
raises(NotValid, 'valid_string("02656c6c6f".decode("hex"))')
|
||||
|
||||
|
||||
def test_valid_anyuri():
|
||||
assert valid_any_uri("urn:oasis:names:tc:SAML:2.0:attrname-format:uri")
|
||||
|
||||
|
||||
|
||||
def test_valid_instance():
|
||||
attr_statem = saml.AttributeStatement()
|
||||
text = ["value of test attribute",
|
||||
"value1 of test attribute",
|
||||
"value2 of test attribute",
|
||||
"value1 of test attribute2",
|
||||
"value2 of test attribute2",]
|
||||
"value2 of test attribute2", ]
|
||||
|
||||
attr_statem.attribute.append(saml.Attribute())
|
||||
attr_statem.attribute.append(saml.Attribute())
|
||||
@@ -80,9 +86,9 @@ def test_valid_instance():
|
||||
attr_statem.attribute[1].friendly_name = text[2]
|
||||
attr_statem.attribute[1].attribute_value.append(saml.AttributeValue())
|
||||
attr_statem.attribute[1].attribute_value[0].text = text[2]
|
||||
|
||||
|
||||
assert valid_instance(attr_statem)
|
||||
|
||||
|
||||
response = samlp.Response()
|
||||
response.id = "response id"
|
||||
response.in_response_to = "request id"
|
||||
@@ -94,8 +100,9 @@ def test_valid_instance():
|
||||
response.status = samlp.Status()
|
||||
response.assertion.append(saml.Assertion())
|
||||
|
||||
raises( MustValueError, 'valid_instance(response)')
|
||||
|
||||
raises(MustValueError, 'valid_instance(response)')
|
||||
|
||||
|
||||
def test_valid_anytype():
|
||||
assert valid_anytype("130.239.16.3")
|
||||
assert valid_anytype("textstring")
|
||||
@@ -103,5 +110,4 @@ def test_valid_anytype():
|
||||
assert valid_anytype("-1234")
|
||||
assert valid_anytype("P1Y2M3DT10H30M")
|
||||
assert valid_anytype("urn:oasis:names:tc:SAML:2.0:attrname-format:uri")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# coding=utf-8
|
||||
from saml2.authn_context import pword
|
||||
from saml2.mdie import to_dict
|
||||
from saml2 import md, assertion
|
||||
@@ -75,7 +76,6 @@ def test_filter_on_attributes_1():
|
||||
assert ava.keys() == ["serialNumber"]
|
||||
assert ava["serialNumber"] == ["12345"]
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
def test_lifetime_1():
|
||||
@@ -172,6 +172,8 @@ def test_ava_filter_2():
|
||||
"surName": "Jeter",
|
||||
"mail": "derek@example.com"}
|
||||
|
||||
# mail removed because it doesn't match the regular expression
|
||||
# So this should fail.
|
||||
raises(MissingValue, policy.filter, ava, 'urn:mace:umu.se:saml:roland:sp',
|
||||
None, [mail], [gn, sn])
|
||||
|
||||
@@ -183,6 +185,44 @@ def test_ava_filter_2():
|
||||
None, [gn, sn, mail])
|
||||
|
||||
|
||||
def test_ava_filter_dont_fail():
|
||||
conf = {
|
||||
"default": {
|
||||
"lifetime": {"minutes": 15},
|
||||
"attribute_restrictions": None, # means all I have
|
||||
},
|
||||
"urn:mace:umu.se:saml:roland:sp": {
|
||||
"lifetime": {"minutes": 5},
|
||||
"attribute_restrictions": {
|
||||
"givenName": None,
|
||||
"surName": None,
|
||||
"mail": [".*@.*\.umu\.se"],
|
||||
},
|
||||
"fail_on_missing_requested": False
|
||||
}}
|
||||
|
||||
policy = Policy(conf)
|
||||
|
||||
ava = {"givenName": "Derek",
|
||||
"surName": "Jeter",
|
||||
"mail": "derek@example.com"}
|
||||
|
||||
# mail removed because it doesn't match the regular expression
|
||||
# So it should fail if the 'fail_on_ ...' flag wasn't set
|
||||
_ava = policy.filter(ava,'urn:mace:umu.se:saml:roland:sp', None,
|
||||
[mail], [gn, sn])
|
||||
|
||||
assert _ava
|
||||
|
||||
ava = {"givenName": "Derek",
|
||||
"surName": "Jeter"}
|
||||
|
||||
# it wasn't there to begin with
|
||||
_ava = policy.filter(ava, 'urn:mace:umu.se:saml:roland:sp',
|
||||
None, [gn, sn, mail])
|
||||
|
||||
assert _ava
|
||||
|
||||
def test_filter_attribute_value_assertions_0(AVA):
|
||||
p = Policy({
|
||||
"default": {
|
||||
@@ -255,6 +295,7 @@ def test_filter_attribute_value_assertions_2(AVA):
|
||||
assert _eq(ava.keys(), ["givenName"])
|
||||
assert ava["givenName"] == ["Roland"]
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -290,7 +331,9 @@ def test_assertion_1(AVA):
|
||||
|
||||
def test_assertion_2():
|
||||
AVA = {'mail': u'roland.hedberg@adm.umu.se',
|
||||
'eduPersonTargetedID': 'http://lingon.ladok.umu.se:8090/idp!http://lingon.ladok.umu.se:8088/sp!95e9ae91dbe62d35198fbbd5e1fb0976',
|
||||
'eduPersonTargetedID': 'http://lingon.ladok.umu'
|
||||
'.se:8090/idp!http://lingon.ladok.umu'
|
||||
'.se:8088/sp!95e9ae91dbe62d35198fbbd5e1fb0976',
|
||||
'displayName': u'Roland Hedberg',
|
||||
'uid': 'http://roland.hedberg.myopenid.com/'}
|
||||
|
||||
@@ -453,6 +496,7 @@ def test_filter_values_req_opt_2():
|
||||
|
||||
raises(MissingValue, "filter_on_attributes(ava, r, o)")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -485,6 +529,7 @@ def test_filter_values_req_opt_4():
|
||||
assert _eq(ava.keys(), ['givenName', 'sn'])
|
||||
assert ava == {'givenName': ['Roland'], 'sn': ['Hedberg']}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -706,7 +751,7 @@ ACD = pword.AuthenticationContextDeclaration(authn_method=authn_method)
|
||||
|
||||
|
||||
def test_assertion_with_noop_attribute_conv():
|
||||
ava = {"urn:oid:2.5.4.4": "Roland", "urn:oid:2.5.4.42": "Hedberg" }
|
||||
ava = {"urn:oid:2.5.4.4": "Roland", "urn:oid:2.5.4.42": "Hedberg"}
|
||||
ast = Assertion(ava)
|
||||
policy = Policy({
|
||||
"default": {
|
||||
@@ -719,7 +764,7 @@ def test_assertion_with_noop_attribute_conv():
|
||||
issuer = Issuer(text="entityid", format=NAMEID_FORMAT_ENTITY)
|
||||
msg = ast.construct("sp_entity_id", "in_response_to", "consumer_url",
|
||||
name_id, [AttributeConverterNOOP(NAME_FORMAT_URI)],
|
||||
policy, issuer=issuer, authn_decl=ACD ,
|
||||
policy, issuer=issuer, authn_decl=ACD,
|
||||
authn_auth="authn_authn")
|
||||
|
||||
print msg
|
||||
@@ -767,7 +812,7 @@ def test_assertion_with_zero_attributes():
|
||||
issuer = Issuer(text="entityid", format=NAMEID_FORMAT_ENTITY)
|
||||
msg = ast.construct("sp_entity_id", "in_response_to", "consumer_url",
|
||||
name_id, [AttributeConverterNOOP(NAME_FORMAT_URI)],
|
||||
policy, issuer=issuer, authn_decl=ACD ,
|
||||
policy, issuer=issuer, authn_decl=ACD,
|
||||
authn_auth="authn_authn")
|
||||
|
||||
print msg
|
||||
@@ -797,4 +842,4 @@ def test_assertion_with_authn_instant():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_assertion_2()
|
||||
test_ava_filter_dont_fail()
|
||||
|
||||
@@ -368,4 +368,4 @@ def test_assertion_consumer_service():
|
||||
"location"] == 'https://www.zimride.com/Shibboleth.sso/SAML2/POST'
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_1()
|
||||
test_1()
|
||||
|
||||
@@ -121,5 +121,4 @@ class TestClass:
|
||||
(ava, inactive) = self.cache.get_identity(nid[2])
|
||||
assert inactive == ["bcde"]
|
||||
assert ava == {}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -172,4 +172,4 @@ class TestPopulationMemoryBased():
|
||||
info = self.population.get_info_from(nid, IDP_OTHER)
|
||||
assert info.keys() == ["not_on_or_after", "name_id", "ava"]
|
||||
assert info["name_id"] == nid
|
||||
assert info["ava"] == {"eduPersonEntitlement": "Anka"}
|
||||
assert info["ava"] == {"eduPersonEntitlement": "Anka"}
|
||||
|
||||
@@ -164,4 +164,4 @@ def test_idp_policy_filter():
|
||||
assert ava.keys() == ["eduPersonTargetedID"] # because no entity category
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_idp_policy_filter()
|
||||
test_idp_policy_filter()
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import base64
|
||||
from saml2.sigver import pre_encryption_part, make_temp
|
||||
from saml2.mdstore import MetadataStore
|
||||
from saml2.saml import assertion_from_string
|
||||
from saml2.saml import assertion_from_string, EncryptedAssertion
|
||||
from saml2.samlp import response_from_string
|
||||
|
||||
from saml2 import sigver
|
||||
from saml2 import sigver, extension_elements_to_elements
|
||||
from saml2 import class_name
|
||||
from saml2 import time_util
|
||||
from saml2 import saml, samlp
|
||||
@@ -25,9 +26,10 @@ PUB_KEY = full_path("test.pem")
|
||||
PRIV_KEY = full_path("test.key")
|
||||
|
||||
|
||||
def _eq(l1,l2):
|
||||
def _eq(l1, l2):
|
||||
return set(l1) == set(l2)
|
||||
|
||||
|
||||
CERT1 = """MIICsDCCAhmgAwIBAgIJAJrzqSSwmDY9MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMDkxMDA2MTk0OTQxWhcNMDkxMTA1MTk0OTQxWjBF
|
||||
@@ -60,7 +62,7 @@ wKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3K
|
||||
jjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w=="""
|
||||
|
||||
from pyasn1.codec.der import decoder
|
||||
|
||||
|
||||
|
||||
def test_cert_from_instance_1():
|
||||
xml_response = open(SIGNED).read()
|
||||
@@ -104,7 +106,6 @@ class FakeConfig():
|
||||
|
||||
|
||||
class TestSecurity():
|
||||
|
||||
def setup_class(self):
|
||||
# This would be one way to initialize the security context :
|
||||
#
|
||||
@@ -126,8 +127,8 @@ class TestSecurity():
|
||||
issue_instant="2009-10-30T13:20:28Z",
|
||||
signature=sigver.pre_signature_part("11111", self.sec.my_cert, 1),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("", "", "surName"): ("Foo", ""),
|
||||
("", "", "givenName"): ("Bar", ""),
|
||||
("", "", "surName"): ("Foo", ""),
|
||||
("", "", "givenName"): ("Bar", ""),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -144,7 +145,7 @@ class TestSecurity():
|
||||
|
||||
def test_non_verify_2(self):
|
||||
xml_response = open(FALSE_SIGNED).read()
|
||||
raises(sigver.SignatureError,self.sec.correctly_signed_response,
|
||||
raises(sigver.SignatureError, self.sec.correctly_signed_response,
|
||||
xml_response)
|
||||
|
||||
def test_sign_assertion(self):
|
||||
@@ -154,8 +155,8 @@ class TestSecurity():
|
||||
#print sign_ass
|
||||
sass = saml.assertion_from_string(sign_ass)
|
||||
#print sass
|
||||
assert _eq(sass.keyswv(), ['attribute_statement', 'issue_instant',
|
||||
'version', 'signature', 'id'])
|
||||
assert _eq(sass.keyswv(), ['attribute_statement', 'issue_instant',
|
||||
'version', 'signature', 'id'])
|
||||
assert sass.version == "2.0"
|
||||
assert sass.id == "11111"
|
||||
assert time_util.str_to_time(sass.issue_instant)
|
||||
@@ -227,19 +228,21 @@ class TestSecurity():
|
||||
|
||||
def test_sign_response(self):
|
||||
response = factory(samlp.Response,
|
||||
assertion=self._assertion,
|
||||
id="22222",
|
||||
signature=sigver.pre_signature_part("22222", self.sec.my_cert))
|
||||
assertion=self._assertion,
|
||||
id="22222",
|
||||
signature=sigver.pre_signature_part("22222",
|
||||
self.sec
|
||||
.my_cert))
|
||||
|
||||
to_sign = [(class_name(self._assertion), self._assertion.id),
|
||||
(class_name(response), response.id)]
|
||||
(class_name(response), response.id)]
|
||||
s_response = sigver.signed_instance_factory(response, self.sec, to_sign)
|
||||
|
||||
|
||||
assert s_response is not None
|
||||
print s_response
|
||||
response = response_from_string(s_response)
|
||||
sass = response.assertion[0]
|
||||
|
||||
|
||||
print sass
|
||||
assert _eq(sass.keyswv(), ['attribute_statement', 'issue_instant',
|
||||
'version', 'signature', 'id'])
|
||||
@@ -252,23 +255,27 @@ class TestSecurity():
|
||||
assert item.id == "22222"
|
||||
|
||||
def test_sign_response_2(self):
|
||||
assertion2 = factory( saml.Assertion,
|
||||
version= "2.0",
|
||||
id= "11122",
|
||||
issue_instant= "2009-10-30T13:20:28Z",
|
||||
signature= sigver.pre_signature_part("11122", self.sec.my_cert),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("","","surName"): ("Fox",""),
|
||||
("","","givenName") :("Bear",""),
|
||||
})
|
||||
)
|
||||
assertion2 = factory(saml.Assertion,
|
||||
version="2.0",
|
||||
id="11122",
|
||||
issue_instant="2009-10-30T13:20:28Z",
|
||||
signature=sigver.pre_signature_part("11122",
|
||||
self.sec
|
||||
.my_cert),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("", "", "surName"): ("Fox", ""),
|
||||
("", "", "givenName"): ("Bear", ""),
|
||||
})
|
||||
)
|
||||
response = factory(samlp.Response,
|
||||
assertion=assertion2,
|
||||
id="22233",
|
||||
signature=sigver.pre_signature_part("22233", self.sec.my_cert))
|
||||
assertion=assertion2,
|
||||
id="22233",
|
||||
signature=sigver.pre_signature_part("22233",
|
||||
self.sec
|
||||
.my_cert))
|
||||
|
||||
to_sign = [(class_name(assertion2), assertion2.id),
|
||||
(class_name(response), response.id)]
|
||||
(class_name(response), response.id)]
|
||||
|
||||
s_response = sigver.signed_instance_factory(response, self.sec, to_sign)
|
||||
|
||||
@@ -277,7 +284,7 @@ class TestSecurity():
|
||||
|
||||
sass = response2.assertion[0]
|
||||
assert _eq(sass.keyswv(), ['attribute_statement', 'issue_instant',
|
||||
'version', 'signature', 'id'])
|
||||
'version', 'signature', 'id'])
|
||||
assert sass.version == "2.0"
|
||||
assert sass.id == "11122"
|
||||
|
||||
@@ -285,105 +292,115 @@ class TestSecurity():
|
||||
s_response)
|
||||
|
||||
assert isinstance(item, samlp.Response)
|
||||
|
||||
def test_sign_verify(self):
|
||||
|
||||
def test_sign_verify(self):
|
||||
response = factory(samlp.Response,
|
||||
assertion=self._assertion,
|
||||
id="22233",
|
||||
signature=sigver.pre_signature_part("22233", self.sec.my_cert))
|
||||
assertion=self._assertion,
|
||||
id="22233",
|
||||
signature=sigver.pre_signature_part("22233",
|
||||
self.sec
|
||||
.my_cert))
|
||||
|
||||
to_sign = [(class_name(self._assertion), self._assertion.id),
|
||||
(class_name(response), response.id)]
|
||||
(class_name(response), response.id)]
|
||||
|
||||
s_response = sigver.signed_instance_factory(response, self.sec, to_sign)
|
||||
|
||||
print s_response
|
||||
res = self.sec.verify_signature("%s" % s_response,
|
||||
node_name=class_name(samlp.Response()))
|
||||
res = self.sec.verify_signature("%s" % s_response,
|
||||
node_name=class_name(samlp.Response()))
|
||||
|
||||
print res
|
||||
print res
|
||||
assert res
|
||||
|
||||
def test_sign_verify_with_cert_from_instance(self):
|
||||
response = factory(samlp.Response,
|
||||
assertion=self._assertion,
|
||||
id="22222",
|
||||
signature=sigver.pre_signature_part("22222", self.sec.my_cert))
|
||||
assertion=self._assertion,
|
||||
id="22222",
|
||||
signature=sigver.pre_signature_part("22222",
|
||||
self.sec
|
||||
.my_cert))
|
||||
|
||||
to_sign = [(class_name(self._assertion), self._assertion.id),
|
||||
(class_name(response), response.id)]
|
||||
(class_name(response), response.id)]
|
||||
|
||||
s_response = sigver.signed_instance_factory(response, self.sec, to_sign)
|
||||
|
||||
response2 = response_from_string(s_response)
|
||||
|
||||
ci = "".join(sigver.cert_from_instance(response2)[0].split())
|
||||
|
||||
|
||||
assert ci == self.sec.my_cert
|
||||
|
||||
res = self.sec.verify_signature("%s" % s_response,
|
||||
node_name=class_name(samlp.Response()))
|
||||
|
||||
res = self.sec.verify_signature("%s" % s_response,
|
||||
node_name=class_name(samlp.Response()))
|
||||
|
||||
assert res
|
||||
|
||||
res = self.sec._check_signature(s_response, response2,
|
||||
class_name(response2), s_response)
|
||||
assert res == response2
|
||||
|
||||
|
||||
def test_sign_verify_assertion_with_cert_from_instance(self):
|
||||
assertion = factory( saml.Assertion,
|
||||
version= "2.0",
|
||||
id= "11100",
|
||||
issue_instant= "2009-10-30T13:20:28Z",
|
||||
signature= sigver.pre_signature_part("11100", self.sec.my_cert),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("","","surName"): ("Fox",""),
|
||||
("","","givenName") :("Bear",""),
|
||||
})
|
||||
)
|
||||
assertion = factory(saml.Assertion,
|
||||
version="2.0",
|
||||
id="11100",
|
||||
issue_instant="2009-10-30T13:20:28Z",
|
||||
signature=sigver.pre_signature_part("11100",
|
||||
self.sec
|
||||
.my_cert),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("", "", "surName"): ("Fox", ""),
|
||||
("", "", "givenName"): ("Bear", ""),
|
||||
})
|
||||
)
|
||||
|
||||
to_sign = [(class_name(assertion), assertion.id)]
|
||||
s_assertion = sigver.signed_instance_factory(assertion, self.sec, to_sign)
|
||||
s_assertion = sigver.signed_instance_factory(assertion, self.sec,
|
||||
to_sign)
|
||||
print s_assertion
|
||||
ass = assertion_from_string(s_assertion)
|
||||
ci = "".join(sigver.cert_from_instance(ass)[0].split())
|
||||
assert ci == self.sec.my_cert
|
||||
|
||||
|
||||
res = self.sec.verify_signature("%s" % s_assertion,
|
||||
node_name=class_name(ass))
|
||||
assert res
|
||||
|
||||
assert res
|
||||
|
||||
res = self.sec._check_signature(s_assertion, ass, class_name(ass))
|
||||
|
||||
|
||||
assert res
|
||||
|
||||
def test_exception_sign_verify_with_cert_from_instance(self):
|
||||
assertion = factory( saml.Assertion,
|
||||
version= "2.0",
|
||||
id= "11100",
|
||||
issue_instant= "2009-10-30T13:20:28Z",
|
||||
#signature= sigver.pre_signature_part("11100", self.sec.my_cert),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("","","surName"): ("Foo",""),
|
||||
("","","givenName") :("Bar",""),
|
||||
})
|
||||
)
|
||||
assertion = factory(saml.Assertion,
|
||||
version="2.0",
|
||||
id="11100",
|
||||
issue_instant="2009-10-30T13:20:28Z",
|
||||
#signature= sigver.pre_signature_part("11100",
|
||||
# self.sec.my_cert),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("", "", "surName"): ("Foo", ""),
|
||||
("", "", "givenName"): ("Bar", ""),
|
||||
})
|
||||
)
|
||||
|
||||
response = factory(samlp.Response,
|
||||
assertion=assertion,
|
||||
id="22222",
|
||||
signature=sigver.pre_signature_part("22222", self.sec.my_cert))
|
||||
assertion=assertion,
|
||||
id="22222",
|
||||
signature=sigver.pre_signature_part("22222",
|
||||
self.sec
|
||||
.my_cert))
|
||||
|
||||
to_sign = [(class_name(response), response.id)]
|
||||
|
||||
|
||||
s_response = sigver.signed_instance_factory(response, self.sec, to_sign)
|
||||
|
||||
response2 = response_from_string(s_response)
|
||||
# Change something that should make everything fail
|
||||
response2.id = "23456"
|
||||
raises(sigver.SignatureError, self.sec._check_signature,
|
||||
s_response, response2, class_name(response2))
|
||||
s_response, response2, class_name(response2))
|
||||
|
||||
|
||||
|
||||
class TestSecurityMetadata():
|
||||
@@ -397,36 +414,71 @@ class TestSecurityMetadata():
|
||||
conf.only_use_keys_in_metadata = False
|
||||
self.sec = sigver.security_context(conf)
|
||||
|
||||
self._assertion = factory( saml.Assertion,
|
||||
version="2.0",
|
||||
id="11111",
|
||||
issue_instant="2009-10-30T13:20:28Z",
|
||||
signature=sigver.pre_signature_part("11111", self.sec.my_cert, 1),
|
||||
attribute_statement=do_attribute_statement({
|
||||
("","","surName"): ("Foo",""),
|
||||
("","","givenName") :("Bar",""),
|
||||
})
|
||||
assertion = factory(
|
||||
saml.Assertion, version="2.0", id="11111",
|
||||
issue_instant="2009-10-30T13:20:28Z",
|
||||
signature=sigver.pre_signature_part("11111", self.sec.my_cert, 1),
|
||||
attribute_statement=do_attribute_statement(
|
||||
{("", "", "surName"): ("Foo", ""),
|
||||
("", "", "givenName"): ("Bar", ""), })
|
||||
)
|
||||
|
||||
def test_sign_assertion(self):
|
||||
ass = self._assertion
|
||||
print ass
|
||||
sign_ass = self.sec.sign_assertion("%s" % ass, node_id=ass.id)
|
||||
#print sign_ass
|
||||
sass = saml.assertion_from_string(sign_ass)
|
||||
#print sass
|
||||
assert _eq(sass.keyswv(), ['attribute_statement', 'issue_instant',
|
||||
'version', 'signature', 'id'])
|
||||
assert sass.version == "2.0"
|
||||
assert sass.id == "11111"
|
||||
assert time_util.str_to_time(sass.issue_instant)
|
||||
|
||||
print "Crypto version : %s" % (self.sec.crypto.version())
|
||||
def test_xbox():
|
||||
conf = config.SPConfig()
|
||||
conf.load_file("server_conf")
|
||||
md = MetadataStore([saml, samlp], None, conf)
|
||||
md.load("local", full_path("idp_example.xml"))
|
||||
|
||||
item = self.sec.check_signature(sass, class_name(sass), sign_ass)
|
||||
conf.metadata = md
|
||||
conf.only_use_keys_in_metadata = False
|
||||
sec = sigver.security_context(conf)
|
||||
|
||||
assertion = factory(
|
||||
saml.Assertion, version="2.0", id="11111",
|
||||
issue_instant="2009-10-30T13:20:28Z",
|
||||
signature=sigver.pre_signature_part("11111", sec.my_cert, 1),
|
||||
attribute_statement=do_attribute_statement(
|
||||
{("", "", "surName"): ("Foo", ""),
|
||||
("", "", "givenName"): ("Bar", ""), })
|
||||
)
|
||||
|
||||
sigass = sec.sign_statement(assertion, class_name(assertion),
|
||||
key_file="pki/mykey.pem", node_id=assertion.id)
|
||||
|
||||
_ass0 = saml.assertion_from_string(sigass)
|
||||
|
||||
encrypted_assertion = EncryptedAssertion()
|
||||
encrypted_assertion.add_extension_element(_ass0)
|
||||
|
||||
_, pre = make_temp("%s" % pre_encryption_part(), decode=False)
|
||||
enctext = sec.crypto.encrypt(
|
||||
"%s" % encrypted_assertion, conf.cert_file, pre, "des-192",
|
||||
'/*[local-name()="EncryptedAssertion"]/*[local-name()="Assertion"]')
|
||||
|
||||
|
||||
decr_text = sec.decrypt(enctext)
|
||||
_seass = saml.encrypted_assertion_from_string(decr_text)
|
||||
assertions = []
|
||||
assers = extension_elements_to_elements(_seass.extension_elements,
|
||||
[saml, samlp])
|
||||
|
||||
sign_cert_file = "pki/mycert.pem"
|
||||
|
||||
for ass in assers:
|
||||
_ass = "%s" % ass
|
||||
#_ass = _ass.replace('xsi:nil="true" ', '')
|
||||
#assert sigass == _ass
|
||||
_txt = sec.verify_signature(_ass, sign_cert_file,
|
||||
node_name=class_name(assertion))
|
||||
if _txt:
|
||||
assertions.append(ass)
|
||||
|
||||
print assertions
|
||||
|
||||
assert isinstance(item, saml.Assertion)
|
||||
|
||||
if __name__ == "__main__":
|
||||
t = TestSecurity()
|
||||
t.setup_class()
|
||||
#t = TestSecurity()
|
||||
#t.setup_class()
|
||||
#t.test_sign_then_encrypt_assertion()
|
||||
test_xbox()
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from saml2 import saml
|
||||
from saml2 import config
|
||||
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
|
||||
|
||||
@@ -9,7 +8,8 @@ from saml2.server import Server
|
||||
from saml2.response import response_factory
|
||||
from saml2.response import StatusResponse
|
||||
from saml2.response import AuthnResponse
|
||||
from saml2.sigver import security_context, MissingKey
|
||||
from saml2.sigver import security_context
|
||||
from saml2.sigver import MissingKey
|
||||
|
||||
from pytest import raises
|
||||
|
||||
@@ -26,7 +26,6 @@ IDENTITY = {"eduPersonAffiliation": ["staff", "member"],
|
||||
"mail": ["foo@gmail.com"],
|
||||
"title": ["shortstop"]}
|
||||
|
||||
|
||||
AUTHN = {
|
||||
"class_ref": INTERNETPROTOCOLPASSWORD,
|
||||
"authn_auth": "http://www.example.com/login"
|
||||
@@ -39,29 +38,28 @@ class TestResponse:
|
||||
name_id = server.ident.transient_nameid(
|
||||
"urn:mace:example.com:saml:roland:sp", "id12")
|
||||
|
||||
self._resp_ = server.create_authn_response(IDENTITY,
|
||||
"id12", # in_response_to
|
||||
"http://lingon.catalogix.se:8087/",
|
||||
|
||||
# consumer_url
|
||||
"urn:mace:example"
|
||||
".com:saml:roland:sp",
|
||||
# sp_entity_id
|
||||
name_id=name_id)
|
||||
self._resp_ = server.create_authn_response(
|
||||
IDENTITY,
|
||||
"id12", # in_response_to
|
||||
"http://lingon.catalogix.se:8087/",
|
||||
# consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp",
|
||||
# sp_entity_id
|
||||
name_id=name_id)
|
||||
|
||||
self._sign_resp_ = server.create_authn_response(
|
||||
IDENTITY,
|
||||
"id12", # in_response_to
|
||||
"http://lingon.catalogix.se:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
"http://lingon.catalogix.se:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
name_id=name_id,
|
||||
sign_assertion=True)
|
||||
|
||||
self._resp_authn = server.create_authn_response(
|
||||
IDENTITY,
|
||||
"id12", # in_response_to
|
||||
"http://lingon.catalogix.se:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
"id12", # in_response_to
|
||||
"http://lingon.catalogix.se:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
name_id=name_id,
|
||||
authn=AUTHN)
|
||||
|
||||
@@ -72,7 +70,8 @@ class TestResponse:
|
||||
def test_1(self):
|
||||
xml_response = ("%s" % (self._resp_,))
|
||||
resp = response_factory(xml_response, self.conf,
|
||||
return_addrs=["http://lingon.catalogix.se:8087/"],
|
||||
return_addrs=[
|
||||
"http://lingon.catalogix.se:8087/"],
|
||||
outstanding_queries={
|
||||
"id12": "http://localhost:8088/sso"},
|
||||
timeslack=10000, decode=False)
|
||||
@@ -83,7 +82,8 @@ class TestResponse:
|
||||
def test_2(self):
|
||||
xml_response = self._sign_resp_
|
||||
resp = response_factory(xml_response, self.conf,
|
||||
return_addrs=["http://lingon.catalogix.se:8087/"],
|
||||
return_addrs=[
|
||||
"http://lingon.catalogix.se:8087/"],
|
||||
outstanding_queries={
|
||||
"id12": "http://localhost:8088/sso"},
|
||||
timeslack=10000, decode=False)
|
||||
@@ -92,16 +92,7 @@ class TestResponse:
|
||||
assert isinstance(resp, AuthnResponse)
|
||||
|
||||
|
||||
def test_only_use_keys_in_metadata(self):
|
||||
conf = config.SPConfig()
|
||||
conf.load_file("sp_2_conf")
|
||||
|
||||
sc = security_context(conf)
|
||||
# should fail
|
||||
raises(MissingKey,
|
||||
'sc.correctly_signed_response("%s" % self._sign_resp_)')
|
||||
|
||||
if __name__ == "__main__":
|
||||
t = TestResponse()
|
||||
t.setup_class()
|
||||
t.test_1()
|
||||
t.test_1()
|
||||
|
||||
@@ -4,6 +4,7 @@ from saml2.sigver import pre_encryption_part, ASSERT_XPATH, EncryptError
|
||||
from saml2.sigver import CryptoBackendXmlSec1
|
||||
from saml2.sigver import pre_encrypt_assertion
|
||||
from pathutils import xmlsec_path
|
||||
from pathutils import full_path
|
||||
|
||||
__author__ = 'roland'
|
||||
|
||||
@@ -65,7 +66,7 @@ def test_enc1():
|
||||
# data_file.close()
|
||||
|
||||
key_type = "des-192"
|
||||
com_list = [xmlsec_path, "encrypt", "--pubkey-cert-pem", "pubkey.pem",
|
||||
com_list = [xmlsec_path, "encrypt", "--pubkey-cert-pem", full_path("pubkey.pem"),
|
||||
"--session-key", key_type, "--xml-data", data,
|
||||
"--node-xpath", ASSERT_XPATH]
|
||||
|
||||
@@ -89,11 +90,11 @@ def test_enc2():
|
||||
IDENTITY, "id12", "http://lingon.catalogix.se:8087/",
|
||||
"urn:mace:example.com:saml:roland:sp", name_id=name_id)
|
||||
|
||||
enc_resp = crypto.encrypt_assertion(resp_, "pubkey.pem",
|
||||
enc_resp = crypto.encrypt_assertion(resp_, full_path("pubkey.pem"),
|
||||
pre_encryption_part())
|
||||
|
||||
print enc_resp
|
||||
assert enc_resp
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_enc1()
|
||||
test_enc1()
|
||||
|
||||
@@ -2,18 +2,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import base64
|
||||
from urlparse import parse_qs
|
||||
from saml2.sigver import pre_encryption_part
|
||||
from saml2.assertion import Policy
|
||||
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
|
||||
from saml2.saml import NameID, NAMEID_FORMAT_TRANSIENT
|
||||
from saml2.samlp import response_from_string
|
||||
|
||||
from saml2.server import Server
|
||||
from saml2 import samlp, saml, client, config
|
||||
from saml2 import samlp
|
||||
from saml2 import saml
|
||||
from saml2 import client
|
||||
from saml2 import config
|
||||
from saml2 import class_name
|
||||
from saml2 import extension_elements_to_elements
|
||||
from saml2 import s_utils
|
||||
from saml2 import sigver
|
||||
from saml2 import time_util
|
||||
from saml2.s_utils import OtherError
|
||||
from saml2.s_utils import do_attribute_statement, factory
|
||||
from saml2.s_utils import do_attribute_statement
|
||||
from saml2.s_utils import factory
|
||||
from saml2.soap import make_soap_enveloped_saml_thingy
|
||||
from saml2 import BINDING_HTTP_POST
|
||||
from saml2 import BINDING_HTTP_REDIRECT
|
||||
@@ -182,7 +189,8 @@ class TestServer1():
|
||||
name_id_policy = resp_args["name_id_policy"]
|
||||
assert _eq(name_id_policy.keyswv(), ["format", "allow_create"])
|
||||
assert name_id_policy.format == saml.NAMEID_FORMAT_TRANSIENT
|
||||
assert resp_args["sp_entity_id"] == "urn:mace:example.com:saml:roland:sp"
|
||||
assert resp_args[
|
||||
"sp_entity_id"] == "urn:mace:example.com:saml:roland:sp"
|
||||
|
||||
def test_sso_response_with_identity(self):
|
||||
name_id = self.server.ident.transient_nameid(
|
||||
@@ -195,8 +203,8 @@ class TestServer1():
|
||||
"mail": "derek.jeter@nyy.mlb.com",
|
||||
"title": "The man"
|
||||
},
|
||||
"id12", # in_response_to
|
||||
"http://localhost:8087/", # destination
|
||||
"id12", # in_response_to
|
||||
"http://localhost:8087/", # destination
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
name_id=name_id,
|
||||
authn=AUTHN
|
||||
@@ -227,7 +235,8 @@ class TestServer1():
|
||||
break
|
||||
assert len(attr.attribute_value) == 1
|
||||
assert attr.name == "urn:oid:1.3.6.1.4.1.5923.1.1.1.7"
|
||||
assert attr.name_format == "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
assert attr.name_format == "urn:oasis:names:tc:SAML:2" \
|
||||
".0:attrname-format:uri"
|
||||
value = attr.attribute_value[0]
|
||||
assert value.text.strip() == "Short stop"
|
||||
assert value.get_type() == "xs:string"
|
||||
@@ -242,13 +251,13 @@ class TestServer1():
|
||||
def test_sso_response_without_identity(self):
|
||||
resp = self.server.create_authn_response(
|
||||
{},
|
||||
"id12", # in_response_to
|
||||
"http://localhost:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
userid="USER1",
|
||||
authn=AUTHN,
|
||||
release_policy=Policy(),
|
||||
best_effort=True
|
||||
"id12", # in_response_to
|
||||
"http://localhost:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
userid="USER1",
|
||||
authn=AUTHN,
|
||||
release_policy=Policy(),
|
||||
best_effort=True
|
||||
)
|
||||
|
||||
print resp.keyswv()
|
||||
@@ -268,12 +277,12 @@ class TestServer1():
|
||||
|
||||
resp = self.server.create_authn_response(
|
||||
{},
|
||||
"id12", # in_response_to
|
||||
"http://localhost:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
userid="USER1",
|
||||
authn=_authn,
|
||||
best_effort=True
|
||||
"id12", # in_response_to
|
||||
"http://localhost:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
userid="USER1",
|
||||
authn=_authn,
|
||||
best_effort=True
|
||||
)
|
||||
|
||||
print resp.keyswv()
|
||||
@@ -297,11 +306,11 @@ class TestServer1():
|
||||
print resp.status
|
||||
assert resp.status.status_code.value == samlp.STATUS_RESPONDER
|
||||
assert resp.status.status_code.status_code.value == \
|
||||
samlp.STATUS_REQUEST_UNSUPPORTED
|
||||
samlp.STATUS_REQUEST_UNSUPPORTED
|
||||
assert resp.status.status_message.text == \
|
||||
"eduPersonAffiliation missing"
|
||||
"eduPersonAffiliation missing"
|
||||
assert resp.issuer.text == "urn:mace:example.com:saml:roland:idp"
|
||||
assert not resp.assertion
|
||||
assert not resp.assertion
|
||||
|
||||
def test_authn_response_0(self):
|
||||
self.server = Server("idp_conf")
|
||||
@@ -346,8 +355,8 @@ class TestServer1():
|
||||
|
||||
signed_resp = self.server.create_authn_response(
|
||||
ava,
|
||||
"id12", # in_response_to
|
||||
"http://lingon.catalogix.se:8087/", # consumer_url
|
||||
"id12", # in_response_to
|
||||
"http://lingon.catalogix.se:8087/", # consumer_url
|
||||
"urn:mace:example.com:saml:roland:sp", # sp_entity_id
|
||||
name_id=name_id,
|
||||
sign_assertion=True
|
||||
@@ -480,7 +489,6 @@ def _logout_request(conf_file):
|
||||
|
||||
|
||||
class TestServerLogout():
|
||||
|
||||
def test_1(self):
|
||||
server = Server("idp_slo_redirect_conf")
|
||||
req_id, request = _logout_request("sp_slo_redirect_conf")
|
||||
@@ -502,4 +510,3 @@ class TestServerLogout():
|
||||
if __name__ == "__main__":
|
||||
ts = TestServer1()
|
||||
ts.setup_class()
|
||||
ts.test_sso_response_specific_instant()
|
||||
@@ -4,21 +4,32 @@
|
||||
import base64
|
||||
import urllib
|
||||
import urlparse
|
||||
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
|
||||
from saml2.response import LogoutResponse
|
||||
from saml2 import BINDING_HTTP_POST
|
||||
from saml2 import BINDING_HTTP_REDIRECT
|
||||
from saml2 import config
|
||||
from saml2 import class_name
|
||||
from saml2 import extension_elements_to_elements
|
||||
from saml2 import saml
|
||||
from saml2 import samlp
|
||||
from saml2 import sigver
|
||||
from saml2 import s_utils
|
||||
from saml2.assertion import Assertion
|
||||
|
||||
from saml2.authn_context import INTERNETPROTOCOLPASSWORD
|
||||
from saml2.client import Saml2Client
|
||||
from saml2 import samlp, BINDING_HTTP_POST, BINDING_HTTP_REDIRECT
|
||||
from saml2 import saml, config, class_name
|
||||
from saml2.config import SPConfig
|
||||
from saml2.response import LogoutResponse
|
||||
from saml2.saml import NAMEID_FORMAT_PERSISTENT
|
||||
from saml2.saml import NAMEID_FORMAT_TRANSIENT
|
||||
from saml2.saml import NameID
|
||||
from saml2.server import Server
|
||||
from saml2.sigver import pre_encryption_part
|
||||
from saml2.s_utils import do_attribute_statement
|
||||
from saml2.s_utils import factory
|
||||
from saml2.time_util import in_a_while
|
||||
|
||||
from py.test import raises
|
||||
from fakeIDP import FakeIDP, unpack_form
|
||||
from fakeIDP import FakeIDP
|
||||
from fakeIDP import unpack_form
|
||||
|
||||
|
||||
AUTHN = {
|
||||
@@ -341,8 +352,123 @@ class TestClient:
|
||||
print my_name
|
||||
assert my_name == "urn:mace:example.com:saml:roland:sp"
|
||||
|
||||
# Below can only be done with dummy Server
|
||||
def test_sign_then_encrypt_assertion(self):
|
||||
# Begin with the IdPs side
|
||||
_sec = self.server.sec
|
||||
|
||||
assertion = s_utils.assertion_factory(
|
||||
subject=factory(saml.Subject, text="_aaa",
|
||||
name_id=factory(
|
||||
saml.NameID,
|
||||
format=saml.NAMEID_FORMAT_TRANSIENT)),
|
||||
attribute_statement=do_attribute_statement(
|
||||
{
|
||||
("", "", "surName"): ("Jeter", ""),
|
||||
("", "", "givenName"): ("Derek", ""),
|
||||
}
|
||||
),
|
||||
issuer=self.server._issuer(),
|
||||
)
|
||||
|
||||
assertion.signature = sigver.pre_signature_part(
|
||||
assertion.id, _sec.my_cert, 1)
|
||||
|
||||
sigass = _sec.sign_statement(assertion, class_name(assertion),
|
||||
key_file="pki/mykey.pem",
|
||||
node_id=assertion.id)
|
||||
# Create an Assertion instance from the signed assertion
|
||||
_ass = saml.assertion_from_string(sigass)
|
||||
|
||||
response = sigver.response_factory(
|
||||
in_response_to="_012345",
|
||||
destination="https:#www.example.com",
|
||||
status=s_utils.success_status_factory(),
|
||||
issuer=self.server._issuer(),
|
||||
assertion=_ass
|
||||
)
|
||||
|
||||
enctext = _sec.crypto.encrypt_assertion(response, _sec.cert_file,
|
||||
pre_encryption_part())
|
||||
|
||||
seresp = samlp.response_from_string(enctext)
|
||||
|
||||
# Now over to the client side
|
||||
_csec = self.client.sec
|
||||
if seresp.encrypted_assertion:
|
||||
decr_text = _csec.decrypt(enctext)
|
||||
seresp = samlp.response_from_string(decr_text)
|
||||
resp_ass = []
|
||||
|
||||
sign_cert_file = "pki/mycert.pem"
|
||||
for enc_ass in seresp.encrypted_assertion:
|
||||
assers = extension_elements_to_elements(
|
||||
enc_ass.extension_elements, [saml, samlp])
|
||||
for ass in assers:
|
||||
if ass.signature:
|
||||
if not _csec.verify_signature("%s" % ass,
|
||||
sign_cert_file,
|
||||
node_name=class_name(ass)):
|
||||
continue
|
||||
resp_ass.append(ass)
|
||||
|
||||
seresp.assertion = resp_ass
|
||||
seresp.encrypted_assertion = None
|
||||
#print _sresp
|
||||
|
||||
assert seresp.assertion
|
||||
|
||||
def test_sign_then_encrypt_assertion2(self):
|
||||
# Begin with the IdPs side
|
||||
_sec = self.server.sec
|
||||
|
||||
nameid_policy = samlp.NameIDPolicy(allow_create="false",
|
||||
format=saml.NAMEID_FORMAT_PERSISTENT)
|
||||
|
||||
asser = Assertion({"givenName": "Derek", "surName": "Jeter"})
|
||||
assertion = asser.construct(
|
||||
self.client.config.entityid, "_012345",
|
||||
"http://lingon.catalogix.se:8087/",
|
||||
factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT),
|
||||
policy=self.server.config.getattr("policy", "idp"),
|
||||
issuer=self.server._issuer(),
|
||||
attrconvs=self.server.config.attribute_converters,
|
||||
authn_class=INTERNETPROTOCOLPASSWORD,
|
||||
authn_auth="http://www.example.com/login")
|
||||
|
||||
assertion.signature = sigver.pre_signature_part(
|
||||
assertion.id, _sec.my_cert, 1)
|
||||
|
||||
sigass = _sec.sign_statement(assertion, class_name(assertion),
|
||||
#key_file="pki/mykey.pem",
|
||||
key_file="test.key",
|
||||
node_id=assertion.id)
|
||||
# Create an Assertion instance from the signed assertion
|
||||
_ass = saml.assertion_from_string(sigass)
|
||||
|
||||
response = sigver.response_factory(
|
||||
in_response_to="_012345",
|
||||
destination="https://www.example.com",
|
||||
status=s_utils.success_status_factory(),
|
||||
issuer=self.server._issuer(),
|
||||
assertion=_ass
|
||||
)
|
||||
|
||||
enctext = _sec.crypto.encrypt_assertion(response, _sec.cert_file,
|
||||
pre_encryption_part())
|
||||
|
||||
#seresp = samlp.response_from_string(enctext)
|
||||
|
||||
resp_str = base64.encodestring(enctext)
|
||||
# Now over to the client side
|
||||
resp = self.client.parse_authn_request_response(
|
||||
resp_str, BINDING_HTTP_POST,
|
||||
{"_012345": "http://foo.example.com/service"})
|
||||
|
||||
#assert resp.encrypted_assertion == []
|
||||
assert resp.assertion
|
||||
assert resp.ava == {'givenName': ['Derek'], 'sn': ['Jeter']}
|
||||
|
||||
# Below can only be done with dummy Server
|
||||
IDP = "urn:mace:example.com:saml:roland:idp"
|
||||
|
||||
|
||||
@@ -448,4 +574,4 @@ class TestClientWithDummy():
|
||||
if __name__ == "__main__":
|
||||
tc = TestClient()
|
||||
tc.setup_class()
|
||||
tc.test_sign_auth_request_0()
|
||||
tc.test_sign_then_encrypt_assertion2()
|
||||
|
||||
@@ -73,6 +73,7 @@ class TestSP():
|
||||
'sn': ['Jeter'],
|
||||
'title': ['The man']}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_sp = TestSP()
|
||||
_sp.setup_class()
|
||||
|
||||
@@ -139,4 +139,4 @@ def test_flow():
|
||||
assert final.response.id == p_res.id
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_flow()
|
||||
test_flow()
|
||||
|
||||
@@ -70,4 +70,4 @@ def test_request_response():
|
||||
r_name_id = _resp.response.name_id
|
||||
|
||||
assert r_name_id.format == NAMEID_FORMAT_PERSISTENT
|
||||
assert r_name_id.text == "foobar"
|
||||
assert r_name_id.text == "foobar"
|
||||
|
||||
@@ -6,6 +6,7 @@ from saml2.server import Server
|
||||
|
||||
__author__ = 'rolandh'
|
||||
|
||||
|
||||
def test_basic():
|
||||
sp = Saml2Client(config_file="servera_conf")
|
||||
idp = Server(config_file="idp_all_conf")
|
||||
@@ -18,7 +19,7 @@ def test_basic():
|
||||
newid = NewID(text="Barfoo")
|
||||
|
||||
mid, mreq = sp.create_manage_name_id_request(destination, name_id=nameid,
|
||||
new_id=newid)
|
||||
new_id=newid)
|
||||
|
||||
print mreq
|
||||
rargs = sp.apply_binding(binding, "%s" % mreq, destination, "")
|
||||
@@ -31,6 +32,7 @@ def test_basic():
|
||||
|
||||
assert mid == _req.message.id
|
||||
|
||||
|
||||
def test_flow():
|
||||
sp = Saml2Client(config_file="servera_conf")
|
||||
idp = Server(config_file="idp_all_conf")
|
||||
@@ -42,7 +44,7 @@ def test_flow():
|
||||
newid = NewID(text="Barfoo")
|
||||
|
||||
mid, midq = sp.create_manage_name_id_request(destination, name_id=nameid,
|
||||
new_id=newid)
|
||||
new_id=newid)
|
||||
|
||||
print midq
|
||||
rargs = sp.apply_binding(binding, "%s" % midq, destination, "")
|
||||
@@ -67,8 +69,13 @@ def test_flow():
|
||||
|
||||
# ---------- @SP ---------------
|
||||
|
||||
_response = sp.parse_manage_name_id_request_response(respargs["data"], binding)
|
||||
_response = sp.parse_manage_name_id_request_response(respargs["data"],
|
||||
binding)
|
||||
|
||||
print _response.response
|
||||
|
||||
assert _response.response.id == mnir.id
|
||||
assert _response.response.id == mnir.id
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_flow()
|
||||
@@ -108,4 +108,4 @@ def test_basic_flow():
|
||||
final = sp.parse_assertion_id_request_response(xmlstr, binding)
|
||||
|
||||
print final.response
|
||||
assert isinstance(final.response, Assertion)
|
||||
assert isinstance(final.response, Assertion)
|
||||
|
||||
@@ -70,4 +70,4 @@ def test_construct_deconstruct_response():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_construct_deconstruct_response()
|
||||
test_construct_deconstruct_response()
|
||||
|
||||
@@ -38,4 +38,4 @@ def test_eptid_shelve():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_eptid_shelve()
|
||||
test_eptid_shelve()
|
||||
|
||||
@@ -149,4 +149,4 @@ def test_authn_3():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_authn_3()
|
||||
test_authn_3()
|
||||
|
||||
@@ -8,7 +8,6 @@ from saml2.cert import OpenSSLWrapper
|
||||
|
||||
|
||||
class TestGenerateCertificates(unittest.TestCase):
|
||||
|
||||
def test_validate_with_root_cert(self):
|
||||
|
||||
cert_info_ca = {
|
||||
@@ -33,23 +32,35 @@ class TestGenerateCertificates(unittest.TestCase):
|
||||
|
||||
ca_cert, ca_key = osw.create_certificate(cert_info_ca, request=False,
|
||||
write_to_file=True,
|
||||
cert_dir=os.path.dirname(os.path.abspath(__file__)) + "/pki")
|
||||
cert_dir=os.path.dirname(
|
||||
os.path.abspath(
|
||||
__file__)) + "/pki")
|
||||
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info, request=True)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info,
|
||||
request=True)
|
||||
|
||||
ca_cert_str = osw.read_str_from_file(ca_cert)
|
||||
ca_key_str = osw.read_str_from_file(ca_key)
|
||||
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str,
|
||||
req_cert_str)
|
||||
|
||||
valid, mess = osw.verify(ca_cert_str, cert_str)
|
||||
self.assertTrue(valid)
|
||||
|
||||
false_ca_cert, false_ca_key = osw.create_certificate(cert_info_ca, request=False, write_to_file=False)
|
||||
false_req_cert_str_1, false_req_key_str_1 = osw.create_certificate(cert_info_ca, request=True)
|
||||
false_cert_str_1 = osw.create_cert_signed_certificate(false_ca_cert, false_ca_key, false_req_cert_str_1)
|
||||
false_req_cert_str_2, false_req_key_str_2 = osw.create_certificate(cert_info, request=True)
|
||||
false_cert_str_2 = osw.create_cert_signed_certificate(false_ca_cert, false_ca_key, false_req_cert_str_2)
|
||||
false_ca_cert, false_ca_key = osw.create_certificate(cert_info_ca,
|
||||
request=False,
|
||||
write_to_file=False)
|
||||
false_req_cert_str_1, false_req_key_str_1 = osw.create_certificate(
|
||||
cert_info_ca, request=True)
|
||||
false_cert_str_1 = osw.create_cert_signed_certificate(false_ca_cert,
|
||||
false_ca_key,
|
||||
false_req_cert_str_1)
|
||||
false_req_cert_str_2, false_req_key_str_2 = osw.create_certificate(
|
||||
cert_info, request=True)
|
||||
false_cert_str_2 = osw.create_cert_signed_certificate(false_ca_cert,
|
||||
false_ca_key,
|
||||
false_req_cert_str_2)
|
||||
|
||||
valid, mess = osw.verify(false_ca_cert, cert_str)
|
||||
self.assertFalse(valid)
|
||||
@@ -106,20 +117,28 @@ class TestGenerateCertificates(unittest.TestCase):
|
||||
|
||||
osw = OpenSSLWrapper()
|
||||
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca, request=False)
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca,
|
||||
request=False)
|
||||
|
||||
req_cert_str, intermediate_1_key_str = osw.create_certificate(cert_intermediate_1_info, request=True)
|
||||
intermediate_cert_1_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str)
|
||||
req_cert_str, intermediate_1_key_str = osw.create_certificate(
|
||||
cert_intermediate_1_info, request=True)
|
||||
intermediate_cert_1_str = osw.create_cert_signed_certificate(
|
||||
ca_cert_str, ca_key_str, req_cert_str)
|
||||
|
||||
req_cert_str, intermediate_2_key_str = osw.create_certificate(cert_intermediate_2_info, request=True)
|
||||
intermediate_cert_2_str = osw.create_cert_signed_certificate(intermediate_cert_1_str, intermediate_1_key_str,
|
||||
req_cert_str)
|
||||
req_cert_str, intermediate_2_key_str = osw.create_certificate(
|
||||
cert_intermediate_2_info, request=True)
|
||||
intermediate_cert_2_str = osw.create_cert_signed_certificate(
|
||||
intermediate_cert_1_str, intermediate_1_key_str,
|
||||
req_cert_str)
|
||||
|
||||
req_cert_str, client_key_str = osw.create_certificate(cert_client_cert_info, request=True)
|
||||
client_cert_str = osw.create_cert_signed_certificate(intermediate_cert_2_str, intermediate_2_key_str,
|
||||
req_cert_str)
|
||||
req_cert_str, client_key_str = osw.create_certificate(
|
||||
cert_client_cert_info, request=True)
|
||||
client_cert_str = osw.create_cert_signed_certificate(
|
||||
intermediate_cert_2_str, intermediate_2_key_str,
|
||||
req_cert_str)
|
||||
|
||||
cert_chain = [intermediate_cert_2_str, intermediate_cert_1_str, ca_cert_str]
|
||||
cert_chain = [intermediate_cert_2_str, intermediate_cert_1_str,
|
||||
ca_cert_str]
|
||||
|
||||
valid, mess = osw.verify_chain(cert_chain, client_cert_str)
|
||||
self.assertTrue(valid)
|
||||
@@ -145,21 +164,23 @@ class TestGenerateCertificates(unittest.TestCase):
|
||||
"organization_unit": "asdfg"
|
||||
}
|
||||
|
||||
|
||||
osw = OpenSSLWrapper()
|
||||
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca, request=False,
|
||||
cipher_passphrase=
|
||||
{"cipher": "blowfish", "passphrase": "qwerty"})
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(
|
||||
cert_info_ca, request=False,
|
||||
cipher_passphrase={"cipher": "blowfish", "passphrase": "qwerty"})
|
||||
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info, request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str,
|
||||
passphrase="qwerty")
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info,
|
||||
request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str,
|
||||
req_cert_str,
|
||||
passphrase="qwerty")
|
||||
|
||||
valid = False
|
||||
try:
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str,
|
||||
passphrase="qwertyqwerty")
|
||||
cert_str = osw.create_cert_signed_certificate(
|
||||
ca_cert_str, ca_key_str, req_cert_str,
|
||||
passphrase="qwertyqwerty")
|
||||
except Exception:
|
||||
valid = True
|
||||
|
||||
@@ -185,39 +206,59 @@ class TestGenerateCertificates(unittest.TestCase):
|
||||
"organization_unit": "asdfg"
|
||||
}
|
||||
|
||||
|
||||
osw = OpenSSLWrapper()
|
||||
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca, request=False)
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca,
|
||||
request=False)
|
||||
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info, request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info,
|
||||
request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str,
|
||||
req_cert_str)
|
||||
|
||||
valid, mess = osw.verify(ca_cert_str, cert_str)
|
||||
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca, request=False, valid_from=1000, valid_to=100000)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info, request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str)
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca,
|
||||
request=False,
|
||||
valid_from=1000,
|
||||
valid_to=100000)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info,
|
||||
request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str,
|
||||
req_cert_str)
|
||||
valid, mess = osw.verify(ca_cert_str, cert_str)
|
||||
self.assertFalse(valid)
|
||||
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca, request=False)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info, request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str, valid_from=1000,
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca,
|
||||
request=False)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info,
|
||||
request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str,
|
||||
req_cert_str,
|
||||
valid_from=1000,
|
||||
valid_to=100000)
|
||||
valid, mess = osw.verify(ca_cert_str, cert_str)
|
||||
self.assertFalse(valid)
|
||||
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca, request=False, valid_from=0, valid_to=1)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info, request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str)
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca,
|
||||
request=False,
|
||||
valid_from=0,
|
||||
valid_to=1)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info,
|
||||
request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str,
|
||||
req_cert_str)
|
||||
time.sleep(2)
|
||||
valid, mess = osw.verify(ca_cert_str, cert_str)
|
||||
self.assertFalse(valid)
|
||||
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca, request=False)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info, request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str, req_cert_str, valid_from=0, valid_to=1)
|
||||
ca_cert_str, ca_key_str = osw.create_certificate(cert_info_ca,
|
||||
request=False)
|
||||
req_cert_str, req_key_str = osw.create_certificate(cert_info,
|
||||
request=True)
|
||||
cert_str = osw.create_cert_signed_certificate(ca_cert_str, ca_key_str,
|
||||
req_cert_str,
|
||||
valid_from=0, valid_to=1)
|
||||
time.sleep(2)
|
||||
valid, mess = osw.verify(ca_cert_str, cert_str)
|
||||
self.assertFalse(valid)
|
||||
self.assertFalse(valid)
|
||||
|
||||
@@ -9,6 +9,7 @@ from saml2.extension.pefim import SPCertEnc
|
||||
from saml2.samlp import Extensions
|
||||
from saml2.samlp import authn_request_from_string
|
||||
from saml2.sigver import read_cert_from_file
|
||||
from pathutils import full_path
|
||||
|
||||
__author__ = 'roland'
|
||||
|
||||
@@ -17,7 +18,7 @@ conf.load_file("server_conf")
|
||||
client = Saml2Client(conf)
|
||||
|
||||
# place a certificate in an authn request
|
||||
cert = read_cert_from_file("test.pem", "pem")
|
||||
cert = read_cert_from_file(full_path("test.pem"), "pem")
|
||||
|
||||
spcertenc = SPCertEnc(
|
||||
x509_data=ds.X509Data(
|
||||
@@ -48,4 +49,4 @@ _elem = extension_elements_to_elements(parsed.extensions.extension_elements,
|
||||
assert len(_elem) == 1
|
||||
_spcertenc = _elem[0]
|
||||
_cert = _spcertenc.x509_data[0].x509_certificate.text
|
||||
assert cert == _cert
|
||||
assert cert == _cert
|
||||
|
||||
@@ -87,7 +87,7 @@ def base_init(imports):
|
||||
line.append("%s%s=%s," % (indent4, _name, _name))
|
||||
line.append("%s)" % indent4)
|
||||
else:
|
||||
# TODO have to keep apart which properties comes from which superior
|
||||
# TODO have to keep apart which properties come from which superior
|
||||
for sup, elems in imports.items():
|
||||
line.append("%s%s.__init__(self, " % (INDENT+INDENT, sup))
|
||||
lattr = elems[:]
|
||||
@@ -2187,5 +2187,3 @@ def main(argv):
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
|
||||
|
||||
140
tools/sync_attrmaps.py
Executable file
140
tools/sync_attrmaps.py
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from importlib import import_module
|
||||
import sys
|
||||
import os
|
||||
|
||||
__author__ = 'roland'
|
||||
|
||||
|
||||
def load(head, tail):
|
||||
if head == "":
|
||||
if sys.path[0] != ".":
|
||||
sys.path.insert(0, ".")
|
||||
else:
|
||||
sys.path.insert(0, head)
|
||||
|
||||
if tail.endswith(".py"):
|
||||
tail = tail[:-3]
|
||||
|
||||
return import_module(tail)
|
||||
|
||||
|
||||
def intcmp(s1, s2):
|
||||
try:
|
||||
_i1 = int(s1)
|
||||
_i2 = int(s2)
|
||||
except ValueError:
|
||||
_i1 = s1
|
||||
_i2 = s2
|
||||
|
||||
if _i1 < _i2:
|
||||
return -1
|
||||
if _i1 > _i2:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
class AMap(object):
|
||||
def __init__(self, head, tail, indent=4 * " "):
|
||||
self.mod = load(head, tail)
|
||||
self.variable = {}
|
||||
self.vars = []
|
||||
self.text = []
|
||||
self.indent = indent
|
||||
for key, val in self.mod.__dict__.items():
|
||||
if key.startswith("__"):
|
||||
continue
|
||||
elif key == "MAP":
|
||||
continue
|
||||
else:
|
||||
self.variable[key] = val
|
||||
self.vars.append(key)
|
||||
self.vars.sort()
|
||||
|
||||
def sync(self):
|
||||
for key, val in self.mod.MAP["fro"].items():
|
||||
try:
|
||||
assert self.mod.MAP["to"][val] == key
|
||||
except KeyError: # missing value
|
||||
print "# Added %s=%s" % (self.mod.MAP["to"][val], key)
|
||||
self.mod.MAP["to"][val] = key
|
||||
except AssertionError:
|
||||
raise Exception("Mismatch key:%s '%s' != '%s'" % (
|
||||
key, val, self.mod.MAP["to"][val]))
|
||||
|
||||
for val in self.mod.MAP["to"].values():
|
||||
if val not in self.mod.MAP["fro"]:
|
||||
print "# Missing URN '%s'" % val
|
||||
|
||||
def do_fro(self):
|
||||
txt = ["%s'fro': {" % self.indent]
|
||||
i2 = self.indent + self.indent
|
||||
_fro = self.mod.MAP["fro"]
|
||||
for var in self.vars:
|
||||
_v = self.variable[var]
|
||||
li = [k[len(_v):] for k in _fro.keys() if k.startswith(_v)]
|
||||
li.sort(intcmp)
|
||||
for item in li:
|
||||
txt.append("%s%s+'%s': '%s'," % (i2, var, item,
|
||||
_fro[_v + item]))
|
||||
txt.append('%s},' % self.indent)
|
||||
return txt
|
||||
|
||||
def do_to(self):
|
||||
txt = ["%s'to': {" % self.indent]
|
||||
i2 = self.indent + self.indent
|
||||
_to = self.mod.MAP["to"]
|
||||
_keys = _to.keys()
|
||||
_keys.sort()
|
||||
invmap = dict([(v, k) for k, v in self.variable.items()])
|
||||
|
||||
for key in _keys:
|
||||
val = _to[key]
|
||||
for _urn, _name in invmap.items():
|
||||
if val.startswith(_urn):
|
||||
txt.append("%s'%s': %s+'%s'," % (i2, key, _name,
|
||||
val[len(_urn):]))
|
||||
|
||||
txt.append('%s}' % self.indent)
|
||||
return txt
|
||||
|
||||
def __str__(self):
|
||||
self.sync()
|
||||
text = []
|
||||
for key in self.vars:
|
||||
text.append("%s = '%s'" % (key, self.variable[key]))
|
||||
|
||||
text.extend(["", ""])
|
||||
|
||||
text.append("MAP = {")
|
||||
text.append("%s'identifier': '%s'," % (self.indent,
|
||||
self.mod.MAP["identifier"]))
|
||||
text.extend(self.do_fro())
|
||||
text.extend(self.do_to())
|
||||
|
||||
text.append("}")
|
||||
text.append("")
|
||||
return "\n".join(text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_name = sys.argv[1]
|
||||
if os.path.isfile(_name):
|
||||
directory, fname = os.path.split(_name)
|
||||
amap = AMap(directory, fname, 4 * " ")
|
||||
f = open(_name)
|
||||
f.write("%s" % amap)
|
||||
f.close()
|
||||
elif os.path.isdir(_name):
|
||||
for fname in os.listdir(_name):
|
||||
if fname == "__init__.py":
|
||||
continue
|
||||
elif fname.endswith(".pyc"):
|
||||
continue
|
||||
print 10 * "=" + fname + 10 * "="
|
||||
amap = AMap(_name, fname, 4 * " ")
|
||||
f = open(fname, "w")
|
||||
f.write("%s" % amap)
|
||||
f.close()
|
||||
Reference in New Issue
Block a user