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