Overview
| Comment: | enable revoking credentials |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
41cbbca855246c9c87507f3e79546b33 |
| User & Date: | lexi on 2021-01-11 02:17:11 |
| Other Links: | manifest | tags |
Context
|
2021-01-11
| ||
| 23:33 | various cleanups, notices no longer originated from self check-in: 1ba4bbc92f user: lexi tags: trunk | |
| 02:17 | enable revoking credentials check-in: 41cbbca855 user: lexi tags: trunk | |
| 01:53 | add auth docs and rsa auth check-in: 0d10a378e9 user: lexi tags: trunk | |
Changes
Modified backend/pgsql.t from [7d329a757a] to [05f7cb1a74].
319 320 321 322 323 324 325 326 327 328 329 330 331 332 ... 357 358 359 360 361 362 363 364 365 366 367 368 369 370 .... 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 .... 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 |
$1::bigint,
(select handle from parsav_actors where id = $1::bigint),
'challenge-rsa', $2::bytea,
$3::bigint, $4::text
) on conflict (name,kind,cred) do update set comment = $4::text returning aid
]]
};
auth_privs_clear = {
params = {uint64}, cmd = true, sql = [[
update parsav_auth set restrict = array[]::text[] where aid = $1::bigint
]];
};
................................................................................
};
auth_enum_handle = {
params = {rawstring}, sql = [[
select aid, kind, comment, netmask, blacklist from parsav_auth where name = $1::text
]];
};
post_save = {
params = {
uint64, uint32, int64;
rawstring, rawstring, rawstring;
}, cmd = true, sql = [[
update parsav_posts set
................................................................................
var react = r:_string(i,5)
lib.str.ncpy(n.reaction, react.ptr, lib.math.smallest(react.ct,[(`n.reaction).tree.type.N]))
end
end
return notes
end];
auth_enum_uid = [terra(
src: &lib.store.source,
uid: uint64
): lib.mem.ptr(lib.mem.ptr(lib.store.auth))
var r = queries.auth_enum_uid.exec(src,uid)
if r.sz == 0 then return [lib.mem.ptr(lib.mem.ptr(lib.store.auth))].null() end
var ret = lib.mem.heapa([lib.mem.ptr(lib.store.auth)], r.sz)
for i=0, r.sz do
var kind = r:_string(i, 1)
var comment = r:_string(i, 2)
var a = [ lib.str.encapsulate(lib.store.auth, {
kind = {`kind.ptr, `kind.ct+1};
comment = {`comment.ptr, `comment.ct+1};
................................................................................
queries.auth_purge_type.exec(src, handle, uid, 'otp-%')
end];
auth_purge_trust = [terra(src: &lib.store.source, uid: uint64, handle: rawstring): {}
queries.auth_purge_type.exec(src, handle, uid, 'trust')
end];
artifact_quicksearch = [terra(
src: &lib.store.source,
hash: binblob
): {uint64, bool}
var srec = queries.artifact_quicksearch.exec(src, hash)
if srec.sz > 0 then
defer srec:free()
|
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > |
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 ... 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 .... 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 .... 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 |
$1::bigint, (select handle from parsav_actors where id = $1::bigint), 'challenge-rsa', $2::bytea, $3::bigint, $4::text ) on conflict (name,kind,cred) do update set comment = $4::text returning aid ]] }; auth_destroy_aid = { params = {uint64}, cmd = true, sql = [[ delete from parsav_auth where aid = $1::bigint ]]; }; auth_destroy_aid_uid = { params = {uint64,uint64}, cmd = true, sql = [[ delete from parsav_auth where aid = $1::bigint and uid = $2::bigint ]]; }; auth_privs_clear = { params = {uint64}, cmd = true, sql = [[ update parsav_auth set restrict = array[]::text[] where aid = $1::bigint ]]; }; ................................................................................ }; auth_enum_handle = { params = {rawstring}, sql = [[ select aid, kind, comment, netmask, blacklist from parsav_auth where name = $1::text ]]; }; auth_fetch_aid = { params = {uint64}, sql = [[ select aid, uid, kind, comment, netmask, blacklist from parsav_auth where aid = $1::bigint ]]; }; post_save = { params = { uint64, uint32, int64; rawstring, rawstring, rawstring; }, cmd = true, sql = [[ update parsav_posts set ................................................................................ var react = r:_string(i,5) lib.str.ncpy(n.reaction, react.ptr, lib.math.smallest(react.ct,[(`n.reaction).tree.type.N])) end end return notes end]; auth_fetch_aid = [terra( src: &lib.store.source, aid: uint64 ): lib.mem.ptr(lib.store.auth) var r = queries.auth_fetch_aid.exec(src,aid) if r.sz == 0 then return [lib.mem.ptr(lib.store.auth)].null() end var kind = r:_string(0, 2) var comment = r:_string(0, 3) var a = [ lib.str.encapsulate(lib.store.auth, { kind = {`kind.ptr, `kind.ct+1}; comment = {`comment.ptr, `comment.ct+1}; }) ] a.ptr.aid = r:int(uint64, 0, 0) a.ptr.uid = r:int(uint64, 0, 1) if r:null(0,3) then a.ptr.netmask.pv = 0 else a.ptr.netmask = r:cidr(0, 4) end a.ptr.blacklist = r:bool(0, 5) return a end]; auth_enum_uid = [terra( src: &lib.store.source, uid: uint64 ): lib.mem.lstptr(lib.store.auth) var r = queries.auth_enum_uid.exec(src,uid) if r.sz == 0 then return [lib.mem.lstptr(lib.store.auth)].null() end var ret = lib.mem.heapa([lib.mem.ptr(lib.store.auth)], r.sz) for i=0, r.sz do var kind = r:_string(i, 1) var comment = r:_string(i, 2) var a = [ lib.str.encapsulate(lib.store.auth, { kind = {`kind.ptr, `kind.ct+1}; comment = {`comment.ptr, `comment.ct+1}; ................................................................................ queries.auth_purge_type.exec(src, handle, uid, 'otp-%') end]; auth_purge_trust = [terra(src: &lib.store.source, uid: uint64, handle: rawstring): {} queries.auth_purge_type.exec(src, handle, uid, 'trust') end]; auth_destroy_aid = [terra( src: &lib.store.source, aid: uint64 ): {} queries.auth_destroy_aid.exec(src,aid) end]; auth_destroy_aid_uid = [terra( src: &lib.store.source, aid: uint64, uid: uint64 ): {} queries.auth_destroy_aid_uid.exec(src,aid,uid) end]; artifact_quicksearch = [terra( src: &lib.store.source, hash: binblob ): {uint64, bool} var srec = queries.artifact_quicksearch.exec(src, hash) if srec.sz > 0 then defer srec:free() |
Modified route.t from [cd7a14ae6e] to [57b2f599e2].
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 ... 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 ... 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 ... 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 |
::badop :: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
::noauth:: do co:complain(401, 'unauthorized', 'you have not supplied the necessary credentials to perform this operation') return end
end
local terra
credsec_for_uid(co: &lib.srv.convo, uid: uint64)
var act = co:ppostv('act')
lib.dbg('showing credentials')
if act:cmp( 'invalidate') then
lib.dbg('setting user\'s cookie validation time to now')
co.who.source:auth_sigtime_user_alter(uid, lib.osclock.time(nil))
-- the current session has been invalidated as well, so we need to immediately install a new authentication cookie with the same aid so the user doesn't need to log back in all over again
co:installkey('?',co.aid)
return
elseif act:cmp( 'newcred') then
var cmt = co:ppostv('comment')
var pw = co:ppostv('newpw')
var rsapub = co:ppostv('newrsa'):blob()
var aid: uint64 = 0
if pw:ref() then
var cpw = co:ppostv('rptpw')
if not pw:cmp(cpw) then
co:complain(400,'enrollment failure','the passwords you supplied do not match')
return
end
aid = co.srv:auth_attach_pw(uid, false, pw, cmt)
elseif rsapub:ref() then
var sig = co:ppostv('sig')
var nonce = co:ppostv('nonce')
var s_noncevld = co:ppostv('noncevld')
var noncevld, ok = lib.math.shorthand.parse(s_noncevld.ptr, s_noncevld.ct)
if not ok then
co:complain(403,'try harder next time','you call that cryptanalysis?')
return
end
var fr = co.srv.pool:frame()
var hmac = lib.crypt.hmacp(&co.srv.pool, lib.crypt.alg.sha256, co.srv.cfg.secret:blob(), nonce)
if not lib.math.truncate64(hmac.ptr, hmac.ct) == noncevld then
co:complain(403,'nice try','what exactly are you trying to accomplish here, buddy')
return
end
var pkres = lib.crypt.loadpub(rsapub.ptr,rsapub.ct+1) -- needs NUL
if not pkres.ok then
co:complain(400,'invalid key','the key you have supplied is not a valid PEM or DER file')
return
end
var pk = pkres.val
defer pk:free()
var decoded = co.srv.pool:alloc(uint8,sig.ct)
var decoded_sz: intptr = 0
if lib.b64.mbedtls_base64_decode(decoded.ptr,sig.ct,&decoded_sz,[&uint8](sig.ptr),sig.ct) ~= 0 then
co:complain(400,'invalid signature','the signature you supplied is not encoded in valid base64')
return
end
var vfy, secl = lib.crypt.verify(&pk, nonce.ptr, nonce.ct, decoded.ptr, decoded_sz)
if not vfy then
co:complain(403,'verification failed','the signature you supplied does not match the required nonce')
return
end
var dbuf: uint8[lib.crypt.const.maxdersz]
var derkey = lib.crypt.der(true, &pk, &dbuf[0])
aid = co.srv:auth_attach_rsa(co.who.id, false, derkey, cmt)
co.srv.pool:reset(fr)
end
................................................................................
co.srv:auth_privs_set(aid, privs)
end
lib.dbg('setting netmask restrictions')
var nm = co:pgetv('netmask')
end
co:reroute('?')
return
end
co:complain(400,'bad request','the operation you have requested is not meaningful in this context')
end
terra http.configure(co: &lib.srv.convo, path: hpath, meth: method.t)
var msg = pstring.null()
-- first things first, do priv checks
if path.ct >= 2 then
if not co.who.rights.powers.config() and (
................................................................................
co.ui_hue = co.srv.cfg.ui_hue
end
msg = 'profile changes saved'
--user_refresh = true -- not really necessary here, actually
elseif path(1):cmp('sec') then
credsec_for_uid(co, co.who.id)
elseif path(1):cmp('avi') then
var act = co:ppostv('act')
if act:ref() and act:cmp('clear') then
co.who.avatarid = 0
co.who.source:actor_save(co.who)
msg = 'avatar reset to default'
else goto badop end
................................................................................
goto nopriv
end
else goto badop end
defer usr:free()
if path.ct == 4 then
if path(3):cmp(lib.str.lit 'cred') then
credsec_for_uid(co, userid)
end
elseif path.ct == 3 then
var purgestr = co:ppostv("purgestr")
var purgekey = co:ppostv("purgekey")
if purgestr:ref() and purgekey:ref() and purgestr(0) ~= 0 then
if purgestr:cmp(purgekey) then -- destroying account! :O
co.srv:actor_purge_uid(userid)
|
| > > > > > > > > > > | | | | | | | | | > | | |
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 ... 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 ... 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 ... 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
::badop :: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
::noauth:: do co:complain(401, 'unauthorized', 'you have not supplied the necessary credentials to perform this operation') return end
end
local terra
credsec_for_uid(co: &lib.srv.convo, uid: uint64)
var act = co:ppostv('act')
if not act then return true end
lib.dbg('handling credential action')
if act:cmp( 'invalidate') then
lib.dbg('setting user\'s cookie validation time to now')
co.who.source:auth_sigtime_user_alter(uid, lib.osclock.time(nil))
-- the current session has been invalidated as well, so we need to immediately install a new authentication cookie with the same aid so the user doesn't need to log back in all over again
co:installkey('?',co.aid)
return false
elseif act:cmp('revoke') then
var s_cred = co:ppostv('cred')
if s_cred:ref() then
var cred, ok = lib.math.shorthand.parse(s_cred.ptr, s_cred.ct)
if ok then
co.srv:auth_destroy_aid_uid(cred,co.who.id)
end
end
return true
elseif act:cmp('newcred') then
var cmt = co:ppostv('comment')
var pw = co:ppostv('newpw')
var rsapub = co:ppostv('newrsa'):blob()
var aid: uint64 = 0
if pw:ref() then
var cpw = co:ppostv('rptpw')
if not pw:cmp(cpw) then
co:complain(400,'enrollment failure','the passwords you supplied do not match')
return false
end
aid = co.srv:auth_attach_pw(uid, false, pw, cmt)
elseif rsapub:ref() then
var sig = co:ppostv('sig')
var nonce = co:ppostv('nonce')
var s_noncevld = co:ppostv('noncevld')
var noncevld, ok = lib.math.shorthand.parse(s_noncevld.ptr, s_noncevld.ct)
if not ok then
co:complain(403,'try harder next time','you call that cryptanalysis?')
return false
end
var fr = co.srv.pool:frame()
var hmac = lib.crypt.hmacp(&co.srv.pool, lib.crypt.alg.sha256, co.srv.cfg.secret:blob(), nonce)
if not lib.math.truncate64(hmac.ptr, hmac.ct) == noncevld then
co:complain(403,'nice try','what exactly are you trying to accomplish here, buddy')
return false
end
var pkres = lib.crypt.loadpub(rsapub.ptr,rsapub.ct+1) -- needs NUL
if not pkres.ok then
co:complain(400,'invalid key','the key you have supplied is not a valid PEM or DER file')
return false
end
var pk = pkres.val
defer pk:free()
var decoded = co.srv.pool:alloc(uint8,sig.ct)
var decoded_sz: intptr = 0
if lib.b64.mbedtls_base64_decode(decoded.ptr,sig.ct,&decoded_sz,[&uint8](sig.ptr),sig.ct) ~= 0 then
co:complain(400,'invalid signature','the signature you supplied is not encoded in valid base64')
return false
end
var vfy, secl = lib.crypt.verify(&pk, nonce.ptr, nonce.ct, decoded.ptr, decoded_sz)
if not vfy then
co:complain(403,'verification failed','the signature you supplied does not match the required nonce')
return false
end
var dbuf: uint8[lib.crypt.const.maxdersz]
var derkey = lib.crypt.der(true, &pk, &dbuf[0])
aid = co.srv:auth_attach_rsa(co.who.id, false, derkey, cmt)
co.srv.pool:reset(fr)
end
................................................................................
co.srv:auth_privs_set(aid, privs)
end
lib.dbg('setting netmask restrictions')
var nm = co:pgetv('netmask')
end
co:reroute('?')
return false
end
co:complain(400,'bad request','the operation you have requested is not meaningful in this context')
return false
end
terra http.configure(co: &lib.srv.convo, path: hpath, meth: method.t)
var msg = pstring.null()
-- first things first, do priv checks
if path.ct >= 2 then
if not co.who.rights.powers.config() and (
................................................................................
co.ui_hue = co.srv.cfg.ui_hue
end
msg = 'profile changes saved'
--user_refresh = true -- not really necessary here, actually
elseif path(1):cmp('sec') then
if not credsec_for_uid(co, co.who.id) then return end
elseif path(1):cmp('avi') then
var act = co:ppostv('act')
if act:ref() and act:cmp('clear') then
co.who.avatarid = 0
co.who.source:actor_save(co.who)
msg = 'avatar reset to default'
else goto badop end
................................................................................
goto nopriv
end
else goto badop end
defer usr:free()
if path.ct == 4 then
if path(3):cmp(lib.str.lit 'cred') then
if not credsec_for_uid(co, userid) then return end
end
elseif path.ct == 3 then
var purgestr = co:ppostv("purgestr")
var purgekey = co:ppostv("purgekey")
if purgestr:ref() and purgekey:ref() and purgestr(0) ~= 0 then
if purgestr:cmp(purgekey) then -- destroying account! :O
co.srv:actor_purge_uid(userid)
|
Modified store.t from [53eb63c414] to [bb9260aa8d].
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
actor_notice_enum: {&m.source, uint64} -> lib.mem.ptr(m.notice)
actor_rel_create: {&m.source, uint16, uint64, uint64} -> {}
actor_rel_destroy: {&m.source, uint16, uint64, uint64} -> {}
actor_rel_calc: {&m.source, uint64, uint64} -> m.relationship
auth_enum_uid: {&m.source, uint64} -> lib.mem.lstptr(m.auth)
auth_enum_handle: {&m.source, rawstring} -> lib.mem.lstptr(m.auth)
auth_attach_pw: {&m.source, uint64, bool, pstr, pstr} -> uint64
auth_attach_rsa: {&m.source, uint64, bool, lib.mem.ptr(uint8), pstr} -> uint64
-- uid: uint64
-- reset: bool (delete other passwords?)
-- pw: pstring
-- comment: pstring
auth_privs_set: {&m.source, uint64, m.privset} -> {}
auth_purge_pw: {&m.source, uint64, rawstring} -> {}
auth_purge_otp: {&m.source, uint64, rawstring} -> {}
auth_purge_trust: {&m.source, uint64, rawstring} -> {}
auth_sigtime_user_fetch: {&m.source, uint64} -> m.timepoint
-- authentication tokens and accounts have a property that controls
-- whether auth cookies dated to a certain point are valid. cookies
-- that are generated before the timepoint are considered invalid.
|
> > > |
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
actor_notice_enum: {&m.source, uint64} -> lib.mem.ptr(m.notice)
actor_rel_create: {&m.source, uint16, uint64, uint64} -> {}
actor_rel_destroy: {&m.source, uint16, uint64, uint64} -> {}
actor_rel_calc: {&m.source, uint64, uint64} -> m.relationship
auth_enum_uid: {&m.source, uint64} -> lib.mem.lstptr(m.auth)
auth_enum_handle: {&m.source, rawstring} -> lib.mem.lstptr(m.auth)
auth_fetch_aid : {&m.source, uint64} -> lib.mem.ptr(m.auth)
auth_attach_pw: {&m.source, uint64, bool, pstr, pstr} -> uint64
auth_attach_rsa: {&m.source, uint64, bool, lib.mem.ptr(uint8), pstr} -> uint64
-- uid: uint64
-- reset: bool (delete other passwords?)
-- pw: pstring
-- comment: pstring
auth_privs_set: {&m.source, uint64, m.privset} -> {}
auth_destroy_aid: {&m.source, uint64} -> {}
auth_destroy_aid_uid: {&m.source, uint64, uint64} -> {}
auth_purge_pw: {&m.source, uint64, rawstring} -> {}
auth_purge_otp: {&m.source, uint64, rawstring} -> {}
auth_purge_trust: {&m.source, uint64, rawstring} -> {}
auth_sigtime_user_fetch: {&m.source, uint64} -> m.timepoint
-- authentication tokens and accounts have a property that controls
-- whether auth cookies dated to a certain point are valid. cookies
-- that are generated before the timepoint are considered invalid.
|