diff options
| author | elijah <elijah@riseup.net> | 2013-05-19 22:28:01 -0700 | 
|---|---|---|
| committer | elijah <elijah@riseup.net> | 2013-05-19 22:28:01 -0700 | 
| commit | f9d6b218be3bdbb2d3c544849b2ab92348d0e394 (patch) | |
| tree | 71cd7ab6e5e9ffb4571b555324ada743c3d29387 | |
| parent | 5d2e69ad4f2b6214df52c617f5e6cb23d9f40944 (diff) | |
many related changes -- allow command line configs, validate addresses, overhaul bootstrap.
| -rw-r--r-- | README.md | 28 | ||||
| -rwxr-xr-x | bin/nickserver | 27 | ||||
| -rw-r--r-- | config/default.yml | 26 | ||||
| -rw-r--r-- | lib/nickserver.rb | 1 | ||||
| -rw-r--r-- | lib/nickserver/config.rb | 2 | ||||
| -rw-r--r-- | lib/nickserver/daemon.rb | 15 | ||||
| -rw-r--r-- | lib/nickserver/email_address.rb | 25 | ||||
| -rw-r--r-- | lib/nickserver/server.rb | 32 | ||||
| -rw-r--r-- | lib/nickserver/version.rb | 2 | ||||
| -rw-r--r-- | test/unit/nickserver_test.rb | 4 | 
10 files changed, 117 insertions, 45 deletions
@@ -1,9 +1,15 @@  Nickserver  ================================== -Nickserver is a server running the Nicknym protocol. This daemon can be run by service providers in order to support Nicknym. +Nickserver is a server running the Nicknym protocol. This daemon can be run by +service providers in order to support Nicknym. -Nicknym is a protocol to map user nicknames to public keys. With Nicknym, the user is able to think solely in terms of nickname, while still being able to communicate with a high degree of security (confidentiality, integrity, and authenticity). Essentially, Nicknym is a system for binding human-memorable nicknames to a cryptographic key via automatic discovery and automatic validation. +Nicknym is a protocol to map user nicknames to public keys. With Nicknym, the +user is able to think solely in terms of nickname, while still being able to +communicate with a high degree of security (confidentiality, integrity, and +authenticity). Essentially, Nicknym is a system for binding human-memorable +nicknames to a cryptographic key via automatic discovery and automatic +validation.  For more information, see https://leap.se/nicknym @@ -20,7 +26,8 @@ You query the nickserver via HTTP. The API is very minimal:      curl -X POST -d address=alice@domain.org https://nicknym.domain.org:6425 -The response consists of a signed JSON document with fields for the available public keys corresponding to the address. +The response consists of a signed JSON document with fields for the available +public keys corresponding to the address.  For more details, see https://leap.se/nicknym @@ -35,6 +42,13 @@ Installation  You have three fine options for installing nickserver: +Install prerequisites + +    $ sudo apt-get install ruby1.9.1-dev libssl-dev + +Note: libssl-dev must be installed before installing the gem EventMachine, +otherwise the gem will get built without TLS support. +  Install from source:      $ git clone git://leap.se/nickserver @@ -52,9 +66,13 @@ Install for development:  Configuration  ================================== -Nickserver loads the configuration files `config/default.yml` and `/etc/leap/nickserver.yml`, if it exists. See `config/default.yml` for the available options. +Nickserver loads the configuration files `config/default.yml` and +`/etc/leap/nickserver.yml`, if it exists. See `config/default.yml` for the +available options. -The default HKP host is set to https://hkps.pool.sks-keyservers.net. The CA for this pool is available here https://sks-keyservers.net/sks-keyservers.netCA.pem +The default HKP host is set to https://hkps.pool.sks-keyservers.net. The CA +for this pool is available here https://sks-keyservers.net/sks- +keyservers.netCA.pem  Usage  ================================== diff --git a/bin/nickserver b/bin/nickserver index 8843dde..062684f 100755 --- a/bin/nickserver +++ b/bin/nickserver @@ -4,27 +4,20 @@  # Nickserver key discovery daemon  # -def load_library(name) -  begin                      # try without rubygems (might be already loaded or not present) -    require name -  rescue LoadError -    begin                    # try it as a gem -      require 'rubygems' -      require name -    rescue LoadError         # try manually, requiring gems in Gemfile if it exists. -      base_directory = File.expand_path('../..', File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__) -      if File.exists?("#{base_directory}/Gemfile.lock") -        ENV['BUNDLE_GEMFILE'] ||= "#{base_directory}/Gemfile" -        require 'bundler' -        Bundler.require(:default) -      end -      $LOAD_PATH << "#{base_directory}/lib" -      require name +def load_local_gem(dir_path='../..') +  base_directory = File.expand_path(dir_path, File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__) +  if !$LOAD_PATH.include? "#{base_directory}/lib" +    if File.exists?("#{base_directory}/Gemfile.lock") +      ENV['BUNDLE_GEMFILE'] ||= "#{base_directory}/Gemfile" +      require 'bundler' +      Bundler.require(:default)      end +    $LOAD_PATH << "#{base_directory}/lib"    end  end -load_library('nickserver') +load_local_gem +require 'nickserver'  Nickserver::Daemon.run('nickserver') do    EventMachine.run do diff --git a/config/default.yml b/config/default.yml index 4328cbd..c31b504 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1,10 +1,24 @@ +# +# nickserver daemon +# +port: 6425 +pid_file: '/tmp/nickserver.pid' +log_file: '/tmp/nickserver.log' +user: ~ +domain: ~ +domains: ~ + +# +# couch +#  couch_host: 'localhost'  couch_port: 5984  couch_database: 'users' -#couch_user: 'nickserver' -#couch_password: 'blahblah' +couch_user: ~ +couch_password: ~ + +# +# HKP +#  hkp_url: 'https://hkps.pool.sks-keyservers.net:/pks/lookup' -port: 6425 -pid_file: '/var/run/nickserver' -user: 'nobody' -log_file: '/var/log/nickserver.log' + diff --git a/lib/nickserver.rb b/lib/nickserver.rb index 9e6464e..951dae9 100644 --- a/lib/nickserver.rb +++ b/lib/nickserver.rb @@ -1,6 +1,7 @@  require "nickserver/version"  require "nickserver/config" +require "nickserver/email_address"  require "nickserver/couch/fetch_key" diff --git a/lib/nickserver/config.rb b/lib/nickserver/config.rb index b283d8b..be401f5 100644 --- a/lib/nickserver/config.rb +++ b/lib/nickserver/config.rb @@ -18,6 +18,8 @@ module Nickserver        attr_accessor :pid_file        attr_accessor :user        attr_accessor :log_file +      attr_accessor :domain +      attr_accessor :domains        attr_accessor :loaded        attr_accessor :verbose diff --git a/lib/nickserver/daemon.rb b/lib/nickserver/daemon.rb index e0bd527..651c6ce 100644 --- a/lib/nickserver/daemon.rb +++ b/lib/nickserver/daemon.rb @@ -67,7 +67,7 @@ module Nickserver          create_pid_file(Config.pid_file, Config.user)          catch_interrupt          redirect_output -        drop_permissions_to(Config.user) +        drop_permissions_to(Config.user) if Config.user          File.umask 0000          yield        end @@ -77,7 +77,7 @@ module Nickserver        File.open file, 'w' do |f|          f.write("#{Process.pid}\n")        end -      FileUtils.chown(user, nil, file) +      FileUtils.chown(user, nil, file) if Process::Sys.getuid == 0      rescue Errno::EACCES        bail "insufficient permission to create to pid file `#{file}`"      rescue Errno::ENOENT @@ -207,13 +207,22 @@ module Nickserver            when 'status'    then ARGV.shift; @command = :status            when 'version'   then ARGV.shift; @command = :version            when '--verbose' then ARGV.shift; Config.versbose = true -          when /^-/        then usage("Unknown option: #{ARGV[0].inspect}") +          when /^-/        then override_default_config(ARGV.shift, ARGV.shift)            else break          end        end        usage("Missing command") unless @command      end +    def override_default_config(flag, value) +      flag = flag.sub /^--/, '' +      if Config.respond_to?("#{flag}=") +        Config.send("#{flag}=", value) +      else +        usage("Unknown option: --#{flag}") +      end +    end +      #      # COMMANDS      # diff --git a/lib/nickserver/email_address.rb b/lib/nickserver/email_address.rb new file mode 100644 index 0000000..26053a2 --- /dev/null +++ b/lib/nickserver/email_address.rb @@ -0,0 +1,25 @@ +# +# This rather crazy regexp is from here: http://code.iamcal.com/php/rfc822/ +# Licensed GPLv3 +# +# It is too liberal, allowing "!@x" as a valid address, for example, but it does +# follow the specification rather closely. +# + +module Nickserver +  EmailAddress = begin +    qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]' +    dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]' +    atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+' +    quoted_pair = '\\x5c[\\x00-\\x7f]' +    domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d" +    quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22" +    domain_ref = atom +    sub_domain = "(?:#{domain_ref}|#{domain_literal})" +    word = "(?:#{atom}|#{quoted_string})" +    domain = "#{sub_domain}(?:\\x2e#{sub_domain})*" +    local_part = "#{word}(?:\\x2e#{word})*" +    addr_spec = "#{local_part}\\x40#{domain}" +    /\A#{addr_spec}\z/n +  end +end diff --git a/lib/nickserver/server.rb b/lib/nickserver/server.rb index 0bda4f1..2f4d4f0 100644 --- a/lib/nickserver/server.rb +++ b/lib/nickserver/server.rb @@ -21,7 +21,7 @@ module Nickserver      #      def self.start(opts={})        Nickserver::Config.load -      options = {:host => '0.0.0.0', :port => Nickserver::Config.port}.merge(opts) +      options = {:host => '0.0.0.0', :port => Nickserver::Config.port.to_i}.merge(opts)        EM.start_server options[:host], options[:port], Nickserver::Server      end @@ -34,6 +34,8 @@ module Nickserver        uid = get_uid_from_request        if uid.nil?          send_not_found +      elsif uid !~ EmailAddress +        send_error("Not a valid address")        else          send_key(uid)        end @@ -42,11 +44,11 @@ module Nickserver      private      def send_error(msg = "not supported") -      send_response(:status => 500, :content => msg) +      send_response(:status => 500, :content => "500 #{msg}\n")      end -    def send_not_found(msg = "404 Not Found") -      send_response(:status => 404, :content => msg) +    def send_not_found(msg = "Not Found") +      send_response(:status => 404, :content => "404 #{msg}\n")      end      def send_response(opts = {}) @@ -100,14 +102,24 @@ module Nickserver      # Return true if the user address is for a user of this service provider.      # e.g. if the provider is example.org, then alice@example.org returns true.      # -    # Currently, we rely on whatever hostname the client voluntarily specifies -    # in the headers of the http request. +    # If 'domain' is not configured, we rely on the Host header of the HTTP request.      #      def local_address?(uid) -      hostname = @http_headers.split(/\0/).grep(/^Host: /).first.split(':')[1].strip.sub(/^nicknym\./, '') -      return uid =~ /^.*@#{Regexp.escape(hostname)}$/ -    #rescue -    #  false +      uid_domain = uid.sub(/^.*@(.*)$/, "\\1") +      if Config.domain +        return uid_domain == Config.domain +      else +        # no domain configured, use Host header +        host_header = @http_headers.split(/\0/).grep(/^Host: /).first +        if host_header.nil? +          send_error("HTTP request must include a Host header.") +        else +          host = host_header.split(':')[1].strip.sub(/^nicknym\./, '') +          return uid_domain == host +        end +      end +    rescue +      return false      end    end  end
\ No newline at end of file diff --git a/lib/nickserver/version.rb b/lib/nickserver/version.rb index 6e86d39..1910fe1 100644 --- a/lib/nickserver/version.rb +++ b/lib/nickserver/version.rb @@ -1,3 +1,3 @@  module Nickserver -  VERSION = "0.2.0" +  VERSION = "0.2.1"  end diff --git a/test/unit/nickserver_test.rb b/test/unit/nickserver_test.rb index c746ef5..3a286fa 100644 --- a/test/unit/nickserver_test.rb +++ b/test/unit/nickserver_test.rb @@ -8,9 +8,7 @@ require 'json'  #  # (2) All requests to nickserver are to localhost.  # -# (3) the "Host" header for requests to nickserver must be set, because this -# is how it decides if a request is local. I am not happy about this design, -# but that is how it works for now. +# (3) the "Host" header for requests to nickserver must be set (or Config.domain set)  #  # (4) When stubbing requests to couchdb, the couchdb host is changed from the  # default (localhost) to a dummy value (notlocalhost).  | 
