summaryrefslogtreecommitdiff
path: root/src/nsssd/nsssd_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nsssd/nsssd_main.c')
-rw-r--r--src/nsssd/nsssd_main.c419
1 files changed, 419 insertions, 0 deletions
diff --git a/src/nsssd/nsssd_main.c b/src/nsssd/nsssd_main.c
new file mode 100644
index 0000000..8673df4
--- /dev/null
+++ b/src/nsssd/nsssd_main.c
@@ -0,0 +1,419 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+#include <skalibs/uint32.h>
+#include <skalibs/uint64.h>
+#include <skalibs/error.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/tai.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/pwd-def.h>
+#include <nsss/grp-def.h>
+#include <nsss/shadow-def.h>
+#include <nsss/nsss-switch.h>
+#include <nsss/nsssd.h>
+
+static unsigned int initted = 0 ;
+
+static void get0 (char *s, size_t n)
+{
+ tain_t deadline ;
+ tain_ulong(&deadline, 30) ;
+ tain_add_g(&deadline, &deadline) ;
+ if (buffer_timed_get_g(buffer_0small, s, n, &deadline) < n)
+ strerr_diefu1sys(111, "read from stdin") ;
+}
+
+static void put1 (char const *s, size_t n)
+{
+ size_t w = 0 ;
+ tain_t deadline ;
+ tain_ulong(&deadline, 30) ;
+ tain_add_g(&deadline, &deadline) ;
+ while (!buffer_putall(buffer_1, s, n, &w))
+ {
+ if (!buffer_timed_flush_g(buffer_1, &deadline))
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+}
+
+static void flush1 (void)
+{
+ tain_t deadline ;
+ tain_ulong(&deadline, 2) ;
+ tain_add_g(&deadline, &deadline) ;
+ if (!buffer_timed_flush_g(buffer_1, &deadline))
+ strerr_diefu1sys(111, "write to stdout") ;
+}
+
+static void answer (int e)
+{
+ unsigned char c = e ;
+ buffer_putnoflush(buffer_1, (char *)&c, 1) ;
+ flush1() ;
+}
+
+static inline void print_pw (struct passwd const *pw)
+{
+ size_t len, namelen, passwdlen, gecoslen, dirlen, shelllen ;
+ char pack[12] ;
+ namelen = strlen(pw->pw_name) + 1 ;
+ passwdlen = strlen(pw->pw_passwd) + 1 ;
+ gecoslen = strlen(pw->pw_gecos) + 1 ;
+ dirlen = strlen(pw->pw_dir) + 1 ;
+ shelllen = strlen(pw->pw_shell) + 1 ;
+ len = namelen + passwdlen + gecoslen + dirlen + shelllen ;
+ if (len > 0xffffffff) { answer(ENAMETOOLONG) ; return ; }
+ put1("", 1) ;
+ uint32_pack_big(pack, pw->pw_uid) ;
+ uint32_pack_big(pack + 4, pw->pw_gid) ;
+ uint32_pack_big(pack + 8, len) ;
+ put1(pack, 12) ;
+ put1(pw->pw_name, namelen) ;
+ put1(pw->pw_passwd, passwdlen) ;
+ put1(pw->pw_gecos, gecoslen) ;
+ put1(pw->pw_dir, dirlen) ;
+ put1(pw->pw_shell, shelllen) ;
+ flush1() ;
+}
+
+static inline void print_gr (struct group const *gr)
+{
+ size_t len, namelen, passwdlen ;
+ size_t n = 0 ;
+ char pack[12] ;
+ namelen = strlen(gr->gr_name) + 1 ;
+ passwdlen = strlen(gr->gr_passwd) + 1 ;
+ len = namelen + passwdlen ;
+ for (char **p = gr->gr_mem ; *p ; n++, p++) len += strlen(*p) + 1 ;
+ if (len > 0xffffffffu || n > 0x30000000u) { answer(ENAMETOOLONG) ; return ; }
+ put1("", 1) ;
+ uint32_pack_big(pack, gr->gr_gid) ;
+ uint32_pack_big(pack, len) ;
+ uint32_pack_big(pack, n) ;
+ put1(pack, 12) ;
+ put1(gr->gr_name, namelen) ;
+ put1(gr->gr_passwd, passwdlen) ;
+ for (size_t i = 0 ; i < n ; i++)
+ put1(gr->gr_mem[i], strlen(gr->gr_mem[i]) + 1) ;
+ flush1() ;
+}
+
+static inline void print_sp (struct spwd const *sp)
+{
+ size_t len, namplen, pwdplen ;
+ char pack[60] ;
+ namplen = strlen(sp->sp_namp) + 1 ;
+ pwdplen = strlen(sp->sp_pwdp) + 1 ;
+ len = namplen + pwdplen ;
+ if (len > 0xffffffff) { answer(ENAMETOOLONG) ; return ; }
+ put1("", 1) ;
+ uint64_pack_big(pack, sp->sp_lstchg) ;
+ uint64_pack_big(pack + 8, sp->sp_min) ;
+ uint64_pack_big(pack + 16, sp->sp_max) ;
+ uint64_pack_big(pack + 24, sp->sp_warn) ;
+ uint64_pack_big(pack + 32, sp->sp_inact) ;
+ uint64_pack_big(pack + 40, sp->sp_expire) ;
+ uint64_pack_big(pack + 48, sp->sp_flag) ;
+ uint32_pack_big(pack + 56, len) ;
+ put1(pack, 60) ;
+ put1(sp->sp_namp, namplen) ;
+ put1(sp->sp_pwdp, pwdplen) ;
+ flush1() ;
+}
+
+
+static inline void do_pwend (void *a)
+{
+ nsssd_pwd_end(a) ;
+ answer(0) ;
+}
+
+static inline void do_pwrewind (void *a)
+{
+ if (!(initted & 1))
+ {
+ if (!nsssd_pwd_start(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ initted |= 1 ;
+ }
+ if (!nsssd_pwd_rewind(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ answer(0) ;
+}
+
+static inline void do_pwget (void *a)
+{
+ struct passwd pw ;
+ if (!(initted & 1))
+ {
+ if (!nsssd_pwd_start(a))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ initted |= 1 ;
+ }
+ if (!nsssd_pwd_get(a, &pw))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ print_pw(&pw) ;
+}
+
+static inline void do_pwnam (void *a)
+{
+ struct passwd pw ;
+ uint32_t len ;
+ char buf[4] ;
+ get0(buf, 4) ;
+ uint32_unpack_big(buf, &len) ;
+ if (!len || len > NSSS_SWITCH_NAME_MAXLEN - 1)
+ {
+ answer(EPROTO) ;
+ return ;
+ }
+ {
+ char name[len] ;
+ get0(name, len) ;
+ if (name[len-1])
+ {
+ answer(EPROTO) ;
+ return ;
+ }
+ if (!nsssd_pwd_getbyname(a, &pw, name))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ }
+ print_pw(&pw) ;
+}
+
+static inline void do_pwuid (void *a)
+{
+ struct passwd pw ;
+ uint32_t uid ;
+ char buf[4] ;
+ get0(buf, 4) ;
+ uint32_unpack_big(buf, &uid) ;
+ if (!nsssd_pwd_getbyuid(a, &pw, uid))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ print_pw(&pw) ;
+}
+
+static inline void do_grend (void *a)
+{
+ nsssd_grp_end(a) ;
+ answer(0) ;
+}
+
+static inline void do_grrewind (void *a)
+{
+ if (!(initted & 2))
+ {
+ if (!nsssd_grp_start(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ initted |= 2 ;
+ }
+ if (!nsssd_grp_rewind(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ answer(0) ;
+}
+
+static inline void do_grget (void *a)
+{
+ struct group gr ;
+ if (!(initted & 2))
+ {
+ if (!nsssd_grp_start(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ initted |= 2 ;
+ }
+ if (!nsssd_grp_get(a, &gr))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ print_gr(&gr) ;
+}
+
+static inline void do_grnam (void *a)
+{
+ struct group gr ;
+ uint32_t len ;
+ char buf[4] ;
+ get0(buf, 4) ;
+ uint32_unpack_big(buf, &len) ;
+ if (!len || len > NSSS_SWITCH_NAME_MAXLEN - 1)
+ {
+ answer(EPROTO) ;
+ return ;
+ }
+ {
+ char name[len] ;
+ get0(name, len) ;
+ if (name[len-1])
+ {
+ answer(EPROTO) ;
+ return ;
+ }
+ if (!nsssd_grp_getbyname(a, &gr, name))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ }
+ print_gr(&gr) ;
+}
+
+static inline void do_grgid (void *a)
+{
+ struct group gr ;
+ uint32_t gid ;
+ char buf[4] ;
+ get0(buf, 4) ;
+ uint32_unpack_big(buf, &gid) ;
+ if (!nsssd_grp_getbygid(a, &gr, gid))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ print_gr(&gr) ;
+}
+
+static inline void do_spend (void *a)
+{
+ nsssd_shadow_end(a) ;
+ answer(0) ;
+}
+
+static inline void do_sprewind (void *a)
+{
+ if (!(initted & 4))
+ {
+ if (!nsssd_shadow_start(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ initted |= 4 ;
+ }
+ if (!nsssd_shadow_rewind(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ answer(0) ;
+}
+
+static inline void do_spget (void *a)
+{
+ struct spwd sp ;
+ if (!(initted & 4))
+ {
+ if (!nsssd_shadow_start(a))
+ {
+ answer(errno) ;
+ return ;
+ }
+ initted |= 4 ;
+ }
+ if (!nsssd_shadow_get(a, &sp))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ print_sp(&sp) ;
+}
+static inline void do_spnam (void *a)
+{
+ struct spwd sp ;
+ uint32_t len ;
+ char buf[4] ;
+ get0(buf, 4) ;
+ uint32_unpack_big(buf, &len) ;
+ if (!len || len > NSSS_SWITCH_NAME_MAXLEN - 1)
+ {
+ answer(EPROTO) ;
+ return ;
+ }
+ {
+ char name[len] ;
+ get0(name, len) ;
+ if (name[len-1])
+ {
+ answer(EPROTO) ;
+ return ;
+ }
+ if (!nsssd_shadow_getbyname(a, &sp, name))
+ {
+ answer(errno ? errno : NSSSD_EOF) ;
+ return ;
+ }
+ }
+ print_sp(&sp) ;
+}
+
+
+int nsssd_main (char const *const *argv, char const *const *envp)
+{
+ void *a = nsssd_handle_init() ;
+ if (ndelay_on(0) < 0) strerr_diefu1sys(111, "set stdin non-blocking") ;
+ tain_now_g() ;
+ if (!nsssd_handle_start(a, argv, envp))
+ strerr_diefu1sys(111, "nsssd_handle_start") ;
+
+ for (;;)
+ {
+ tain_t deadline ;
+ char c ;
+ tain_add_g(&deadline, &tain_infinite_relative) ;
+ if (!buffer_timed_get_g(buffer_0small, &c, 1, &deadline)) break ;
+ errno = 0 ;
+ switch (c)
+ {
+ case NSSS_SWITCH_PWD_END : do_pwend(a) ; break ;
+ case NSSS_SWITCH_PWD_REWIND : do_pwrewind(a) ; break ;
+ case NSSS_SWITCH_PWD_GET : do_pwget(a) ; break ;
+ case NSSS_SWITCH_PWD_GETBYNAME : do_pwnam(a) ; break ;
+ case NSSS_SWITCH_PWD_GETBYUID : do_pwuid(a) ; break ;
+ case NSSS_SWITCH_GRP_END : do_grend(a) ; break ;
+ case NSSS_SWITCH_GRP_REWIND : do_grrewind(a) ; break ;
+ case NSSS_SWITCH_GRP_GET : do_grget(a) ; break ;
+ case NSSS_SWITCH_GRP_GETBYNAME : do_grnam(a) ; break ;
+ case NSSS_SWITCH_GRP_GETBYGID : do_grgid(a) ; break ;
+ case NSSS_SWITCH_SHADOW_END : do_spend(a) ; break ;
+ case NSSS_SWITCH_SHADOW_REWIND : do_sprewind(a) ; break ;
+ case NSSS_SWITCH_SHADOW_GET : do_spget(a) ; break ;
+ case NSSS_SWITCH_SHADOW_GETBYNAME : do_spnam(a) ; break ;
+ default :
+ errno = EPROTO ;
+ strerr_diefu1sys(1, "interpret stdin") ;
+ }
+ }
+ nsssd_handle_end(a) ;
+ return 0 ;
+}