Differences From
Artifact [4721bcd333]:
1 1 -- vim: ft=terra
2 2 local util = lib.util
3 3 local secmode = lib.enum { 'public', 'private', 'lockdown', 'isolate' }
4 4 local pstring = lib.mem.ptr(int8)
5 5 local struct srv
6 6 local struct cfgcache {
7 7 secret: lib.mem.ptr(int8)
8 - instance: lib.mem.ptr(int8)
9 - overlord: &srv
10 8 pol_sec: secmode.t
11 9 pol_reg: bool
10 + credmgd: bool
11 + maxupsz: intptr
12 + instance: lib.mem.ptr(int8)
13 + overlord: &srv
12 14 }
13 15 local struct srv {
14 16 sources: lib.mem.ptr(lib.store.source)
15 17 webmgr: lib.net.mg_mgr
16 18 webcon: &lib.net.mg_connection
17 19 cfg: cfgcache
18 20 id: rawstring
................................................................................
108 110 end)
109 111
110 112 local struct convo {
111 113 srv: &srv
112 114 con: &lib.net.mg_connection
113 115 msg: &lib.net.mg_http_message
114 116 aid: uint64 -- 0 if logged out
117 + aid_issue: lib.store.timepoint
115 118 who: &lib.store.actor -- who we're logged in as, if aid ~= 0
116 119 peer: lib.store.inet
117 120 reqtype: lib.http.mime.t -- negotiated content type
118 121 -- cache
119 122 navbar: lib.mem.ptr(int8)
120 123 actorcache: lib.mem.cache(lib.mem.ptr(lib.store.actor),32) -- naive cache to avoid unnecessary queries
121 124 -- private
................................................................................
154 157
155 158 body:send(self.con, 303, [lib.mem.ptr(lib.http.header)] {
156 159 ptr = &hdrs[0], ct = [hdrs.type.N] - lib.trn(cookie == nil,1,0)
157 160 })
158 161 end
159 162
160 163 terra convo:reroute(dest: rawstring) self:reroute_cookie(dest,nil) end
164 +
165 +terra convo:installkey(dest: rawstring, aid: uint64)
166 + var sesskey: int8[lib.session.maxlen + #lib.session.cookiename + #"=; Path=/" + 1]
167 + do var p = &sesskey[0]
168 + p = lib.str.ncpy(p, [lib.session.cookiename .. '='], [#lib.session.cookiename + 1])
169 + p = p + lib.session.cookie_gen(self.srv.cfg.secret, aid, lib.osclock.time(nil), p)
170 + lib.dbg('sending cookie ',{&sesskey[0],15})
171 + p = lib.str.ncpy(p, '; Path=/', 9)
172 + end
173 + self:reroute_cookie(dest, &sesskey[0])
174 +end
161 175
162 176 terra convo:complain(code: uint16, title: rawstring, msg: rawstring)
163 177 var hdrs = array(
164 178 lib.http.header { key = 'Content-Type', value = 'text/html; charset=UTF-8' },
165 179 lib.http.header { key = 'Cache-Control', value = 'no-store' }
166 180 )
167 181
................................................................................
232 246 var r = self.vbofs
233 247 self.vbofs = self.vbofs + o + 1
234 248 @(self.vbofs - 1) = 0
235 249 var norm = lib.str.normalize([lib.mem.ptr(int8)]{ptr = r, ct = o})
236 250 return norm.ptr, norm.ct
237 251 else return nil, 0 end
238 252 end
253 +terra convo:ppostv(name: rawstring)
254 + var s,l = self:postv(name)
255 + return pstring { ptr = s, ct = l }
256 +end
239 257
240 258 terra convo:getv(name: rawstring)
241 259 if self.varbuf.ptr == nil then
242 260 self.varbuf = lib.mem.heapa(int8, self.msg.query.len + self.msg.body.len)
243 261 self.vbofs = self.varbuf.ptr
244 262 end
245 263 var o = lib.net.mg_http_get_var(&self.msg.query, name, self.vbofs, self.varbuf.ct - (self.vbofs - self.varbuf.ptr))
................................................................................
247 265 var r = self.vbofs
248 266 self.vbofs = self.vbofs + o + 1
249 267 @(self.vbofs - 1) = 0
250 268 var norm = lib.str.normalize([lib.mem.ptr(int8)]{ptr = r, ct = o})
251 269 return norm.ptr, norm.ct
252 270 else return nil, 0 end
253 271 end
272 +terra convo:pgetv(name: rawstring)
273 + var s,l = self:getv(name)
274 + return pstring { ptr = s, ct = l }
275 +end
254 276
255 277 local urimatch = macro(function(uri, ptn)
256 278 return `lib.net.mg_globmatch(ptn, [#ptn], uri.ptr, uri.ct+1)
257 279 end)
258 280
259 281 local route = {} -- these are defined in route.t, as they need access to renderers
260 282 terra route.dispatch_http :: {&convo, lib.mem.ptr(int8), lib.http.method.t} -> {}
................................................................................
303 325
304 326 switch event do
305 327 case lib.net.MG_EV_HTTP_MSG then
306 328 lib.dbg('routing HTTP request')
307 329 var msg = [&lib.net.mg_http_message](p)
308 330 var co = convo {
309 331 con = con, srv = server, msg = msg;
310 - aid = 0, who = nil, peer = peer;
332 + aid = 0, aid_issue = 0, who = nil;
311 333 reqtype = lib.http.mime.none;
334 + peer = peer;
312 335 } co.varbuf.ptr = nil
313 336 co.navbar.ptr = nil
314 337 co.actorcache.top = 0
315 338 co.actorcache.cur = 0
316 339
317 340 -- first, check for an accept header. if it's there, we need to
318 341 -- iterate over the values and pick the highest-priority one
................................................................................
388 411 end
389 412 if val.ptr == nil then goto nocookie end
390 413 val.ct = (cookies + i) - val.ptr
391 414 if lib.str.ncmp(key.ptr, lib.session.cookiename, lib.math.biggest([#lib.session.cookiename], key.ct)) ~= 0 then
392 415 goto nocookie
393 416 end
394 417 ::foundcookie:: do
395 - var aid = lib.session.cookie_interpret(server.cfg.secret,
418 + var aid, tp = lib.session.cookie_interpret(server.cfg.secret,
396 419 [lib.mem.ptr(int8)]{ptr=val.ptr,ct=val.ct},
397 420 lib.osclock.time(nil))
398 - if aid ~= 0 then co.aid = aid end
421 + if aid ~= 0 then co.aid = aid co.aid_issue = tp end
399 422 end ::nocookie::;
400 423 end
401 424
402 425 if co.aid ~= 0 then
403 - var sess, usr = co.srv:actor_session_fetch(co.aid, peer)
404 - if sess.ok == false then co.aid = 0 else
426 + var sess, usr = co.srv:actor_session_fetch(co.aid, peer, co.aid_issue)
427 + if sess.ok == false then co.aid = 0 co.aid_issue = 0 else
405 428 co.who = usr.ptr
406 429 co.who.rights.powers = server:actor_powers_fetch(co.who.id)
407 430 end
408 431 end
409 432
410 433 var uridec = lib.mem.heapa(int8, msg.uri.len) defer uridec:free()
411 434 var urideclen = lib.net.mg_url_decode(msg.uri.ptr, msg.uri.len, uridec.ptr, uridec.ct, 1)
................................................................................
640 663 self.sources:free()
641 664 end
642 665
643 666 terra cfgcache:load()
644 667 self.instance = self.overlord:conf_get('instance-name')
645 668 self.secret = self.overlord:conf_get('server-secret')
646 669
647 - self.pol_reg = false
670 + do self.pol_reg = false
648 671 var sreg = self.overlord:conf_get('policy-self-register')
649 - if sreg.ptr ~= nil then
672 + if sreg:ref() then
650 673 if lib.str.cmp(sreg.ptr, 'on') == 0
651 674 then self.pol_reg = true
652 675 else self.pol_reg = false
653 676 end
654 677 end
655 - sreg:free()
678 + sreg:free() end
679 +
680 + do self.credmgd = false
681 + var sreg = self.overlord:conf_get('credential-store')
682 + if sreg:ref() then
683 + if lib.str.cmp(sreg.ptr, 'managed') == 0
684 + then self.credmgd = true
685 + else self.credmgd = false
686 + end
687 + end
688 + sreg:free() end
689 +
690 + do self.maxupsz = [1024 * 100] -- 100 kilobyte default
691 + var sreg = self.overlord:conf_get('maximum-artifact-size')
692 + if sreg:ref() then
693 + var sz, ok = lib.math.fsz_parse(sreg)
694 + if ok then self.maxupsz = sz else
695 + lib.warn('invalid configuration value for maximum-artifact-size; keeping default 100K upload limit')
696 + end
697 + end
698 + sreg:free() end
656 699
657 700 self.pol_sec = secmode.lockdown
658 701 var smode = self.overlord:conf_get('policy-security')
659 702 if smode.ptr ~= nil then
660 703 if lib.str.cmp(smode.ptr, 'public') == 0 then
661 704 self.pol_sec = secmode.public
662 705 elseif lib.str.cmp(smode.ptr, 'private') == 0 then