summaryrefslogtreecommitdiffstats
path: root/lib/puppet/network/xmlrpc/processor.rb
blob: e016b177b67de6a50084b0c519d4179264214c59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
require 'puppet/network/authorization'
require 'xmlrpc/server'

# Just silly.
class ::XMLRPC::FaultException
    def to_s
        self.message
    end
end

module Puppet::Network
    # Most of our subclassing is just so that we can get
    # access to information from the request object, like
    # the client name and IP address.
    module XMLRPCProcessor
        include Puppet::Network::Authorization

        ERR_UNAUTHORIZED = 30

        def add_handler(interface, handler)
            @loadedhandlers << interface.prefix
            super(interface, handler)
        end

        def handler_loaded?(handler)
            @loadedhandlers.include?(handler.to_s)
        end

        # Convert our data and client request into xmlrpc calls, and verify
        # they're authorized and such-like.  This method differs from the
        # default in that it expects a ClientRequest object in addition to the
        # data.
        def process(data, request)
            call, params = parser().parseMethodCall(data)
            params << request.name << request.ip
            handler, method = call.split(".")
            request.handler = handler
            request.method = method
            begin
                verify(request)
            rescue InvalidClientRequest => detail
                raise ::XMLRPC::FaultException.new(ERR_UNAUTHORIZED, detail.to_s)
            end
            handle(request.call, *params)
        end

        private

        # Provide error handling for method calls.
        def protect_service(obj, *args)
            begin
                obj.call(*args)
            rescue ::XMLRPC::FaultException
                raise
            rescue Puppet::AuthorizationError => detail
                Puppet.err "Permission denied: #{detail}"
                raise ::XMLRPC::FaultException.new(
                    1, detail.to_s
                )
            rescue Puppet::Error => detail
                puts detail.backtrace if Puppet[:trace]
                Puppet.err detail.to_s
                error = ::XMLRPC::FaultException.new(
                    1, detail.to_s
                )
                error.set_backtrace detail.backtrace
                raise error
            rescue => detail
                puts detail.backtrace if Puppet[:trace]
                Puppet.err "Could not call: #{detail}"
                error = ::XMLRPC::FaultException.new(1, detail.to_s)
                error.set_backtrace detail.backtrace
                raise error
            end
        end

        # Set up our service hook and init our handler list.
        def setup_processor
            @loadedhandlers = []
            self.set_service_hook do |obj, *args|
                protect_service(obj, *args)
            end
        end
    end
end