Differences From
Artifact [6caa1366ba]:
140 140 -- pick an auth method
141 141 lib.render.login(co, act.ptr, &cs, pstring.null())
142 142 else var aid: uint64 = 0
143 143 lib.dbg('authentication attempt beginning')
144 144 -- attempt login with provided method
145 145 if lib.str.ncmp('pw', am, lib.math.biggest(2,aml)) == 0 and chrs ~= nil then
146 146 aid = co.srv:actor_auth_pw(co.peer,
147 - [lib.mem.ptr(int8)]{ptr=usn,ct=usnl},
148 - [lib.mem.ptr(int8)]{ptr=chrs,ct=chrsl})
149 - elseif lib.str.ncmp('otp', am, lib.math.biggest(2,aml)) == 0 and chrs ~= nil then
147 + pstring {ptr=usn,ct=usnl},
148 + pstring {ptr=chrs,ct=chrsl})
149 + elseif lib.str.ncmp('challenge', am, lib.math.biggest(9,aml)) == 0 and chrs ~= nil then
150 + lib.dbg('challenge attempt beginning')
151 + var s_time = co:ppostv('time')
152 + var s_vfy = co:ppostv('vfy')
153 + var token = co:ppostv('token')
154 + if s_time:ref() and s_vfy:ref() and token:ref() then
155 + lib.dbg('checking hmac validity')
156 + var vftok = co:stra(128) vftok:ppush(token):ppush(s_time)
157 + var hmac = lib.crypt.hmacp(&co.srv.pool, lib.crypt.alg.sha256, co.srv.cfg.secret:blob(), vftok:finalize())
158 + var vfy, vfyok = lib.math.shorthand.parse(s_vfy.ptr, s_vfy.ct)
159 + if vfyok and lib.math.truncate64(hmac.ptr,hmac.ct) == vfy then
160 + lib.dbg('checking expiration time')
161 + var time, timeok = lib.math.shorthand.parse(s_time.ptr, s_time.ct)
162 + if timeok and lib.osclock.time(nil) - time < [2 * 60] then -- two minutes
163 + lib.dbg('decoding base64')
164 + var bin = co.srv.pool:alloc(uint8, chrsl)
165 + var binlen: intptr
166 + if lib.b64.mbedtls_base64_decode(bin.ptr, bin.ct, &binlen, [&uint8](chrs), chrsl) == 0 then
167 + lib.dbg('running signature <',{chrs,chrsl},'> against challenge keys for token [', {token.ptr,token.ct}, ']')
168 + aid = co.srv:actor_auth_challenge(co.peer,
169 + pstring {usn,usnl}, binblob{bin.ptr,binlen}, token)
170 + end
171 + end
172 + end
173 + end
174 + elseif lib.str.ncmp('otp', am, lib.math.biggest(3,aml)) == 0 and chrs ~= nil then
150 175 lib.dbg('using otp auth')
151 176 -- ยทยทยท --
152 177 else lib.dbg('invalid auth method') end
153 178
154 179 -- error out
155 180 if aid == 0 then
156 181 lib.render.login(co, nil, nil, 'authentication failure')
................................................................................
339 364 co.who.source:auth_sigtime_user_alter(uid, lib.osclock.time(nil))
340 365 -- 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
341 366 co:installkey('?',co.aid)
342 367 return
343 368 elseif act:cmp( 'newcred') then
344 369 var cmt = co:ppostv('comment')
345 370 var pw = co:ppostv('newpw')
371 + var rsapub = co:ppostv('newrsa'):blob()
346 372 var aid: uint64 = 0
347 373 if pw:ref() then
348 374 var cpw = co:ppostv('rptpw')
349 375 if not pw:cmp(cpw) then
350 376 co:complain(400,'enrollment failure','the passwords you supplied do not match')
351 377 return
352 378 end
353 379 aid = co.srv:auth_attach_pw(uid, false, pw, cmt)
354 - else
355 - var key = co:ppostv('newkey')
356 - if key:ref() then
380 + elseif rsapub:ref() then
381 + var sig = co:ppostv('sig')
382 + var nonce = co:ppostv('nonce')
383 + var s_noncevld = co:ppostv('noncevld')
384 + var noncevld, ok = lib.math.shorthand.parse(s_noncevld.ptr, s_noncevld.ct)
385 + if not ok then
386 + co:complain(403,'try harder next time','you call that cryptanalysis?')
387 + return
388 + end
357 389
390 + var fr = co.srv.pool:frame()
391 + var hmac = lib.crypt.hmacp(&co.srv.pool, lib.crypt.alg.sha256, co.srv.cfg.secret:blob(), nonce)
392 + if not lib.math.truncate64(hmac.ptr, hmac.ct) == noncevld then
393 + co:complain(403,'nice try','what exactly are you trying to accomplish here, buddy')
394 + return
395 + end
396 +
397 + var pkres = lib.crypt.loadpub(rsapub.ptr,rsapub.ct+1) -- needs NUL
398 + if not pkres.ok then
399 + co:complain(400,'invalid key','the key you have supplied is not a valid PEM or DER file')
400 + return
401 + end
402 + var pk = pkres.val
403 + defer pk:free()
404 +
405 + var decoded = co.srv.pool:alloc(uint8,sig.ct)
406 + var decoded_sz: intptr = 0
407 + if lib.b64.mbedtls_base64_decode(decoded.ptr,sig.ct,&decoded_sz,[&uint8](sig.ptr),sig.ct) ~= 0 then
408 + co:complain(400,'invalid signature','the signature you supplied is not encoded in valid base64')
409 + return
410 + end
411 +
412 + var vfy, secl = lib.crypt.verify(&pk, nonce.ptr, nonce.ct, decoded.ptr, decoded_sz)
413 + if not vfy then
414 + co:complain(403,'verification failed','the signature you supplied does not match the required nonce')
415 + return
358 416 end
417 +
418 + var dbuf: uint8[lib.crypt.const.maxdersz]
419 + var derkey = lib.crypt.der(true, &pk, &dbuf[0])
420 + aid = co.srv:auth_attach_rsa(co.who.id, false, derkey, cmt)
421 + co.srv.pool:reset(fr)
359 422 end
360 423 if aid ~= 0 then
361 424 lib.dbg('setting credential restrictions')
362 425 var privs = [(function()
363 426 local check = quote end
364 427 local me = symbol(lib.store.privset)
365 428 for i,v in ipairs(lib.store.privset.members) do