759bb749cfe0a2cef1b11664df7ddeab42d7a41a
[project/luci.git] / modules / luci-mod-rpc / luasrc / controller / rpc.lua
1 -- Copyright 2008 Steven Barth <steven@midlink.org>
2 -- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
3 -- Licensed to the public under the Apache License 2.0.
4
5 local require = require
6 local pairs = pairs
7 local print = print
8 local pcall = pcall
9 local table = table
10
11 module "luci.controller.rpc"
12
13 function index()
14         local function authenticator(validator, accs)
15                 local auth = luci.http.formvalue("auth", true)
16                 if auth then -- if authentication token was given
17                         local sdat = (luci.util.ubus("session", "get", { ubus_rpc_session = auth }) or { }).values
18                         if sdat then -- if given token is valid
19                                 if sdat.user and luci.util.contains(accs, sdat.user) then
20                                         return sdat.user, auth
21                                 end
22                         end
23                 end
24                 luci.http.status(403, "Forbidden")
25         end
26
27         local rpc = node("rpc")
28         rpc.sysauth = "root"
29         rpc.sysauth_authenticator = authenticator
30         rpc.notemplate = true
31
32         entry({"rpc", "uci"}, call("rpc_uci"))
33         entry({"rpc", "fs"}, call("rpc_fs"))
34         entry({"rpc", "sys"}, call("rpc_sys"))
35         entry({"rpc", "ipkg"}, call("rpc_ipkg"))
36         entry({"rpc", "auth"}, call("rpc_auth")).sysauth = false
37 end
38
39 function rpc_auth()
40         local jsonrpc = require "luci.jsonrpc"
41         local http    = require "luci.http"
42         local sys     = require "luci.sys"
43         local ltn12   = require "luci.ltn12"
44         local util    = require "luci.util"
45
46         local loginstat
47
48         local server = {}
49         server.challenge = function(user, pass)
50                 local sid, token, secret
51
52                 local config = require "luci.config"
53
54                 if sys.user.checkpasswd(user, pass) then
55                         local sdat = util.ubus("session", "create", { timeout = config.sauth.sessiontime })
56                         if sdat then
57                                 sid = sdat.ubus_rpc_session
58                                 token = sys.uniqueid(16)
59                                 secret = sys.uniqueid(16)
60
61                                 http.header("Set-Cookie", "sysauth="..sid.."; path=/")
62                                 util.ubus("session", "set", {
63                                         ubus_rpc_session = sid,
64                                         values = {
65                                                 user = user,
66                                                 token = token,
67                                                 secret = secret
68                                         }
69                                 })
70                         end
71                 end
72
73                 return sid and {sid=sid, token=token, secret=secret}
74         end
75
76         server.login = function(...)
77                 local challenge = server.challenge(...)
78                 return challenge and challenge.sid
79         end
80
81         http.prepare_content("application/json")
82         ltn12.pump.all(jsonrpc.handle(server, http.source()), http.write)
83 end
84
85 function rpc_uci()
86         if not pcall(require, "luci.model.uci") then
87                 luci.http.status(404, "Not Found")
88                 return nil
89         end
90         local uci     = require "luci.jsonrpcbind.uci"
91         local jsonrpc = require "luci.jsonrpc"
92         local http    = require "luci.http"
93         local ltn12   = require "luci.ltn12"
94
95         http.prepare_content("application/json")
96         ltn12.pump.all(jsonrpc.handle(uci, http.source()), http.write)
97 end
98
99 function rpc_fs()
100         local util    = require "luci.util"
101         local io      = require "io"
102         local fs2     = util.clone(require "nixio.fs")
103         local jsonrpc = require "luci.jsonrpc"
104         local http    = require "luci.http"
105         local ltn12   = require "luci.ltn12"
106
107         function fs2.readfile(filename)
108                 local stat, mime = pcall(require, "mime")
109                 if not stat then
110                         error("Base64 support not available. Please install LuaSocket.")
111                 end
112
113                 local fp = io.open(filename)
114                 if not fp then
115                         return nil
116                 end
117
118                 local output = {}
119                 local sink = ltn12.sink.table(output)
120                 local source = ltn12.source.chain(ltn12.source.file(fp), mime.encode("base64"))
121                 return ltn12.pump.all(source, sink) and table.concat(output)
122         end
123
124         function fs2.writefile(filename, data)
125                 local stat, mime = pcall(require, "mime")
126                 if not stat then
127                         error("Base64 support not available. Please install LuaSocket.")
128                 end
129
130                 local  file = io.open(filename, "w")
131                 local  sink = file and ltn12.sink.chain(mime.decode("base64"), ltn12.sink.file(file))
132                 return sink and ltn12.pump.all(ltn12.source.string(data), sink) or false
133         end
134
135         http.prepare_content("application/json")
136         ltn12.pump.all(jsonrpc.handle(fs2, http.source()), http.write)
137 end
138
139 function rpc_sys()
140         local sys     = require "luci.sys"
141         local jsonrpc = require "luci.jsonrpc"
142         local http    = require "luci.http"
143         local ltn12   = require "luci.ltn12"
144
145         http.prepare_content("application/json")
146         ltn12.pump.all(jsonrpc.handle(sys, http.source()), http.write)
147 end
148
149 function rpc_ipkg()
150         if not pcall(require, "luci.model.ipkg") then
151                 luci.http.status(404, "Not Found")
152                 return nil
153         end
154         local ipkg    = require "luci.model.ipkg"
155         local jsonrpc = require "luci.jsonrpc"
156         local http    = require "luci.http"
157         local ltn12   = require "luci.ltn12"
158
159         http.prepare_content("application/json")
160         ltn12.pump.all(jsonrpc.handle(ipkg, http.source()), http.write)
161 end