luci-app-adblock: sync with adblock 3.5.2
[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 local type = type
11 local tonumber = tonumber
12
13 module "luci.controller.rpc"
14
15
16 local function session_retrieve(sid, allowed_users)
17         local util = require "luci.util"
18         local sdat = util.ubus("session", "get", {
19                 ubus_rpc_session = sid
20         })
21
22         if type(sdat) == "table" and
23            type(sdat.values) == "table" and
24            type(sdat.values.token) == "string" and
25            type(sdat.values.secret) == "string" and
26            type(sdat.values.username) == "string" and
27            util.contains(allowed_users, sdat.values.username)
28         then
29                 return sid, sdat.values
30         end
31
32         return nil
33 end
34
35 local function authenticator(validator, accs)
36         local auth = luci.http.formvalue("auth", true)
37                 or luci.http.getcookie("sysauth")
38
39         if auth then -- if authentication token was given
40                 local sid, sdat = session_retrieve(auth, accs)
41                 if sdat then -- if given token is valid
42                         return sdat.username, sid
43                 end
44                 luci.http.status(403, "Forbidden")
45         end
46 end
47
48 function index()
49         local rpc = node("rpc")
50         rpc.sysauth = "root"
51         rpc.sysauth_authenticator = authenticator
52         rpc.notemplate = true
53
54         entry({"rpc", "uci"}, call("rpc_uci"))
55         entry({"rpc", "fs"}, call("rpc_fs"))
56         entry({"rpc", "sys"}, call("rpc_sys"))
57         entry({"rpc", "ipkg"}, call("rpc_ipkg"))
58         entry({"rpc", "auth"}, call("rpc_auth")).sysauth = false
59 end
60
61 function rpc_auth()
62         local jsonrpc = require "luci.jsonrpc"
63         local http    = require "luci.http"
64         local sys     = require "luci.sys"
65         local ltn12   = require "luci.ltn12"
66         local util    = require "luci.util"
67
68         local server = {}
69         server.challenge = function(user, pass)
70                 local config = require "luci.config"
71                 local login = util.ubus("session", "login", {
72                         username = user,
73                         password = pass,
74                         timeout  = tonumber(config.sauth.sessiontime)
75                 })
76
77                 if type(login) == "table" and
78                    type(login.ubus_rpc_session) == "string"
79                 then
80                         util.ubus("session", "set", {
81                                 ubus_rpc_session = login.ubus_rpc_session,
82                                 values = {
83                                         token = sys.uniqueid(16),
84                                         secret = sys.uniqueid(16)
85                                 }
86                         })
87
88                         local sid, sdat = session_retrieve(login.ubus_rpc_session, { user })
89                         if sdat then
90                                 return {
91                                         sid = sid,
92                                         token = sdat.token,
93                                         secret = sdat.secret
94                                 }
95                         end
96                 end
97
98                 return nil
99         end
100
101         server.login = function(...)
102                 local challenge = server.challenge(...)
103                 if challenge then
104                         http.header("Set-Cookie", 'sysauth=%s; path=%s' %{
105                                 challenge.sid,
106                                 http.getenv("SCRIPT_NAME")
107                         })
108                         return challenge.sid
109                 end
110         end
111
112         http.prepare_content("application/json")
113         ltn12.pump.all(jsonrpc.handle(server, http.source()), http.write)
114 end
115
116 function rpc_uci()
117         if not pcall(require, "luci.model.uci") then
118                 luci.http.status(404, "Not Found")
119                 return nil
120         end
121         local uci     = require "luci.jsonrpcbind.uci"
122         local jsonrpc = require "luci.jsonrpc"
123         local http    = require "luci.http"
124         local ltn12   = require "luci.ltn12"
125
126         http.prepare_content("application/json")
127         ltn12.pump.all(jsonrpc.handle(uci, http.source()), http.write)
128 end
129
130 function rpc_fs()
131         local util    = require "luci.util"
132         local io      = require "io"
133         local fs2     = util.clone(require "nixio.fs")
134         local jsonrpc = require "luci.jsonrpc"
135         local http    = require "luci.http"
136         local ltn12   = require "luci.ltn12"
137
138         function fs2.readfile(filename)
139                 local stat, mime = pcall(require, "mime")
140                 if not stat then
141                         error("Base64 support not available. Please install LuaSocket.")
142                 end
143
144                 local fp = io.open(filename)
145                 if not fp then
146                         return nil
147                 end
148
149                 local output = {}
150                 local sink = ltn12.sink.table(output)
151                 local source = ltn12.source.chain(ltn12.source.file(fp), mime.encode("base64"))
152                 return ltn12.pump.all(source, sink) and table.concat(output)
153         end
154
155         function fs2.writefile(filename, data)
156                 local stat, mime = pcall(require, "mime")
157                 if not stat then
158                         error("Base64 support not available. Please install LuaSocket.")
159                 end
160
161                 local  file = io.open(filename, "w")
162                 local  sink = file and ltn12.sink.chain(mime.decode("base64"), ltn12.sink.file(file))
163                 return sink and ltn12.pump.all(ltn12.source.string(data), sink) or false
164         end
165
166         http.prepare_content("application/json")
167         ltn12.pump.all(jsonrpc.handle(fs2, http.source()), http.write)
168 end
169
170 function rpc_sys()
171         local sys     = require "luci.sys"
172         local jsonrpc = require "luci.jsonrpc"
173         local http    = require "luci.http"
174         local ltn12   = require "luci.ltn12"
175
176         http.prepare_content("application/json")
177         ltn12.pump.all(jsonrpc.handle(sys, http.source()), http.write)
178 end
179
180 function rpc_ipkg()
181         if not pcall(require, "luci.model.ipkg") then
182                 luci.http.status(404, "Not Found")
183                 return nil
184         end
185         local ipkg    = require "luci.model.ipkg"
186         local jsonrpc = require "luci.jsonrpc"
187         local http    = require "luci.http"
188         local ltn12   = require "luci.ltn12"
189
190         http.prepare_content("application/json")
191         ltn12.pump.all(jsonrpc.handle(ipkg, http.source()), http.write)
192 end