Differences From
Artifact [b388ba7244]:
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])