~ubuntu-branches/ubuntu/trusty/puppet/trusty

« back to all changes in this revision

Viewing changes to lib/puppet/network/http_server/mongrel.rb

  • Committer: Package Import Robot
  • Author(s): Stig Sandbeck Mathisen
  • Date: 2011-10-22 14:08:22 UTC
  • mfrom: (1.1.25) (3.1.32 sid)
  • Revision ID: package-import@ubuntu.com-20111022140822-odxde5lohc45yhuz
Tags: 2.7.6-1
* New upstream release (CVE-2011-3872)
* Remove cherry-picked "groupadd_aix_warning" patch
* Install all new manpages

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env ruby
2
 
# File:       06-11-14-mongrel_xmlrpc.rb
3
 
# Author:     Manuel Holtgrewe <purestorm at ggnore.net>
4
 
#
5
 
# Copyright (c) 2006 Manuel Holtgrewe, 2007 Luke Kanies
6
 
#
7
 
# This file is based heavily on a file retrieved from
8
 
# http://ttt.ggnore.net/2006/11/15/xmlrpc-with-mongrel-and-ruby-off-rails/
9
 
 
10
 
require 'rubygems'
11
 
require 'mongrel'
12
 
require 'xmlrpc/server'
13
 
require 'puppet/network/xmlrpc/server'
14
 
require 'puppet/network/http_server'
15
 
require 'puppet/network/client_request'
16
 
require 'puppet/network/handler'
17
 
 
18
 
require 'resolv'
19
 
 
20
 
# This handler can be hooked into Mongrel to accept HTTP requests. After
21
 
# checking whether the request itself is sane, the handler forwards it
22
 
# to an internal instance of XMLRPC::BasicServer to process it.
23
 
#
24
 
# You can access the server by calling the Handler's "xmlrpc_server"
25
 
# attribute accessor method and add XMLRPC handlers there. For example:
26
 
#
27
 
# <pre>
28
 
# handler = XmlRpcHandler.new
29
 
# handler.xmlrpc_server.add_handler("my.add") { |a, b| a.to_i + b.to_i }
30
 
# </pre>
31
 
module Puppet::Network
32
 
  class HTTPServer::Mongrel < ::Mongrel::HttpHandler
33
 
    attr_reader :xmlrpc_server
34
 
 
35
 
    def initialize(handlers)
36
 
      if Puppet[:debug]
37
 
        $mongrel_debug_client = true
38
 
        Puppet.debug 'Mongrel client debugging enabled. [$mongrel_debug_client = true].'
39
 
      end
40
 
      # Create a new instance of BasicServer. We are supposed to subclass it
41
 
      # but that does not make sense since we would not introduce any new
42
 
      # behaviour and we have to subclass Mongrel::HttpHandler so our handler
43
 
      # works for Mongrel.
44
 
      @xmlrpc_server = Puppet::Network::XMLRPCServer.new
45
 
      handlers.each do |name|
46
 
        unless handler = Puppet::Network::Handler.handler(name)
47
 
          raise ArgumentError, "Invalid handler #{name}"
48
 
        end
49
 
        @xmlrpc_server.add_handler(handler.interface, handler.new({}))
50
 
      end
51
 
    end
52
 
 
53
 
    # This method produces the same results as XMLRPC::CGIServer.serve
54
 
    # from Ruby's stdlib XMLRPC implementation.
55
 
    def process(request, response)
56
 
      # Make sure this has been a POST as required for XMLRPC.
57
 
      request_method = request.params[Mongrel::Const::REQUEST_METHOD] || Mongrel::Const::GET
58
 
      if request_method != "POST"
59
 
        response.start(405) { |head, out| out.write("Method Not Allowed") }
60
 
        return
61
 
      end
62
 
 
63
 
      # Make sure the user has sent text/xml data.
64
 
      request_mime = request.params["CONTENT_TYPE"] || "text/plain"
65
 
      if parse_content_type(request_mime).first != "text/xml"
66
 
        response.start(400) { |head, out| out.write("Bad Request") }
67
 
        return
68
 
      end
69
 
 
70
 
      # Make sure there is data in the body at all.
71
 
      length = request.params[Mongrel::Const::CONTENT_LENGTH].to_i
72
 
      if length <= 0
73
 
        response.start(411) { |head, out| out.write("Length Required") }
74
 
        return
75
 
      end
76
 
 
77
 
      # Check the body to be valid.
78
 
      if request.body.nil? or request.body.size != length
79
 
        response.start(400) { |head, out| out.write("Bad Request") }
80
 
        return
81
 
      end
82
 
 
83
 
      info = client_info(request)
84
 
 
85
 
      # All checks above passed through
86
 
      response.start(200) do |head, out|
87
 
        head["Content-Type"] = "text/xml; charset=utf-8"
88
 
        begin
89
 
          out.write(@xmlrpc_server.process(request.body, info))
90
 
        rescue => detail
91
 
          puts detail.backtrace
92
 
          raise
93
 
        end
94
 
      end
95
 
    end
96
 
 
97
 
    private
98
 
 
99
 
    def client_info(request)
100
 
      params = request.params
101
 
      ip = params["HTTP_X_FORWARDED_FOR"] ? params["HTTP_X_FORWARDED_FOR"].split(',').last.strip : params["REMOTE_ADDR"]
102
 
      # JJM #906 The following dn.match regular expression is forgiving
103
 
      # enough to match the two Distinguished Name string contents
104
 
      # coming from Apache, Pound or other reverse SSL proxies.
105
 
      if dn = params[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
106
 
        client = dn_matchdata[1].to_str
107
 
        valid = (params[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
108
 
      else
109
 
        begin
110
 
          client = Resolv.getname(ip)
111
 
        rescue => detail
112
 
          Puppet.err "Could not resolve #{ip}: #{detail}"
113
 
          client = "unknown"
114
 
        end
115
 
        valid = false
116
 
      end
117
 
 
118
 
      info = Puppet::Network::ClientRequest.new(client, ip, valid)
119
 
 
120
 
      info
121
 
    end
122
 
 
123
 
    # Taken from XMLRPC::ParseContentType
124
 
    def parse_content_type(str)
125
 
      a, *b = str.split(";")
126
 
      return a.strip, *b
127
 
    end
128
 
  end
129
 
end
130