2022-04-20 07:19:34 +03:00
|
|
|
const std = @import("std");
|
|
|
|
const os = std.os;
|
|
|
|
const fmt = std.fmt;
|
2022-07-06 13:19:15 +03:00
|
|
|
const log = std.log;
|
2022-04-20 07:19:34 +03:00
|
|
|
const mem = std.mem;
|
2022-04-21 09:30:39 +03:00
|
|
|
const process = std.process;
|
2022-07-06 13:19:15 +03:00
|
|
|
const once = std.once;
|
2022-04-20 07:19:34 +03:00
|
|
|
|
|
|
|
const DB = @import("DB.zig");
|
|
|
|
const File = @import("File.zig");
|
2022-07-04 06:09:03 +03:00
|
|
|
const ErrCtx = @import("ErrCtx.zig");
|
2022-04-20 07:19:34 +03:00
|
|
|
const CGroup = @import("Group.zig").CGroup;
|
|
|
|
const PackedGroup = @import("PackedGroup.zig");
|
|
|
|
const CUser = @import("User.zig").CUser;
|
|
|
|
const PackedUser = @import("PackedUser.zig");
|
|
|
|
|
|
|
|
const c = @cImport({
|
|
|
|
@cInclude("nss.h");
|
|
|
|
});
|
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
const ENV_DB = "TURBONSS_DB";
|
2022-07-06 13:53:34 +03:00
|
|
|
const ENV_VERBOSE = "TURBONSS_VERBOSE";
|
2022-07-06 13:19:15 +03:00
|
|
|
const ENV_OMIT_MEMBERS = "TURBONSS_OMIT_MEMBERS";
|
2022-04-21 09:30:39 +03:00
|
|
|
|
2022-07-06 13:53:34 +03:00
|
|
|
export var turbonss_db_path: [:0]const u8 = "/etc/turbonss/db.turbo";
|
2022-04-20 07:19:34 +03:00
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
pub var log_level: std.log.Level = .err;
|
|
|
|
|
2022-04-20 07:19:34 +03:00
|
|
|
// State is a type of the global variable holding the process state:
|
|
|
|
// the DB handle and all the iterators.
|
|
|
|
const State = struct {
|
|
|
|
file: ?File,
|
2022-07-06 13:19:15 +03:00
|
|
|
getpwent_iterator: ?PackedUser.Iterator = null,
|
|
|
|
getgrent_iterator: ?PackedGroup.Iterator = null,
|
2022-04-20 07:19:34 +03:00
|
|
|
omit_members: bool,
|
|
|
|
};
|
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
// global_state is initialized on first call to an nss function
|
|
|
|
var global_state: State = undefined;
|
2022-07-06 13:29:36 +03:00
|
|
|
var global_init = once(init);
|
2022-04-20 07:19:34 +03:00
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
// assigns State from environment variables et al
|
|
|
|
fn init() void {
|
|
|
|
if (os.getenvZ(ENV_VERBOSE)) |env|
|
|
|
|
log_level = if (mem.eql(u8, mem.sliceTo(env, 0), "1"))
|
|
|
|
.debug
|
|
|
|
else
|
|
|
|
.err;
|
2022-04-21 09:30:39 +03:00
|
|
|
|
2022-07-06 13:53:34 +03:00
|
|
|
const fname = os.getenvZ(ENV_DB) orelse turbonss_db_path[0..];
|
2022-07-06 13:19:15 +03:00
|
|
|
log.debug("opening {s}", .{fname});
|
2022-04-21 09:30:39 +03:00
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
const env_omit_members = os.getenvZ(ENV_OMIT_MEMBERS) orelse "auto";
|
|
|
|
const omit_members = shouldOmitMembers(env_omit_members, os.argv);
|
|
|
|
log.debug("omitting members from getgr* calls: {any}\n", .{omit_members});
|
2022-04-21 09:30:39 +03:00
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
const file = File.open(fname) catch |err| {
|
|
|
|
log.warn("open '{s}': {s}", .{ fname, @errorName(err) });
|
2022-04-20 07:19:34 +03:00
|
|
|
return;
|
|
|
|
};
|
2022-07-06 13:19:15 +03:00
|
|
|
log.debug("turbonss database opened", .{});
|
2022-04-20 07:19:34 +03:00
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
global_state = State{
|
|
|
|
.file = file,
|
|
|
|
.omit_members = omit_members,
|
|
|
|
};
|
2022-04-20 07:19:34 +03:00
|
|
|
}
|
|
|
|
|
2022-07-06 13:19:15 +03:00
|
|
|
fn shouldOmitMembers(envvar: []const u8, argv: [][*:0]u8) bool {
|
|
|
|
if (mem.eql(u8, envvar, "1")) return true;
|
|
|
|
if (mem.eql(u8, envvar, "0")) return false;
|
2022-04-20 07:19:34 +03:00
|
|
|
if (argv.len == 0) return false;
|
|
|
|
return mem.eql(u8, mem.sliceTo(argv[0], 0), "id");
|
|
|
|
}
|
|
|
|
|
|
|
|
export fn _nss_turbo_getpwuid_r(
|
|
|
|
uid: c_uint,
|
2022-07-06 13:53:34 +03:00
|
|
|
pwd: *CUser,
|
2022-04-20 07:19:34 +03:00
|
|
|
buf: [*]u8,
|
2022-07-06 13:53:34 +03:00
|
|
|
buflen: usize,
|
2022-04-20 07:19:34 +03:00
|
|
|
errnop: *c_int,
|
|
|
|
) c.enum_nss_status {
|
2022-07-06 13:53:34 +03:00
|
|
|
const db = get_db(errnop) orelse return c.NSS_STATUS_UNAVAIL;
|
|
|
|
|
|
|
|
if (db.getpwuid(uid, buf[0..buflen])) |maybe_cuser| {
|
|
|
|
if (maybe_cuser) |cuser| {
|
|
|
|
pwd.* = cuser;
|
|
|
|
return c.NSS_STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
errnop.* = @enumToInt(os.E.NOENT);
|
|
|
|
return c.NSS_STATUS_NOTFOUND;
|
|
|
|
}
|
|
|
|
} else |err| switch (err) {
|
|
|
|
error.BufferTooSmall => {
|
2022-04-21 09:30:39 +03:00
|
|
|
errnop.* = @enumToInt(os.E.RANGE);
|
|
|
|
return c.NSS_STATUS_TRYAGAIN;
|
|
|
|
},
|
|
|
|
}
|
2022-07-06 13:53:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn get_db(errnop: *c_int) ?DB {
|
|
|
|
global_init.call();
|
2022-04-21 09:30:39 +03:00
|
|
|
|
2022-07-06 13:53:34 +03:00
|
|
|
if (global_state.file) |file| {
|
|
|
|
return file.db;
|
|
|
|
} else {
|
|
|
|
errnop.* = @enumToInt(os.E.AGAIN);
|
|
|
|
return null;
|
|
|
|
}
|
2022-04-21 09:30:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const testing = std.testing;
|
|
|
|
|
|
|
|
test "nss_turbo_getpwuid_r" {
|
2022-07-04 06:09:03 +03:00
|
|
|
var errc = ErrCtx{};
|
|
|
|
var tf = try File.TestDB.init(testing.allocator, &errc);
|
2022-06-07 06:30:18 +03:00
|
|
|
defer tf.deinit();
|
2022-04-20 07:19:34 +03:00
|
|
|
}
|