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)
|