parsav  Diff

Differences From Artifact [6caa1366ba]:

To Artifact [cd7a14ae6e]:


   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