parsav  Diff

Differences From Artifact [b388ba7244]:

To Artifact [7d329a757a]:


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131












132
133
134
135
136
137
138
...
292
293
294
295
296
297
298











299
300
301
302
303
304
305
....
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311











































1312
1313
1314
1315
1316
1317
1318
....
1615
1616
1617
1618
1619
1620
1621















1622
1623
1624
1625
1626
1627
1628
				$11::integer,$4::bigint
			) returning id
		]];
	};

	actor_auth_pw = {
		params = {pstring,rawstring,pstring,lib.store.inet}, sql = [[
			select a.aid, a.uid, a.name from parsav_auth as a
				left join parsav_actors as u on u.id = a.uid
			where (a.uid is null or u.handle = $1::text or (
					a.uid = 0 and a.name = $1::text
				)) and
				(a.kind = 'trust' or (a.kind = $2::text and a.cred = $3::bytea)) and
				(a.netmask is null or a.netmask >> $4::inet)
			order by blacklist desc limit 1
		]];












	};

	actor_enum_local = {
		params = {}, sql = [[
			select id, nym, handle, origin, bio,
			       null::text, rank, quota, key, epithet,
			       knownsince::bigint,
................................................................................

	auth_create_pw = {
		params = {uint64, binblob, int64, pstring}, sql = [[
			insert into parsav_auth (uid, name, kind, cred, valperiod, comment) values (
				$1::bigint,
				(select handle from parsav_actors where id = $1::bigint),
				'pw-sha256', $2::bytea,











				$3::bigint, $4::text
			) on conflict (name,kind,cred) do update set comment = $4::text returning aid
		]]
	};

	auth_privs_clear = {
		params = {uint64}, cmd = true, sql = [[
................................................................................
		(cs.trust << r:bool(0,3))
		return cs, true
	end];
	 
	actor_auth_pw = [terra(
			src: &lib.store.source,
			ip: lib.store.inet,
			username: lib.mem.ptr(int8),
			cred: lib.mem.ptr(int8)
		): {uint64, uint64, pstring}

		[ checksha(`src, 256, ip, username, cred) ] -- most common
		[ checksha(`src, 512, ip, username, cred) ] -- most secure
		[ checksha(`src, 384, ip, username, cred) ] -- weird
		[ checksha(`src, 224, ip, username, cred) ] -- weirdest

		-- TODO: check pbkdf2-hmac
		-- TODO: check OTP
		return 0, 0, pstring.null()
	end];












































	actor_stats = [terra(src: &lib.store.source, uid: uint64)
		var r = queries.actor_stats.exec(src, uid)
		if r.sz == 0 then lib.bail('error fetching actor stats!') end
		var s: lib.store.actor_stats
		s.posts = r:int(uint64, 0, 0)
		s.follows = r:int(uint64, 0, 1)
................................................................................
		if reset then queries.auth_purge_type.exec(src, nil, uid, 'pw-%') end
		var r = queries.auth_create_pw.exec(src, uid, binblob {ptr = &hash[0], ct = [hash.type.N]}, lib.osclock.time(nil), comment)
		if r.sz == 0 then return 0 end
		var aid = r:int(uint64,0,0)
		r:free()
		return aid
	end];
















	auth_privs_set = [terra(
		src: &lib.store.source,
		aid: uint64,
		set: lib.store.privset
	): {}
		var map = array([lib.store.privmap])







|








>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>







 







|
|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
....
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
....
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
				$11::integer,$4::bigint
			) returning id
		]];
	};

	actor_auth_pw = {
		params = {pstring,rawstring,pstring,lib.store.inet}, sql = [[
			select a.aid, a.uid, a.name, a.blacklist from parsav_auth as a
				left join parsav_actors as u on u.id = a.uid
			where (a.uid is null or u.handle = $1::text or (
					a.uid = 0 and a.name = $1::text
				)) and
				(a.kind = 'trust' or (a.kind = $2::text and a.cred = $3::bytea)) and
				(a.netmask is null or a.netmask >> $4::inet)
			order by blacklist desc limit 1
		]];
	};
	actor_auth_challenge = {
		params = {pstring,pstring,lib.store.inet}, sql = [[
			select a.aid, a.uid, a.name, a.blacklist, a.cred 
			from parsav_auth as a
				left join parsav_actors as u on u.id = a.uid
			where a.kind = 'challenge-' || $1::text and
				(a.netmask is null or a.netmask >> $3::inet) and
				(a.uid     is null or u.handle  =  $2::text or
					(a.uid = 0 and a.name = $2::text))
			order by blacklist desc
		]];
	};

	actor_enum_local = {
		params = {}, sql = [[
			select id, nym, handle, origin, bio,
			       null::text, rank, quota, key, epithet,
			       knownsince::bigint,
................................................................................

	auth_create_pw = {
		params = {uint64, binblob, int64, pstring}, sql = [[
			insert into parsav_auth (uid, name, kind, cred, valperiod, comment) values (
				$1::bigint,
				(select handle from parsav_actors where id = $1::bigint),
				'pw-sha256', $2::bytea,
				$3::bigint, $4::text
			) on conflict (name,kind,cred) do update set comment = $4::text returning aid
		]]
	};

	auth_create_rsa = {
		params = {uint64, binblob, int64, pstring}, sql = [[
			insert into parsav_auth (uid, name, kind, cred, valperiod, comment) values (
				$1::bigint,
				(select handle from parsav_actors where id = $1::bigint),
				'challenge-rsa', $2::bytea,
				$3::bigint, $4::text
			) on conflict (name,kind,cred) do update set comment = $4::text returning aid
		]]
	};

	auth_privs_clear = {
		params = {uint64}, cmd = true, sql = [[
................................................................................
		(cs.trust << r:bool(0,3))
		return cs, true
	end];
	 
	actor_auth_pw = [terra(
			src: &lib.store.source,
			ip: lib.store.inet,
			username: pstring,
			cred: pstring
		): {uint64, uint64, pstring}

		[ checksha(`src, 256, ip, username, cred) ] -- most common
		[ checksha(`src, 512, ip, username, cred) ] -- most secure
		[ checksha(`src, 384, ip, username, cred) ] -- weird
		[ checksha(`src, 224, ip, username, cred) ] -- weirdest

		-- TODO: check pbkdf2-hmac
		-- TODO: check OTP
		return 0, 0, pstring.null()
	end];

	actor_auth_challenge = [terra(
		src: &lib.store.source,
		ip: lib.store.inet,
		username: pstring,
		sig: binblob,
		token: pstring
	): {uint64, uint64, pstring}
		-- we need to iterate through all the challenge types. right now that's just RSA
		lib.dbg('checking against token ', {token.ptr,token.ct})
		var rsakeys = queries.actor_auth_challenge.exec(src, 'rsa', username, ip)
		var toprops = [terra(res: &pqr, i: intptr)
			return {
				aid = res:int(uint64, i, 0);
				uid = res:int(uint64, i, 1);
				name = res:_string(i, 2);
				blacklist = res:bool(i, 3);
				pubkey = res:bin(i, 4);
			}
		end]
		if rsakeys.sz > 0 then defer rsakeys:free()
			for i=0, rsakeys.sz do var props = toprops(&rsakeys, i)
				lib.dbg('loading next RSA pubkey')
				var pub = lib.crypt.loadpub(props.pubkey.ptr, props.pubkey.ct)
				if pub.ok then defer pub.val:free()
					lib.dbg('checking pubkey against response')
					var vfy, secl = lib.crypt.verify(&pub.val, token.ptr, token.ct, sig.ptr, sig.ct)
					if vfy then
						lib.dbg('signature verified')
						if props.blacklist then lib.dbg('key blacklisted!') goto fail end
						var dupname = lib.str.dup(props.name.ptr)
						return props.aid, props.uid, pstring {dupname, props.name.ct}
					end
				else lib.warn('invalid pubkey in authentication table for user ',{props.name.ptr, props.name.ct}) end
			end
		end

		-- and so on

		lib.dbg('no challenges were successful')
		::fail::return 0, 0, pstring.null()
	end];


	actor_stats = [terra(src: &lib.store.source, uid: uint64)
		var r = queries.actor_stats.exec(src, uid)
		if r.sz == 0 then lib.bail('error fetching actor stats!') end
		var s: lib.store.actor_stats
		s.posts = r:int(uint64, 0, 0)
		s.follows = r:int(uint64, 0, 1)
................................................................................
		if reset then queries.auth_purge_type.exec(src, nil, uid, 'pw-%') end
		var r = queries.auth_create_pw.exec(src, uid, binblob {ptr = &hash[0], ct = [hash.type.N]}, lib.osclock.time(nil), comment)
		if r.sz == 0 then return 0 end
		var aid = r:int(uint64,0,0)
		r:free()
		return aid
	end];

	auth_attach_rsa = [terra(
		src: &lib.store.source,
		uid: uint64,
		reset: bool,
		pub: binblob,
		comment: pstring
	): uint64
		if reset then queries.auth_purge_type.exec(src, nil, uid, 'challenge-%') end
		var r = queries.auth_create_rsa.exec(src, uid, pub, lib.osclock.time(nil), comment)
		if r.sz == 0 then return 0 end
		var aid = r:int(uint64,0,0)
		r:free()
		return aid
	end];

	auth_privs_set = [terra(
		src: &lib.store.source,
		aid: uint64,
		set: lib.store.privset
	): {}
		var map = array([lib.store.privmap])