bringing in godfat's redesigned authenticator architecture with per-class setups... also a whole bunch of whitespace changes
This commit is contained in:
Коммит
691c58d721
|
@ -1 +1 @@
|
||||||
See History.txt
|
See History.txt
|
||||||
|
|
62
History.txt
62
History.txt
|
@ -1,8 +1,8 @@
|
||||||
=== 0.8.0 :: In Progress...
|
=== 0.8.0 :: In Progress...
|
||||||
|
|
||||||
* NEW:
|
* NEW:
|
||||||
* Support for localization via Ruby-GetText.
|
* Support for localization via Ruby-GetText.
|
||||||
See http://code.google.com/p/rubycas-server/wiki/Localization
|
See http://code.google.com/p/rubycas-server/wiki/Localization
|
||||||
for details. [antono]
|
for details. [antono]
|
||||||
* Switched to Picnic 0.8.x, so RubyCAS-Server is now based on Rack
|
* Switched to Picnic 0.8.x, so RubyCAS-Server is now based on Rack
|
||||||
and Camping 2.0 and is now compatible with Passenger Phusion
|
and Camping 2.0 and is now compatible with Passenger Phusion
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
* Re-licensed under the MIT License.
|
* Re-licensed under the MIT License.
|
||||||
|
|
||||||
* FIXED:
|
* FIXED:
|
||||||
* Fixed weird problems with loading controllers when using older versions of
|
* Fixed weird problems with loading controllers when using older versions of
|
||||||
activesupport and/or rubygems.
|
activesupport and/or rubygems.
|
||||||
* Failure to connect to a service during a single sign out request is now
|
* Failure to connect to a service during a single sign out request is now
|
||||||
handled gracefully.
|
handled gracefully.
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
=== 0.7.1 :: 2008-11-10
|
=== 0.7.1 :: 2008-11-10
|
||||||
|
|
||||||
* Fixed dependency loading problems introduced by upstream changes in RubyGems
|
* Fixed dependency loading problems introduced by upstream changes in RubyGems
|
||||||
1.3.1.
|
1.3.1.
|
||||||
|
|
||||||
=== 0.7.0 :: 2008-11-04
|
=== 0.7.0 :: 2008-11-04
|
||||||
|
@ -34,18 +34,18 @@
|
||||||
to CAS clients alongside the username. For an example of how to do this see
|
to CAS clients alongside the username. For an example of how to do this see
|
||||||
the included SQL authenticator. Also have a look at:
|
the included SQL authenticator. Also have a look at:
|
||||||
http://groups.google.com/group/rubycas-server/browse_thread/thread/5eade3793cb590e9
|
http://groups.google.com/group/rubycas-server/browse_thread/thread/5eade3793cb590e9
|
||||||
Note that extra attributes of type other than String or Numeric are serialized
|
Note that extra attributes of type other than String or Numeric are serialized
|
||||||
into YAML format before being sent along to the client.
|
into YAML format before being sent along to the client.
|
||||||
* Added an MD5-password version of the SQL authenticator for Drupal and any other
|
* Added an MD5-password version of the SQL authenticator for Drupal and any other
|
||||||
database that stores its passwords in hashed form (thanks malcolmm).
|
database that stores its passwords in hashed form (thanks malcolmm).
|
||||||
* Added new Google authenticator for authenticating against Google/GMail
|
* Added new Google authenticator for authenticating against Google/GMail
|
||||||
accounts.
|
accounts.
|
||||||
|
|
||||||
* CHANGED:
|
* CHANGED:
|
||||||
* Service URIs are now automatically normalized. For example, if the service
|
* Service URIs are now automatically normalized. For example, if the service
|
||||||
URI given to the server has a 'ticket' parameter, the ticket will now be
|
URI given to the server has a 'ticket' parameter, the ticket will now be
|
||||||
automatically stripped. This is to avert any possible issues raised by
|
automatically stripped. This is to avert any possible issues raised by
|
||||||
misbehaving CAS clients (the CAS ticket should never be part of the service
|
misbehaving CAS clients (the CAS ticket should never be part of the service
|
||||||
URI). Same goes for other CAS-related parameters like 'service', 'renew',
|
URI). Same goes for other CAS-related parameters like 'service', 'renew',
|
||||||
and 'gateway'. Additionally, the trailing '/' and '?' characters are
|
and 'gateway'. Additionally, the trailing '/' and '?' characters are
|
||||||
automatically stripped from URLs, since, for example, "http://google.com/"
|
automatically stripped from URLs, since, for example, "http://google.com/"
|
||||||
|
@ -65,8 +65,8 @@
|
||||||
auto-indentation has been turned off). Apparently the whitespace was
|
auto-indentation has been turned off). Apparently the whitespace was
|
||||||
causing problems with mod_auth_cas. See:
|
causing problems with mod_auth_cas. See:
|
||||||
http://groups.google.com/group/rubycas-server/browse_thread/thread/e482fe09999b73d3
|
http://groups.google.com/group/rubycas-server/browse_thread/thread/e482fe09999b73d3
|
||||||
* When used without pre-authentication, the LDAP authenticator now tries to
|
* When used without pre-authentication, the LDAP authenticator now tries to
|
||||||
bind by searching for the given username in the LDAP directory based on the
|
bind by searching for the given username in the LDAP directory based on the
|
||||||
configured username_attribute. Prior to this change the authenticator
|
configured username_attribute. Prior to this change the authenticator
|
||||||
attempted to bind with the LDAP server by assuming that the username credential
|
attempted to bind with the LDAP server by assuming that the username credential
|
||||||
matches the user's CN. This is no longer the case.
|
matches the user's CN. This is no longer the case.
|
||||||
|
@ -74,12 +74,12 @@
|
||||||
are missing or incorrect) will now have HTTP status code 422. Internal server
|
are missing or incorrect) will now have HTTP status code 422. Internal server
|
||||||
errors (where the server rather than the client is at fault) have error 500.
|
errors (where the server rather than the client is at fault) have error 500.
|
||||||
Previously most responses had error code 200, regardless of their contents.
|
Previously most responses had error code 200, regardless of their contents.
|
||||||
|
|
||||||
* FIXED:
|
* FIXED:
|
||||||
* Fixed logout action to work properly with ActiveRecord 2.1 (eager loading behaviour
|
* Fixed logout action to work properly with ActiveRecord 2.1 (eager loading behaviour
|
||||||
was changed upstream forcing a change to the way we look for ProxyGrantingTickets
|
was changed upstream forcing a change to the way we look for ProxyGrantingTickets
|
||||||
to delete on logout).
|
to delete on logout).
|
||||||
* When running under Mongrel, the USR2 signal should now restart the server as
|
* When running under Mongrel, the USR2 signal should now restart the server as
|
||||||
expected -- however currently this only works when the server is running
|
expected -- however currently this only works when the server is running
|
||||||
in the foregaround. When daemonized, USR2 will shut down the server without
|
in the foregaround. When daemonized, USR2 will shut down the server without
|
||||||
restarting (see issue #58).
|
restarting (see issue #58).
|
||||||
|
@ -108,7 +108,7 @@
|
||||||
* An encryption-enabled version of the SQL authenticator is now
|
* An encryption-enabled version of the SQL authenticator is now
|
||||||
available. For more info have a look at:
|
available. For more info have a look at:
|
||||||
http://code.google.com/p/rubycas-server/wiki/UsingTheSQLEncryptedAuthenticator
|
http://code.google.com/p/rubycas-server/wiki/UsingTheSQLEncryptedAuthenticator
|
||||||
* Better compatibility with Oracle databases. The database migration
|
* Better compatibility with Oracle databases. The database migration
|
||||||
no longer tries to create tables with long names when long
|
no longer tries to create tables with long names when long
|
||||||
table names are not supported by the underlying database connector
|
table names are not supported by the underlying database connector
|
||||||
(issue #15).
|
(issue #15).
|
||||||
|
@ -129,7 +129,7 @@
|
||||||
* Tickets generated by the server should now be a lot more secure.
|
* Tickets generated by the server should now be a lot more secure.
|
||||||
The random string generator used for generating tickets now uses
|
The random string generator used for generating tickets now uses
|
||||||
Crypt::ISAAC. Tickets have also been extended in length; STs, PTs
|
Crypt::ISAAC. Tickets have also been extended in length; STs, PTs
|
||||||
and LTs can now extend up to 32 characters, and PGTs and PGT-IOUs
|
and LTs can now extend up to 32 characters, and PGTs and PGT-IOUs
|
||||||
up to 64.
|
up to 64.
|
||||||
|
|
||||||
=== 0.5.0 :: 2007-09-20
|
=== 0.5.0 :: 2007-09-20
|
||||||
|
@ -138,8 +138,8 @@
|
||||||
login page is made with gateway=true as one of the parameters, the CAS
|
login page is made with gateway=true as one of the parameters, the CAS
|
||||||
server will immediately redirect back to the target service along with
|
server will immediately redirect back to the target service along with
|
||||||
a service ticket if an SSO session exists for the user (or without a
|
a service ticket if an SSO session exists for the user (or without a
|
||||||
service ticket if there is no pre-existing SSO session).
|
service ticket if there is no pre-existing SSO session).
|
||||||
Note that if you are using RubyCAS-Client and want gatewaying, you will
|
Note that if you are using RubyCAS-Client and want gatewaying, you will
|
||||||
need to upgrade it to 1.1.0 as gatewaying was broken in prior versions.
|
need to upgrade it to 1.1.0 as gatewaying was broken in prior versions.
|
||||||
* If gateway=true is specified as part of the logout URI, the server will
|
* If gateway=true is specified as part of the logout URI, the server will
|
||||||
log the user out and immediately redirect them back to the specified
|
log the user out and immediately redirect them back to the specified
|
||||||
|
@ -162,9 +162,9 @@
|
||||||
this new RubyCAS-Server version.
|
this new RubyCAS-Server version.
|
||||||
* Multiple authenticators can now be specified. During authentication,
|
* Multiple authenticators can now be specified. During authentication,
|
||||||
credentials are presented to the first authenticator, then the second,
|
credentials are presented to the first authenticator, then the second,
|
||||||
and so on, until the user is validated by any one authenticator or fails
|
and so on, until the user is validated by any one authenticator or fails
|
||||||
validation for all of them. [jzylks]
|
validation for all of them. [jzylks]
|
||||||
* When using webrick, you can now run with SSL disabled by omitting the
|
* When using webrick, you can now run with SSL disabled by omitting the
|
||||||
ssl_cert and ssl_key parameters.
|
ssl_cert and ssl_key parameters.
|
||||||
* Changed incorrect MySQL example database configuration -- option should
|
* Changed incorrect MySQL example database configuration -- option should
|
||||||
be 'host:' not 'server:' (issue #22).
|
be 'host:' not 'server:' (issue #22).
|
||||||
|
@ -177,11 +177,11 @@
|
||||||
LDAP server).
|
LDAP server).
|
||||||
* The validate() method in your authenticators now receives a :service element
|
* The validate() method in your authenticators now receives a :service element
|
||||||
(in addition to :username, and :password). This is simply the service
|
(in addition to :username, and :password). This is simply the service
|
||||||
url (if any) specified in the user's CAS request. If you call
|
url (if any) specified in the user's CAS request. If you call
|
||||||
read_standard_credentials(credentials) at the top of your validator, the value
|
read_standard_credentials(credentials) at the top of your validator, the value
|
||||||
will also be available as @service along with @username and @password.
|
will also be available as @service along with @username and @password.
|
||||||
* By request, a :username_prefix option has been added to the ldap
|
* By request, a :username_prefix option has been added to the ldap
|
||||||
configuration. If entered, this string will be automatically prefixed to
|
configuration. If entered, this string will be automatically prefixed to
|
||||||
the username entered by the user.
|
the username entered by the user.
|
||||||
* A bug having to do with handling authenticator errors has been fixed.
|
* A bug having to do with handling authenticator errors has been fixed.
|
||||||
Any authenticator error messages should now be correctly shown on the
|
Any authenticator error messages should now be correctly shown on the
|
||||||
|
@ -193,9 +193,9 @@
|
||||||
=== 0.4.1 :: 2007-06-07
|
=== 0.4.1 :: 2007-06-07
|
||||||
|
|
||||||
* This release restores compatiblity with older versions of rubygems
|
* This release restores compatiblity with older versions of rubygems
|
||||||
(pre-0.9.0). To achieve this, we alias the 'gem' method to the old
|
(pre-0.9.0). To achieve this, we alias the 'gem' method to the old
|
||||||
'require_gem' if 'gem' is not already defined.
|
'require_gem' if 'gem' is not already defined.
|
||||||
* rubycas-server-ctl will now quiety delete an orphaned .pid file
|
* rubycas-server-ctl will now quiety delete an orphaned .pid file
|
||||||
instead complaining loudly and refusing to start up.
|
instead complaining loudly and refusing to start up.
|
||||||
* Fixed minor bug in rubycas-server-ctl that sometimes incorrectly reported
|
* Fixed minor bug in rubycas-server-ctl that sometimes incorrectly reported
|
||||||
startup problems when in fact the server had started just fine.
|
startup problems when in fact the server had started just fine.
|
||||||
|
@ -221,9 +221,9 @@
|
||||||
In the future we may allow autocomplete to be re-enabled using a
|
In the future we may allow autocomplete to be re-enabled using a
|
||||||
configuration setting.
|
configuration setting.
|
||||||
* When the user visits the login page and is already authenticated (i.e. they
|
* When the user visits the login page and is already authenticated (i.e. they
|
||||||
have a valid ticket granting cookie), a message is shown at the top
|
have a valid ticket granting cookie), a message is shown at the top
|
||||||
indicating that they are already logged in.
|
indicating that they are already logged in.
|
||||||
* sqlite3-ruby is no longer required by the gem as a dependency. The user
|
* sqlite3-ruby is no longer required by the gem as a dependency. The user
|
||||||
must now install it manually prior to installing rubycas-server. The
|
must now install it manually prior to installing rubycas-server. The
|
||||||
building of sqlite3 native extensions appears to be somewhat flakey
|
building of sqlite3 native extensions appears to be somewhat flakey
|
||||||
and probably defeats the original purpose of using it (which was
|
and probably defeats the original purpose of using it (which was
|
||||||
|
@ -242,9 +242,9 @@
|
||||||
However, other exceptions should still be raised when errors ought
|
However, other exceptions should still be raised when errors ought
|
||||||
not be recoverable (i.e. programming errors).
|
not be recoverable (i.e. programming errors).
|
||||||
* Fixed serious vulnerability in LDAP authenticator where under some
|
* Fixed serious vulnerability in LDAP authenticator where under some
|
||||||
cirumstances the user could just enter '*' as their username to match
|
cirumstances the user could just enter '*' as their username to match
|
||||||
any username. The LDAP authenticator will now refuse to process logins
|
any username. The LDAP authenticator will now refuse to process logins
|
||||||
with usernames that contain the characters * ( ) \ / and the NULL
|
with usernames that contain the characters * ( ) \ / and the NULL
|
||||||
character \0.
|
character \0.
|
||||||
* Views are no longer xhtml-validated. Markaby's auto-validation was turned
|
* Views are no longer xhtml-validated. Markaby's auto-validation was turned
|
||||||
off to allow for use of the autocomplete property on inputs, since this is
|
off to allow for use of the autocomplete property on inputs, since this is
|
||||||
|
@ -259,7 +259,7 @@
|
||||||
|
|
||||||
* ruby-casserver now behaves more like a real command-line app, accepting
|
* ruby-casserver now behaves more like a real command-line app, accepting
|
||||||
various command line arguments including -h (help), -v (version), -c (use
|
various command line arguments including -h (help), -v (version), -c (use
|
||||||
an alternate config.yml), and -d (daemonize, when using webrick or mongrel
|
an alternate config.yml), and -d (daemonize, when using webrick or mongrel
|
||||||
mode).
|
mode).
|
||||||
* Special characters in CAS XML responses are now properly encoded into XML
|
* Special characters in CAS XML responses are now properly encoded into XML
|
||||||
entities
|
entities
|
||||||
|
|
|
@ -3,7 +3,7 @@ History.txt
|
||||||
LICENSE.txt
|
LICENSE.txt
|
||||||
Manifest.txt
|
Manifest.txt
|
||||||
PostInstall.txt
|
PostInstall.txt
|
||||||
README.txt
|
README.rdoc
|
||||||
Rakefile
|
Rakefile
|
||||||
bin/rubycas-server
|
bin/rubycas-server
|
||||||
bin/rubycas-server-ctl
|
bin/rubycas-server-ctl
|
||||||
|
@ -32,6 +32,10 @@ lib/casserver/load_picnic.rb
|
||||||
lib/casserver/localization.rb
|
lib/casserver/localization.rb
|
||||||
lib/casserver/models.rb
|
lib/casserver/models.rb
|
||||||
lib/casserver/postambles.rb
|
lib/casserver/postambles.rb
|
||||||
|
lib/casserver/template/erb/layout.html.erb
|
||||||
|
lib/casserver/template/erb/login.html.erb
|
||||||
|
lib/casserver/template/erb/login_form.html.erb
|
||||||
|
lib/casserver/template/erb/logout.html.erb
|
||||||
lib/casserver/utils.rb
|
lib/casserver/utils.rb
|
||||||
lib/casserver/version.rb
|
lib/casserver/version.rb
|
||||||
lib/casserver/views.rb
|
lib/casserver/views.rb
|
||||||
|
|
230
Rakefile
230
Rakefile
|
@ -1,115 +1,115 @@
|
||||||
require 'config/requirements'
|
require 'config/requirements'
|
||||||
require 'config/hoe' # setup Hoe + all gem configuration
|
require 'config/hoe' # setup Hoe + all gem configuration
|
||||||
|
|
||||||
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
||||||
|
|
||||||
desc "generate a self signed SSL certificate (in order to get going easily)"
|
desc "generate a self signed SSL certificate (in order to get going easily)"
|
||||||
task :generate_ssl_certificate do
|
task :generate_ssl_certificate do
|
||||||
`mkdir -p ssl/newcerts ssl/private`
|
`mkdir -p ssl/newcerts ssl/private`
|
||||||
File.open("ssl/openssl.cnf", "w") do |f|
|
File.open("ssl/openssl.cnf", "w") do |f|
|
||||||
f.write <<-EOF
|
f.write <<-EOF
|
||||||
#
|
#
|
||||||
# OpenSSL configuration file.
|
# OpenSSL configuration file.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Establish working directory.
|
# Establish working directory.
|
||||||
|
|
||||||
dir = .
|
dir = .
|
||||||
|
|
||||||
[ ca ]
|
[ ca ]
|
||||||
default_ca = CA_default
|
default_ca = CA_default
|
||||||
|
|
||||||
[ CA_default ]
|
[ CA_default ]
|
||||||
serial = $dir/serial
|
serial = $dir/serial
|
||||||
database = $dir/index.txt
|
database = $dir/index.txt
|
||||||
new_certs_dir = $dir/newcerts
|
new_certs_dir = $dir/newcerts
|
||||||
certificate = $dir/cacert.pem
|
certificate = $dir/cacert.pem
|
||||||
private_key = $dir/private/cakey.pem
|
private_key = $dir/private/cakey.pem
|
||||||
default_days = 365
|
default_days = 365
|
||||||
default_md = md5
|
default_md = md5
|
||||||
preserve = no
|
preserve = no
|
||||||
email_in_dn = no
|
email_in_dn = no
|
||||||
nameopt = default_ca
|
nameopt = default_ca
|
||||||
certopt = default_ca
|
certopt = default_ca
|
||||||
policy = policy_match
|
policy = policy_match
|
||||||
|
|
||||||
[ policy_match ]
|
[ policy_match ]
|
||||||
countryName = match
|
countryName = match
|
||||||
stateOrProvinceName = match
|
stateOrProvinceName = match
|
||||||
organizationName = match
|
organizationName = match
|
||||||
organizationalUnitName = optional
|
organizationalUnitName = optional
|
||||||
commonName = supplied
|
commonName = supplied
|
||||||
emailAddress = optional
|
emailAddress = optional
|
||||||
|
|
||||||
[ req ]
|
[ req ]
|
||||||
default_bits = 1024 # Size of keys
|
default_bits = 1024 # Size of keys
|
||||||
default_keyfile = key.pem # name of generated keys
|
default_keyfile = key.pem # name of generated keys
|
||||||
default_md = md5 # message digest algorithm
|
default_md = md5 # message digest algorithm
|
||||||
string_mask = nombstr # permitted characters
|
string_mask = nombstr # permitted characters
|
||||||
distinguished_name = req_distinguished_name
|
distinguished_name = req_distinguished_name
|
||||||
req_extensions = v3_req
|
req_extensions = v3_req
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
[ req_distinguished_name ]
|
||||||
# Variable name Prompt string
|
# Variable name Prompt string
|
||||||
#---------------------- ----------------------------------
|
#---------------------- ----------------------------------
|
||||||
0.organizationName = Organization Name (company)
|
0.organizationName = Organization Name (company)
|
||||||
organizationalUnitName = Organizational Unit Name (department, division)
|
organizationalUnitName = Organizational Unit Name (department, division)
|
||||||
emailAddress = Email Address
|
emailAddress = Email Address
|
||||||
emailAddress_max = 40
|
emailAddress_max = 40
|
||||||
localityName = Locality Name (city, district)
|
localityName = Locality Name (city, district)
|
||||||
stateOrProvinceName = State or Province Name (full name)
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
countryName = Country Name (2 letter code)
|
countryName = Country Name (2 letter code)
|
||||||
countryName_min = 2
|
countryName_min = 2
|
||||||
countryName_max = 2
|
countryName_max = 2
|
||||||
commonName = Common Name (hostname, IP, or your name)
|
commonName = Common Name (hostname, IP, or your name)
|
||||||
commonName_max = 64
|
commonName_max = 64
|
||||||
|
|
||||||
# Default values for the above, for consistency and less typing.
|
# Default values for the above, for consistency and less typing.
|
||||||
# Variable name Value
|
# Variable name Value
|
||||||
#------------------------------ ------------------------------
|
#------------------------------ ------------------------------
|
||||||
0.organizationName_default = The Sample Company
|
0.organizationName_default = The Sample Company
|
||||||
localityName_default = Metropolis
|
localityName_default = Metropolis
|
||||||
stateOrProvinceName_default = New York
|
stateOrProvinceName_default = New York
|
||||||
countryName_default = US
|
countryName_default = US
|
||||||
commonName_default = localhost
|
commonName_default = localhost
|
||||||
|
|
||||||
[ v3_ca ]
|
[ v3_ca ]
|
||||||
basicConstraints = CA:TRUE
|
basicConstraints = CA:TRUE
|
||||||
subjectKeyIdentifier = hash
|
subjectKeyIdentifier = hash
|
||||||
authorityKeyIdentifier = keyid:always,issuer:always
|
authorityKeyIdentifier = keyid:always,issuer:always
|
||||||
|
|
||||||
[ v3_req ]
|
[ v3_req ]
|
||||||
basicConstraints = CA:FALSE
|
basicConstraints = CA:FALSE
|
||||||
subjectKeyIdentifier = hash
|
subjectKeyIdentifier = hash
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
`cd ssl && echo '01' > serial`
|
`cd ssl && echo '01' > serial`
|
||||||
`cd ssl && touch index.txt`
|
`cd ssl && touch index.txt`
|
||||||
|
|
||||||
puts
|
puts
|
||||||
puts "When asked for a passphrase enter one, for example rubycas"
|
puts "When asked for a passphrase enter one, for example rubycas"
|
||||||
puts
|
puts
|
||||||
|
|
||||||
`cd ssl && openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 365 -config ./openssl.cnf`
|
`cd ssl && openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 365 -config ./openssl.cnf`
|
||||||
`cd ssl && openssl req -new -nodes -out req.pem -config ./openssl.cnf`
|
`cd ssl && openssl req -new -nodes -out req.pem -config ./openssl.cnf`
|
||||||
`cd ssl && openssl ca -out cert.pem -config ./openssl.cnf -infiles req.pem`
|
`cd ssl && openssl ca -out cert.pem -config ./openssl.cnf -infiles req.pem`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
puts
|
puts
|
||||||
puts "If you are using Firefox and want to access the CAS server through localhost you need to add an exception:"
|
puts "If you are using Firefox and want to access the CAS server through localhost you need to add an exception:"
|
||||||
puts " 1. Go to Preferences > Advanced > Encryption > View Certificates"
|
puts " 1. Go to Preferences > Advanced > Encryption > View Certificates"
|
||||||
puts " 2. Click the Tab Servers"
|
puts " 2. Click the Tab Servers"
|
||||||
puts " 3. Click the Button Add Exception"
|
puts " 3. Click the Button Add Exception"
|
||||||
puts " 4. Enter https://localhost:<port> into the textfield and press Get Certificate"
|
puts " 4. Enter https://localhost:<port> into the textfield and press Get Certificate"
|
||||||
puts " 5. Then press View"
|
puts " 5. Then press View"
|
||||||
puts " 6. Then press Confirm Security Exception"
|
puts " 6. Then press Confirm Security Exception"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "clear all generated files for SSL certificate"
|
desc "clear all generated files for SSL certificate"
|
||||||
task :clear_ssl_certificate do
|
task :clear_ssl_certificate do
|
||||||
`rm -rf ssl`
|
`rm -rf ssl`
|
||||||
end
|
end
|
||||||
|
|
12
config.ru
12
config.ru
|
@ -26,13 +26,17 @@ require 'picnic'
|
||||||
require 'casserver'
|
require 'casserver'
|
||||||
|
|
||||||
CASServer.create
|
CASServer.create
|
||||||
|
hack = lambda{ |env|
|
||||||
|
ActiveRecord::Base.verify_active_connections!
|
||||||
|
CASServer.call(env)
|
||||||
|
}
|
||||||
|
|
||||||
if $CONF.uri_path
|
if $CONF.uri_path
|
||||||
map($CONF.uri_path) do
|
map($CONF.uri_path) do
|
||||||
# FIXME: this probably isn't the smartest way of remapping the themes dir to uri_path/themes
|
# FIXME: this probably isn't the smartest way of remapping the themes dir to uri_path/themes
|
||||||
use Rack::Static, $CONF[:static] if $CONF[:static]
|
use Rack::Static, $CONF[:static] if $CONF[:static]
|
||||||
run CASServer
|
run hack
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
run CASServer
|
run hack
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,6 +34,12 @@ def CASServer.create
|
||||||
CASServer::Models::Base.establish_connection($CONF.database) unless CASServer::Models::Base.connected?
|
CASServer::Models::Base.establish_connection($CONF.database) unless CASServer::Models::Base.connected?
|
||||||
CASServer::Models.create_schema
|
CASServer::Models.create_schema
|
||||||
|
|
||||||
|
# setup all the authenticators
|
||||||
|
$AUTH.zip($CONF.authenticator).each_with_index{ |auth_conf, index|
|
||||||
|
auth, conf = auth_conf
|
||||||
|
auth.setup(conf.merge(:auth_index => index))
|
||||||
|
}
|
||||||
|
|
||||||
#TODO: these warnings should eventually be deleted
|
#TODO: these warnings should eventually be deleted
|
||||||
if $CONF.service_ticket_expiry
|
if $CONF.service_ticket_expiry
|
||||||
$LOG.warn "The 'service_ticket_expiry' option has been renamed to 'maximum_unused_service_ticket_lifetime'. Please make the necessary change to your config file!"
|
$LOG.warn "The 'service_ticket_expiry' option has been renamed to 'maximum_unused_service_ticket_lifetime'. Please make the necessary change to your config file!"
|
||||||
|
|
|
@ -17,13 +17,13 @@ module Authlogic
|
||||||
class AES256
|
class AES256
|
||||||
class << self
|
class << self
|
||||||
attr_writer :key
|
attr_writer :key
|
||||||
|
|
||||||
def encrypt(*tokens)
|
def encrypt(*tokens)
|
||||||
aes.encrypt
|
aes.encrypt
|
||||||
aes.key = @key
|
aes.key = @key
|
||||||
[aes.update(tokens.join) + aes.final].pack("m").chomp
|
[aes.update(tokens.join) + aes.final].pack("m").chomp
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches?(crypted, *tokens)
|
def matches?(crypted, *tokens)
|
||||||
aes.decrypt
|
aes.decrypt
|
||||||
aes.key = @key
|
aes.key = @key
|
||||||
|
@ -31,7 +31,7 @@ module Authlogic
|
||||||
rescue OpenSSL::CipherError
|
rescue OpenSSL::CipherError
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def aes
|
def aes
|
||||||
raise ArgumentError.new("You must provide a key like #{name}.key = my_key before using the #{name}") if @key.blank?
|
raise ArgumentError.new("You must provide a key like #{name}.key = my_key before using the #{name}") if @key.blank?
|
||||||
|
@ -40,4 +40,4 @@ module Authlogic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,12 +48,12 @@ module Authlogic
|
||||||
@cost ||= 10
|
@cost ||= 10
|
||||||
end
|
end
|
||||||
attr_writer :cost
|
attr_writer :cost
|
||||||
|
|
||||||
# Creates a BCrypt hash for the password passed.
|
# Creates a BCrypt hash for the password passed.
|
||||||
def encrypt(*tokens)
|
def encrypt(*tokens)
|
||||||
::BCrypt::Password.create(join_tokens(tokens), :cost => cost)
|
::BCrypt::Password.create(join_tokens(tokens), :cost => cost)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Does the hash match the tokens? Uses the same tokens that were used to encrypt.
|
# Does the hash match the tokens? Uses the same tokens that were used to encrypt.
|
||||||
def matches?(hash, *tokens)
|
def matches?(hash, *tokens)
|
||||||
$LOG.debug hash
|
$LOG.debug hash
|
||||||
|
@ -63,7 +63,7 @@ module Authlogic
|
||||||
return false if hash.blank?
|
return false if hash.blank?
|
||||||
hash == join_tokens(tokens)
|
hash == join_tokens(tokens)
|
||||||
end
|
end
|
||||||
|
|
||||||
# This method is used as a flag to tell Authlogic to "resave" the password upon a successful login, using the new cost
|
# This method is used as a flag to tell Authlogic to "resave" the password upon a successful login, using the new cost
|
||||||
def cost_matches?(hash)
|
def cost_matches?(hash)
|
||||||
hash = new_from_hash(hash)
|
hash = new_from_hash(hash)
|
||||||
|
@ -73,12 +73,12 @@ module Authlogic
|
||||||
hash.cost == cost
|
hash.cost == cost
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def join_tokens(tokens)
|
def join_tokens(tokens)
|
||||||
tokens.flatten.join
|
tokens.flatten.join
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_from_hash(hash)
|
def new_from_hash(hash)
|
||||||
begin
|
begin
|
||||||
::BCrypt::Password.new(hash)
|
::BCrypt::Password.new(hash)
|
||||||
|
@ -89,4 +89,4 @@ module Authlogic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
require "digest/md5"
|
require "digest/md5"
|
||||||
|
|
||||||
module Authlogic
|
module Authlogic
|
||||||
module CryptoProviders
|
module CryptoProviders
|
||||||
# This class was made for the users transitioning from md5 based systems.
|
# This class was made for the users transitioning from md5 based systems.
|
||||||
# I highly discourage using this crypto provider as it superbly inferior
|
# I highly discourage using this crypto provider as it superbly inferior
|
||||||
# to your other options.
|
# to your other options.
|
||||||
#
|
#
|
||||||
# Please use any other provider offered by Authlogic.
|
# Please use any other provider offered by Authlogic.
|
||||||
class MD5
|
class MD5
|
||||||
class << self
|
class << self
|
||||||
attr_accessor :join_token
|
attr_accessor :join_token
|
||||||
|
|
||||||
# The number of times to loop through the encryption.
|
# The number of times to loop through the encryption.
|
||||||
def stretches
|
def stretches
|
||||||
@stretches ||= 1
|
@stretches ||= 1
|
||||||
end
|
end
|
||||||
attr_writer :stretches
|
attr_writer :stretches
|
||||||
|
|
||||||
# Turns your raw password into a MD5 hash.
|
# Turns your raw password into a MD5 hash.
|
||||||
def encrypt(*tokens)
|
def encrypt(*tokens)
|
||||||
digest = tokens.flatten.join(join_token)
|
digest = tokens.flatten.join(join_token)
|
||||||
stretches.times { digest = Digest::MD5.hexdigest(digest) }
|
stretches.times { digest = Digest::MD5.hexdigest(digest) }
|
||||||
digest
|
digest
|
||||||
end
|
end
|
||||||
|
|
||||||
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
||||||
def matches?(crypted, *tokens)
|
def matches?(crypted, *tokens)
|
||||||
encrypt(*tokens) == crypted
|
encrypt(*tokens) == crypted
|
||||||
|
@ -31,4 +31,4 @@ module Authlogic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,13 +10,13 @@ module Authlogic
|
||||||
@join_token ||= "--"
|
@join_token ||= "--"
|
||||||
end
|
end
|
||||||
attr_writer :join_token
|
attr_writer :join_token
|
||||||
|
|
||||||
# The number of times to loop through the encryption. This is ten because that is what restful_authentication defaults to.
|
# The number of times to loop through the encryption. This is ten because that is what restful_authentication defaults to.
|
||||||
def stretches
|
def stretches
|
||||||
@stretches ||= 10
|
@stretches ||= 10
|
||||||
end
|
end
|
||||||
attr_writer :stretches
|
attr_writer :stretches
|
||||||
|
|
||||||
# Turns your raw password into a Sha1 hash.
|
# Turns your raw password into a Sha1 hash.
|
||||||
def encrypt(*tokens)
|
def encrypt(*tokens)
|
||||||
tokens = tokens.flatten
|
tokens = tokens.flatten
|
||||||
|
@ -24,7 +24,7 @@ module Authlogic
|
||||||
stretches.times { digest = Digest::SHA1.hexdigest([digest, *tokens].join(join_token)) }
|
stretches.times { digest = Digest::SHA1.hexdigest([digest, *tokens].join(join_token)) }
|
||||||
digest
|
digest
|
||||||
end
|
end
|
||||||
|
|
||||||
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
||||||
def matches?(crypted, *tokens)
|
def matches?(crypted, *tokens)
|
||||||
encrypt(*tokens) == crypted
|
encrypt(*tokens) == crypted
|
||||||
|
@ -32,4 +32,4 @@ module Authlogic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,20 +26,20 @@ module Authlogic
|
||||||
class Sha512
|
class Sha512
|
||||||
class << self
|
class << self
|
||||||
attr_accessor :join_token
|
attr_accessor :join_token
|
||||||
|
|
||||||
# The number of times to loop through the encryption. This is ten because that is what restful_authentication defaults to.
|
# The number of times to loop through the encryption. This is ten because that is what restful_authentication defaults to.
|
||||||
def stretches
|
def stretches
|
||||||
@stretches ||= 20
|
@stretches ||= 20
|
||||||
end
|
end
|
||||||
attr_writer :stretches
|
attr_writer :stretches
|
||||||
|
|
||||||
# Turns your raw password into a Sha512 hash.
|
# Turns your raw password into a Sha512 hash.
|
||||||
def encrypt(*tokens)
|
def encrypt(*tokens)
|
||||||
digest = tokens.flatten.join(join_token)
|
digest = tokens.flatten.join(join_token)
|
||||||
stretches.times { digest = Digest::SHA512.hexdigest(digest) }
|
stretches.times { digest = Digest::SHA512.hexdigest(digest) }
|
||||||
digest
|
digest
|
||||||
end
|
end
|
||||||
|
|
||||||
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
||||||
def matches?(crypted, *tokens)
|
def matches?(crypted, *tokens)
|
||||||
encrypt(*tokens) == crypted
|
encrypt(*tokens) == crypted
|
||||||
|
@ -47,4 +47,4 @@ module Authlogic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,24 +1,31 @@
|
||||||
module CASServer
|
module CASServer
|
||||||
module Authenticators
|
module Authenticators
|
||||||
class Base
|
class Base
|
||||||
|
def self.setup opts
|
||||||
|
# this would be called at rubycas-server start-up,
|
||||||
|
# override this method to setup what you need,
|
||||||
|
# e.g. setup database connection.
|
||||||
|
# leave it empty if you don't need to setup something.
|
||||||
|
end
|
||||||
|
|
||||||
attr_accessor :options
|
attr_accessor :options
|
||||||
attr_reader :username # make this accessible so that we can pick up any
|
attr_reader :username # make this accessible so that we can pick up any
|
||||||
# transformations done within the authenticator
|
# transformations done within the authenticator
|
||||||
|
|
||||||
def validate(credentials)
|
def validate(credentials)
|
||||||
raise NotImplementedError, "This method must be implemented by a class extending #{self.class}"
|
raise NotImplementedError, "This method must be implemented by a class extending #{self.class}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure(options)
|
def configure(options)
|
||||||
raise ArgumentError, "options must be a HashWithIndifferentAccess" unless options.kind_of? HashWithIndifferentAccess
|
raise ArgumentError, "options must be a HashWithIndifferentAccess" unless options.kind_of? HashWithIndifferentAccess
|
||||||
@options = options.dup
|
@options = options.dup
|
||||||
@extra_attributes = {}
|
@extra_attributes = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def extra_attributes
|
def extra_attributes
|
||||||
@extra_attributes
|
@extra_attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def read_standard_credentials(credentials)
|
def read_standard_credentials(credentials)
|
||||||
@username = credentials[:username]
|
@username = credentials[:username]
|
||||||
|
@ -26,7 +33,7 @@ module CASServer
|
||||||
@service = credentials[:service]
|
@service = credentials[:service]
|
||||||
@request = credentials[:request]
|
@request = credentials[:request]
|
||||||
end
|
end
|
||||||
|
|
||||||
def extra_attributes_to_extract
|
def extra_attributes_to_extract
|
||||||
if @options[:extra_attributes].kind_of? Array
|
if @options[:extra_attributes].kind_of? Array
|
||||||
attrs = @options[:extra_attributes]
|
attrs = @options[:extra_attributes]
|
||||||
|
@ -36,13 +43,13 @@ module CASServer
|
||||||
$LOG.error("Can't figure out attribute list from #{@options[:extra_attributes].inspect}. This must be an Aarray of column names or a comma-separated list.")
|
$LOG.error("Can't figure out attribute list from #{@options[:extra_attributes].inspect}. This must be an Aarray of column names or a comma-separated list.")
|
||||||
attrs = []
|
attrs = []
|
||||||
end
|
end
|
||||||
|
|
||||||
$LOG.debug("#{self.class.name} will try to extract the following extra_attributes: #{attrs.inspect}")
|
$LOG.debug("#{self.class.name} will try to extract the following extra_attributes: #{attrs.inspect}")
|
||||||
return attrs
|
return attrs
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AuthenticatorError < Exception
|
class AuthenticatorError < Exception
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ require 'casserver/authenticators/base'
|
||||||
# fall back to some other authentication mechanism.
|
# fall back to some other authentication mechanism.
|
||||||
#
|
#
|
||||||
# Here's an example of how to use two chained authenticators in the config.yml
|
# Here's an example of how to use two chained authenticators in the config.yml
|
||||||
# file. The server will first use the ClientCertificate authenticator, and
|
# file. The server will first use the ClientCertificate authenticator, and
|
||||||
# only fall back to the SQL authenticator of the first one fails:
|
# only fall back to the SQL authenticator of the first one fails:
|
||||||
#
|
#
|
||||||
# authenticator:
|
# authenticator:
|
||||||
|
@ -30,17 +30,17 @@ require 'casserver/authenticators/base'
|
||||||
class CASServer::Authenticators::ClientCertificate < CASServer::Authenticators::Base
|
class CASServer::Authenticators::ClientCertificate < CASServer::Authenticators::Base
|
||||||
def validate(credentials)
|
def validate(credentials)
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
|
||||||
@client_cert = credentials[:request]['SSL_CLIENT_CERT']
|
@client_cert = credentials[:request]['SSL_CLIENT_CERT']
|
||||||
|
|
||||||
# note that I haven't actually tested to see if SSL_CLIENT_CERT gets
|
# note that I haven't actually tested to see if SSL_CLIENT_CERT gets
|
||||||
# filled with data when a client cert is provided, but this should be
|
# filled with data when a client cert is provided, but this should be
|
||||||
# the case at least in theory :)
|
# the case at least in theory :)
|
||||||
|
|
||||||
return false if @client_cert.blank?
|
return false if @client_cert.blank?
|
||||||
|
|
||||||
# IMPLEMENT SSL CERTIFICATE VALIDATION CODE HERE
|
# IMPLEMENT SSL CERTIFICATE VALIDATION CODE HERE
|
||||||
|
|
||||||
return true # if SSL certificate is valid, false otherwise
|
return true # if SSL certificate is valid, false otherwise
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'net/http'
|
||||||
require 'net/https'
|
require 'net/https'
|
||||||
require 'timeout'
|
require 'timeout'
|
||||||
|
|
||||||
# Validates Google accounts against Google's authentication service -- in other
|
# Validates Google accounts against Google's authentication service -- in other
|
||||||
# words, this authenticator allows users to log in to CAS using their
|
# words, this authenticator allows users to log in to CAS using their
|
||||||
# Gmail/Google accounts.
|
# Gmail/Google accounts.
|
||||||
class CASServer::Authenticators::Google < CASServer::Authenticators::Base
|
class CASServer::Authenticators::Google < CASServer::Authenticators::Base
|
||||||
|
@ -12,19 +12,19 @@ class CASServer::Authenticators::Google < CASServer::Authenticators::Base
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
|
||||||
return false if @username.blank? || @password.blank?
|
return false if @username.blank? || @password.blank?
|
||||||
|
|
||||||
auth_data = {
|
auth_data = {
|
||||||
'Email' => @username,
|
'Email' => @username,
|
||||||
'Passwd' => @password,
|
'Passwd' => @password,
|
||||||
'service' => 'xapi',
|
'service' => 'xapi',
|
||||||
'source' => 'RubyCAS-Server',
|
'source' => 'RubyCAS-Server',
|
||||||
'accountType' => 'HOSTED_OR_GOOGLE'
|
'accountType' => 'HOSTED_OR_GOOGLE'
|
||||||
}
|
}
|
||||||
|
|
||||||
url = URI.parse('https://www.google.com/accounts/ClientLogin')
|
url = URI.parse('https://www.google.com/accounts/ClientLogin')
|
||||||
http = Net::HTTP.new(url.host, url.port)
|
http = Net::HTTP.new(url.host, url.port)
|
||||||
http.use_ssl = true
|
http.use_ssl = true
|
||||||
|
|
||||||
# TODO: make the timeout configurable
|
# TODO: make the timeout configurable
|
||||||
wait_seconds = 10
|
wait_seconds = 10
|
||||||
begin
|
begin
|
||||||
|
@ -34,7 +34,7 @@ class CASServer::Authenticators::Google < CASServer::Authenticators::Base
|
||||||
req.set_form_data(auth_data,'&')
|
req.set_form_data(auth_data,'&')
|
||||||
conn.request(req)
|
conn.request(req)
|
||||||
end
|
end
|
||||||
|
|
||||||
case res
|
case res
|
||||||
when Net::HTTPSuccess
|
when Net::HTTPSuccess
|
||||||
true
|
true
|
||||||
|
|
|
@ -26,47 +26,47 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
|
||||||
return false if @password.blank?
|
return false if @password.blank?
|
||||||
|
|
||||||
raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
||||||
raise CASServer::AuthenticatorError, "Invalid LDAP authenticator configuration!" unless @options[:ldap]
|
raise CASServer::AuthenticatorError, "Invalid LDAP authenticator configuration!" unless @options[:ldap]
|
||||||
raise CASServer::AuthenticatorError, "You must specify a server host in the LDAP configuration!" unless @options[:ldap][:host] || @options[:ldap][:server]
|
raise CASServer::AuthenticatorError, "You must specify a server host in the LDAP configuration!" unless @options[:ldap][:host] || @options[:ldap][:server]
|
||||||
|
|
||||||
raise CASServer::AuthenticatorError, "The username '#{@username}' contains invalid characters." if (@username =~ /[*\(\)\0\/]/)
|
raise CASServer::AuthenticatorError, "The username '#{@username}' contains invalid characters." if (@username =~ /[*\(\)\0\/]/)
|
||||||
|
|
||||||
preprocess_username
|
preprocess_username
|
||||||
|
|
||||||
@ldap = Net::LDAP.new
|
@ldap = Net::LDAP.new
|
||||||
|
|
||||||
|
|
||||||
@options[:ldap][:host] ||= @options[:ldap][:server]
|
@options[:ldap][:host] ||= @options[:ldap][:server]
|
||||||
@ldap.host = @options[:ldap][:host]
|
@ldap.host = @options[:ldap][:host]
|
||||||
@ldap.port = @options[:ldap][:port] if @options[:ldap][:port]
|
@ldap.port = @options[:ldap][:port] if @options[:ldap][:port]
|
||||||
@ldap.encryption(@options[:ldap][:encryption].intern) if @options[:ldap][:encryption]
|
@ldap.encryption(@options[:ldap][:encryption].intern) if @options[:ldap][:encryption]
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if @options[:ldap][:auth_user]
|
if @options[:ldap][:auth_user]
|
||||||
bind_success = bind_by_username_with_preauthentication
|
bind_success = bind_by_username_with_preauthentication
|
||||||
else
|
else
|
||||||
bind_success = bind_by_username
|
bind_success = bind_by_username
|
||||||
end
|
end
|
||||||
|
|
||||||
return false unless bind_success
|
return false unless bind_success
|
||||||
|
|
||||||
entry = find_user
|
entry = find_user
|
||||||
extract_extra_attributes(entry)
|
extract_extra_attributes(entry)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
rescue Net::LDAP::LdapError => e
|
rescue Net::LDAP::LdapError => e
|
||||||
raise CASServer::AuthenticatorError,
|
raise CASServer::AuthenticatorError,
|
||||||
"LDAP authentication failed with '#{e}'. Check your authenticator configuration."
|
"LDAP authentication failed with '#{e}'. Check your authenticator configuration."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def default_username_attribute
|
def default_username_attribute
|
||||||
"cn"
|
"cn"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# Add prefix to username, if :username_prefix was specified in the :ldap config.
|
# Add prefix to username, if :username_prefix was specified in the :ldap config.
|
||||||
def preprocess_username
|
def preprocess_username
|
||||||
|
@ -78,34 +78,34 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
||||||
# added to the LDAP query for the username.
|
# added to the LDAP query for the username.
|
||||||
def bind_by_username
|
def bind_by_username
|
||||||
username_attribute = options[:ldap][:username_attribute] || default_username_attribute
|
username_attribute = options[:ldap][:username_attribute] || default_username_attribute
|
||||||
|
|
||||||
@ldap.bind_as(:base => @options[:ldap][:base], :password => @password, :filter => user_filter)
|
@ldap.bind_as(:base => @options[:ldap][:base], :password => @password, :filter => user_filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
# If an auth_user is specified, we will connect ("pre-authenticate") with the
|
# If an auth_user is specified, we will connect ("pre-authenticate") with the
|
||||||
# LDAP server using the authenticator account, and then attempt to bind as the
|
# LDAP server using the authenticator account, and then attempt to bind as the
|
||||||
# user who is actually trying to authenticate. Note that you need to set up
|
# user who is actually trying to authenticate. Note that you need to set up
|
||||||
# the special authenticator account first. Also, auth_user must be the authenticator
|
# the special authenticator account first. Also, auth_user must be the authenticator
|
||||||
# user's full CN, which is probably not the same as their username.
|
# user's full CN, which is probably not the same as their username.
|
||||||
#
|
#
|
||||||
# This pre-authentication process is necessary because binding can only be done
|
# This pre-authentication process is necessary because binding can only be done
|
||||||
# using the CN, so having just the username is not enough. We connect as auth_user,
|
# using the CN, so having just the username is not enough. We connect as auth_user,
|
||||||
# and then try to find the target user's CN based on the given username. Then we bind
|
# and then try to find the target user's CN based on the given username. Then we bind
|
||||||
# as the target user to validate their credentials.
|
# as the target user to validate their credentials.
|
||||||
def bind_by_username_with_preauthentication
|
def bind_by_username_with_preauthentication
|
||||||
raise CASServer::AuthenticatorError, "A password must be specified in the configuration for the authenticator user!" unless
|
raise CASServer::AuthenticatorError, "A password must be specified in the configuration for the authenticator user!" unless
|
||||||
@options[:ldap][:auth_password]
|
@options[:ldap][:auth_password]
|
||||||
|
|
||||||
@ldap.authenticate(@options[:ldap][:auth_user], @options[:ldap][:auth_password])
|
@ldap.authenticate(@options[:ldap][:auth_user], @options[:ldap][:auth_password])
|
||||||
|
|
||||||
@ldap.bind_as(:base => @options[:ldap][:base], :password => @password, :filter => user_filter)
|
@ldap.bind_as(:base => @options[:ldap][:base], :password => @password, :filter => user_filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Combine the filter for finding the user with the optional extra filter specified in the config
|
# Combine the filter for finding the user with the optional extra filter specified in the config
|
||||||
# (if any).
|
# (if any).
|
||||||
def user_filter
|
def user_filter
|
||||||
username_attribute = options[:ldap][:username_attribute] || default_username_attribute
|
username_attribute = options[:ldap][:username_attribute] || default_username_attribute
|
||||||
|
|
||||||
filter = Net::LDAP::Filter.eq(username_attribute, @username)
|
filter = Net::LDAP::Filter.eq(username_attribute, @username)
|
||||||
unless @options[:ldap][:filter].blank?
|
unless @options[:ldap][:filter].blank?
|
||||||
filter &= Net::LDAP::Filter.construct(@options[:ldap][:filter])
|
filter &= Net::LDAP::Filter.construct(@options[:ldap][:filter])
|
||||||
|
@ -113,14 +113,14 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
||||||
|
|
||||||
filter
|
filter
|
||||||
end
|
end
|
||||||
|
|
||||||
# Finds the user based on the user_filter (this is called after authentication).
|
# Finds the user based on the user_filter (this is called after authentication).
|
||||||
# We do this to make it possible to extract extra_attributes.
|
# We do this to make it possible to extract extra_attributes.
|
||||||
def find_user
|
def find_user
|
||||||
results = @ldap.search( :base => options[:ldap][:base], :filter => user_filter)
|
results = @ldap.search( :base => options[:ldap][:base], :filter => user_filter)
|
||||||
return results.first
|
return results.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_extra_attributes(ldap_entry)
|
def extract_extra_attributes(ldap_entry)
|
||||||
@extra_attributes = {}
|
@extra_attributes = {}
|
||||||
extra_attributes_to_extract.each do |attr|
|
extra_attributes_to_extract.each do |attr|
|
||||||
|
@ -136,7 +136,7 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if @extra_attributes.empty?
|
if @extra_attributes.empty?
|
||||||
$LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
|
$LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
|
||||||
else
|
else
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# I started working on this but run into a wall, so I am commiting what I've got
|
# I started working on this but run into a wall, so I am commiting what I've got
|
||||||
# done and leaving it here with hopes of one day finishing it.
|
# done and leaving it here with hopes of one day finishing it.
|
||||||
#
|
#
|
||||||
# The main problem is that although I've got the Lan Manager/NTLM password hash,
|
# The main problem is that although I've got the Lan Manager/NTLM password hash,
|
||||||
# I'm not sure what to do with it. i.e. I need to check it against the AD or SMB
|
# I'm not sure what to do with it. i.e. I need to check it against the AD or SMB
|
||||||
# server or something... maybe faking an SMB share connection and using the LM
|
# server or something... maybe faking an SMB share connection and using the LM
|
||||||
|
@ -35,10 +35,10 @@ module CASServer
|
||||||
else
|
else
|
||||||
raise "Invalid NTLM reply from client."
|
raise "Invalid NTLM reply from client."
|
||||||
end
|
end
|
||||||
|
|
||||||
if t1
|
if t1
|
||||||
$LOG.debug "T1: #{t1.inspect}"
|
$LOG.debug "T1: #{t1.inspect}"
|
||||||
|
|
||||||
# now put together a Type2 message asking for the client to send
|
# now put together a Type2 message asking for the client to send
|
||||||
# back NTLM credentials (LM hash and such)
|
# back NTLM credentials (LM hash and such)
|
||||||
t2 = Net::NTLM::Message::Type2.new
|
t2 = Net::NTLM::Message::Type2.new
|
||||||
|
@ -46,11 +46,11 @@ module CASServer
|
||||||
t2.set_flag :NTLM
|
t2.set_flag :NTLM
|
||||||
t2.context = 0x0000000000000000 # this can probably just be left unassigned
|
t2.context = 0x0000000000000000 # this can probably just be left unassigned
|
||||||
t2.challenge = 0x0123456789abcdef # this should be a random 8-byte integer
|
t2.challenge = 0x0123456789abcdef # this should be a random 8-byte integer
|
||||||
|
|
||||||
$LOG.debug "T2: #{t2.inspect}"
|
$LOG.debug "T2: #{t2.inspect}"
|
||||||
$LOG.debug "T2: #{t2.serialize}"
|
$LOG.debug "T2: #{t2.serialize}"
|
||||||
headers["WWW-Authenticate"] = "NTLM #{t2.encode64}"
|
headers["WWW-Authenticate"] = "NTLM #{t2.encode64}"
|
||||||
|
|
||||||
# the client should respond to this with a Type3 message...
|
# the client should respond to this with a Type3 message...
|
||||||
r('401', '', headers)
|
r('401', '', headers)
|
||||||
return
|
return
|
||||||
|
@ -58,7 +58,7 @@ module CASServer
|
||||||
# NOTE: for some reason the server never receives the T3 response, even though monitoring
|
# NOTE: for some reason the server never receives the T3 response, even though monitoring
|
||||||
# the HTTP traffic I can see that the client does send it back... there's probably
|
# the HTTP traffic I can see that the client does send it back... there's probably
|
||||||
# another bug hiding somewhere here
|
# another bug hiding somewhere here
|
||||||
|
|
||||||
lm_response = t3.lm_response
|
lm_response = t3.lm_response
|
||||||
ntlm_response = t3.ntlm_response
|
ntlm_response = t3.ntlm_response
|
||||||
username = t3.user
|
username = t3.user
|
||||||
|
@ -67,8 +67,8 @@ module CASServer
|
||||||
# call would do it?
|
# call would do it?
|
||||||
$LOG.debug "T3 LM: #{lm_response.inspect}"
|
$LOG.debug "T3 LM: #{lm_response.inspect}"
|
||||||
$LOG.debug "T3 NTLM: #{ntlm_response.inspect}"
|
$LOG.debug "T3 NTLM: #{ntlm_response.inspect}"
|
||||||
|
|
||||||
# assuming the authentication was successful, we'll now need to do something in the
|
# assuming the authentication was successful, we'll now need to do something in the
|
||||||
# controller acting as if we'd received correct login credentials (i.e. proceed as if
|
# controller acting as if we'd received correct login credentials (i.e. proceed as if
|
||||||
# CAS authentication was successful).... if authentication failed, then we should
|
# CAS authentication was successful).... if authentication failed, then we should
|
||||||
# just fall back to old-school web-based authentication, asking the user to enter
|
# just fall back to old-school web-based authentication, asking the user to enter
|
||||||
|
@ -85,4 +85,4 @@ module CASServer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,10 +13,10 @@ class CASServer::Authenticators::OpenID < CASServer::Authenticators::Base
|
||||||
def validate(credentials)
|
def validate(credentials)
|
||||||
raise NotImplementedError, "The OpenID authenticator is not yet implemented. "+
|
raise NotImplementedError, "The OpenID authenticator is not yet implemented. "+
|
||||||
"See http://code.google.com/p/rubycas-server/issues/detail?id=36 if you are interested in helping this along."
|
"See http://code.google.com/p/rubycas-server/issues/detail?id=36 if you are interested in helping this along."
|
||||||
|
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
|
||||||
store = OpenID::Store::Memory.new
|
store = OpenID::Store::Memory.new
|
||||||
consumer = OpenID::Consumer.new({}, store)
|
consumer = OpenID::Consumer.new({}, store)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,15 +7,15 @@ rescue LoadError
|
||||||
require 'active_record'
|
require 'active_record'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Authenticates against a plain SQL table.
|
# Authenticates against a plain SQL table.
|
||||||
#
|
#
|
||||||
# This assumes that all of your users are stored in a table that has a 'username'
|
# This assumes that all of your users are stored in a table that has a 'username'
|
||||||
# column and a 'password' column. When the user logs in, CAS conects to the
|
# column and a 'password' column. When the user logs in, CAS conects to the
|
||||||
# database and looks for a matching username/password in the users table. If a
|
# database and looks for a matching username/password in the users table. If a
|
||||||
# matching username and password is found, authentication is successful.
|
# matching username and password is found, authentication is successful.
|
||||||
#
|
#
|
||||||
# Any database backend supported by ActiveRecord can be used.
|
# Any database backend supported by ActiveRecord can be used.
|
||||||
#
|
#
|
||||||
# Config example:
|
# Config example:
|
||||||
#
|
#
|
||||||
# authenticator:
|
# authenticator:
|
||||||
|
@ -24,7 +24,7 @@ end
|
||||||
# adapter: mysql
|
# adapter: mysql
|
||||||
# database: some_database_with_users_table
|
# database: some_database_with_users_table
|
||||||
# username: root
|
# username: root
|
||||||
# password:
|
# password:
|
||||||
# server: localhost
|
# server: localhost
|
||||||
# user_table: users
|
# user_table: users
|
||||||
# username_column: username
|
# username_column: username
|
||||||
|
@ -34,10 +34,10 @@ end
|
||||||
# provide the client with the authenticated user's username. However it is now
|
# provide the client with the authenticated user's username. However it is now
|
||||||
# possible for the server to provide the client with additional attributes.
|
# possible for the server to provide the client with additional attributes.
|
||||||
# You can configure the SQL authenticator to provide data from additional
|
# You can configure the SQL authenticator to provide data from additional
|
||||||
# columns in the users table by listing the names of the columns under the
|
# columns in the users table by listing the names of the columns under the
|
||||||
# 'extra_attributes' option. Note though that this functionality is experimental.
|
# 'extra_attributes' option. Note though that this functionality is experimental.
|
||||||
# It should work with RubyCAS-Client, but may or may not work with other CAS
|
# It should work with RubyCAS-Client, but may or may not work with other CAS
|
||||||
# clients.
|
# clients.
|
||||||
#
|
#
|
||||||
# For example, with this configuration, the 'full_name' and 'access_level'
|
# For example, with this configuration, the 'full_name' and 'access_level'
|
||||||
# columns will be provided to your CAS clients along with the username:
|
# columns will be provided to your CAS clients along with the username:
|
||||||
|
@ -51,43 +51,53 @@ end
|
||||||
# username_column: username
|
# username_column: username
|
||||||
# password_column: password
|
# password_column: password
|
||||||
# extra_attributes: full_name, access_level
|
# extra_attributes: full_name, access_level
|
||||||
#
|
#
|
||||||
class CASServer::Authenticators::SQL < CASServer::Authenticators::Base
|
class CASServer::Authenticators::SQL < CASServer::Authenticators::Base
|
||||||
|
def self.setup opts
|
||||||
|
raise CASServer::AuthenticatorError, "Invalid authenticator configuration!" unless opts[:database]
|
||||||
|
|
||||||
|
user_model_name = "CASUser_#{opts[:auth_index]}"
|
||||||
|
$LOG.debug "CREATING USER MODEL #{user_model_name}"
|
||||||
|
|
||||||
|
class_eval %{
|
||||||
|
class #{user_model_name} < ActiveRecord::Base
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
@user_model = const_get(user_model_name)
|
||||||
|
@user_model.establish_connection(opts[:database])
|
||||||
|
@user_model.set_table_name(opts[:user_table] || 'users')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.user_model
|
||||||
|
@user_model
|
||||||
|
end
|
||||||
|
|
||||||
def validate(credentials)
|
def validate(credentials)
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
raise_if_not_configured
|
||||||
raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
|
||||||
|
user_model = self.class.user_model
|
||||||
user_model = establish_database_connection_if_necessary
|
|
||||||
|
|
||||||
username_column = @options[:username_column] || 'username'
|
username_column = @options[:username_column] || 'username'
|
||||||
password_column = @options[:password_column] || 'password'
|
password_column = @options[:password_column] || 'password'
|
||||||
|
|
||||||
results = user_model.find(:all, :conditions => ["#{username_column} = ? AND #{password_column} = ?", @username, @password])
|
results = user_model.find(:all, :conditions => ["#{username_column} = ? AND #{password_column} = ?", @username, @password])
|
||||||
|
|
||||||
if results.size > 0
|
if results.size > 0
|
||||||
$LOG.warn("#{self.class}: Multiple matches found for user #{@username.inspect}") if results.size > 1
|
$LOG.warn("#{self.class}: Multiple matches found for user #{@username.inspect}") if results.size > 1
|
||||||
|
|
||||||
unless @options[:extra_attributes].blank?
|
unless @options[:extra_attributes].blank?
|
||||||
if results.size > 1
|
if results.size > 1
|
||||||
$LOG.warn("#{self.class}: Unable to extract extra_attributes because multiple matches were found for #{@username.inspect}")
|
$LOG.warn("#{self.class}: Unable to extract extra_attributes because multiple matches were found for #{@username.inspect}")
|
||||||
else
|
else
|
||||||
user = results.first
|
user = results.first
|
||||||
|
|
||||||
@extra_attributes = {}
|
extract_extra(user)
|
||||||
extra_attributes_to_extract.each do |col|
|
log_extra
|
||||||
@extra_attributes[col] = user.send(col)
|
|
||||||
end
|
|
||||||
|
|
||||||
if @extra_attributes.empty?
|
|
||||||
$LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
|
|
||||||
else
|
|
||||||
$LOG.debug("#{self.class}: Read the following extra_attributes for user #{@username.inspect}: #{@extra_attributes.inspect}")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
|
@ -95,25 +105,24 @@ class CASServer::Authenticators::SQL < CASServer::Authenticators::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def establish_database_connection_if_necessary
|
def raise_if_not_configured
|
||||||
raise CASServer::AuthenticatorError, "Invalid authenticator configuration!" unless @options[:database]
|
raise CASServer::AuthenticatorError.new(
|
||||||
|
"Cannot validate credentials because the authenticator hasn't yet been configured"
|
||||||
user_model_name = "CASUser_#{@options[:auth_index]}"
|
) unless @options
|
||||||
if self.class.const_defined?(user_model_name)
|
|
||||||
$LOG.debug "REUSING USER MODEL #{user_model_name}"
|
|
||||||
user_model = self.class.const_get(user_model_name)
|
|
||||||
else
|
|
||||||
$LOG.debug "CREATING USER MODEL #{user_model_name}"
|
|
||||||
self.class.class_eval %{
|
|
||||||
class #{user_model_name} < ActiveRecord::Base
|
|
||||||
end
|
|
||||||
}
|
|
||||||
user_model = self.class.const_get(user_model_name)
|
|
||||||
user_model.establish_connection(options[:database])
|
|
||||||
user_model.set_table_name @options[:user_table] || "users"
|
|
||||||
end
|
|
||||||
|
|
||||||
user_model
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
def extract_extra user
|
||||||
|
@extra_attributes = {}
|
||||||
|
extra_attributes_to_extract.each do |col|
|
||||||
|
@extra_attributes[col] = user.send(col)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_extra
|
||||||
|
if @extra_attributes.empty?
|
||||||
|
$LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
|
||||||
|
else
|
||||||
|
$LOG.debug("#{self.class}: Read the following extra_attributes for user #{@username.inspect}: #{@extra_attributes.inspect}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -15,15 +15,15 @@ rescue LoadError
|
||||||
require 'active_record'
|
require 'active_record'
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is a version of the SQL authenticator that works nicely with Authlogic.
|
# This is a version of the SQL authenticator that works nicely with Authlogic.
|
||||||
# Passwords are encrypted the same way as it done in Authlogic.
|
# Passwords are encrypted the same way as it done in Authlogic.
|
||||||
# Before use you this, you MUST configure rest_auth_digest_streches and rest_auth_site_key in
|
# Before use you this, you MUST configure rest_auth_digest_streches and rest_auth_site_key in
|
||||||
# config.
|
# config.
|
||||||
#
|
#
|
||||||
# Using this authenticator requires restful authentication plugin on rails (client) side.
|
# Using this authenticator requires restful authentication plugin on rails (client) side.
|
||||||
#
|
#
|
||||||
# * git://github.com/binarylogic/authlogic.git
|
# * git://github.com/binarylogic/authlogic.git
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
|
|
||||||
# authenticator:
|
# authenticator:
|
||||||
|
@ -44,11 +44,10 @@ class CASServer::Authenticators::SQLAuthlogic < CASServer::Authenticators::SQL
|
||||||
|
|
||||||
def validate(credentials)
|
def validate(credentials)
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
raise_if_not_configured
|
||||||
raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
|
||||||
|
user_model = self.class.user_model
|
||||||
user_model = establish_database_connection_if_necessary
|
|
||||||
|
|
||||||
username_column = @options[:username_column] || "login"
|
username_column = @options[:username_column] || "login"
|
||||||
password_column = @options[:password_column] || "crypted_password"
|
password_column = @options[:password_column] || "crypted_password"
|
||||||
salt_column = @options[:salt_column]
|
salt_column = @options[:salt_column]
|
||||||
|
@ -70,17 +69,10 @@ class CASServer::Authenticators::SQLAuthlogic < CASServer::Authenticators::SQL
|
||||||
if results.size > 1
|
if results.size > 1
|
||||||
$LOG.warn("#{self.class}: Unable to extract extra_attributes because multiple matches were found for #{@username.inspect}")
|
$LOG.warn("#{self.class}: Unable to extract extra_attributes because multiple matches were found for #{@username.inspect}")
|
||||||
else
|
else
|
||||||
|
|
||||||
@extra_attributes = {}
|
extract_extra(user)
|
||||||
extra_attributes_to_extract.each do |col|
|
log_extra
|
||||||
@extra_attributes[col] = user.send(col)
|
|
||||||
end
|
|
||||||
|
|
||||||
if @extra_attributes.empty?
|
|
||||||
$LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
|
|
||||||
else
|
|
||||||
$LOG.debug("#{self.class}: Read the following extra_attributes for user #{@username.inspect}: #{@extra_attributes.inspect}")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'casserver/authenticators/base'
|
require 'casserver/authenticators/sql'
|
||||||
|
|
||||||
require 'digest/sha1'
|
require 'digest/sha1'
|
||||||
require 'digest/sha2'
|
require 'digest/sha2'
|
||||||
|
@ -6,58 +6,15 @@ require 'digest/sha2'
|
||||||
$: << File.dirname(File.expand_path(__FILE__)) + "/../../../vendor/isaac_0.9.1"
|
$: << File.dirname(File.expand_path(__FILE__)) + "/../../../vendor/isaac_0.9.1"
|
||||||
require 'crypt/ISAAC'
|
require 'crypt/ISAAC'
|
||||||
|
|
||||||
begin
|
# This is a more secure version of the SQL authenticator. Passwords are encrypted
|
||||||
require 'active_record'
|
|
||||||
rescue LoadError
|
|
||||||
require 'rubygems'
|
|
||||||
require 'active_record'
|
|
||||||
end
|
|
||||||
|
|
||||||
# This is a more secure version of the SQL authenticator. Passwords are encrypted
|
|
||||||
# rather than being stored in plain text.
|
# rather than being stored in plain text.
|
||||||
#
|
#
|
||||||
# Based on code contributed by Ben Mabey.
|
# Based on code contributed by Ben Mabey.
|
||||||
#
|
#
|
||||||
# Using this authenticator requires some configuration on the client side. Please see
|
# Using this authenticator requires some configuration on the client side. Please see
|
||||||
# http://code.google.com/p/rubycas-server/wiki/UsingTheSQLEncryptedAuthenticator
|
# http://code.google.com/p/rubycas-server/wiki/UsingTheSQLEncryptedAuthenticator
|
||||||
class CASServer::Authenticators::SQLEncrypted < CASServer::Authenticators::Base
|
class CASServer::Authenticators::SQLEncrypted < CASServer::Authenticators::SQL
|
||||||
|
# Include this module into your application's user model.
|
||||||
def validate(credentials)
|
|
||||||
read_standard_credentials(credentials)
|
|
||||||
|
|
||||||
raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
|
||||||
|
|
||||||
user_model = establish_database_connection_if_necessary
|
|
||||||
|
|
||||||
username_column = @options[:username_column] || "username"
|
|
||||||
encrypt_function = @options[:encrypt_function] || 'user.encrypted_password == Digest::SHA256.hexdigest("#{user.encryption_salt}::#{@password}")'
|
|
||||||
|
|
||||||
results = user_model.find(:all, :conditions => ["#{username_column} = ?", @username])
|
|
||||||
|
|
||||||
if results.size > 0
|
|
||||||
$LOG.warn("Multiple matches found for user '#{@username}'") if results.size > 1
|
|
||||||
user = results.first
|
|
||||||
|
|
||||||
unless @options[:extra_attributes].blank?
|
|
||||||
@extra_attributes = {}
|
|
||||||
extra_attributes_to_extract.each do |col|
|
|
||||||
@extra_attributes[col] = user.send(col)
|
|
||||||
end
|
|
||||||
|
|
||||||
if @extra_attributes.empty?
|
|
||||||
$LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
|
|
||||||
else
|
|
||||||
$LOG.debug("#{self.class}: Read the following extra_attributes for user #{@username.inspect}: #{@extra_attributes.inspect}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return eval(encrypt_function)
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Include this module into your application's user model.
|
|
||||||
#
|
#
|
||||||
# Your model must have an 'encrypted_password' column where the password will be stored,
|
# Your model must have an 'encrypted_password' column where the password will be stored,
|
||||||
# and an 'encryption_salt' column that will be populated with a random string before
|
# and an 'encryption_salt' column that will be populated with a random string before
|
||||||
|
@ -67,40 +24,44 @@ class CASServer::Authenticators::SQLEncrypted < CASServer::Authenticators::Base
|
||||||
raise "#{self} should be inclued in an ActiveRecord class!" unless mod.respond_to?(:before_save)
|
raise "#{self} should be inclued in an ActiveRecord class!" unless mod.respond_to?(:before_save)
|
||||||
mod.before_save :generate_encryption_salt
|
mod.before_save :generate_encryption_salt
|
||||||
end
|
end
|
||||||
|
|
||||||
def encrypt(str)
|
def encrypt(str)
|
||||||
generate_encryption_salt unless encryption_salt
|
generate_encryption_salt unless encryption_salt
|
||||||
Digest::SHA256.hexdigest("#{encryption_salt}::#{str}")
|
Digest::SHA256.hexdigest("#{encryption_salt}::#{str}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def password=(password)
|
def password=(password)
|
||||||
self[:encrypted_password] = encrypt(password)
|
self[:encrypted_password] = encrypt(password)
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_encryption_salt
|
def generate_encryption_salt
|
||||||
self.encryption_salt = Digest::SHA1.hexdigest(Crypt::ISAAC.new.rand(2**31).to_s) unless
|
self.encryption_salt = Digest::SHA1.hexdigest(Crypt::ISAAC.new.rand(2**31).to_s) unless
|
||||||
encryption_salt
|
encryption_salt
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
def self.setup opts
|
||||||
def establish_database_connection_if_necessary
|
super(opts)
|
||||||
raise CASServer::AuthenticatorError, "Invalid authenticator configuration!" unless @options[:database]
|
user_model.__send__(:include, EncryptedPassword)
|
||||||
|
end
|
||||||
|
|
||||||
user_model_name = "CASUser_#{@options[:auth_index]}"
|
def validate(credentials)
|
||||||
if self.class.const_defined?(user_model_name)
|
read_standard_credentials(credentials)
|
||||||
user_model = self.class.const_get(user_model_name)
|
raise_if_not_configured
|
||||||
|
|
||||||
|
user_model = self.class.user_model
|
||||||
|
|
||||||
|
username_column = @options[:username_column] || "username"
|
||||||
|
encrypt_function = @options[:encrypt_function] || 'user.encrypted_password == Digest::SHA256.hexdigest("#{user.encryption_salt}::#{@password}")'
|
||||||
|
|
||||||
|
results = user_model.find(:all, :conditions => ["#{username_column} = ?", @username])
|
||||||
|
|
||||||
|
if results.size > 0
|
||||||
|
$LOG.warn("Multiple matches found for user '#{@username}'") if results.size > 1
|
||||||
|
user = results.first
|
||||||
|
return eval(encrypt_function)
|
||||||
else
|
else
|
||||||
self.class.class_eval %{
|
return false
|
||||||
class #{user_model_name} < ActiveRecord::Base
|
|
||||||
include EncryptedPassword
|
|
||||||
end
|
|
||||||
}
|
|
||||||
user_model = self.class.const_get(user_model_name)
|
|
||||||
user_model.set_table_name @options[:user_table] || "users"
|
|
||||||
user_model.establish_connection(options[:database])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
user_model
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,11 +9,11 @@ require 'digest/md5'
|
||||||
# Drupal, you should use 'name' for the :username_column config option, and
|
# Drupal, you should use 'name' for the :username_column config option, and
|
||||||
# 'pass' for the :password_column.
|
# 'pass' for the :password_column.
|
||||||
class CASServer::Authenticators::SQLMd5 < CASServer::Authenticators::SQL
|
class CASServer::Authenticators::SQLMd5 < CASServer::Authenticators::SQL
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def read_standard_credentials(credentials)
|
def read_standard_credentials(credentials)
|
||||||
super
|
super
|
||||||
@password = Digest::MD5.hexdigest(@password)
|
@password = Digest::MD5.hexdigest(@password)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,10 +9,10 @@ rescue LoadError
|
||||||
require 'active_record'
|
require 'active_record'
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is a version of the SQL authenticator that works nicely with RestfulAuthentication.
|
# This is a version of the SQL authenticator that works nicely with RestfulAuthentication.
|
||||||
# Passwords are encrypted the same way as it done in RestfulAuthentication.
|
# Passwords are encrypted the same way as it done in RestfulAuthentication.
|
||||||
# Before use you this, you MUST configure rest_auth_digest_streches and rest_auth_site_key in
|
# Before use you this, you MUST configure rest_auth_digest_streches and rest_auth_site_key in
|
||||||
# config.
|
# config.
|
||||||
#
|
#
|
||||||
# Using this authenticator requires restful authentication plugin on rails (client) side.
|
# Using this authenticator requires restful authentication plugin on rails (client) side.
|
||||||
#
|
#
|
||||||
|
@ -22,27 +22,26 @@ class CASServer::Authenticators::SQLRestAuth < CASServer::Authenticators::SQLEnc
|
||||||
|
|
||||||
def validate(credentials)
|
def validate(credentials)
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
raise_if_not_configured
|
||||||
raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
|
||||||
|
user_model = self.class.user_model
|
||||||
|
|
||||||
user_model = establish_database_connection_if_necessary
|
|
||||||
|
|
||||||
username_column = @options[:username_column] || "email"
|
username_column = @options[:username_column] || "email"
|
||||||
|
|
||||||
results = user_model.find(:all, :conditions => ["#{username_column} = ?", @username])
|
results = user_model.find(:all, :conditions => ["#{username_column} = ?", @username])
|
||||||
|
|
||||||
if results.size > 0
|
if results.size > 0
|
||||||
$LOG.warn("Multiple matches found for user '#{@username}'") if results.size > 1
|
$LOG.warn("Multiple matches found for user '#{@username}'") if results.size > 1
|
||||||
user = results.first
|
user = results.first
|
||||||
return (user.crypted_password == user.encrypt(@password))
|
return (user.crypted_password == user.encrypt(@password))
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module EncryptedPassword
|
module EncryptedPassword
|
||||||
|
|
||||||
# XXX: this constants MUST be defined in config.
|
# XXX: this constants MUST be defined in config.
|
||||||
# For more details # look at restful-authentication docs.
|
# For more details # look at restful-authentication docs.
|
||||||
#
|
#
|
||||||
REST_AUTH_DIGEST_STRETCHES = $CONF.rest_auth_digest_streches
|
REST_AUTH_DIGEST_STRETCHES = $CONF.rest_auth_digest_streches
|
||||||
|
@ -51,11 +50,11 @@ class CASServer::Authenticators::SQLRestAuth < CASServer::Authenticators::SQLEnc
|
||||||
def self.included(mod)
|
def self.included(mod)
|
||||||
raise "#{self} should be inclued in an ActiveRecord class!" unless mod.respond_to?(:before_save)
|
raise "#{self} should be inclued in an ActiveRecord class!" unless mod.respond_to?(:before_save)
|
||||||
end
|
end
|
||||||
|
|
||||||
def encrypt(password)
|
def encrypt(password)
|
||||||
password_digest(password, self.salt)
|
password_digest(password, self.salt)
|
||||||
end
|
end
|
||||||
|
|
||||||
def secure_digest(*args)
|
def secure_digest(*args)
|
||||||
Digest::SHA1.hexdigest(args.flatten.join('--'))
|
Digest::SHA1.hexdigest(args.flatten.join('--'))
|
||||||
end
|
end
|
||||||
|
@ -66,6 +65,6 @@ class CASServer::Authenticators::SQLRestAuth < CASServer::Authenticators::SQLEnc
|
||||||
digest = secure_digest(digest, salt, password, REST_AUTH_SITE_KEY)
|
digest = secure_digest(digest, salt, password, REST_AUTH_SITE_KEY)
|
||||||
end
|
end
|
||||||
digest
|
digest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
require 'casserver/authenticators/base'
|
require 'casserver/authenticators/base'
|
||||||
|
|
||||||
# Dummy authenticator used for testing.
|
# Dummy authenticator used for testing.
|
||||||
# Accepts any username as valid as long as the password is "testpassword"; otherwise authentication fails.
|
# Accepts any username as valid as long as the password is "testpassword"; otherwise authentication fails.
|
||||||
# Raises an AuthenticationError when username is "do_error" (this is useful to test the Exception
|
# Raises an AuthenticationError when username is "do_error" (this is useful to test the Exception
|
||||||
# handling functionality).
|
# handling functionality).
|
||||||
class CASServer::Authenticators::Test < CASServer::Authenticators::Base
|
class CASServer::Authenticators::Test < CASServer::Authenticators::Base
|
||||||
def validate(credentials)
|
def validate(credentials)
|
||||||
read_standard_credentials(credentials)
|
read_standard_credentials(credentials)
|
||||||
|
|
||||||
raise CASServer::AuthenticatorError, "Username is 'do_error'!" if @username == 'do_error'
|
raise CASServer::AuthenticatorError, "Username is 'do_error'!" if @username == 'do_error'
|
||||||
|
|
||||||
@extra_attributes[:test_string] = "testing!"
|
@extra_attributes[:test_string] = "testing!"
|
||||||
@extra_attributes[:test_numeric] = 123.45
|
@extra_attributes[:test_numeric] = 123.45
|
||||||
@extra_attributes[:test_serialized] = {:foo => 'bar', :alpha => [1,2,3]}
|
@extra_attributes[:test_serialized] = {:foo => 'bar', :alpha => [1,2,3]}
|
||||||
|
|
||||||
return @password == "testpassword"
|
return @password == "testpassword"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,19 +11,19 @@ module CASServer::CAS
|
||||||
# 3.5 (login ticket)
|
# 3.5 (login ticket)
|
||||||
lt = LoginTicket.new
|
lt = LoginTicket.new
|
||||||
lt.ticket = "LT-" + CASServer::Utils.random_string
|
lt.ticket = "LT-" + CASServer::Utils.random_string
|
||||||
|
|
||||||
lt.client_hostname = @env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']
|
lt.client_hostname = @env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']
|
||||||
lt.save!
|
lt.save!
|
||||||
$LOG.debug("Generated login ticket '#{lt.ticket}' for client" +
|
$LOG.debug("Generated login ticket '#{lt.ticket}' for client" +
|
||||||
" at '#{lt.client_hostname}'")
|
" at '#{lt.client_hostname}'")
|
||||||
lt
|
lt
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates a TicketGrantingTicket for the given username. This is done when the user logs in
|
# Creates a TicketGrantingTicket for the given username. This is done when the user logs in
|
||||||
# for the first time to establish their SSO session (after their credentials have been validated).
|
# for the first time to establish their SSO session (after their credentials have been validated).
|
||||||
#
|
#
|
||||||
# The optional 'extra_attributes' parameter takes a hash of additional attributes
|
# The optional 'extra_attributes' parameter takes a hash of additional attributes
|
||||||
# that will be sent along with the username in the CAS response to subsequent
|
# that will be sent along with the username in the CAS response to subsequent
|
||||||
# validation requests from clients.
|
# validation requests from clients.
|
||||||
def generate_ticket_granting_ticket(username, extra_attributes = {})
|
def generate_ticket_granting_ticket(username, extra_attributes = {})
|
||||||
# 3.6 (ticket granting cookie/ticket)
|
# 3.6 (ticket granting cookie/ticket)
|
||||||
|
@ -34,11 +34,11 @@ module CASServer::CAS
|
||||||
tgt.client_hostname = @env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']
|
tgt.client_hostname = @env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']
|
||||||
tgt.save!
|
tgt.save!
|
||||||
$LOG.debug("Generated ticket granting ticket '#{tgt.ticket}' for user" +
|
$LOG.debug("Generated ticket granting ticket '#{tgt.ticket}' for user" +
|
||||||
" '#{tgt.username}' at '#{tgt.client_hostname}'" +
|
" '#{tgt.username}' at '#{tgt.client_hostname}'" +
|
||||||
(extra_attributes.blank? ? "" : " with extra attributes #{extra_attributes.inspect}"))
|
(extra_attributes.blank? ? "" : " with extra attributes #{extra_attributes.inspect}"))
|
||||||
tgt
|
tgt
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_service_ticket(service, username, tgt)
|
def generate_service_ticket(service, username, tgt)
|
||||||
# 3.1 (service ticket)
|
# 3.1 (service ticket)
|
||||||
st = ServiceTicket.new
|
st = ServiceTicket.new
|
||||||
|
@ -52,7 +52,7 @@ module CASServer::CAS
|
||||||
" for user '#{st.username}' at '#{st.client_hostname}'")
|
" for user '#{st.username}' at '#{st.client_hostname}'")
|
||||||
st
|
st
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_proxy_ticket(target_service, pgt)
|
def generate_proxy_ticket(target_service, pgt)
|
||||||
# 3.2 (proxy ticket)
|
# 3.2 (proxy ticket)
|
||||||
pt = ProxyTicket.new
|
pt = ProxyTicket.new
|
||||||
|
@ -68,19 +68,19 @@ module CASServer::CAS
|
||||||
" ticket '#{pgt.ticket}'")
|
" ticket '#{pgt.ticket}'")
|
||||||
pt
|
pt
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_proxy_granting_ticket(pgt_url, st)
|
def generate_proxy_granting_ticket(pgt_url, st)
|
||||||
uri = URI.parse(pgt_url)
|
uri = URI.parse(pgt_url)
|
||||||
https = Net::HTTP.new(uri.host,uri.port)
|
https = Net::HTTP.new(uri.host,uri.port)
|
||||||
https.use_ssl = true
|
https.use_ssl = true
|
||||||
|
|
||||||
# Here's what's going on here:
|
# Here's what's going on here:
|
||||||
#
|
#
|
||||||
# 1. We generate a ProxyGrantingTicket (but don't store it in the database just yet)
|
# 1. We generate a ProxyGrantingTicket (but don't store it in the database just yet)
|
||||||
# 2. Deposit the PGT and it's associated IOU at the proxy callback URL.
|
# 2. Deposit the PGT and it's associated IOU at the proxy callback URL.
|
||||||
# 3. If the proxy callback URL responds with HTTP code 200, store the PGT and return it;
|
# 3. If the proxy callback URL responds with HTTP code 200, store the PGT and return it;
|
||||||
# otherwise don't save it and return nothing.
|
# otherwise don't save it and return nothing.
|
||||||
#
|
#
|
||||||
https.start do |conn|
|
https.start do |conn|
|
||||||
path = uri.path.empty? ? '/' : uri.path
|
path = uri.path.empty? ? '/' : uri.path
|
||||||
path += '?' + uri.query unless (uri.query.nil? || uri.query.empty?)
|
path += '?' + uri.query unless (uri.query.nil? || uri.query.empty?)
|
||||||
|
@ -90,12 +90,12 @@ module CASServer::CAS
|
||||||
pgt.iou = "PGTIOU-" + CASServer::Utils.random_string(57)
|
pgt.iou = "PGTIOU-" + CASServer::Utils.random_string(57)
|
||||||
pgt.service_ticket_id = st.id
|
pgt.service_ticket_id = st.id
|
||||||
pgt.client_hostname = @env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']
|
pgt.client_hostname = @env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']
|
||||||
|
|
||||||
# FIXME: The CAS protocol spec says to use 'pgt' as the parameter, but in practice
|
# FIXME: The CAS protocol spec says to use 'pgt' as the parameter, but in practice
|
||||||
# the JA-SIG and Yale server implementations use pgtId. We'll go with the
|
# the JA-SIG and Yale server implementations use pgtId. We'll go with the
|
||||||
# in-practice standard.
|
# in-practice standard.
|
||||||
path += (uri.query.nil? || uri.query.empty? ? '?' : '&') + "pgtId=#{pgt.ticket}&pgtIou=#{pgt.iou}"
|
path += (uri.query.nil? || uri.query.empty? ? '?' : '&') + "pgtId=#{pgt.ticket}&pgtIou=#{pgt.iou}"
|
||||||
|
|
||||||
response = conn.request_get(path)
|
response = conn.request_get(path)
|
||||||
# TODO: follow redirects... 2.5.4 says that redirects MAY be followed
|
# TODO: follow redirects... 2.5.4 says that redirects MAY be followed
|
||||||
# NOTE: The following response codes are valid according to the JA-SIG implementation even without following redirects
|
# NOTE: The following response codes are valid according to the JA-SIG implementation even without following redirects
|
||||||
|
@ -111,10 +111,10 @@ module CASServer::CAS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_login_ticket(ticket)
|
def validate_login_ticket(ticket)
|
||||||
$LOG.debug("Validating login ticket '#{ticket}'")
|
$LOG.debug("Validating login ticket '#{ticket}'")
|
||||||
|
|
||||||
success = false
|
success = false
|
||||||
if ticket.nil?
|
if ticket.nil?
|
||||||
error = _("Your login request did not include a login ticket. There may be a problem with the authentication system.")
|
error = _("Your login request did not include a login ticket. There may be a problem with the authentication system.")
|
||||||
|
@ -133,15 +133,15 @@ module CASServer::CAS
|
||||||
error = _("The login ticket you provided is invalid. There may be a problem with the authentication system.")
|
error = _("The login ticket you provided is invalid. There may be a problem with the authentication system.")
|
||||||
$LOG.warn "Invalid login ticket '#{ticket}'"
|
$LOG.warn "Invalid login ticket '#{ticket}'"
|
||||||
end
|
end
|
||||||
|
|
||||||
lt.consume! if lt
|
lt.consume! if lt
|
||||||
|
|
||||||
error
|
error
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_ticket_granting_ticket(ticket)
|
def validate_ticket_granting_ticket(ticket)
|
||||||
$LOG.debug("Validating ticket granting ticket '#{ticket}'")
|
$LOG.debug("Validating ticket granting ticket '#{ticket}'")
|
||||||
|
|
||||||
if ticket.nil?
|
if ticket.nil?
|
||||||
error = "No ticket granting ticket given."
|
error = "No ticket granting ticket given."
|
||||||
$LOG.debug error
|
$LOG.debug error
|
||||||
|
@ -156,13 +156,13 @@ module CASServer::CAS
|
||||||
error = "Invalid ticket granting ticket '#{ticket}' (no matching ticket found in the database)."
|
error = "Invalid ticket granting ticket '#{ticket}' (no matching ticket found in the database)."
|
||||||
$LOG.warn(error)
|
$LOG.warn(error)
|
||||||
end
|
end
|
||||||
|
|
||||||
[tgt, error]
|
[tgt, error]
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_service_ticket(service, ticket, allow_proxy_tickets = false)
|
def validate_service_ticket(service, ticket, allow_proxy_tickets = false)
|
||||||
$LOG.debug "Validating service/proxy ticket '#{ticket}' for service '#{service}'"
|
$LOG.debug "Validating service/proxy ticket '#{ticket}' for service '#{service}'"
|
||||||
|
|
||||||
if service.nil? or ticket.nil?
|
if service.nil? or ticket.nil?
|
||||||
error = Error.new(:INVALID_REQUEST, "Ticket or service parameter was missing in the request.")
|
error = Error.new(:INVALID_REQUEST, "Ticket or service parameter was missing in the request.")
|
||||||
$LOG.warn "#{error.code} - #{error.message}"
|
$LOG.warn "#{error.code} - #{error.message}"
|
||||||
|
@ -187,18 +187,18 @@ module CASServer::CAS
|
||||||
error = Error.new(:INVALID_TICKET, "Ticket '#{ticket}' not recognized.")
|
error = Error.new(:INVALID_TICKET, "Ticket '#{ticket}' not recognized.")
|
||||||
$LOG.warn("#{error.code} - #{error.message}")
|
$LOG.warn("#{error.code} - #{error.message}")
|
||||||
end
|
end
|
||||||
|
|
||||||
if st
|
if st
|
||||||
st.consume!
|
st.consume!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
[st, error]
|
[st, error]
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_proxy_ticket(service, ticket)
|
def validate_proxy_ticket(service, ticket)
|
||||||
pt, error = validate_service_ticket(service, ticket, true)
|
pt, error = validate_service_ticket(service, ticket, true)
|
||||||
|
|
||||||
if pt.kind_of?(CASServer::Models::ProxyTicket) && !error
|
if pt.kind_of?(CASServer::Models::ProxyTicket) && !error
|
||||||
if not pt.granted_by_pgt
|
if not pt.granted_by_pgt
|
||||||
error = Error.new(:INTERNAL_ERROR, "Proxy ticket '#{pt}' belonging to user '#{pt.username}' is not associated with a proxy granting ticket.")
|
error = Error.new(:INTERNAL_ERROR, "Proxy ticket '#{pt}' belonging to user '#{pt.username}' is not associated with a proxy granting ticket.")
|
||||||
|
@ -207,10 +207,10 @@ module CASServer::CAS
|
||||||
" (associated with proxy ticket '#{pt}' and belonging to user '#{pt.username}' is not associated with a service ticket.")
|
" (associated with proxy ticket '#{pt}' and belonging to user '#{pt.username}' is not associated with a service ticket.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[pt, error]
|
[pt, error]
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_proxy_granting_ticket(ticket)
|
def validate_proxy_granting_ticket(ticket)
|
||||||
if ticket.nil?
|
if ticket.nil?
|
||||||
error = Error.new(:INVALID_REQUEST, "pgt parameter was missing in the request.")
|
error = Error.new(:INVALID_REQUEST, "pgt parameter was missing in the request.")
|
||||||
|
@ -226,10 +226,10 @@ module CASServer::CAS
|
||||||
error = Error.new(:BAD_PGT, "Invalid proxy granting ticket '#{ticket}' (no matching ticket found in the database).")
|
error = Error.new(:BAD_PGT, "Invalid proxy granting ticket '#{ticket}' (no matching ticket found in the database).")
|
||||||
$LOG.warn("#{error.code} - #{error.message}")
|
$LOG.warn("#{error.code} - #{error.message}")
|
||||||
end
|
end
|
||||||
|
|
||||||
[pgt, error]
|
[pgt, error]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Takes an existing ServiceTicket object (presumably pulled from the database)
|
# Takes an existing ServiceTicket object (presumably pulled from the database)
|
||||||
# and sends a POST with logout information to the service that the ticket
|
# and sends a POST with logout information to the service that the ticket
|
||||||
# was generated for.
|
# was generated for.
|
||||||
|
@ -240,13 +240,13 @@ module CASServer::CAS
|
||||||
uri = URI.parse(st.service)
|
uri = URI.parse(st.service)
|
||||||
http = Net::HTTP.new(uri.host, uri.port)
|
http = Net::HTTP.new(uri.host, uri.port)
|
||||||
#http.use_ssl = true if uri.scheme = 'https'
|
#http.use_ssl = true if uri.scheme = 'https'
|
||||||
|
|
||||||
time = Time.now
|
time = Time.now
|
||||||
rand = CASServer::Utils.random_string
|
rand = CASServer::Utils.random_string
|
||||||
|
|
||||||
path = uri.path
|
path = uri.path
|
||||||
path = '/' if path.empty?
|
path = '/' if path.empty?
|
||||||
|
|
||||||
req = Net::HTTP::Post.new(path)
|
req = Net::HTTP::Post.new(path)
|
||||||
req.set_form_data(
|
req.set_form_data(
|
||||||
'logoutRequest' => %{<samlp:LogoutRequest ID="#{rand}" Version="2.0" IssueInstant="#{time.rfc2822}">
|
'logoutRequest' => %{<samlp:LogoutRequest ID="#{rand}" Version="2.0" IssueInstant="#{time.rfc2822}">
|
||||||
|
@ -254,11 +254,11 @@ module CASServer::CAS
|
||||||
<samlp:SessionIndex>#{st.ticket}</samlp:SessionIndex>
|
<samlp:SessionIndex>#{st.ticket}</samlp:SessionIndex>
|
||||||
</samlp:LogoutRequest>}
|
</samlp:LogoutRequest>}
|
||||||
)
|
)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
http.start do |conn|
|
http.start do |conn|
|
||||||
response = conn.request(req)
|
response = conn.request(req)
|
||||||
|
|
||||||
if response.kind_of? Net::HTTPSuccess
|
if response.kind_of? Net::HTTPSuccess
|
||||||
$LOG.info "Logout notification successfully posted to #{st.service.inspect}."
|
$LOG.info "Logout notification successfully posted to #{st.service.inspect}."
|
||||||
return true
|
return true
|
||||||
|
@ -272,14 +272,14 @@ module CASServer::CAS
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def service_uri_with_ticket(service, st)
|
def service_uri_with_ticket(service, st)
|
||||||
raise ArgumentError, "Second argument must be a ServiceTicket!" unless st.kind_of? CASServer::Models::ServiceTicket
|
raise ArgumentError, "Second argument must be a ServiceTicket!" unless st.kind_of? CASServer::Models::ServiceTicket
|
||||||
|
|
||||||
# This will choke with a URI::InvalidURIError if service URI is not properly URI-escaped...
|
# This will choke with a URI::InvalidURIError if service URI is not properly URI-escaped...
|
||||||
# This exception is handled further upstream (i.e. in the controller).
|
# This exception is handled further upstream (i.e. in the controller).
|
||||||
service_uri = URI.parse(service)
|
service_uri = URI.parse(service)
|
||||||
|
|
||||||
if service.include? "?"
|
if service.include? "?"
|
||||||
if service_uri.query.empty?
|
if service_uri.query.empty?
|
||||||
query_separator = ""
|
query_separator = ""
|
||||||
|
@ -289,11 +289,11 @@ module CASServer::CAS
|
||||||
else
|
else
|
||||||
query_separator = "?"
|
query_separator = "?"
|
||||||
end
|
end
|
||||||
|
|
||||||
service_with_ticket = service + query_separator + "ticket=" + st.ticket
|
service_with_ticket = service + query_separator + "ticket=" + st.ticket
|
||||||
service_with_ticket
|
service_with_ticket
|
||||||
end
|
end
|
||||||
|
|
||||||
# Strips CAS-related parameters from a service URL and normalizes it,
|
# Strips CAS-related parameters from a service URL and normalizes it,
|
||||||
# removing trailing / and ?. Also converts any spaces to +.
|
# removing trailing / and ?. Also converts any spaces to +.
|
||||||
#
|
#
|
||||||
|
@ -310,16 +310,16 @@ module CASServer::CAS
|
||||||
['service', 'ticket', 'gateway', 'renew'].each do |p|
|
['service', 'ticket', 'gateway', 'renew'].each do |p|
|
||||||
clean_service.sub!(Regexp.new("&?#{p}=[^&]*"), '')
|
clean_service.sub!(Regexp.new("&?#{p}=[^&]*"), '')
|
||||||
end
|
end
|
||||||
|
|
||||||
clean_service.gsub!(/[\/\?&]$/, '') # remove trailing ?, /, or &
|
clean_service.gsub!(/[\/\?&]$/, '') # remove trailing ?, /, or &
|
||||||
clean_service.gsub!('?&', '?')
|
clean_service.gsub!('?&', '?')
|
||||||
clean_service.gsub!(' ', '+')
|
clean_service.gsub!(' ', '+')
|
||||||
|
|
||||||
$LOG.debug("Cleaned dirty service URL #{dirty_service.inspect} to #{clean_service.inspect}") if
|
$LOG.debug("Cleaned dirty service URL #{dirty_service.inspect} to #{clean_service.inspect}") if
|
||||||
dirty_service != clean_service
|
dirty_service != clean_service
|
||||||
|
|
||||||
return clean_service
|
return clean_service
|
||||||
end
|
end
|
||||||
module_function :clean_service_url
|
module_function :clean_service_url
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
|
||||||
|
require 'active_support'
|
||||||
|
|
||||||
conf_defaults = {
|
conf_defaults = {
|
||||||
:maximum_unused_login_ticket_lifetime => 5.minutes,
|
:maximum_unused_login_ticket_lifetime => 5.minutes,
|
||||||
:maximum_unused_service_ticket_lifetime => 5.minutes, # CAS Protocol Spec, sec. 3.2.1 (recommended expiry time)
|
:maximum_unused_service_ticket_lifetime => 5.minutes, # CAS Protocol Spec, sec. 3.2.1 (recommended expiry time)
|
||||||
|
@ -29,7 +32,7 @@ unless $CONF[:authenticator]
|
||||||
your config file.
|
your config file.
|
||||||
|
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
"
|
"
|
||||||
raise Picnic::Conf::Error, err
|
raise Picnic::Conf::Error, err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -39,6 +42,7 @@ begin
|
||||||
$CONF[:authenticator].each { |authenticator| $AUTH << authenticator[:class].constantize}
|
$CONF[:authenticator].each { |authenticator| $AUTH << authenticator[:class].constantize}
|
||||||
else
|
else
|
||||||
$AUTH << $CONF[:authenticator][:class].constantize
|
$AUTH << $CONF[:authenticator][:class].constantize
|
||||||
|
$CONF[:authenticator] = [$CONF[:authenticator]]
|
||||||
end
|
end
|
||||||
rescue NameError
|
rescue NameError
|
||||||
if $CONF[:authenticator].instance_of? Array
|
if $CONF[:authenticator].instance_of? Array
|
||||||
|
@ -52,7 +56,6 @@ rescue NameError
|
||||||
require 'casserver/'+auth_rb
|
require 'casserver/'+auth_rb
|
||||||
end
|
end
|
||||||
$AUTH << authenticator[:class].constantize
|
$AUTH << authenticator[:class].constantize
|
||||||
$CONF[:authenticator] = [$CONF[:authenticator]]
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if $CONF[:authenticator][:source]
|
if $CONF[:authenticator][:source]
|
||||||
|
|
|
@ -7,7 +7,7 @@ elsif File.exists?(picnic = File.expand_path(File.dirname(File.expand_path(__FIL
|
||||||
else
|
else
|
||||||
puts "Loading picnic from rubygems..."
|
puts "Loading picnic from rubygems..."
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Try to load dev version of picnic if available (for example 'zuk-picnic' from Github)
|
# Try to load dev version of picnic if available (for example 'zuk-picnic' from Github)
|
||||||
gem /^.*?-picnic$/
|
gem /^.*?-picnic$/
|
||||||
|
|
|
@ -4,13 +4,13 @@ require "gettext/cgi"
|
||||||
module CASServer
|
module CASServer
|
||||||
include GetText
|
include GetText
|
||||||
bindtextdomain("rubycas-server", :path => File.join(File.dirname(File.expand_path(__FILE__)), "../../locale"))
|
bindtextdomain("rubycas-server", :path => File.join(File.dirname(File.expand_path(__FILE__)), "../../locale"))
|
||||||
|
|
||||||
def service(*a)
|
def service(*a)
|
||||||
GetText.locale = determine_locale
|
GetText.locale = determine_locale
|
||||||
#puts GetText.locale.inspect
|
#puts GetText.locale.inspect
|
||||||
super(*a)
|
super(*a)
|
||||||
end
|
end
|
||||||
|
|
||||||
def determine_locale
|
def determine_locale
|
||||||
|
|
||||||
source = nil
|
source = nil
|
||||||
|
@ -39,7 +39,7 @@ module CASServer
|
||||||
$LOG.debug "Detected locale is #{lang.inspect} (from #{source})"
|
$LOG.debug "Detected locale is #{lang.inspect} (from #{source})"
|
||||||
|
|
||||||
lang.gsub!('_','-')
|
lang.gsub!('_','-')
|
||||||
|
|
||||||
# TODO: Need to confirm that this method of splitting the accepted
|
# TODO: Need to confirm that this method of splitting the accepted
|
||||||
# language string is correct.
|
# language string is correct.
|
||||||
if lang =~ /[,;\|]/
|
if lang =~ /[,;\|]/
|
||||||
|
@ -47,35 +47,36 @@ module CASServer
|
||||||
else
|
else
|
||||||
langs = [lang]
|
langs = [lang]
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: This method of selecting the desired language might not be
|
# TODO: This method of selecting the desired language might not be
|
||||||
# standards-compliant. For example, http://www.w3.org/TR/ltli/
|
# standards-compliant. For example, http://www.w3.org/TR/ltli/
|
||||||
# suggests that de-de and de-*-DE might be acceptable identifiers
|
# suggests that de-de and de-*-DE might be acceptable identifiers
|
||||||
# for selecting various wildcards. The algorithm below does not
|
# for selecting various wildcards. The algorithm below does not
|
||||||
# currently support anything like this.
|
# currently support anything like this.
|
||||||
|
|
||||||
available = available_locales
|
available = available_locales
|
||||||
|
|
||||||
# Try to pick a locale exactly matching the desired identifier, otherwise
|
# Try to pick a locale exactly matching the desired identifier, otherwise
|
||||||
# fall back to locale without region (i.e. given "en-US; de-DE", we would
|
# fall back to locale without region (i.e. given "en-US; de-DE", we would
|
||||||
# first look for "en-US", then "en", then "de-DE", then "de").
|
# first look for "en-US", then "en", then "de-DE", then "de").
|
||||||
|
|
||||||
chosen_lang = nil
|
chosen_lang = nil
|
||||||
langs.each do |l|
|
langs.each do |l|
|
||||||
a = available.find{|a| a == l || a =~ Regexp.new("#{l}-\w*")}
|
a = available.find{ |a| a =~ Regexp.new("\\A#{l}\\Z", 'i') ||
|
||||||
|
a =~ Regexp.new("#{l}-\w*", 'i') }
|
||||||
if a
|
if a
|
||||||
chosen_lang = a
|
chosen_lang = a
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
chosen_lang = "en" if chosen_lang.blank?
|
chosen_lang = "en" if chosen_lang.blank?
|
||||||
|
|
||||||
$LOG.debug "Chosen locale is #{chosen_lang.inspect}"
|
$LOG.debug "Chosen locale is #{chosen_lang.inspect}"
|
||||||
|
|
||||||
return chosen_lang
|
return chosen_lang
|
||||||
end
|
end
|
||||||
|
|
||||||
def available_locales
|
def available_locales
|
||||||
(Dir.glob(File.join(File.dirname(File.expand_path(__FILE__)), "../../locale/[a-z]*")).map{|path| File.basename(path)} << "en").uniq.collect{|l| l.gsub('_','-')}
|
(Dir.glob(File.join(File.dirname(File.expand_path(__FILE__)), "../../locale/[a-z]*")).map{|path| File.basename(path)} << "en").uniq.collect{|l| l.gsub('_','-')}
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
require 'camping/ar'
|
require 'camping/ar'
|
||||||
|
|
||||||
module CASServer::Models
|
module CASServer::Models
|
||||||
|
|
||||||
module Consumable
|
module Consumable
|
||||||
def consume!
|
def consume!
|
||||||
self.consumed = Time.now
|
self.consumed = Time.now
|
||||||
|
@ -15,7 +15,7 @@ module CASServer::Models
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
def cleanup(max_lifetime, max_unconsumed_lifetime)
|
def cleanup(max_lifetime, max_unconsumed_lifetime)
|
||||||
transaction do
|
transaction do
|
||||||
conditions = ["created_on < ? OR (consumed IS NULL AND created_on < ?)",
|
conditions = ["created_on < ? OR (consumed IS NULL AND created_on < ?)",
|
||||||
Time.now - max_lifetime,
|
Time.now - max_lifetime,
|
||||||
Time.now - max_unconsumed_lifetime]
|
Time.now - max_unconsumed_lifetime]
|
||||||
expired_tickets_count = count(:conditions => conditions)
|
expired_tickets_count = count(:conditions => conditions)
|
||||||
|
@ -28,78 +28,78 @@ module CASServer::Models
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Ticket < Base
|
class Ticket < Base
|
||||||
def to_s
|
def to_s
|
||||||
ticket
|
ticket
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.cleanup(max_lifetime)
|
def self.cleanup(max_lifetime)
|
||||||
transaction do
|
transaction do
|
||||||
conditions = ["created_on < ?", Time.now - max_lifetime]
|
conditions = ["created_on < ?", Time.now - max_lifetime]
|
||||||
expired_tickets_count = count(:conditions => conditions)
|
expired_tickets_count = count(:conditions => conditions)
|
||||||
|
|
||||||
$LOG.debug("Destroying #{expired_tickets_count} expired #{self.name.demodulize}"+
|
$LOG.debug("Destroying #{expired_tickets_count} expired #{self.name.demodulize}"+
|
||||||
"#{'s' if expired_tickets_count > 1}.") if expired_tickets_count > 0
|
"#{'s' if expired_tickets_count > 1}.") if expired_tickets_count > 0
|
||||||
|
|
||||||
destroy_all(conditions)
|
destroy_all(conditions)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class LoginTicket < Ticket
|
class LoginTicket < Ticket
|
||||||
set_table_name 'casserver_lt'
|
set_table_name 'casserver_lt'
|
||||||
include Consumable
|
include Consumable
|
||||||
end
|
end
|
||||||
|
|
||||||
class ServiceTicket < Ticket
|
class ServiceTicket < Ticket
|
||||||
set_table_name 'casserver_st'
|
set_table_name 'casserver_st'
|
||||||
include Consumable
|
include Consumable
|
||||||
|
|
||||||
belongs_to :granted_by_tgt,
|
belongs_to :granted_by_tgt,
|
||||||
:class_name => 'CASServer::Models::TicketGrantingTicket',
|
:class_name => 'CASServer::Models::TicketGrantingTicket',
|
||||||
:foreign_key => :granted_by_tgt_id
|
:foreign_key => :granted_by_tgt_id
|
||||||
has_one :proxy_granting_ticket,
|
has_one :proxy_granting_ticket,
|
||||||
:foreign_key => :created_by_st_id
|
:foreign_key => :created_by_st_id
|
||||||
|
|
||||||
def matches_service?(service)
|
def matches_service?(service)
|
||||||
CASServer::CAS.clean_service_url(self.service) ==
|
CASServer::CAS.clean_service_url(self.service) ==
|
||||||
CASServer::CAS.clean_service_url(service)
|
CASServer::CAS.clean_service_url(service)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ProxyTicket < ServiceTicket
|
class ProxyTicket < ServiceTicket
|
||||||
belongs_to :granted_by_pgt,
|
belongs_to :granted_by_pgt,
|
||||||
:class_name => 'CASServer::Models::ProxyGrantingTicket',
|
:class_name => 'CASServer::Models::ProxyGrantingTicket',
|
||||||
:foreign_key => :granted_by_pgt_id
|
:foreign_key => :granted_by_pgt_id
|
||||||
end
|
end
|
||||||
|
|
||||||
class TicketGrantingTicket < Ticket
|
class TicketGrantingTicket < Ticket
|
||||||
set_table_name 'casserver_tgt'
|
set_table_name 'casserver_tgt'
|
||||||
|
|
||||||
serialize :extra_attributes
|
serialize :extra_attributes
|
||||||
|
|
||||||
has_many :granted_service_tickets,
|
has_many :granted_service_tickets,
|
||||||
:class_name => 'CASServer::Models::ServiceTicket',
|
:class_name => 'CASServer::Models::ServiceTicket',
|
||||||
:foreign_key => :granted_by_tgt_id
|
:foreign_key => :granted_by_tgt_id
|
||||||
end
|
end
|
||||||
|
|
||||||
class ProxyGrantingTicket < Ticket
|
class ProxyGrantingTicket < Ticket
|
||||||
set_table_name 'casserver_pgt'
|
set_table_name 'casserver_pgt'
|
||||||
belongs_to :service_ticket
|
belongs_to :service_ticket
|
||||||
has_many :granted_proxy_tickets,
|
has_many :granted_proxy_tickets,
|
||||||
:class_name => 'CASServer::Models::ProxyTicket',
|
:class_name => 'CASServer::Models::ProxyTicket',
|
||||||
:foreign_key => :granted_by_pgt_id
|
:foreign_key => :granted_by_pgt_id
|
||||||
end
|
end
|
||||||
|
|
||||||
class Error
|
class Error
|
||||||
attr_reader :code, :message
|
attr_reader :code, :message
|
||||||
|
|
||||||
def initialize(code, message)
|
def initialize(code, message)
|
||||||
@code = code
|
@code = code
|
||||||
@message = message
|
@message = message
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
message
|
message
|
||||||
end
|
end
|
||||||
|
@ -109,14 +109,14 @@ module CASServer::Models
|
||||||
def self.up
|
def self.up
|
||||||
if ActiveRecord::Base.connection.table_alias_length > 30
|
if ActiveRecord::Base.connection.table_alias_length > 30
|
||||||
$LOG.info("Creating database with long table names...")
|
$LOG.info("Creating database with long table names...")
|
||||||
|
|
||||||
create_table :casserver_login_tickets, :force => true do |t|
|
create_table :casserver_login_tickets, :force => true do |t|
|
||||||
t.column :ticket, :string, :null => false
|
t.column :ticket, :string, :null => false
|
||||||
t.column :created_on, :timestamp, :null => false
|
t.column :created_on, :timestamp, :null => false
|
||||||
t.column :consumed, :datetime, :null => true
|
t.column :consumed, :datetime, :null => true
|
||||||
t.column :client_hostname, :string, :null => false
|
t.column :client_hostname, :string, :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :casserver_service_tickets, :force => true do |t|
|
create_table :casserver_service_tickets, :force => true do |t|
|
||||||
t.column :ticket, :string, :null => false
|
t.column :ticket, :string, :null => false
|
||||||
t.column :service, :string, :null => false
|
t.column :service, :string, :null => false
|
||||||
|
@ -127,14 +127,14 @@ module CASServer::Models
|
||||||
t.column :type, :string, :null => false
|
t.column :type, :string, :null => false
|
||||||
t.column :proxy_granting_ticket_id, :integer, :null => true
|
t.column :proxy_granting_ticket_id, :integer, :null => true
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :casserver_ticket_granting_tickets, :force => true do |t|
|
create_table :casserver_ticket_granting_tickets, :force => true do |t|
|
||||||
t.column :ticket, :string, :null => false
|
t.column :ticket, :string, :null => false
|
||||||
t.column :created_on, :timestamp, :null => false
|
t.column :created_on, :timestamp, :null => false
|
||||||
t.column :client_hostname, :string, :null => false
|
t.column :client_hostname, :string, :null => false
|
||||||
t.column :username, :string, :null => false
|
t.column :username, :string, :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :casserver_proxy_granting_tickets, :force => true do |t|
|
create_table :casserver_proxy_granting_tickets, :force => true do |t|
|
||||||
t.column :ticket, :string, :null => false
|
t.column :ticket, :string, :null => false
|
||||||
t.column :created_on, :timestamp, :null => false
|
t.column :created_on, :timestamp, :null => false
|
||||||
|
@ -144,7 +144,7 @@ module CASServer::Models
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.down
|
def self.down
|
||||||
if ActiveRecord::Base.connection.table_alias_length > 30
|
if ActiveRecord::Base.connection.table_alias_length > 30
|
||||||
drop_table :casserver_proxy_granting_tickets
|
drop_table :casserver_proxy_granting_tickets
|
||||||
|
@ -154,8 +154,8 @@ module CASServer::Models
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Oracle table names cannot exceed 30 chars...
|
# Oracle table names cannot exceed 30 chars...
|
||||||
# See http://code.google.com/p/rubycas-server/issues/detail?id=15
|
# See http://code.google.com/p/rubycas-server/issues/detail?id=15
|
||||||
class ShortenTableNames < V 0.5
|
class ShortenTableNames < V 0.5
|
||||||
def self.up
|
def self.up
|
||||||
|
@ -172,7 +172,7 @@ module CASServer::Models
|
||||||
t.column :consumed, :datetime, :null => true
|
t.column :consumed, :datetime, :null => true
|
||||||
t.column :client_hostname, :string, :null => false
|
t.column :client_hostname, :string, :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :casserver_st, :force => true do |t|
|
create_table :casserver_st, :force => true do |t|
|
||||||
t.column :ticket, :string, :null => false
|
t.column :ticket, :string, :null => false
|
||||||
t.column :service, :string, :null => false
|
t.column :service, :string, :null => false
|
||||||
|
@ -183,14 +183,14 @@ module CASServer::Models
|
||||||
t.column :type, :string, :null => false
|
t.column :type, :string, :null => false
|
||||||
t.column :proxy_granting_ticket_id, :integer, :null => true
|
t.column :proxy_granting_ticket_id, :integer, :null => true
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :casserver_tgt, :force => true do |t|
|
create_table :casserver_tgt, :force => true do |t|
|
||||||
t.column :ticket, :string, :null => false
|
t.column :ticket, :string, :null => false
|
||||||
t.column :created_on, :timestamp, :null => false
|
t.column :created_on, :timestamp, :null => false
|
||||||
t.column :client_hostname, :string, :null => false
|
t.column :client_hostname, :string, :null => false
|
||||||
t.column :username, :string, :null => false
|
t.column :username, :string, :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :casserver_pgt, :force => true do |t|
|
create_table :casserver_pgt, :force => true do |t|
|
||||||
t.column :ticket, :string, :null => false
|
t.column :ticket, :string, :null => false
|
||||||
t.column :created_on, :timestamp, :null => false
|
t.column :created_on, :timestamp, :null => false
|
||||||
|
@ -200,7 +200,7 @@ module CASServer::Models
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.down
|
def self.down
|
||||||
if ActiveRecord::Base.connection.table_alias_length > 30
|
if ActiveRecord::Base.connection.table_alias_length > 30
|
||||||
rename_table :casserver_lt, :cassserver_login_tickets
|
rename_table :casserver_lt, :cassserver_login_tickets
|
||||||
|
@ -215,17 +215,17 @@ module CASServer::Models
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AddTgtToSt < V 0.7
|
class AddTgtToSt < V 0.7
|
||||||
def self.up
|
def self.up
|
||||||
add_column :casserver_st, :tgt_id, :integer, :null => true
|
add_column :casserver_st, :tgt_id, :integer, :null => true
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.down
|
def self.down
|
||||||
remove_column :casserver_st, :tgt_id, :integer
|
remove_column :casserver_st, :tgt_id, :integer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ChangeServiceToText < V 0.71
|
class ChangeServiceToText < V 0.71
|
||||||
def self.up
|
def self.up
|
||||||
# using change_column to change the column type from :string to :text
|
# using change_column to change the column type from :string to :text
|
||||||
|
@ -235,17 +235,17 @@ module CASServer::Models
|
||||||
say "WARNING: All existing service tickets are being deleted."
|
say "WARNING: All existing service tickets are being deleted."
|
||||||
add_column :casserver_st, :service, :text
|
add_column :casserver_st, :service, :text
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.down
|
def self.down
|
||||||
change_column :casserver_st, :service, :string
|
change_column :casserver_st, :service, :string
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AddExtraAttributes < V 0.72
|
class AddExtraAttributes < V 0.72
|
||||||
def self.up
|
def self.up
|
||||||
add_column :casserver_tgt, :extra_attributes, :text
|
add_column :casserver_tgt, :extra_attributes, :text
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.down
|
def self.down
|
||||||
remove_column :casserver_tgt, :extra_attributes
|
remove_column :casserver_tgt, :extra_attributes
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,50 +1,50 @@
|
||||||
module CASServer
|
module CASServer
|
||||||
module Postambles
|
module Postambles
|
||||||
|
|
||||||
def webrick
|
def webrick
|
||||||
require 'webrick/httpserver'
|
require 'webrick/httpserver'
|
||||||
require 'webrick/https'
|
require 'webrick/https'
|
||||||
require 'camping/webrick'
|
require 'camping/webrick'
|
||||||
|
|
||||||
# TODO: verify the certificate's validity
|
# TODO: verify the certificate's validity
|
||||||
# example of how to do this is here: http://pablotron.org/download/ruri-20050331.rb
|
# example of how to do this is here: http://pablotron.org/download/ruri-20050331.rb
|
||||||
|
|
||||||
cert_path = $CONF.ssl_cert
|
cert_path = $CONF.ssl_cert
|
||||||
key_path = $CONF.ssl_key || $CONF.ssl_cert
|
key_path = $CONF.ssl_key || $CONF.ssl_cert
|
||||||
# look for the key in the ssl_cert if no ssl_key is specified
|
# look for the key in the ssl_cert if no ssl_key is specified
|
||||||
|
|
||||||
webrick_options = {:BindAddress => "0.0.0.0", :Port => $CONF.port}
|
webrick_options = {:BindAddress => "0.0.0.0", :Port => $CONF.port}
|
||||||
|
|
||||||
unless cert_path.nil? && key_path.nil?
|
unless cert_path.nil? && key_path.nil?
|
||||||
raise "'#{cert_path}' is not a valid ssl certificate. Your 'ssl_cert' configuration" +
|
raise "'#{cert_path}' is not a valid ssl certificate. Your 'ssl_cert' configuration" +
|
||||||
" setting must be a path to a valid ssl certificate file." unless
|
" setting must be a path to a valid ssl certificate file." unless
|
||||||
File.exists? cert_path
|
File.exists? cert_path
|
||||||
|
|
||||||
raise "'#{key_path}' is not a valid ssl private key. Your 'ssl_key' configuration" +
|
raise "'#{key_path}' is not a valid ssl private key. Your 'ssl_key' configuration" +
|
||||||
" setting must be a path to a valid ssl private key file." unless
|
" setting must be a path to a valid ssl private key file." unless
|
||||||
File.exists? key_path
|
File.exists? key_path
|
||||||
|
|
||||||
cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
|
cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
|
||||||
key = OpenSSL::PKey::RSA.new(File.read(key_path))
|
key = OpenSSL::PKey::RSA.new(File.read(key_path))
|
||||||
|
|
||||||
webrick_options[:SSLEnable] = true
|
webrick_options[:SSLEnable] = true
|
||||||
webrick_options[:SSLVerifyClient] = ::OpenSSL::SSL::VERIFY_NONE
|
webrick_options[:SSLVerifyClient] = ::OpenSSL::SSL::VERIFY_NONE
|
||||||
webrick_options[:SSLCertificate] = cert
|
webrick_options[:SSLCertificate] = cert
|
||||||
webrick_options[:SSLPrivateKey] = key
|
webrick_options[:SSLPrivateKey] = key
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
s = WEBrick::HTTPServer.new(webrick_options)
|
s = WEBrick::HTTPServer.new(webrick_options)
|
||||||
rescue Errno::EACCES
|
rescue Errno::EACCES
|
||||||
puts "\nThe server could not launch. Are you running on a privileged port? (e.g. port 443) If so, you must run the server as root."
|
puts "\nThe server could not launch. Are you running on a privileged port? (e.g. port 443) If so, you must run the server as root."
|
||||||
exit 2
|
exit 2
|
||||||
end
|
end
|
||||||
|
|
||||||
CASServer.create
|
CASServer.create
|
||||||
s.mount "#{$CONF.uri_path}", WEBrick::CampingHandler, CASServer
|
s.mount "#{$CONF.uri_path}", WEBrick::CampingHandler, CASServer
|
||||||
|
|
||||||
puts "\n** CASServer is running at http#{webrick_options[:SSLEnable] ? 's' : ''}://#{Socket.gethostname}:#{$CONF.port}#{$CONF.uri_path} and logging to '#{$CONF.log[:file]}'\n\n"
|
puts "\n** CASServer is running at http#{webrick_options[:SSLEnable] ? 's' : ''}://#{Socket.gethostname}:#{$CONF.port}#{$CONF.uri_path} and logging to '#{$CONF.log[:file]}'\n\n"
|
||||||
|
|
||||||
# This lets Ctrl+C shut down your server
|
# This lets Ctrl+C shut down your server
|
||||||
trap(:INT) do
|
trap(:INT) do
|
||||||
s.shutdown
|
s.shutdown
|
||||||
|
@ -52,7 +52,7 @@ module CASServer
|
||||||
trap(:TERM) do
|
trap(:TERM) do
|
||||||
s.shutdown
|
s.shutdown
|
||||||
end
|
end
|
||||||
|
|
||||||
if $DAEMONIZE
|
if $DAEMONIZE
|
||||||
WEBrick::Daemon.start do
|
WEBrick::Daemon.start do
|
||||||
write_pid_file if $PID_FILE
|
write_pid_file if $PID_FILE
|
||||||
|
@ -63,33 +63,33 @@ module CASServer
|
||||||
s.start
|
s.start
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def mongrel
|
def mongrel
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'mongrel/camping'
|
require 'mongrel/camping'
|
||||||
|
|
||||||
if $DAEMONIZE
|
if $DAEMONIZE
|
||||||
# check if log and pid are writable before daemonizing, otherwise we won't be able to notify
|
# check if log and pid are writable before daemonizing, otherwise we won't be able to notify
|
||||||
# the user if we run into trouble later (since once daemonized, we can't write to stdout/stderr)
|
# the user if we run into trouble later (since once daemonized, we can't write to stdout/stderr)
|
||||||
check_pid_writable if $PID_FILE
|
check_pid_writable if $PID_FILE
|
||||||
check_log_writable
|
check_log_writable
|
||||||
end
|
end
|
||||||
|
|
||||||
CASServer.create
|
CASServer.create
|
||||||
|
|
||||||
puts "\n** CASServer is starting. Look in '#{$CONF.log[:file]}' for further notices."
|
puts "\n** CASServer is starting. Look in '#{$CONF.log[:file]}' for further notices."
|
||||||
|
|
||||||
settings = {:host => "0.0.0.0", :log_file => $CONF.log[:file], :cwd => $CASSERVER_HOME}
|
settings = {:host => "0.0.0.0", :log_file => $CONF.log[:file], :cwd => $CASSERVER_HOME}
|
||||||
|
|
||||||
# need to close all IOs before daemonizing
|
# need to close all IOs before daemonizing
|
||||||
$LOG.close if $DAEMONIZE
|
$LOG.close if $DAEMONIZE
|
||||||
|
|
||||||
begin
|
begin
|
||||||
config = Mongrel::Configurator.new settings do
|
config = Mongrel::Configurator.new settings do
|
||||||
daemonize :log_file => $CONF.log[:file], :cwd => $CASSERVER_HOME if $DAEMONIZE
|
daemonize :log_file => $CONF.log[:file], :cwd => $CASSERVER_HOME if $DAEMONIZE
|
||||||
|
|
||||||
listener :port => $CONF.port do
|
listener :port => $CONF.port do
|
||||||
uri $CONF.uri_path, :handler => Mongrel::Camping::CampingHandler.new(CASServer)
|
uri $CONF.uri_path, :handler => Mongrel::Camping::CampingHandler.new(CASServer)
|
||||||
setup_signals
|
setup_signals
|
||||||
|
@ -98,12 +98,12 @@ module CASServer
|
||||||
rescue Errno::EADDRINUSE
|
rescue Errno::EADDRINUSE
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
config.run
|
config.run
|
||||||
|
|
||||||
CASServer.init_logger
|
CASServer.init_logger
|
||||||
CASServer.init_db_logger
|
CASServer.init_db_logger
|
||||||
|
|
||||||
if $DAEMONIZE && $PID_FILE
|
if $DAEMONIZE && $PID_FILE
|
||||||
write_pid_file
|
write_pid_file
|
||||||
unless File.exists? $PID_FILE
|
unless File.exists? $PID_FILE
|
||||||
|
@ -111,7 +111,7 @@ module CASServer
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "\n** CASServer is running at http://localhost:#{$CONF.port}#{$CONF.uri_path} and logging to '#{$CONF.log[:file]}'"
|
puts "\n** CASServer is running at http://localhost:#{$CONF.port}#{$CONF.uri_path} and logging to '#{$CONF.log[:file]}'"
|
||||||
config.join
|
config.join
|
||||||
|
|
||||||
|
@ -119,22 +119,22 @@ module CASServer
|
||||||
|
|
||||||
puts "\n** CASServer is stopped (#{Time.now})"
|
puts "\n** CASServer is stopped (#{Time.now})"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def fastcgi
|
def fastcgi
|
||||||
require 'camping/fastcgi'
|
require 'camping/fastcgi'
|
||||||
Dir.chdir('/srv/www/camping/casserver/')
|
Dir.chdir('/srv/www/camping/casserver/')
|
||||||
|
|
||||||
CASServer.create
|
CASServer.create
|
||||||
Camping::FastCGI.start(CASServer)
|
Camping::FastCGI.start(CASServer)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def cgi
|
def cgi
|
||||||
CASServer.create
|
CASServer.create
|
||||||
puts CASServer.run
|
puts CASServer.run
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def check_log_writable
|
def check_log_writable
|
||||||
log_file = $CONF.log['file']
|
log_file = $CONF.log['file']
|
||||||
|
@ -146,10 +146,10 @@ module CASServer
|
||||||
end
|
end
|
||||||
f.close
|
f.close
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_pid_writable
|
def check_pid_writable
|
||||||
$LOG.debug "Checking if pid file '#{$PID_FILE}' is writable"
|
$LOG.debug "Checking if pid file '#{$PID_FILE}' is writable"
|
||||||
begin
|
begin
|
||||||
f = open($PID_FILE, 'w')
|
f = open($PID_FILE, 'w')
|
||||||
rescue
|
rescue
|
||||||
$stderr.puts "Couldn't write to log at '#{$PID_FILE}' (#{$!})."
|
$stderr.puts "Couldn't write to log at '#{$PID_FILE}' (#{$!})."
|
||||||
|
@ -157,18 +157,18 @@ module CASServer
|
||||||
end
|
end
|
||||||
f.close
|
f.close
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_pid_file
|
def write_pid_file
|
||||||
$LOG.debug "Writing pid '#{Process.pid}' to pid file '#{$PID_FILE}'"
|
$LOG.debug "Writing pid '#{Process.pid}' to pid file '#{$PID_FILE}'"
|
||||||
open($PID_FILE, "w") { |file| file.write(Process.pid) }
|
open($PID_FILE, "w") { |file| file.write(Process.pid) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear_pid_file
|
def clear_pid_file
|
||||||
if $PID_FILE && File.exists?($PID_FILE)
|
if $PID_FILE && File.exists?($PID_FILE)
|
||||||
$LOG.debug "Clearing pid file '#{$PID_FILE}'"
|
$LOG.debug "Clearing pid file '#{$PID_FILE}'"
|
||||||
File.unlink $PID_FILE
|
File.unlink $PID_FILE
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,19 +4,19 @@ module CASServer
|
||||||
def random_string(max_length = 29)
|
def random_string(max_length = 29)
|
||||||
rg = Crypt::ISAAC.new
|
rg = Crypt::ISAAC.new
|
||||||
max = 4294619050
|
max = 4294619050
|
||||||
r = "#{Time.now.to_i}r%X%X%X%X%X%X%X%X" %
|
r = "#{Time.now.to_i}r%X%X%X%X%X%X%X%X" %
|
||||||
[rg.rand(max), rg.rand(max), rg.rand(max), rg.rand(max),
|
[rg.rand(max), rg.rand(max), rg.rand(max), rg.rand(max),
|
||||||
rg.rand(max), rg.rand(max), rg.rand(max), rg.rand(max)]
|
rg.rand(max), rg.rand(max), rg.rand(max), rg.rand(max)]
|
||||||
r[0..max_length-1]
|
r[0..max_length-1]
|
||||||
end
|
end
|
||||||
module_function :random_string
|
module_function :random_string
|
||||||
|
|
||||||
def log_controller_action(controller, params)
|
def log_controller_action(controller, params)
|
||||||
$LOG << "\n"
|
$LOG << "\n"
|
||||||
|
|
||||||
/`(.*)'/.match(caller[1])
|
/`(.*)'/.match(caller[1])
|
||||||
method = $~[1]
|
method = $~[1]
|
||||||
|
|
||||||
if params.respond_to? :dup
|
if params.respond_to? :dup
|
||||||
params2 = params.dup
|
params2 = params.dup
|
||||||
params2['password'] = '******' if params2['password']
|
params2['password'] = '******' if params2['password']
|
||||||
|
@ -27,4 +27,4 @@ module CASServer
|
||||||
end
|
end
|
||||||
module_function :log_controller_action
|
module_function :log_controller_action
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
Markaby::Builder.set(:auto_validation, false)
|
Markaby::Builder.set(:auto_validation, false)
|
||||||
|
|
||||||
# disabled XML indentation because it was causing problems with mod_auth_cas
|
# disabled XML indentation because it was causing problems with mod_auth_cas
|
||||||
#Markaby::Builder.set(:indent, 2)
|
#Markaby::Builder.set(:indent, 2)
|
||||||
|
|
||||||
module CASServer::Views
|
module CASServer::Views
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ module CASServer::Views
|
||||||
# wrap as XHTML only when auto_validation is on, otherwise pass right through
|
# wrap as XHTML only when auto_validation is on, otherwise pass right through
|
||||||
if @use_layout
|
if @use_layout
|
||||||
xhtml_strict do
|
xhtml_strict do
|
||||||
head do
|
head do
|
||||||
title { "#{organization} #{_(' Central Login')}" }
|
title { "#{organization} #{_(' Central Login')}" }
|
||||||
link(:rel => "stylesheet", :type => "text/css", :href => "/themes/cas.css")
|
link(:rel => "stylesheet", :type => "text/css", :href => "/themes/cas.css")
|
||||||
link(:rel => "stylesheet", :type => "text/css", :href => "/themes/#{current_theme}/theme.css")
|
link(:rel => "stylesheet", :type => "text/css", :href => "/themes/#{current_theme}/theme.css")
|
||||||
|
@ -21,7 +21,7 @@ module CASServer::Views
|
||||||
File.exists?("#{$APP_ROOT}/public/themes/#{current_theme}/favicon.png")
|
File.exists?("#{$APP_ROOT}/public/themes/#{current_theme}/favicon.png")
|
||||||
end
|
end
|
||||||
body(:onload => "if (document.getElementById('username')) document.getElementById('username').focus()") do
|
body(:onload => "if (document.getElementById('username')) document.getElementById('username').focus()") do
|
||||||
self << yield
|
self << yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -34,7 +34,7 @@ module CASServer::Views
|
||||||
# The full login page.
|
# The full login page.
|
||||||
def login
|
def login
|
||||||
@use_layout = true
|
@use_layout = true
|
||||||
|
|
||||||
table(:id => "login-box") do
|
table(:id => "login-box") do
|
||||||
tr do
|
tr do
|
||||||
td(:colspan => 2) do
|
td(:colspan => 2) do
|
||||||
|
@ -62,11 +62,12 @@ module CASServer::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Just the login form.
|
# Just the login form.
|
||||||
def login_form
|
def login_form
|
||||||
|
submitbutton = _("Please wait...")
|
||||||
form(:method => "post", :action => @form_action || '/login', :id => "login-form",
|
form(:method => "post", :action => @form_action || '/login', :id => "login-form",
|
||||||
:onsubmit => "submitbutton = document.getElementById('login-submit'); submitbutton.value='#{ _("Please wait...") }'; submitbutton.disabled=true; return true;") do
|
:onsubmit => "submitbutton = document.getElementById('login-submit'); submitbutton.value='#{submitbutton}'; submitbutton.disabled=true; return true;") do
|
||||||
table(:id => "form-layout") do
|
table(:id => "form-layout") do
|
||||||
tr do
|
tr do
|
||||||
td(:id => "username-label-container") do
|
td(:id => "username-label-container") do
|
||||||
|
@ -82,7 +83,7 @@ module CASServer::Views
|
||||||
label(:id => "password-label", :for => "password") { _( "Password" ) }
|
label(:id => "password-label", :for => "password") { _( "Password" ) }
|
||||||
end
|
end
|
||||||
td(:id => "password-container") do
|
td(:id => "password-container") do
|
||||||
input(:type => "password", :id => "password", :name => "password",
|
input(:type => "password", :id => "password", :name => "password",
|
||||||
:size => "32", :tabindex => "2", :accesskey => "p", :autocomplete => "off")
|
:size => "32", :tabindex => "2", :accesskey => "p", :autocomplete => "off")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -100,11 +101,11 @@ module CASServer::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 2.3.2
|
# 2.3.2
|
||||||
def logout
|
def logout
|
||||||
@use_layout = true
|
@use_layout = true
|
||||||
|
|
||||||
table(:id => "login-box") do
|
table(:id => "login-box") do
|
||||||
tr do
|
tr do
|
||||||
td(:colspan => 2) do
|
td(:colspan => 2) do
|
||||||
|
@ -128,7 +129,7 @@ module CASServer::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 2.4.2
|
# 2.4.2
|
||||||
# CAS 1.0 validate response.
|
# CAS 1.0 validate response.
|
||||||
def validate
|
def validate
|
||||||
|
@ -138,7 +139,7 @@ module CASServer::Views
|
||||||
text "no\n\n"
|
text "no\n\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 2.5.2
|
# 2.5.2
|
||||||
# CAS 2.0 service validate response.
|
# CAS 2.0 service validate response.
|
||||||
def service_validate
|
def service_validate
|
||||||
|
@ -160,7 +161,7 @@ module CASServer::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 2.6.2
|
# 2.6.2
|
||||||
# CAS 2.0 proxy validate response.
|
# CAS 2.0 proxy validate response.
|
||||||
def proxy_validate
|
def proxy_validate
|
||||||
|
@ -189,7 +190,7 @@ module CASServer::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 2.7.2
|
# 2.7.2
|
||||||
# CAS 2.0 proxy request response.
|
# CAS 2.0 proxy request response.
|
||||||
def proxy
|
def proxy
|
||||||
|
@ -205,31 +206,31 @@ module CASServer::Views
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure
|
def configure
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def themes_dir
|
def themes_dir
|
||||||
File.dirname(File.expand_path(__FILE__))+'../themes'
|
File.dirname(File.expand_path(__FILE__))+'../themes'
|
||||||
end
|
end
|
||||||
module_function :themes_dir
|
module_function :themes_dir
|
||||||
|
|
||||||
def current_theme
|
def current_theme
|
||||||
$CONF.theme || "simple"
|
$CONF.theme || "simple"
|
||||||
end
|
end
|
||||||
module_function :current_theme
|
module_function :current_theme
|
||||||
|
|
||||||
def organization
|
def organization
|
||||||
$CONF.organization || ""
|
$CONF.organization || ""
|
||||||
end
|
end
|
||||||
module_function :organization
|
module_function :organization
|
||||||
|
|
||||||
def infoline
|
def infoline
|
||||||
$CONF.infoline || ""
|
$CONF.infoline || ""
|
||||||
end
|
end
|
||||||
module_function :infoline
|
module_function :infoline
|
||||||
|
|
||||||
def serialize_extra_attribute(value)
|
def serialize_extra_attribute(value)
|
||||||
if value.kind_of?(String) || value.kind_of?(Numeric)
|
if value.kind_of?(String) || value.kind_of?(Numeric)
|
||||||
value
|
value
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
require File.dirname(__FILE__)+'/casserver'
|
require File.dirname(__FILE__)+'/casserver'
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
require File.dirname(__FILE__)+'/../casserver/version.rb'
|
require File.dirname(__FILE__)+'/../casserver/version.rb'
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2008-11-12 12:49-0500\n"
|
"PO-Revision-Date: 2008-11-12 12:49-0500\n"
|
||||||
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
||||||
"Language-Team: German\n"
|
"Language-Team: German\n"
|
||||||
|
@ -62,7 +62,7 @@ msgstr ""
|
||||||
"Der Server kann diese Gateway-Anfrage nicht erfüllen, da keine Service-"
|
"Der Server kann diese Gateway-Anfrage nicht erfüllen, da keine Service-"
|
||||||
"Parameter übergeben wurden."
|
"Parameter übergeben wurden."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -79,41 +79,49 @@ msgstr ""
|
||||||
"Der CAS-Login-URI konnte nicht erraten werden. Bitte ergänzen Sie Ihre "
|
"Der CAS-Login-URI konnte nicht erraten werden. Bitte ergänzen Sie Ihre "
|
||||||
"Anfrage um einen submitToURI Parameter."
|
"Anfrage um einen submitToURI Parameter."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Sie haben sich erfolgreich am Central Authentication Service angemeldet."
|
"Sie haben sich erfolgreich am Central Authentication Service angemeldet."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr "Falscher Benutzername oder Passwort."
|
msgstr "Falscher Benutzername oder Passwort."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Sie haben sich erfolgreich vom Central Authentication Service abgemeldet."
|
"Sie haben sich erfolgreich vom Central Authentication Service abgemeldet."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr " Bitte klicken Sie auf den folgenden Link, um fortzufahren:"
|
msgstr " Bitte klicken Sie auf den folgenden Link, um fortzufahren:"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Für die Generierung eines Login-Tickets, ist eine POST-Anfrage erforderlich."
|
"Für die Generierung eines Login-Tickets, ist eine POST-Anfrage erforderlich."
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " Zentrales Login"
|
msgstr " Zentrales Login"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "Benutzername"
|
msgstr "Benutzername"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Passwort"
|
msgstr "Passwort"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "ANMELDEN"
|
msgstr "ANMELDEN"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2008-11-12 12:30-0500\n"
|
"PO-Revision-Date: 2008-11-12 12:30-0500\n"
|
||||||
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
||||||
"Language-Team: Spanish\n"
|
"Language-Team: Spanish\n"
|
||||||
|
@ -61,7 +61,7 @@ msgstr ""
|
||||||
"El servidor no puede cumplir con esta petición, porque no fue parámetro de "
|
"El servidor no puede cumplir con esta petición, porque no fue parámetro de "
|
||||||
"servicio prestado."
|
"servicio prestado."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -78,38 +78,46 @@ msgstr ""
|
||||||
"No podía adivinar el URI de acceso CAS. Suministro submitToURI un parámetro "
|
"No podía adivinar el URI de acceso CAS. Suministro submitToURI un parámetro "
|
||||||
"con su solicitud."
|
"con su solicitud."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr "Inicio de sesión satisfactorio."
|
msgstr "Inicio de sesión satisfactorio."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr "Incorrecto nombre de usuario o contraseña."
|
msgstr "Incorrecto nombre de usuario o contraseña."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr "Cierre de sesión satisfactorio."
|
msgstr "Cierre de sesión satisfactorio."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr " Por favor, haga clic en el vínculo siguiente para continuar:"
|
msgstr " Por favor, haga clic en el vínculo siguiente para continuar:"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr "Para generar un ticket de acceso, usted debe hacer una petición POST."
|
msgstr "Para generar un ticket de acceso, usted debe hacer una petición POST."
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " Servicio de Autenticación Central"
|
msgstr " Servicio de Autenticación Central"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "Usuario"
|
msgstr "Usuario"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Contraseña"
|
msgstr "Contraseña"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "INICIAR SESIÓN"
|
msgstr "INICIAR SESIÓN"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2008-11-12 11:53-0500\n"
|
"PO-Revision-Date: 2008-11-12 11:53-0500\n"
|
||||||
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
||||||
"Language-Team: French\n"
|
"Language-Team: French\n"
|
||||||
|
@ -61,7 +61,7 @@ msgstr ""
|
||||||
"Le serveur ne peut pas répondre à cette demande (pas de 'service' paramètre "
|
"Le serveur ne peut pas répondre à cette demande (pas de 'service' paramètre "
|
||||||
"a été donné)."
|
"a été donné)."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -77,40 +77,48 @@ msgstr ""
|
||||||
"Impossible de deviner le CAS de connexion URI. S'il vous plaît fournir une "
|
"Impossible de deviner le CAS de connexion URI. S'il vous plaît fournir une "
|
||||||
"submitToURI paramètre à votre demande."
|
"submitToURI paramètre à votre demande."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vous vous êtes authentifié(e) auprès du Service Central d'Authentification."
|
"Vous vous êtes authentifié(e) auprès du Service Central d'Authentification."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr "Les informations transmises n'ont pas permis de vous authentifier"
|
msgstr "Les informations transmises n'ont pas permis de vous authentifier"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr "Vous vous êtes déconnecté(e) du Service Central d'Authentification."
|
msgstr "Vous vous êtes déconnecté(e) du Service Central d'Authentification."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr " S'il vous plaît cliquer sur le lien suivant pour continuer:"
|
msgstr " S'il vous plaît cliquer sur le lien suivant pour continuer:"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Pour générer un ticket de connexion, vous devez faire une requête POST."
|
"Pour générer un ticket de connexion, vous devez faire une requête POST."
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " Service Central d'Authentification."
|
msgstr " Service Central d'Authentification."
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "Identifiant"
|
msgstr "Identifiant"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Mot de passe"
|
msgstr "Mot de passe"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "SE CONNECTER"
|
msgstr "SE CONNECTER"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2008-11-12 13:04-0500\n"
|
"PO-Revision-Date: 2008-11-12 13:04-0500\n"
|
||||||
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
||||||
"Language-Team: Japanese\n"
|
"Language-Team: Japanese\n"
|
||||||
|
@ -65,7 +65,7 @@ msgstr ""
|
||||||
"サービスパラメーターが指定されていないので、サーバーはゲートウェイリクエスト"
|
"サービスパラメーターが指定されていないので、サーバーはゲートウェイリクエスト"
|
||||||
"を満たす事ができません。"
|
"を満たす事ができません。"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -81,38 +81,46 @@ msgstr ""
|
||||||
"CASのURIを推測することができませんでした。リクエストにsubmitToURIパラメータを"
|
"CASのURIを推測することができませんでした。リクエストにsubmitToURIパラメータを"
|
||||||
"指定してください。"
|
"指定してください。"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr "ログインしました"
|
msgstr "ログインしました"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr "ユーザー名またはパスワードが間違っています"
|
msgstr "ユーザー名またはパスワードが間違っています"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr "ログアウトしました。"
|
msgstr "ログアウトしました。"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr " 継続するには、以下のリンクをクリックしてください:"
|
msgstr " 継続するには、以下のリンクをクリックしてください:"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr "ログインチケットを発行するには、POSTリクエストを送る必要があります。"
|
msgstr "ログインチケットを発行するには、POSTリクエストを送る必要があります。"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " 統合ログイン"
|
msgstr " 統合ログイン"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "ユーザー名"
|
msgstr "ユーザー名"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "パスワード"
|
msgstr "パスワード"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "ログイン"
|
msgstr "ログイン"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2008-11-12 11:03-0500\n"
|
"PO-Revision-Date: 2008-11-12 11:03-0500\n"
|
||||||
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
"Last-Translator: Matt Zukowski <mzukowski@urbacon.net>\n"
|
||||||
"Language-Team: Polish\n"
|
"Language-Team: Polish\n"
|
||||||
|
@ -62,7 +62,7 @@ msgstr ""
|
||||||
"Serwer nie może spełnić tego żądania bramowego, ponieważ nie został podany "
|
"Serwer nie może spełnić tego żądania bramowego, ponieważ nie został podany "
|
||||||
"parametr usługi."
|
"parametr usługi."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -78,38 +78,46 @@ msgstr ""
|
||||||
"Nie można odgadnąć URI do logowania do CAS. Proszę dostarczyć parametr "
|
"Nie można odgadnąć URI do logowania do CAS. Proszę dostarczyć parametr "
|
||||||
"submitToURI."
|
"submitToURI."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr "Jesteś zalogowany."
|
msgstr "Jesteś zalogowany."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr "Niepoprawny użytkownik lub hasło."
|
msgstr "Niepoprawny użytkownik lub hasło."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr "Jesteś wylogowany."
|
msgstr "Jesteś wylogowany."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr " Proszę kliknąć na poniższy link, aby kontynuować:"
|
msgstr " Proszę kliknąć na poniższy link, aby kontynuować:"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr "Aby wygenerować login bilet, musisz złożyć żądanie POST."
|
msgstr "Aby wygenerować login bilet, musisz złożyć żądanie POST."
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " Centralna Usługa Uwierzytelniania"
|
msgstr " Centralna Usługa Uwierzytelniania"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "Użytkownik"
|
msgstr "Użytkownik"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Hasło"
|
msgstr "Hasło"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "ZALOGUJ"
|
msgstr "ZALOGUJ"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2009-03-17 20:55+0200\n"
|
"PO-Revision-Date: 2009-03-17 20:55+0200\n"
|
||||||
"Last-Translator: Kivanio Barbosa <kivanio@gmail.com>\n"
|
"Last-Translator: Kivanio Barbosa <kivanio@gmail.com>\n"
|
||||||
"Language-Team: Brazil\n"
|
"Language-Team: Brazil\n"
|
||||||
|
@ -61,7 +61,7 @@ msgstr ""
|
||||||
"O servidor não pode completar a solicitação porque não foi enviado o "
|
"O servidor não pode completar a solicitação porque não foi enviado o "
|
||||||
"paramêtro do serviço."
|
"paramêtro do serviço."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -77,39 +77,47 @@ msgstr ""
|
||||||
"Não encontramos a URI de acesso ao CAS. Por favor, informe corretamente no "
|
"Não encontramos a URI de acesso ao CAS. Por favor, informe corretamente no "
|
||||||
"submitToURI com sua solicitação."
|
"submitToURI com sua solicitação."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr "Login efetuado com sucesso."
|
msgstr "Login efetuado com sucesso."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr "Usuário ou Senha está incorreto."
|
msgstr "Usuário ou Senha está incorreto."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr "Você saiu do sistema com sucesso."
|
msgstr "Você saiu do sistema com sucesso."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr " Por favor, clique no seguinte link para continuar:"
|
msgstr " Por favor, clique no seguinte link para continuar:"
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Para gerar um ticket de acceso, você deve fazer uma requisição via POST."
|
"Para gerar um ticket de acceso, você deve fazer uma requisição via POST."
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " Central de Autenticação"
|
msgstr " Central de Autenticação"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "Usuário"
|
msgstr "Usuário"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Senha"
|
msgstr "Senha"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "ENTRAR"
|
msgstr "ENTRAR"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2008-11-04 12:32+0200\n"
|
"PO-Revision-Date: 2008-11-04 12:32+0200\n"
|
||||||
"Last-Translator: Antono Vasiljev <antono.vasiljev@gmail.com>\n"
|
"Last-Translator: Antono Vasiljev <antono.vasiljev@gmail.com>\n"
|
||||||
"Language-Team: Russian <ru@li.org>\n"
|
"Language-Team: Russian <ru@li.org>\n"
|
||||||
|
@ -57,7 +57,7 @@ msgstr ""
|
||||||
"Этот сервер не может выполнить этот запрос, поскольку не были указаны "
|
"Этот сервер не может выполнить этот запрос, поскольку не были указаны "
|
||||||
"праметры сервиса."
|
"праметры сервиса."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -73,38 +73,46 @@ msgstr ""
|
||||||
"Не возможно угадать адрес входа на CAS. Пожалуйста, передайте с запросом "
|
"Не возможно угадать адрес входа на CAS. Пожалуйста, передайте с запросом "
|
||||||
"параметр submitToURI."
|
"параметр submitToURI."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr "Вы успешно вошли."
|
msgstr "Вы успешно вошли."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr "Неверное имя пользователя или пароль."
|
msgstr "Неверное имя пользователя или пароль."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr "Вы успешно вышли."
|
msgstr "Вы успешно вышли."
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr " Перейдите по ссылке чтобы продолжить: "
|
msgstr " Перейдите по ссылке чтобы продолжить: "
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr "Чтобы сгенерировать входной билет вы должны делать POST запрос."
|
msgstr "Чтобы сгенерировать входной билет вы должны делать POST запрос."
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " Центральный вход"
|
msgstr " Центральный вход"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "Логин"
|
msgstr "Логин"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Пароль"
|
msgstr "Пароль"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "Войти"
|
msgstr "Войти"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-05-06 18:16-0400\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2008-10-29 20:55+0200\n"
|
"PO-Revision-Date: 2008-10-29 20:55+0200\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -55,7 +55,7 @@ msgid ""
|
||||||
"was given."
|
"was given."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:195
|
#: lib/casserver/controllers.rb:59 lib/casserver/controllers.rb:179
|
||||||
msgid ""
|
msgid ""
|
||||||
"The target service your browser supplied appears to be invalid. Please "
|
"The target service your browser supplied appears to be invalid. Please "
|
||||||
"contact your system administrator for help."
|
"contact your system administrator for help."
|
||||||
|
@ -67,38 +67,46 @@ msgid ""
|
||||||
"with your request."
|
"with your request."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:184
|
#: lib/casserver/controllers.rb:168
|
||||||
msgid "You have successfully logged in."
|
msgid "You have successfully logged in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:200
|
#: lib/casserver/controllers.rb:184
|
||||||
msgid "Incorrect username or password."
|
msgid "Incorrect username or password."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:257
|
#: lib/casserver/controllers.rb:267
|
||||||
msgid "You have successfully logged out."
|
msgid "You have successfully logged out."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:260
|
#: lib/casserver/controllers.rb:269
|
||||||
msgid " Please click on the following link to continue:"
|
msgid " Please click on the following link to continue:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/controllers.rb:410
|
#: lib/casserver/controllers.rb:419
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:113
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/casserver/views.rb:94
|
#: lib/casserver/views.rb:92
|
||||||
|
msgid "Remeber me on this computer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: rubycas-server \n"
|
"Project-Id-Version: rubycas-server \n"
|
||||||
"POT-Creation-Date: 2009-09-29 16:29+0800\n"
|
"POT-Creation-Date: 2009-09-29 17:04+0800\n"
|
||||||
"PO-Revision-Date: 2009-03-17 20:55+0200\n"
|
"PO-Revision-Date: 2009-03-17 20:55+0200\n"
|
||||||
"Last-Translator: Lin Jen-Shin <godfat@godfat.org>\n"
|
"Last-Translator: Lin Jen-Shin <godfat@godfat.org>\n"
|
||||||
"Language-Team: Traditional Chinese\n"
|
"Language-Team: Traditional Chinese\n"
|
||||||
|
@ -87,23 +87,27 @@ msgstr " 請點以下的連結繼續"
|
||||||
msgid "To generate a login ticket, you must make a POST request."
|
msgid "To generate a login ticket, you must make a POST request."
|
||||||
msgstr "你必須使用 POST 來產生登入憑証"
|
msgstr "你必須使用 POST 來產生登入憑証"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:43 lib/casserver/views.rb:119
|
#: lib/casserver/views.rb:43 lib/casserver/views.rb:120
|
||||||
msgid " Central Login"
|
msgid " Central Login"
|
||||||
msgstr " 整合登入"
|
msgstr " 整合登入"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:73
|
#: lib/casserver/views.rb:68
|
||||||
|
msgid "Please wait..."
|
||||||
|
msgstr "請稍候..."
|
||||||
|
|
||||||
|
#: lib/casserver/views.rb:74
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "帳號"
|
msgstr "帳號"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:82
|
#: lib/casserver/views.rb:83
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "密碼"
|
msgstr "密碼"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:91
|
#: lib/casserver/views.rb:92
|
||||||
msgid "Remeber me on this computer"
|
msgid "Remeber me on this computer"
|
||||||
msgstr "在這台電腦上記住我"
|
msgstr "在這台電腦上記住我"
|
||||||
|
|
||||||
#: lib/casserver/views.rb:100
|
#: lib/casserver/views.rb:101
|
||||||
msgid "LOGIN"
|
msgid "LOGIN"
|
||||||
msgstr "登入"
|
msgstr "登入"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
* {
|
* {
|
||||||
font-family: Verdana, sans-serif;
|
font-family: Verdana, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -7,115 +7,115 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.button {
|
input.button {
|
||||||
/*font-weight: bold;*/
|
/*font-weight: bold;*/
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-box {
|
#login-box {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 350px;
|
width: 350px;
|
||||||
top: 130px;
|
top: 130px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headline-container {
|
#headline-container {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
border-bottom: 1px solid #899989;
|
border-bottom: 1px solid #899989;
|
||||||
font-family: Tahoma, Verdana, sans-serif;
|
font-family: Tahoma, Verdana, sans-serif;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
padding-right: 7px;
|
padding-right: 7px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
letter-spacing: -0.25px;
|
letter-spacing: -0.25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logo-container {
|
#logo-container {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logo {
|
#logo {
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-form-container {
|
#login-form-container {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#username,
|
#username,
|
||||||
#password {
|
#password {
|
||||||
width: 10em;
|
width: 10em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-form {
|
#login-form {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#form-layout {
|
#form-layout {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 6px;
|
top: 6px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#form-layout td {
|
#form-layout td {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#form-layout td#submit-container {
|
#form-layout td#submit-container {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#infoline {
|
#infoline {
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#messagebox-container {
|
#messagebox-container {
|
||||||
padding-left: 11px;
|
padding-left: 11px;
|
||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.messagebox {
|
div.messagebox {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
padding-left: 55px;
|
padding-left: 55px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.mistake {
|
div.mistake {
|
||||||
color: #d00;
|
color: #d00;
|
||||||
background-image: url(warning.png);
|
background-image: url(warning.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 10px 5px;
|
background-position: 10px 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.confirmation {
|
div.confirmation {
|
||||||
color: #280;
|
color: #280;
|
||||||
background-image: url(ok.png);
|
background-image: url(ok.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 10px 5px;
|
background-position: 10px 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.notice {
|
div.notice {
|
||||||
color: #04c;
|
color: #04c;
|
||||||
background-image: url(notice.png);
|
background-image: url(notice.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 10px 5px;
|
background-position: 10px 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
body {
|
body {
|
||||||
background-image: url(bg.png);
|
background-image: url(bg.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
#headline-container {
|
#headline-container {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-box {
|
#login-box {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 450px;
|
width: 450px;
|
||||||
top: 110px;
|
top: 110px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-form {
|
#login-form {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border: 1px #aaa solid;
|
border: 1px #aaa solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logo-container {
|
#logo-container {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logo {
|
#logo {
|
||||||
width: 128px;
|
width: 128px;
|
||||||
height: 128px;
|
height: 128px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
body {
|
body {
|
||||||
background-image: url(bg.png);
|
background-image: url(bg.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
color: #5c6156;
|
color: #5c6156;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-form {
|
#login-form {
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-image: url(login_box_bg.png);
|
background-image: url(login_box_bg.png);
|
||||||
height: 175px;
|
height: 175px;
|
||||||
width: 210px;
|
width: 210px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logo-container {
|
#logo-container {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logo {
|
#logo {
|
||||||
|
@ -24,10 +24,10 @@ label {
|
||||||
}
|
}
|
||||||
|
|
||||||
#infoline {
|
#infoline {
|
||||||
color: #5c6156;
|
color: #5c6156;
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headline-container {
|
#headline-container {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
8
setup.rb
8
setup.rb
|
@ -659,7 +659,7 @@ module FileOperations
|
||||||
def ruby(*args)
|
def ruby(*args)
|
||||||
command config('rubyprog'), *args
|
command config('rubyprog'), *args
|
||||||
end
|
end
|
||||||
|
|
||||||
def make(task = nil)
|
def make(task = nil)
|
||||||
command(*[config('makeprog'), task].compact)
|
command(*[config('makeprog'), task].compact)
|
||||||
end
|
end
|
||||||
|
@ -722,7 +722,7 @@ module HookScriptAPI
|
||||||
def srcdirectory?(path)
|
def srcdirectory?(path)
|
||||||
File.dir?(srcfile(path))
|
File.dir?(srcfile(path))
|
||||||
end
|
end
|
||||||
|
|
||||||
def srcfile?(path)
|
def srcfile?(path)
|
||||||
File.file?(srcfile(path))
|
File.file?(srcfile(path))
|
||||||
end
|
end
|
||||||
|
@ -826,7 +826,7 @@ class ToplevelInstaller
|
||||||
__send__ "exec_#{task}"
|
__send__ "exec_#{task}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_metaconfigs
|
def run_metaconfigs
|
||||||
@config.load_script "#{@ardir}/metaconfig"
|
@config.load_script "#{@ardir}/metaconfig"
|
||||||
end
|
end
|
||||||
|
@ -1404,7 +1404,7 @@ class Installer
|
||||||
end
|
end
|
||||||
|
|
||||||
# picked up many entries from cvs-1.11.1/src/ignore.c
|
# picked up many entries from cvs-1.11.1/src/ignore.c
|
||||||
JUNK_FILES = %w(
|
JUNK_FILES = %w(
|
||||||
core RCSLOG tags TAGS .make.state
|
core RCSLOG tags TAGS .make.state
|
||||||
.nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
|
.nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
|
||||||
*~ *.old *.bak *.BAK *.orig *.rej _$* *$
|
*~ *.old *.bak *.BAK *.orig *.rej _$* *$
|
||||||
|
|
|
@ -31,4 +31,4 @@ namespace :manifest do
|
||||||
task :refresh do
|
task :refresh do
|
||||||
`rake check_manifest | patch -p0 > Manifest.txt`
|
`rake check_manifest | patch -p0 > Manifest.txt`
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,5 +7,5 @@ end
|
||||||
desc 'Creates mo files from po files and puts them to locale dir'
|
desc 'Creates mo files from po files and puts them to locale dir'
|
||||||
task :mo do
|
task :mo do
|
||||||
require 'gettext/utils'
|
require 'gettext/utils'
|
||||||
GetText.create_mofiles(true, "po", "locale")
|
GetText.create_mofiles(true, "po", "locale")
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
* Add a C version of the ISAAC algorithm and make it possible to install
|
* Add a C version of the ISAAC algorithm and make it possible to install
|
||||||
the pure Ruby version and/or a version using a C extension for better
|
the pure Ruby version and/or a version using a C extension for better
|
||||||
performance.
|
performance.
|
||||||
|
|
|
@ -1,171 +1,171 @@
|
||||||
module Crypt
|
module Crypt
|
||||||
|
|
||||||
# ISAAC is a fast, strong random number generator. Details on the
|
# ISAAC is a fast, strong random number generator. Details on the
|
||||||
# algorithm can be found here: http://burtleburtle.net/bob/rand/isaac.html
|
# algorithm can be found here: http://burtleburtle.net/bob/rand/isaac.html
|
||||||
# This provides a consistent and capable algorithm for producing
|
# This provides a consistent and capable algorithm for producing
|
||||||
# independent streams of quality random numbers.
|
# independent streams of quality random numbers.
|
||||||
|
|
||||||
class ISAAC
|
class ISAAC
|
||||||
|
|
||||||
attr_accessor :randrsl, :randcnt
|
attr_accessor :randrsl, :randcnt
|
||||||
attr_accessor :mm, :aa, :bb, :cc
|
attr_accessor :mm, :aa, :bb, :cc
|
||||||
|
|
||||||
# When a Crypt::ISAAC object is created, it needs to be seeded for
|
# When a Crypt::ISAAC object is created, it needs to be seeded for
|
||||||
# random number generation. If the system has a /dev/urandom file,
|
# random number generation. If the system has a /dev/urandom file,
|
||||||
# that will be used to do the seeding by default. If false is explictly
|
# that will be used to do the seeding by default. If false is explictly
|
||||||
# passed when creating the object, it will instead use /dev/random to
|
# passed when creating the object, it will instead use /dev/random to
|
||||||
# generate its seeds. Be warned that this may make for SLOW
|
# generate its seeds. Be warned that this may make for SLOW
|
||||||
# initialization.
|
# initialization.
|
||||||
# If the requested source (/dev/urandom or /dev/random) do not exist,
|
# If the requested source (/dev/urandom or /dev/random) do not exist,
|
||||||
# the system will fall back to a simplistic initialization mechanism
|
# the system will fall back to a simplistic initialization mechanism
|
||||||
# using the builtin Mersenne Twister PRNG.
|
# using the builtin Mersenne Twister PRNG.
|
||||||
|
|
||||||
def initialize(noblock = true)
|
def initialize(noblock = true)
|
||||||
@mm = []
|
@mm = []
|
||||||
@randrsl = []
|
@randrsl = []
|
||||||
# Best initialization of the generator would be by pulling
|
# Best initialization of the generator would be by pulling
|
||||||
# numbers from /dev/random.
|
# numbers from /dev/random.
|
||||||
rnd_source = noblock ? '/dev/urandom' : '/dev/random'
|
rnd_source = noblock ? '/dev/urandom' : '/dev/random'
|
||||||
if (FileTest.exist? rnd_source)
|
if (FileTest.exist? rnd_source)
|
||||||
File.open(rnd_source,'r') do |r|
|
File.open(rnd_source,'r') do |r|
|
||||||
256.times do |t|
|
256.times do |t|
|
||||||
z = r.read(4)
|
z = r.read(4)
|
||||||
x = z.unpack('V')[0]
|
x = z.unpack('V')[0]
|
||||||
@randrsl[t] = x
|
@randrsl[t] = x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# If urandom isn't available, the standard Ruby PRNG makes an
|
# If urandom isn't available, the standard Ruby PRNG makes an
|
||||||
# adequate fallback.
|
# adequate fallback.
|
||||||
256.times do |t|
|
256.times do |t|
|
||||||
@randrsl[t] = Kernel.rand(4294967295)
|
@randrsl[t] = Kernel.rand(4294967295)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
randinit(true)
|
randinit(true)
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Works just like the standard rand() function. If called with an
|
# Works just like the standard rand() function. If called with an
|
||||||
# integer argument, rand() will return positive random number in
|
# integer argument, rand() will return positive random number in
|
||||||
# the range of 0 to (argument - 1). If called without an integer
|
# the range of 0 to (argument - 1). If called without an integer
|
||||||
# argument, rand() returns a positive floating point number less than 1.
|
# argument, rand() returns a positive floating point number less than 1.
|
||||||
|
|
||||||
def rand(*num)
|
|
||||||
if (@randcnt == 1)
|
|
||||||
isaac
|
|
||||||
@randcnt = 256
|
|
||||||
end
|
|
||||||
@randcnt -= 1
|
|
||||||
if num[0].to_i > 0
|
|
||||||
@randrsl[@randcnt].modulo(num[0])
|
|
||||||
else
|
|
||||||
".#{@randrsl[@randcnt]}".to_f
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def isaac
|
def rand(*num)
|
||||||
i = 0
|
if (@randcnt == 1)
|
||||||
x = 0
|
isaac
|
||||||
y = 0
|
@randcnt = 256
|
||||||
|
end
|
||||||
|
@randcnt -= 1
|
||||||
|
if num[0].to_i > 0
|
||||||
|
@randrsl[@randcnt].modulo(num[0])
|
||||||
|
else
|
||||||
|
".#{@randrsl[@randcnt]}".to_f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@cc += 1
|
def isaac
|
||||||
@bb += @cc
|
i = 0
|
||||||
@bb & 0xffffffff
|
x = 0
|
||||||
|
y = 0
|
||||||
|
|
||||||
while (i < 256) do
|
@cc += 1
|
||||||
x = @mm[i]
|
@bb += @cc
|
||||||
@aa = (@mm[(i + 128) & 255] + (@aa^(@aa << 13)) ) & 0xffffffff
|
@bb & 0xffffffff
|
||||||
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
|
||||||
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
x = @mm[i]
|
while (i < 256) do
|
||||||
@aa = (@mm[(i+128)&255] + (@aa^(0x03ffffff & (@aa >> 6))) ) & 0xffffffff
|
x = @mm[i]
|
||||||
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
@aa = (@mm[(i + 128) & 255] + (@aa^(@aa << 13)) ) & 0xffffffff
|
||||||
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
||||||
i += 1
|
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
||||||
|
i += 1
|
||||||
|
|
||||||
x = @mm[i]
|
x = @mm[i]
|
||||||
@aa = (@mm[(i + 128)&255] + (@aa^(@aa << 2)) ) & 0xffffffff
|
@aa = (@mm[(i+128)&255] + (@aa^(0x03ffffff & (@aa >> 6))) ) & 0xffffffff
|
||||||
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
||||||
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
x = @mm[i]
|
x = @mm[i]
|
||||||
@aa = (@mm[(i+128)&255] + (@aa^(0x0000ffff & (@aa >> 16))) ) & 0xffffffff
|
@aa = (@mm[(i + 128)&255] + (@aa^(@aa << 2)) ) & 0xffffffff
|
||||||
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
||||||
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
||||||
i += 1
|
i += 1
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def randinit(flag)
|
x = @mm[i]
|
||||||
i = 0
|
@aa = (@mm[(i+128)&255] + (@aa^(0x0000ffff & (@aa >> 16))) ) & 0xffffffff
|
||||||
a = 0
|
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
||||||
b = 0
|
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
||||||
c = 0
|
i += 1
|
||||||
d = 0
|
end
|
||||||
e = 0
|
end
|
||||||
f = 0
|
|
||||||
g = 0
|
|
||||||
@aa = @bb = @cc = 0
|
|
||||||
a = b = c = d = e = f = g = h = 0x9e3779b9
|
|
||||||
|
|
||||||
while (i < 4) do
|
def randinit(flag)
|
||||||
a ^= b<<1; d += a; b += c
|
i = 0
|
||||||
b ^= 0x3fffffff & (c>>2); e += b; c += d
|
a = 0
|
||||||
c ^= d << 8; f += c; d += e
|
b = 0
|
||||||
d ^= 0x0000ffff & (e >> 16); g += d; e += f
|
c = 0
|
||||||
e ^= f << 10; h += e; f += g
|
d = 0
|
||||||
f ^= 0x0fffffff & (g >> 4); a += f; g += h
|
e = 0
|
||||||
g ^= h << 8; b += g; h += a
|
f = 0
|
||||||
h ^= 0x007fffff & (a >> 9); c += h; a += b
|
g = 0
|
||||||
i += 1
|
@aa = @bb = @cc = 0
|
||||||
end
|
a = b = c = d = e = f = g = h = 0x9e3779b9
|
||||||
|
|
||||||
i = 0
|
while (i < 4) do
|
||||||
while (i < 256) do
|
a ^= b<<1; d += a; b += c
|
||||||
if (flag)
|
b ^= 0x3fffffff & (c>>2); e += b; c += d
|
||||||
a+=@randrsl[i ].to_i; b+=@randrsl[i+1].to_i;
|
c ^= d << 8; f += c; d += e
|
||||||
c+=@randrsl[i+2]; d+=@randrsl[i+3];
|
d ^= 0x0000ffff & (e >> 16); g += d; e += f
|
||||||
e+=@randrsl[i+4]; f+=@randrsl[i+5];
|
e ^= f << 10; h += e; f += g
|
||||||
g+=@randrsl[i+6]; h+=@randrsl[i+7];
|
f ^= 0x0fffffff & (g >> 4); a += f; g += h
|
||||||
end
|
g ^= h << 8; b += g; h += a
|
||||||
|
h ^= 0x007fffff & (a >> 9); c += h; a += b
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
|
||||||
a^=b<<11; d+=a; b+=c;
|
i = 0
|
||||||
b^=0x3fffffff & (c>>2); e+=b; c+=d;
|
while (i < 256) do
|
||||||
c^=d<<8; f+=c; d+=e;
|
if (flag)
|
||||||
d^=0x0000ffff & (e>>16); g+=d; e+=f;
|
a+=@randrsl[i ].to_i; b+=@randrsl[i+1].to_i;
|
||||||
e^=f<<10; h+=e; f+=g;
|
c+=@randrsl[i+2]; d+=@randrsl[i+3];
|
||||||
f^=0x0fffffff & (g>>4); a+=f; g+=h;
|
e+=@randrsl[i+4]; f+=@randrsl[i+5];
|
||||||
g^=h<<8; b+=g; h+=a;
|
g+=@randrsl[i+6]; h+=@randrsl[i+7];
|
||||||
h^=0x007fffff & (a>>9); c+=h; a+=b;
|
end
|
||||||
@mm[i]=a;@mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
|
|
||||||
@mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
|
|
||||||
i += 8
|
|
||||||
end
|
|
||||||
|
|
||||||
if flag
|
a^=b<<11; d+=a; b+=c;
|
||||||
i = 0
|
b^=0x3fffffff & (c>>2); e+=b; c+=d;
|
||||||
while (i < 256)
|
c^=d<<8; f+=c; d+=e;
|
||||||
a+=@mm[i ]; b+=@mm[i+1]; c+=@mm[i+2]; d+=@mm[i+3];
|
d^=0x0000ffff & (e>>16); g+=d; e+=f;
|
||||||
e+=@mm[i+4]; f+=@mm[i+5]; g+=@mm[i+6]; h+=@mm[i+7];
|
e^=f<<10; h+=e; f+=g;
|
||||||
a^=b<<11; d+=a; b+=c;
|
f^=0x0fffffff & (g>>4); a+=f; g+=h;
|
||||||
b^=0x3fffffff & (c>>2); e+=b; c+=d;
|
g^=h<<8; b+=g; h+=a;
|
||||||
c^=d<<8; f+=c; d+=e;
|
h^=0x007fffff & (a>>9); c+=h; a+=b;
|
||||||
d^=0x0000ffff & (e>>16); g+=d; e+=f;
|
@mm[i]=a;@mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
|
||||||
e^=f<<10; h+=e; f+=g;
|
@mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
|
||||||
f^=0x0fffffff & (g>>4); a+=f; g+=h;
|
i += 8
|
||||||
g^=h<<8; b+=g; h+=a;
|
end
|
||||||
h^=0x007fffff & (a>>9); c+=h; a+=b;
|
|
||||||
@mm[i ]=a; @mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
|
|
||||||
@mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
|
|
||||||
i += 8
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
isaac()
|
if flag
|
||||||
@randcnt=256; # /* prepare to use the first set of results */
|
i = 0
|
||||||
end
|
while (i < 256)
|
||||||
end
|
a+=@mm[i ]; b+=@mm[i+1]; c+=@mm[i+2]; d+=@mm[i+3];
|
||||||
|
e+=@mm[i+4]; f+=@mm[i+5]; g+=@mm[i+6]; h+=@mm[i+7];
|
||||||
|
a^=b<<11; d+=a; b+=c;
|
||||||
|
b^=0x3fffffff & (c>>2); e+=b; c+=d;
|
||||||
|
c^=d<<8; f+=c; d+=e;
|
||||||
|
d^=0x0000ffff & (e>>16); g+=d; e+=f;
|
||||||
|
e^=f<<10; h+=e; f+=g;
|
||||||
|
f^=0x0fffffff & (g>>4); a+=f; g+=h;
|
||||||
|
g^=h<<8; b+=g; h+=a;
|
||||||
|
h^=0x007fffff & (a>>9); c+=h; a+=b;
|
||||||
|
@mm[i ]=a; @mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
|
||||||
|
@mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
|
||||||
|
i += 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
isaac()
|
||||||
|
@randcnt=256; # /* prepare to use the first set of results */
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,9 +22,9 @@ KINDS = [
|
||||||
|
|
||||||
#{{{ list of files to be ignored stolen from setup.rb
|
#{{{ list of files to be ignored stolen from setup.rb
|
||||||
mapping = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' }
|
mapping = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' }
|
||||||
ignore_files = %w[core RCSLOG tags TAGS .make.state .nse_depinfo
|
ignore_files = %w[core RCSLOG tags TAGS .make.state .nse_depinfo
|
||||||
#* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$
|
#* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$
|
||||||
*.org *.in .* ]
|
*.org *.in .* ]
|
||||||
#end of robbery
|
#end of robbery
|
||||||
IGNORE_FILES = ignore_files.map do |x|
|
IGNORE_FILES = ignore_files.map do |x|
|
||||||
Regexp.new('\A' + x.gsub(/[\.\$\#\*]/){|c| mapping[c]} + '\z')
|
Regexp.new('\A' + x.gsub(/[\.\$\#\*]/){|c| mapping[c]} + '\z')
|
||||||
|
@ -96,7 +96,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
module Actions
|
module Actions
|
||||||
|
|
||||||
class InstallFile
|
class InstallFile
|
||||||
|
|
||||||
attr_reader :source, :destination, :mode
|
attr_reader :source, :destination, :mode
|
||||||
|
@ -119,7 +119,7 @@ module Actions
|
||||||
end
|
end
|
||||||
|
|
||||||
def eql?(other)
|
def eql?(other)
|
||||||
self.class == other.class &&
|
self.class == other.class &&
|
||||||
@source == other.source &&
|
@source == other.source &&
|
||||||
@destination == other.destination &&
|
@destination == other.destination &&
|
||||||
@mode == other.mode
|
@mode == other.mode
|
||||||
|
@ -146,7 +146,7 @@ module Actions
|
||||||
end
|
end
|
||||||
|
|
||||||
def <=>(other)
|
def <=>(other)
|
||||||
FULL_ORDER[self, other] || self.directory <=> other.directory
|
FULL_ORDER[self, other] || self.directory <=> other.directory
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -254,17 +254,17 @@ class PackageSpecification_1_0
|
||||||
|
|
||||||
def self.declare_file_type(args, &handle_arg)
|
def self.declare_file_type(args, &handle_arg)
|
||||||
str_arr_p = lambda{|x| Array === x && x.all?{|y| String === y}}
|
str_arr_p = lambda{|x| Array === x && x.all?{|y| String === y}}
|
||||||
|
|
||||||
# strict type checking --- we don't want this to be extended arbitrarily
|
# strict type checking --- we don't want this to be extended arbitrarily
|
||||||
unless args.size == 1 && Hash === args.first &&
|
unless args.size == 1 && Hash === args.first &&
|
||||||
args.first.all?{|f,r| [Proc, String, NilClass].include?(r.class) &&
|
args.first.all?{|f,r| [Proc, String, NilClass].include?(r.class) &&
|
||||||
(String === f || str_arr_p[f])} or
|
(String === f || str_arr_p[f])} or
|
||||||
args.all?{|x| String === x || str_arr_p[x]}
|
args.all?{|x| String === x || str_arr_p[x]}
|
||||||
raise SpecificationError,
|
raise SpecificationError,
|
||||||
"Unspecified semantics for the given arguments: #{args.inspect}"
|
"Unspecified semantics for the given arguments: #{args.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.size == 1 && Hash === args.first
|
if args.size == 1 && Hash === args.first
|
||||||
args.first.to_a.each do |file, rename_info|
|
args.first.to_a.each do |file, rename_info|
|
||||||
if Array === file
|
if Array === file
|
||||||
# ignoring boring files
|
# ignoring boring files
|
||||||
|
@ -284,7 +284,7 @@ class PackageSpecification_1_0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#{{{ define the file tagging methods
|
#{{{ define the file tagging methods
|
||||||
KINDS.each { |kind|
|
KINDS.each { |kind|
|
||||||
define_method(kind) { |*args| # if this were 1.9 we could also take a block
|
define_method(kind) { |*args| # if this were 1.9 we could also take a block
|
||||||
|
@ -330,7 +330,7 @@ class PackageSpecification_1_0
|
||||||
target, options = @translate[kind][replaced_path]
|
target, options = @translate[kind][replaced_path]
|
||||||
options ||= TRANSLATE_DEFAULT_OPTIONS
|
options ||= TRANSLATE_DEFAULT_OPTIONS
|
||||||
if target && (replaced_path == dir || options[:inherit])
|
if target && (replaced_path == dir || options[:inherit])
|
||||||
dir = (target != '' ? File.join(target, *kept_dir_parts) :
|
dir = (target != '' ? File.join(target, *kept_dir_parts) :
|
||||||
File.join(*kept_dir_parts))
|
File.join(*kept_dir_parts))
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
@ -339,7 +339,7 @@ class PackageSpecification_1_0
|
||||||
end
|
end
|
||||||
dir
|
dir
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_file(kind, filename, new_filename_info, &callback)
|
def add_file(kind, filename, new_filename_info, &callback)
|
||||||
#TODO: refactor!!!
|
#TODO: refactor!!!
|
||||||
if File.directory? filename #XXX setup.rb and rpa-base defined File.dir?
|
if File.directory? filename #XXX setup.rb and rpa-base defined File.dir?
|
||||||
|
@ -423,7 +423,7 @@ class PackageSpecification_1_0
|
||||||
unless options.noop
|
unless options.noop
|
||||||
t = Test::Unit::AutoRunner.new(true)
|
t = Test::Unit::AutoRunner.new(true)
|
||||||
t.process_args(@unit_tests)
|
t.process_args(@unit_tests)
|
||||||
t.run
|
t.run
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -445,7 +445,7 @@ class PackageSpecification_1_0
|
||||||
key_val_pairs = additional_translations.to_a
|
key_val_pairs = additional_translations.to_a
|
||||||
option_pairs = key_val_pairs.select{|(k,v)| Symbol === k}
|
option_pairs = key_val_pairs.select{|(k,v)| Symbol === k}
|
||||||
default_opts.update(Hash[*option_pairs.flatten])
|
default_opts.update(Hash[*option_pairs.flatten])
|
||||||
|
|
||||||
(key_val_pairs - option_pairs).each do |key, val|
|
(key_val_pairs - option_pairs).each do |key, val|
|
||||||
add_translation(kind, key, val, default_opts)
|
add_translation(kind, key, val, default_opts)
|
||||||
end
|
end
|
||||||
|
@ -486,7 +486,7 @@ class PackageSpecification_1_0
|
||||||
opts.separator " setup compiles ruby extentions and others XXX"
|
opts.separator " setup compiles ruby extentions and others XXX"
|
||||||
opts.separator " install installs files"
|
opts.separator " install installs files"
|
||||||
opts.separator " test runs unit tests"
|
opts.separator " test runs unit tests"
|
||||||
|
|
||||||
|
|
||||||
opts.separator ""
|
opts.separator ""
|
||||||
opts.separator "Specific options:"
|
opts.separator "Specific options:"
|
||||||
|
@ -532,7 +532,7 @@ class PackageSpecification_1_0
|
||||||
opts.on "--vendor", "install into distribution directories (for packagers)" do
|
opts.on "--vendor", "install into distribution directories (for packagers)" do
|
||||||
@dirs.update VENDOR_DIRS
|
@dirs.update VENDOR_DIRS
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.separator ""
|
opts.separator ""
|
||||||
opts.separator "General options:"
|
opts.separator "General options:"
|
||||||
|
|
||||||
|
|
|
@ -1,76 +1,76 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
if ARGV[0] == 'local'
|
if ARGV[0] == 'local'
|
||||||
begin
|
begin
|
||||||
require '../crypt/ISAAC.rb'
|
require '../crypt/ISAAC.rb'
|
||||||
rescue Exception
|
rescue Exception
|
||||||
require './crypt/ISAAC.rb'
|
require './crypt/ISAAC.rb'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
require 'crypt/ISAACC'
|
require 'crypt/ISAACC'
|
||||||
rescue Exception
|
rescue Exception
|
||||||
require './crypt/ISAAC.rb'
|
require './crypt/ISAAC.rb'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class TC_ISAAC < Test::Unit::TestCase
|
class TC_ISAAC < Test::Unit::TestCase
|
||||||
def setup
|
def setup
|
||||||
assert_nothing_raised("Failed to create a Crypt::ISAAC object.") do
|
assert_nothing_raised("Failed to create a Crypt::ISAAC object.") do
|
||||||
@generator = Crypt::ISAAC.new
|
@generator = Crypt::ISAAC.new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def testKind
|
def testKind
|
||||||
assert_kind_of(Crypt::ISAAC,@generator,"The created object is not a Crypt::ISAAC or subclass thereof.")
|
assert_kind_of(Crypt::ISAAC,@generator,"The created object is not a Crypt::ISAAC or subclass thereof.")
|
||||||
end
|
end
|
||||||
|
|
||||||
def testInteger
|
def testInteger
|
||||||
assert_nothing_raised("Failed while generating an integer random number.") do
|
assert_nothing_raised("Failed while generating an integer random number.") do
|
||||||
mynum = @generator.rand(1000000)
|
mynum = @generator.rand(1000000)
|
||||||
assert_kind_of(Integer,mynum,"The generator failed to return an integer number in response to @generator.rand(1000000).")
|
assert_kind_of(Integer,mynum,"The generator failed to return an integer number in response to @generator.rand(1000000).")
|
||||||
assert((mynum >= 0),"The generator returned a number that is less than 0 (#{mynum}).")
|
assert((mynum >= 0),"The generator returned a number that is less than 0 (#{mynum}).")
|
||||||
assert((mynum < 1000000),"The generator returned a number that is greater than or equal to 1000000 (#{mynum}).")
|
assert((mynum < 1000000),"The generator returned a number that is greater than or equal to 1000000 (#{mynum}).")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def testFloat
|
def testFloat
|
||||||
assert_nothing_raised("Failed while generating a floating point random number.") do
|
assert_nothing_raised("Failed while generating a floating point random number.") do
|
||||||
mynum = @generator.rand()
|
mynum = @generator.rand()
|
||||||
assert_kind_of(Float,mynum,"The generator failed to return a floating point number in response to @generator.rand().")
|
assert_kind_of(Float,mynum,"The generator failed to return a floating point number in response to @generator.rand().")
|
||||||
assert((mynum >= 0),"The generator returned a number that is less than 0 (#{mynum}).")
|
assert((mynum >= 0),"The generator returned a number that is less than 0 (#{mynum}).")
|
||||||
assert((mynum < 1),"The generator returned a number that is greater than or equal to 1 (#{mynum}).")
|
assert((mynum < 1),"The generator returned a number that is greater than or equal to 1 (#{mynum}).")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def testIterations
|
def testIterations
|
||||||
puts
|
puts
|
||||||
count = 0
|
count = 0
|
||||||
assert_nothing_raised("Failed on iteration #{count} while trying to generate 100000 random numbers.") do
|
assert_nothing_raised("Failed on iteration #{count} while trying to generate 100000 random numbers.") do
|
||||||
100000.times do
|
100000.times do
|
||||||
count += 1
|
count += 1
|
||||||
x = @generator.rand(4294967295)
|
x = @generator.rand(4294967295)
|
||||||
print [x].pack('V').unpack('H8') if count % 1000 == 0
|
print [x].pack('V').unpack('H8') if count % 1000 == 0
|
||||||
if (count % 7000) == 0
|
if (count % 7000) == 0
|
||||||
print "\n"
|
print "\n"
|
||||||
else
|
else
|
||||||
print " " if count % 1000 == 0
|
print " " if count % 1000 == 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
puts "\n100000 numbers generated"
|
puts "\n100000 numbers generated"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def testDualStreams
|
def testDualStreams
|
||||||
g1 = nil
|
g1 = nil
|
||||||
g2 = nil
|
g2 = nil
|
||||||
assert_nothing_raised("Failed to pull numbers from two independent streams.") do
|
assert_nothing_raised("Failed to pull numbers from two independent streams.") do
|
||||||
g1 = Crypt::ISAAC.new
|
g1 = Crypt::ISAAC.new
|
||||||
g2 = Crypt::ISAAC.new
|
g2 = Crypt::ISAAC.new
|
||||||
assert((g1 != g2),"The generators are the same. This should not happen.")
|
assert((g1 != g2),"The generators are the same. This should not happen.")
|
||||||
1000.times do
|
1000.times do
|
||||||
g1.rand(4294967295)
|
g1.rand(4294967295)
|
||||||
g2.rand(4294967295)
|
g2.rand(4294967295)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
h1. RubyCAS-Server
|
h1. RubyCAS-Server
|
||||||
|
|
||||||
Please see "http://code.google.com/p/rubycas-server/":http://code.google.com/p/rubycas-server/ for more information.
|
Please see "http://code.google.com/p/rubycas-server/":http://code.google.com/p/rubycas-server/ for more information.
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
* MA 02111-1307 USA *
|
* MA 02111-1307 USA *
|
||||||
* *
|
* *
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
|
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
|
||||||
{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
|
{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
|
||||||
{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
|
{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
|
||||||
|
|
|
@ -1,138 +1,138 @@
|
||||||
body {
|
body {
|
||||||
background-color: #E1D1F1;
|
background-color: #E1D1F1;
|
||||||
font-family: "Georgia", sans-serif;
|
font-family: "Georgia", sans-serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
padding: 1.6em 0 0 0;
|
padding: 1.6em 0 0 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 4em;
|
font-size: 4em;
|
||||||
line-height: 0.8em;
|
line-height: 0.8em;
|
||||||
letter-spacing: -0.1ex;
|
letter-spacing: -0.1ex;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
li {
|
li {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
list-style-type: square;
|
list-style-type: square;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: #5E5AFF;
|
color: #5E5AFF;
|
||||||
background-color: #DAC;
|
background-color: #DAC;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
blockquote {
|
blockquote {
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
border-left: 1px solid #111;
|
border-left: 1px solid #111;
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
}
|
}
|
||||||
.caps {
|
.caps {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
width: 45em;
|
width: 45em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.coda {
|
.coda {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
color: #77f;
|
color: #77f;
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
color: #ff8;
|
color: #ff8;
|
||||||
background-color: #111;
|
background-color: #111;
|
||||||
padding: 2px 10px 2px 10px;
|
padding: 2px 10px 2px 10px;
|
||||||
border-style: dashed;
|
border-style: dashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
padding: 2px 10px 2px 10px;
|
padding: 2px 10px 2px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.success {
|
.success {
|
||||||
color: #0CC52B;
|
color: #0CC52B;
|
||||||
}
|
}
|
||||||
|
|
||||||
.failed {
|
.failed {
|
||||||
color: #E90A1B;
|
color: #E90A1B;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unknown {
|
.unknown {
|
||||||
color: #995000;
|
color: #995000;
|
||||||
}
|
}
|
||||||
pre, code {
|
pre, code {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
color: #ff8;
|
color: #ff8;
|
||||||
background-color: #111;
|
background-color: #111;
|
||||||
padding: 2px 10px 2px 10px;
|
padding: 2px 10px 2px 10px;
|
||||||
}
|
}
|
||||||
.comment { color: #aaa; font-style: italic; }
|
.comment { color: #aaa; font-style: italic; }
|
||||||
.keyword { color: #eff; font-weight: bold; }
|
.keyword { color: #eff; font-weight: bold; }
|
||||||
.punct { color: #eee; font-weight: bold; }
|
.punct { color: #eee; font-weight: bold; }
|
||||||
.symbol { color: #0bb; }
|
.symbol { color: #0bb; }
|
||||||
.string { color: #6b4; }
|
.string { color: #6b4; }
|
||||||
.ident { color: #ff8; }
|
.ident { color: #ff8; }
|
||||||
.constant { color: #66f; }
|
.constant { color: #66f; }
|
||||||
.regex { color: #ec6; }
|
.regex { color: #ec6; }
|
||||||
.number { color: #F99; }
|
.number { color: #F99; }
|
||||||
.expr { color: #227; }
|
.expr { color: #227; }
|
||||||
|
|
||||||
#version {
|
#version {
|
||||||
float: right;
|
float: right;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
background-color: #B3ABFF;
|
background-color: #B3ABFF;
|
||||||
color: #141331;
|
color: #141331;
|
||||||
padding: 15px 20px 10px 20px;
|
padding: 15px 20px 10px 20px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
border: 3px solid #141331;
|
border: 3px solid #141331;
|
||||||
}
|
}
|
||||||
|
|
||||||
#version .numbers {
|
#version .numbers {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 4em;
|
font-size: 4em;
|
||||||
line-height: 0.8em;
|
line-height: 0.8em;
|
||||||
letter-spacing: -0.1ex;
|
letter-spacing: -0.1ex;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#version p {
|
#version p {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #141331;
|
color: #141331;
|
||||||
background-color: #B3ABFF;
|
background-color: #B3ABFF;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#version a {
|
#version a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #141331;
|
color: #141331;
|
||||||
background-color: #B3ABFF;
|
background-color: #B3ABFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clickable {
|
.clickable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
cursor: hand;
|
cursor: hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче