wip getpwnam
This commit is contained in:
parent
9e80d6676b
commit
4469d174ea
91
lib/DB.zig
91
lib/DB.zig
@ -14,12 +14,13 @@ const ArenaAllocator = std.heap.ArenaAllocator;
|
|||||||
const Corpus = @import("Corpus.zig");
|
const Corpus = @import("Corpus.zig");
|
||||||
const pad = @import("padding.zig");
|
const pad = @import("padding.zig");
|
||||||
const compress = @import("compress.zig");
|
const compress = @import("compress.zig");
|
||||||
const PackedUser = @import("PackedUser.zig");
|
|
||||||
const User = @import("User.zig");
|
|
||||||
const Group = @import("Group.zig");
|
const Group = @import("Group.zig");
|
||||||
const CGroup = Group.CGroup;
|
const CGroup = Group.CGroup;
|
||||||
const PackedGroup = @import("PackedGroup.zig");
|
const PackedGroup = @import("PackedGroup.zig");
|
||||||
const GroupStored = PackedGroup.GroupStored;
|
const GroupStored = PackedGroup.GroupStored;
|
||||||
|
const User = @import("User.zig");
|
||||||
|
const CUser = User.CUser;
|
||||||
|
const PackedUser = @import("PackedUser.zig");
|
||||||
const ShellSections = @import("shell.zig").ShellWriter.ShellSections;
|
const ShellSections = @import("shell.zig").ShellWriter.ShellSections;
|
||||||
const ShellReader = @import("shell.zig").ShellReader;
|
const ShellReader = @import("shell.zig").ShellReader;
|
||||||
const ShellWriter = @import("shell.zig").ShellWriter;
|
const ShellWriter = @import("shell.zig").ShellWriter;
|
||||||
@ -123,6 +124,8 @@ pub fn fromCorpus(
|
|||||||
.getpw_bufsize = corpus.getpw_bufsize,
|
.getpw_bufsize = corpus.getpw_bufsize,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std.debug.print("fromCorpus shell.index: {any}\n", .{shell.index.constSlice()});
|
||||||
|
|
||||||
return DB{
|
return DB{
|
||||||
.header = header,
|
.header = header,
|
||||||
.bdz_gid = bdz_gid,
|
.bdz_gid = bdz_gid,
|
||||||
@ -169,6 +172,8 @@ pub fn iov(self: *const DB) BoundedArray(os.iovec_const, DB_fields.len * 2) {
|
|||||||
*const Header => mem.asBytes(value),
|
*const Header => mem.asBytes(value),
|
||||||
else => mem.sliceAsBytes(value),
|
else => mem.sliceAsBytes(value),
|
||||||
};
|
};
|
||||||
|
if (mem.eql(u8, field.name, "shell_index"))
|
||||||
|
std.debug.print("shell_index original: {any}\n", .{value});
|
||||||
result.appendAssumeCapacity(os.iovec_const{
|
result.appendAssumeCapacity(os.iovec_const{
|
||||||
.iov_base = bytes.ptr,
|
.iov_base = bytes.ptr,
|
||||||
.iov_len = bytes.len,
|
.iov_len = bytes.len,
|
||||||
@ -219,15 +224,13 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
|
|||||||
offset += lengths[i];
|
offset += lengths[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std.debug.print("GOT shell_index: {any}\n", .{result.shell_index});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dumps PackedGroup to []u8 and returns a CGroup.
|
// dumps PackedGroup to []u8 and returns a CGroup.
|
||||||
fn getGroup(
|
fn getGroup(self: *const DB, group: PackedGroup, buf: *[]u8) error{OutOfMemory}!CGroup {
|
||||||
self: *const DB,
|
|
||||||
group: PackedGroup,
|
|
||||||
buf: *[]u8,
|
|
||||||
) error{OutOfMemory}!CGroup {
|
|
||||||
const members_slice = self.groupmembers[group.members_offset..];
|
const members_slice = self.groupmembers[group.members_offset..];
|
||||||
var vit = compress.VarintSliceIteratorMust(members_slice);
|
var vit = compress.VarintSliceIteratorMust(members_slice);
|
||||||
const num_members = vit.remaining;
|
const num_members = vit.remaining;
|
||||||
@ -271,7 +274,8 @@ fn getGroup(
|
|||||||
fn getgrnam(self: *const DB, name: []const u8, buf: *[]u8) error{OutOfMemory}!?CGroup {
|
fn getgrnam(self: *const DB, name: []const u8, buf: *[]u8) error{OutOfMemory}!?CGroup {
|
||||||
const idx = bdz.search(self.bdz_groupname, name);
|
const idx = bdz.search(self.bdz_groupname, name);
|
||||||
const offset = self.idx_groupname2group[idx];
|
const offset = self.idx_groupname2group[idx];
|
||||||
const group = PackedGroup.fromBytes(self.groups[offset << 3 ..]).group;
|
const nbits = PackedGroup.alignment_bits;
|
||||||
|
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
||||||
if (!mem.eql(u8, name, group.name())) return null;
|
if (!mem.eql(u8, name, group.name())) return null;
|
||||||
return try self.getGroup(group, buf);
|
return try self.getGroup(group, buf);
|
||||||
}
|
}
|
||||||
@ -280,16 +284,69 @@ fn getgrnam(self: *const DB, name: []const u8, buf: *[]u8) error{OutOfMemory}!?C
|
|||||||
fn getgrgid(self: *const DB, gid: u32, buf: *[]u8) error{OutOfMemory}!?CGroup {
|
fn getgrgid(self: *const DB, gid: u32, buf: *[]u8) error{OutOfMemory}!?CGroup {
|
||||||
const idx = bdz.search_u32(self.bdz_gid, gid);
|
const idx = bdz.search_u32(self.bdz_gid, gid);
|
||||||
const offset = self.idx_gid2group[idx];
|
const offset = self.idx_gid2group[idx];
|
||||||
const group = PackedGroup.fromBytes(self.groups[offset << 3 ..]).group;
|
const nbits = PackedGroup.alignment_bits;
|
||||||
|
const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group;
|
||||||
if (gid != group.gid()) return null;
|
if (gid != group.gid()) return null;
|
||||||
return try self.getGroup(group, buf);
|
return try self.getGroup(group, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pushStr(str: []const u8, buf: *[]u8, offset: *usize) [*]const u8 {
|
||||||
|
const start = offset.*;
|
||||||
|
mem.copy(u8, buf.*[offset.*..], str);
|
||||||
|
buf.*[offset.* + str.len] = 0;
|
||||||
|
offset.* += str.len + 1;
|
||||||
|
return @ptrCast([*]const u8, &buf.*[start]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getUser(self: *const DB, user: PackedUser, buf: *[]u8) error{OutOfMemory}!CUser {
|
||||||
|
const shell_reader = ShellReader{
|
||||||
|
.index = self.shell_index,
|
||||||
|
.blob = self.shell_blob,
|
||||||
|
};
|
||||||
|
const name = user.name();
|
||||||
|
const gecos = user.gecos();
|
||||||
|
const home = user.home();
|
||||||
|
const shell = user.shell(shell_reader);
|
||||||
|
|
||||||
|
const strlen =
|
||||||
|
name.len + 1 +
|
||||||
|
gecos.len + 1 +
|
||||||
|
home.len + 1 +
|
||||||
|
shell.len + 1;
|
||||||
|
if (strlen > buf.len) return error.OutOfMemory;
|
||||||
|
|
||||||
|
var offset: usize = 0;
|
||||||
|
const pw_name = pushStr(name, buf, &offset);
|
||||||
|
const pw_gecos = pushStr(gecos, buf, &offset);
|
||||||
|
const pw_dir = pushStr(home, buf, &offset);
|
||||||
|
const pw_shell = pushStr(shell, buf, &offset);
|
||||||
|
|
||||||
|
return CUser{
|
||||||
|
.pw_name = pw_name,
|
||||||
|
.pw_uid = user.uid(),
|
||||||
|
.pw_gid = user.gid(),
|
||||||
|
.pw_gecos = pw_gecos,
|
||||||
|
.pw_dir = pw_dir,
|
||||||
|
.pw_shell = pw_shell,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a CUser entry by name.
|
||||||
|
fn getpwnam(self: *const DB, name: []const u8, buf: *[]u8) error{OutOfMemory}!?CUser {
|
||||||
|
const idx = bdz.search(self.bdz_username, name);
|
||||||
|
const offset = self.idx_name2user[idx];
|
||||||
|
const nbits = PackedUser.alignment_bits;
|
||||||
|
const user = PackedUser.fromBytes(self.users[offset << nbits ..]).user;
|
||||||
|
if (!mem.eql(u8, name, user.name())) return null;
|
||||||
|
return try self.getUser(user, buf);
|
||||||
|
}
|
||||||
|
|
||||||
fn shellSections(
|
fn shellSections(
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
corpus: *const Corpus,
|
corpus: *const Corpus,
|
||||||
) error{OutOfMemory}!ShellSections {
|
) error{OutOfMemory}!ShellSections {
|
||||||
var popcon = ShellWriter.init(allocator);
|
var popcon = ShellWriter.init(allocator);
|
||||||
|
errdefer popcon.deinit();
|
||||||
for (corpus.users.items(.shell)) |shell|
|
for (corpus.users.items(.shell)) |shell|
|
||||||
try popcon.put(shell);
|
try popcon.put(shell);
|
||||||
return popcon.toOwnedSections(max_shells);
|
return popcon.toOwnedSections(max_shells);
|
||||||
@ -609,6 +666,22 @@ test "getgr_bufsize" {
|
|||||||
try testing.expectError(error.OutOfMemory, db.getgrnam("all", &buf));
|
try testing.expectError(error.OutOfMemory, db.getgrnam("all", &buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "getpwnam" {
|
||||||
|
var arena = ArenaAllocator.init(testing.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
var corpus = try Corpus.testCorpus(arena.allocator());
|
||||||
|
var db = try DB.fromCorpus(arena.allocator(), &corpus);
|
||||||
|
std.debug.print("db.shell.index: {any}\n", .{db.shell_index});
|
||||||
|
var buf = try arena.allocator().alloc(u8, db.header.getpw_bufsize);
|
||||||
|
|
||||||
|
const vidmantas = (try db.getpwnam("vidmantas", &buf)).?;
|
||||||
|
try testing.expectEqual(vidmantas.pw_uid, 128);
|
||||||
|
try testing.expectEqual(vidmantas.pw_gid, 128);
|
||||||
|
try testing.expectEqualStrings(vidmantas.pw_name[0..9], "vidmantas");
|
||||||
|
try testing.expectEqualStrings(vidmantas.pw_gecos[0..10], "Vidmantas Kaminskas");
|
||||||
|
try testing.expectEqualStrings(vidmantas.pw_dir[0..10], "/home/vidmantas");
|
||||||
|
}
|
||||||
|
|
||||||
test "additionalGids" {
|
test "additionalGids" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
var corpus = try Corpus.testCorpus(allocator);
|
var corpus = try Corpus.testCorpus(allocator);
|
||||||
|
@ -209,7 +209,8 @@ pub fn shell(self: PackedUser, shell_reader: shellImport.ShellReader) []const u8
|
|||||||
return shell_reader.get(self.inner.shell_len_or_idx);
|
return shell_reader.get(self.inner.shell_len_or_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const max_str_len = math.maxInt(fieldInfo(Inner, .shell_len_or_idx).field_type) + 1 +
|
pub const max_str_len =
|
||||||
|
math.maxInt(fieldInfo(Inner, .shell_len_or_idx).field_type) + 1 +
|
||||||
math.maxInt(fieldInfo(Inner, .home_len).field_type) + 1 +
|
math.maxInt(fieldInfo(Inner, .home_len).field_type) + 1 +
|
||||||
math.maxInt(fieldInfo(Inner, .name_len).field_type) + 1 +
|
math.maxInt(fieldInfo(Inner, .name_len).field_type) + 1 +
|
||||||
math.maxInt(fieldInfo(Inner, .gecos_len).field_type);
|
math.maxInt(fieldInfo(Inner, .gecos_len).field_type);
|
||||||
|
12
lib/User.zig
12
lib/User.zig
@ -6,6 +6,8 @@ const Allocator = mem.Allocator;
|
|||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
const BoundedArray = std.BoundedArray;
|
const BoundedArray = std.BoundedArray;
|
||||||
|
|
||||||
|
const pw_passwd = "x\x00";
|
||||||
|
|
||||||
const User = @This();
|
const User = @This();
|
||||||
const PackedUser = @import("PackedUser.zig");
|
const PackedUser = @import("PackedUser.zig");
|
||||||
const validate = @import("validate.zig");
|
const validate = @import("validate.zig");
|
||||||
@ -126,6 +128,16 @@ pub fn fromReader(allocator: Allocator, reader: anytype) ![]User {
|
|||||||
_ = users;
|
_ = users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const CUser = extern struct {
|
||||||
|
pw_name: [*]const u8,
|
||||||
|
pw_passwd: [*]const u8 = pw_passwd,
|
||||||
|
pw_uid: u32,
|
||||||
|
pw_gid: u32,
|
||||||
|
pw_gecos: [*]const u8,
|
||||||
|
pw_dir: [*]const u8,
|
||||||
|
pw_shell: [*]const u8,
|
||||||
|
};
|
||||||
|
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
pub const max_user = User{
|
pub const max_user = User{
|
||||||
|
@ -22,6 +22,8 @@ pub const ShellReader = struct {
|
|||||||
|
|
||||||
// get returns a shell at the given index.
|
// get returns a shell at the given index.
|
||||||
pub fn get(self: *const ShellReader, idx: u8) []const u8 {
|
pub fn get(self: *const ShellReader, idx: u8) []const u8 {
|
||||||
|
std.debug.print("\nrequested shell at index {d}; ", .{idx});
|
||||||
|
std.debug.print("start:{d} end:{d}\n", .{ self.index[idx], self.index[idx + 1] });
|
||||||
return self.blob[self.index[idx]..self.index[idx + 1]];
|
return self.blob[self.index[idx]..self.index[idx + 1]];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -73,6 +75,7 @@ pub const ShellWriter = struct {
|
|||||||
self.index.set(idx8, offset);
|
self.index.set(idx8, offset);
|
||||||
}
|
}
|
||||||
self.index.appendAssumeCapacity(@intCast(u8, self.blob.len));
|
self.index.appendAssumeCapacity(@intCast(u8, self.blob.len));
|
||||||
|
std.debug.print("\nGEN shell_index: {any}\n", .{self.index.constSlice()});
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,9 +144,7 @@ pub const ShellWriter = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const total = std.math.min(deque.count(), limit);
|
const total = std.math.min(deque.count(), limit);
|
||||||
var topShells = BoundedArray([]const u8, max_shells).init(total) catch |err| switch (err) {
|
var topShells = BoundedArray([]const u8, max_shells).init(total) catch unreachable;
|
||||||
error.Overflow => unreachable,
|
|
||||||
};
|
|
||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < total) : (i += 1)
|
while (i < total) : (i += 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user