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])
|