bringing in godfat's redesigned authenticator architecture with per-class setups... also a whole bunch of whitespace changes

This commit is contained in:
Matt Zukowski 2010-02-01 14:04:42 -05:00
Родитель 79351dec4f 29a09c6b61
Коммит 691c58d721
55 изменённых файлов: 1163 добавлений и 1108 удалений

Просмотреть файл

@ -1 +1 @@
See History.txt See 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
Просмотреть файл

@ -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

Просмотреть файл

@ -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;
} }

Просмотреть файл

@ -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

6
vendor/isaac_0.9.1/TODO поставляемый
Просмотреть файл

@ -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.

302
vendor/isaac_0.9.1/crypt/ISAAC.rb поставляемый
Просмотреть файл

@ -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

32
vendor/isaac_0.9.1/setup.rb поставляемый
Просмотреть файл

@ -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:"

128
vendor/isaac_0.9.1/test/TC_ISAAC.rb поставляемый
Просмотреть файл

@ -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;
} }