From 434f9e15714a51880eac2680e1e464949f3162c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Fri, 8 Jul 2022 06:29:42 +0300 Subject: [PATCH] wip initgroups_dyn --- src/DB.zig | 21 +++++---- src/libnss.zig | 125 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 106 insertions(+), 40 deletions(-) diff --git a/src/DB.zig b/src/DB.zig index 5c10b66..6f639ca 100644 --- a/src/DB.zig +++ b/src/DB.zig @@ -280,7 +280,7 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB { } // dumps PackedGroup to []u8 and returns a CGroup. -pub fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup { +pub fn packCGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup { const members_slice = self.groupmembers[group.members_offset..]; var vit = compress.VarintSliceIteratorMust(members_slice); const num_members = vit.remaining; @@ -328,7 +328,7 @@ pub fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSma const nbits = PackedGroup.alignment_bits; const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group; if (!mem.eql(u8, name, group.name())) return null; - return try self.getGroup(group, buf); + return try self.packCGroup(group, buf); } // get a CGroup entry by it's gid. @@ -339,7 +339,7 @@ pub fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{BufferTooSmall}!?CGr const nbits = PackedGroup.alignment_bits; const group = PackedGroup.fromBytes(self.groups[offset << nbits ..]).group; if (gid != group.gid()) return null; - return try self.getGroup(group, buf); + return try self.packCGroup(group, buf); } fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*:0]const u8 { @@ -350,7 +350,7 @@ fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*:0]const u8 { return buf[start .. start + str.len :0].ptr; } -fn getUser(self: *const DB, user: PackedUser, buf: []u8) error{BufferTooSmall}!CUser { +pub fn writeUser(self: *const DB, user: PackedUser, buf: []u8) error{BufferTooSmall}!CUser { const shell_reader = ShellReader{ .index = self.shell_index, .blob = self.shell_blob, @@ -383,8 +383,7 @@ fn getUser(self: *const DB, user: PackedUser, buf: []u8) error{BufferTooSmall}!C }; } -// get a CUser entry by name. -pub fn getpwnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}!?CUser { +pub fn getUser(self: *const DB, name: []const u8) ?PackedUser { const idx = bdz.search(self.bdz_username, name); // bdz may return a hash that's bigger than the number of users if (idx >= self.header.num_users) return null; @@ -392,7 +391,13 @@ pub fn getpwnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSma 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); + return user; +} + +// get a CUser entry by name. +pub fn getpwnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}!?CUser { + const user = self.getUser(name) orelse return null; + return try self.writeUser(user, buf); } // get a CUser entry by uid. @@ -403,7 +408,7 @@ pub fn getpwuid(self: *const DB, uid: u32, buf: []u8) error{BufferTooSmall}!?CUs const nbits = PackedUser.alignment_bits; const user = PackedUser.fromBytes(self.users[offset << nbits ..]).user; if (uid != user.uid()) return null; - return try self.getUser(user, buf); + return try self.writeUser(user, buf); } fn shellSections( diff --git a/src/libnss.zig b/src/libnss.zig index a9737ec..4a6214f 100644 --- a/src/libnss.zig +++ b/src/libnss.zig @@ -117,13 +117,13 @@ export fn _nss_turbo_getpwuid_r( }, }; - if (cuser) |got| { - passwd.* = got; - return c.NSS_STATUS_SUCCESS; - } else { + const got_cuser = cuser orelse { errnop.* = @enumToInt(os.E.NOENT); return c.NSS_STATUS_NOTFOUND; - } + }; + + passwd.* = got_cuser; + return c.NSS_STATUS_SUCCESS; } export fn _nss_turbo_getpwnam_r( @@ -144,13 +144,13 @@ export fn _nss_turbo_getpwnam_r( }, }; - if (cuser) |got| { - passwd.* = got; - return c.NSS_STATUS_SUCCESS; - } else { + const got_cuser = cuser orelse { errnop.* = @enumToInt(os.E.NOENT); return c.NSS_STATUS_NOTFOUND; - } + }; + + passwd.* = got_cuser; + return c.NSS_STATUS_SUCCESS; } export fn _nss_turbo_getgrgid_r( @@ -168,13 +168,13 @@ export fn _nss_turbo_getgrgid_r( }, }; - if (cgroup) |got| { - gr.* = got; - return c.NSS_STATUS_SUCCESS; - } else { + const got_cgroup = cgroup orelse { errnop.* = @enumToInt(os.E.NOENT); return c.NSS_STATUS_NOTFOUND; - } + }; + + gr.* = got_cgroup; + return c.NSS_STATUS_SUCCESS; } export fn _nss_turbo_getgrnam_r( @@ -194,13 +194,13 @@ export fn _nss_turbo_getgrnam_r( }, }; - if (cgroup) |got| { - group.* = got; - return c.NSS_STATUS_SUCCESS; - } else { + const got_cgroup = cgroup orelse { errnop.* = @enumToInt(os.E.NOENT); return c.NSS_STATUS_NOTFOUND; - } + }; + + group.* = got_cgroup; + return c.NSS_STATUS_SUCCESS; } export fn _nss_turbo_setpwent(_: c_int) void { @@ -221,11 +221,11 @@ export fn _nss_turbo_setpwent(_: c_int) void { export fn _nss_turbo_endpwent() void { global_init.call(); - if (global_state) |*state| { - state.getpwent_iterator_mu.lock(); - defer state.getpwent_iterator_mu.unlock(); - state.getpwent_iterator = null; - } + var state = global_state orelse return; + + state.getpwent_iterator_mu.lock(); + state.getpwent_iterator = null; + state.getpwent_iterator_mu.unlock(); } export fn _nss_turbo_setgrent(_: c_int) void { @@ -239,9 +239,10 @@ export fn _nss_turbo_setgrent(_: c_int) void { export fn _nss_turbo_endgrent() void { var state = getState() orelse return; + state.getgrent_iterator_mu.lock(); - defer state.getgrent_iterator_mu.unlock(); state.getgrent_iterator = null; + state.getgrent_iterator_mu.unlock(); } export fn _nss_turbo_getgrent_r( @@ -261,20 +262,80 @@ export fn _nss_turbo_getgrent_r( return c.NSS_STATUS_UNAVAIL; }; - var group = it.next() orelse { + const group = it.next() orelse { errnop.* = @enumToInt(os.E.NOENT); return c.NSS_STATUS_NOTFOUND; }; - if (state.file.db.getGroup(group, buffer[0..buflen])) |cgroup| { - result.* = cgroup; - return c.NSS_STATUS_SUCCESS; - } else |err| switch (err) { + const buf = buffer[0..buflen]; + const cgroup = state.file.db.packCGroup(group, buf) catch |err| switch (err) { error.BufferTooSmall => { errnop.* = @enumToInt(os.E.RANGE); return c.NSS_STATUS_TRYAGAIN; }, - } + }; + + result.* = cgroup; + return c.NSS_STATUS_SUCCESS; +} + +export fn _nss_turbo_getpwent_r( + result: *CUser, + buffer: [*]u8, + buflen: usize, + errnop: *c_int, +) c.enum_nss_status { + var state = getStateErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; + + state.getpwent_iterator_mu.lock(); + defer state.getpwent_iterator_mu.unlock(); + + var it = state.getpwent_iterator orelse { + // logic from _nss_systemd_getgrent_r + errnop.* = @enumToInt(os.E.HOSTDOWN); + return c.NSS_STATUS_UNAVAIL; + }; + + const user = it.next() orelse { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; + }; + + const buf = buffer[0..buflen]; + const cuser = state.file.db.writeUser(user, buf) catch |err| switch (err) { + error.BufferTooSmall => { + errnop.* = @enumToInt(os.E.RANGE); + return c.NSS_STATUS_TRYAGAIN; + }, + }; + + result.* = cuser; + return c.NSS_STATUS_SUCCESS; +} + +export fn _nss_turbo_initgroups_dyn( + user_name: [*:0]const u8, + _: u32, + start: *c_long, + size: *c_long, + groups: [*]u32, + limit: c_long, + errnop: *c_int, +) c.enum_nss_status { + const db = getDBErrno(errnop) orelse return c.NSS_STATUS_UNAVAIL; + + const user = db.getUser(mem.sliceTo(user_name, 0)) orelse { + errnop.* = @enumToInt(os.E.NOENT); + return c.NSS_STATUS_NOTFOUND; + }; + + _ = user; + _ = start; + _ = size; + _ = groups; + _ = limit; + + return c.NSS_STATUS_SUCCESS; } fn getState() ?State {