parsav  Diff

Differences From Artifact [b388ba7244]:

To Artifact [7d329a757a]:


   116    116   				$11::integer,$4::bigint
   117    117   			) returning id
   118    118   		]];
   119    119   	};
   120    120   
   121    121   	actor_auth_pw = {
   122    122   		params = {pstring,rawstring,pstring,lib.store.inet}, sql = [[
   123         -			select a.aid, a.uid, a.name from parsav_auth as a
          123  +			select a.aid, a.uid, a.name, a.blacklist from parsav_auth as a
   124    124   				left join parsav_actors as u on u.id = a.uid
   125    125   			where (a.uid is null or u.handle = $1::text or (
   126    126   					a.uid = 0 and a.name = $1::text
   127    127   				)) and
   128    128   				(a.kind = 'trust' or (a.kind = $2::text and a.cred = $3::bytea)) and
   129    129   				(a.netmask is null or a.netmask >> $4::inet)
   130    130   			order by blacklist desc limit 1
   131    131   		]];
          132  +	};
          133  +	actor_auth_challenge = {
          134  +		params = {pstring,pstring,lib.store.inet}, sql = [[
          135  +			select a.aid, a.uid, a.name, a.blacklist, a.cred 
          136  +			from parsav_auth as a
          137  +				left join parsav_actors as u on u.id = a.uid
          138  +			where a.kind = 'challenge-' || $1::text and
          139  +				(a.netmask is null or a.netmask >> $3::inet) and
          140  +				(a.uid     is null or u.handle  =  $2::text or
          141  +					(a.uid = 0 and a.name = $2::text))
          142  +			order by blacklist desc
          143  +		]];
   132    144   	};
   133    145   
   134    146   	actor_enum_local = {
   135    147   		params = {}, sql = [[
   136    148   			select id, nym, handle, origin, bio,
   137    149   			       null::text, rank, quota, key, epithet,
   138    150   			       knownsince::bigint,
................................................................................
   292    304   
   293    305   	auth_create_pw = {
   294    306   		params = {uint64, binblob, int64, pstring}, sql = [[
   295    307   			insert into parsav_auth (uid, name, kind, cred, valperiod, comment) values (
   296    308   				$1::bigint,
   297    309   				(select handle from parsav_actors where id = $1::bigint),
   298    310   				'pw-sha256', $2::bytea,
          311  +				$3::bigint, $4::text
          312  +			) on conflict (name,kind,cred) do update set comment = $4::text returning aid
          313  +		]]
          314  +	};
          315  +
          316  +	auth_create_rsa = {
          317  +		params = {uint64, binblob, int64, pstring}, sql = [[
          318  +			insert into parsav_auth (uid, name, kind, cred, valperiod, comment) values (
          319  +				$1::bigint,
          320  +				(select handle from parsav_actors where id = $1::bigint),
          321  +				'challenge-rsa', $2::bytea,
   299    322   				$3::bigint, $4::text
   300    323   			) on conflict (name,kind,cred) do update set comment = $4::text returning aid
   301    324   		]]
   302    325   	};
   303    326   
   304    327   	auth_privs_clear = {
   305    328   		params = {uint64}, cmd = true, sql = [[
................................................................................
  1292   1315   		(cs.trust << r:bool(0,3))
  1293   1316   		return cs, true
  1294   1317   	end];
  1295   1318   	 
  1296   1319   	actor_auth_pw = [terra(
  1297   1320   			src: &lib.store.source,
  1298   1321   			ip: lib.store.inet,
  1299         -			username: lib.mem.ptr(int8),
  1300         -			cred: lib.mem.ptr(int8)
         1322  +			username: pstring,
         1323  +			cred: pstring
  1301   1324   		): {uint64, uint64, pstring}
  1302   1325   
  1303   1326   		[ checksha(`src, 256, ip, username, cred) ] -- most common
  1304   1327   		[ checksha(`src, 512, ip, username, cred) ] -- most secure
  1305   1328   		[ checksha(`src, 384, ip, username, cred) ] -- weird
  1306   1329   		[ checksha(`src, 224, ip, username, cred) ] -- weirdest
  1307   1330   
  1308   1331   		-- TODO: check pbkdf2-hmac
  1309   1332   		-- TODO: check OTP
  1310   1333   		return 0, 0, pstring.null()
  1311   1334   	end];
         1335  +
         1336  +	actor_auth_challenge = [terra(
         1337  +		src: &lib.store.source,
         1338  +		ip: lib.store.inet,
         1339  +		username: pstring,
         1340  +		sig: binblob,
         1341  +		token: pstring
         1342  +	): {uint64, uint64, pstring}
         1343  +		-- we need to iterate through all the challenge types. right now that's just RSA
         1344  +		lib.dbg('checking against token ', {token.ptr,token.ct})
         1345  +		var rsakeys = queries.actor_auth_challenge.exec(src, 'rsa', username, ip)
         1346  +		var toprops = [terra(res: &pqr, i: intptr)
         1347  +			return {
         1348  +				aid = res:int(uint64, i, 0);
         1349  +				uid = res:int(uint64, i, 1);
         1350  +				name = res:_string(i, 2);
         1351  +				blacklist = res:bool(i, 3);
         1352  +				pubkey = res:bin(i, 4);
         1353  +			}
         1354  +		end]
         1355  +		if rsakeys.sz > 0 then defer rsakeys:free()
         1356  +			for i=0, rsakeys.sz do var props = toprops(&rsakeys, i)
         1357  +				lib.dbg('loading next RSA pubkey')
         1358  +				var pub = lib.crypt.loadpub(props.pubkey.ptr, props.pubkey.ct)
         1359  +				if pub.ok then defer pub.val:free()
         1360  +					lib.dbg('checking pubkey against response')
         1361  +					var vfy, secl = lib.crypt.verify(&pub.val, token.ptr, token.ct, sig.ptr, sig.ct)
         1362  +					if vfy then
         1363  +						lib.dbg('signature verified')
         1364  +						if props.blacklist then lib.dbg('key blacklisted!') goto fail end
         1365  +						var dupname = lib.str.dup(props.name.ptr)
         1366  +						return props.aid, props.uid, pstring {dupname, props.name.ct}
         1367  +					end
         1368  +				else lib.warn('invalid pubkey in authentication table for user ',{props.name.ptr, props.name.ct}) end
         1369  +			end
         1370  +		end
         1371  +
         1372  +		-- and so on
         1373  +
         1374  +		lib.dbg('no challenges were successful')
         1375  +		::fail::return 0, 0, pstring.null()
         1376  +	end];
         1377  +
  1312   1378   
  1313   1379   	actor_stats = [terra(src: &lib.store.source, uid: uint64)
  1314   1380   		var r = queries.actor_stats.exec(src, uid)
  1315   1381   		if r.sz == 0 then lib.bail('error fetching actor stats!') end
  1316   1382   		var s: lib.store.actor_stats
  1317   1383   		s.posts = r:int(uint64, 0, 0)
  1318   1384   		s.follows = r:int(uint64, 0, 1)
................................................................................
  1615   1681   		if reset then queries.auth_purge_type.exec(src, nil, uid, 'pw-%') end
  1616   1682   		var r = queries.auth_create_pw.exec(src, uid, binblob {ptr = &hash[0], ct = [hash.type.N]}, lib.osclock.time(nil), comment)
  1617   1683   		if r.sz == 0 then return 0 end
  1618   1684   		var aid = r:int(uint64,0,0)
  1619   1685   		r:free()
  1620   1686   		return aid
  1621   1687   	end];
         1688  +
         1689  +	auth_attach_rsa = [terra(
         1690  +		src: &lib.store.source,
         1691  +		uid: uint64,
         1692  +		reset: bool,
         1693  +		pub: binblob,
         1694  +		comment: pstring
         1695  +	): uint64
         1696  +		if reset then queries.auth_purge_type.exec(src, nil, uid, 'challenge-%') end
         1697  +		var r = queries.auth_create_rsa.exec(src, uid, pub, lib.osclock.time(nil), comment)
         1698  +		if r.sz == 0 then return 0 end
         1699  +		var aid = r:int(uint64,0,0)
         1700  +		r:free()
         1701  +		return aid
         1702  +	end];
  1622   1703   
  1623   1704   	auth_privs_set = [terra(
  1624   1705   		src: &lib.store.source,
  1625   1706   		aid: uint64,
  1626   1707   		set: lib.store.privset
  1627   1708   	): {}
  1628   1709   		var map = array([lib.store.privmap])